/* ============================================
   jutexx.com — CSS base del sitio publico
   Estilo: oscuro, minimalista, tipografia fina
   tipo SpaceX / Google / Apple (Inter).
   Este archivo NO lleva el fondo animado del
   home (esta en fondo-animado.css).
   Los design tokens viven en tokens.css (compartido
   con el admin): cargar tokens.css antes que este.
   ============================================ */

/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; scroll-padding-top: 84px; }
body {
  font-family: var(--font);
  background: #000;
  color: var(--color-text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  font-weight: 300;
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font: inherit; cursor: pointer; color: inherit; background: none; border: none; }

/* --- Progress bar --- */
.progress-bar {
  position: fixed;
  top: 0; left: 0;
  width: 0;
  height: 2px;
  background: linear-gradient(90deg, #fff, #666);
  z-index: 40;
  transition: width 0.1s linear;
}

/* --- Nav (SpaceX-like, fina y espaciada) --- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 20;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 26px 40px;
  transition: background 0.4s, backdrop-filter 0.4s, padding 0.4s;
}
.nav.scrolled {
  background: rgba(0,0,0,0.8);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--color-line-soft);
  padding: 14px 40px;
}
.nav .brand {
  display: flex;
  justify-self: start;
  align-items: center;
  gap: 10px;
  font-size: .95rem;
  font-weight: 300;
  letter-spacing: .35em;
  text-transform: uppercase;
}
.nav .brand img { width: 28px; height: 28px; }
.nav .links { display: flex; justify-self: center; gap: 34px; }
.nav .links a {
  font-size: .74rem;
  font-weight: 300;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--color-soft);
  padding: 4px 0;
  position: relative;
  transition: color .3s;
}
.nav .links a::after {
  content: "";
  position: absolute;
  bottom: 0; left: 0;
  width: 100%; height: 1px;
  background: #fff;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform .35s;
}
.nav .links a:hover,
.nav .links a.active { color: #fff; }
.nav .links a:hover::after,
.nav .links a.active::after { transform: scaleX(1); transform-origin: left; }
.nav .clock-wrap {
  display: flex;
  justify-self: end;
  align-items: center;
  gap: 8px;
  color: #777;
  font-size: .72rem;
  font-variant-numeric: tabular-nums;
}
.nav .live-dot {
  width: 6px; height: 6px;
  background: var(--accent);
  border-radius: 50%;
  animation: pulse 2s infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
.nav .clock { letter-spacing: .25em; }
/* Instagram en el nav: línea fina, apagado; se enciende en verde al pasar. */
.nav .nav-ig {
  display: inline-flex;
  align-items: center;
  color: #888;
  margin-right: 10px;
  transition: color .25s ease;
}
.nav .nav-ig:hover, .nav .nav-ig:focus-visible { color: var(--accent); outline: none; }
.menu .menu-ig {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: #888;
}
.menu .menu-ig span { font-size: .8em; letter-spacing: .18em; }

/* --- Burger (mobile) --- */
.burger {
  display: none;
  position: absolute;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  z-index: 35;
  width: 44px; height: 44px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.burger span {
  display: block;
  width: 26px; height: 2px;
  background: #fff;
  margin: 0;
  transition: transform .35s, opacity .35s;
}
.burger.active span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.burger.active span:nth-child(2) { opacity: 0; }
.burger.active span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

/* --- Menu movil --- */
.menu {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: rgba(0,0,0,0.95);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 34px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s;
}
.menu.open { opacity: 1; pointer-events: auto; }
.menu a {
  font-size: 1.4rem;
  font-weight: 200;
  letter-spacing: .25em;
  text-transform: uppercase;
  color: #fff;
}
.menu a:active { color: #999; }
body.menu-open { overflow: hidden; }

/* --- Layout --- */
.section {
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 100px 24px;
  position: relative;
  z-index: 2;
  text-align: center;
}
.content { width: 100%; max-width: 1100px; margin: 0 auto; }
.wide { width: 100%; max-width: 1100px; margin: 0 auto; }

/* --- Hero (home) --- */
.hero-inner { position: relative; z-index: 1; width: 100%; max-width: 1100px; margin: 0 auto; }
.kicker {
  font-size: clamp(1.8rem, 5.5vw, 3.4rem);
  font-weight: 200;
  letter-spacing: .04em;
  text-transform: uppercase;
  line-height: 1.1;
  color: #fff;
  margin-bottom: 32px;
  min-height: 1.4em;
}
.kicker b { font-weight: 300; color: #fff; }

/* Rotador del kicker (home): glitch en cada cambio de palabra */
@keyframes kicker-glitch {
  0%   { transform: translate(0, 0); text-shadow: -2px 0 rgba(255,0,102,.85), 2px 0 rgba(0,204,255,.85); }
  25%  { transform: translate(-3px, 1px) skewX(-6deg); }
  50%  { transform: translate(3px, -1px) skewX(0deg); }
  75%  { transform: translate(-2px, 1px) skewX(6deg); }
  100% { transform: translate(0, 0); text-shadow: -2px 0 rgba(255,0,102,.85), 2px 0 rgba(0,204,255,.85); }
}
.kicker.k-rot.glitching { animation: kicker-glitch .3s steps(2, end) 1; }
/* Una sola línea siempre: el JS achica la letra si la frase no entra. */
.kicker.k-rot { white-space: nowrap; }
.hero-logo-wrap {
  position: relative;
  display: inline-block;
  width: min(380px, 70vw);
}
.hero-logo-wrap .hero-logo {
  display: block;
  width: 100%;
  height: auto;
  position: relative;
  z-index: 1;
}

/* --- Glitch del logo (RGB split + cortes, estilo hacker) --- */
.hero-logo-wrap::before,
.hero-logo-wrap::after {
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background: url("/logos/logo-blanco.png") center / contain no-repeat;
  pointer-events: none;
  opacity: 0;
  z-index: 2;
  will-change: transform, opacity, clip-path;
}
.hero-logo-wrap::before {
  filter: brightness(0) invert(1) sepia(1) saturate(10000%) hue-rotate(320deg);
  animation: glitch-r 3.8s infinite;
}
.hero-logo-wrap::after {
  filter: brightness(0) invert(1) sepia(1) saturate(10000%) hue-rotate(160deg);
  animation: glitch-c 3.8s infinite;
}

@keyframes glitch-r {
  0%, 24%, 41%, 58%, 89%, 100% { opacity: 0; transform: none; clip-path: none; }
  25%  { opacity: .65; transform: translate(-7px, 1px); }
  27%  { opacity: .7;  transform: translate(-4px, -2px); clip-path: polygon(0 12%, 100% 12%, 100% 26%, 0 26%); }
  29%  { opacity: 0; transform: translate(-7px, 1px); clip-path: none; }
  90%  { opacity: .65; transform: translate(-7px, 2px); }
  92%  { opacity: .75; transform: translate(-5px, -1px); clip-path: polygon(0 58%, 100% 58%, 100% 72%, 0 72%); }
  94%  { opacity: .7;  transform: translate(-8px, 2px); clip-path: polygon(0 34%, 100% 34%, 100% 41%, 0 41%); }
  96%  { opacity: 0; transform: none; clip-path: none; }
}

@keyframes glitch-c {
  0%, 24%, 41%, 58%, 89%, 100% { opacity: 0; transform: none; clip-path: none; }
  25%  { opacity: .65; transform: translate(7px, -1px); }
  27%  { opacity: .7;  transform: translate(4px, 2px); clip-path: polygon(0 46%, 100% 46%, 100% 60%, 0 60%); }
  29%  { opacity: 0; transform: translate(7px, -1px); clip-path: none; }
  90%  { opacity: .65; transform: translate(7px, -2px); }
  92%  { opacity: .75; transform: translate(5px, 1px); clip-path: polygon(0 6%, 100% 6%, 100% 18%, 0 18%); }
  94%  { opacity: .7;  transform: translate(8px, -1px); clip-path: polygon(0 70%, 100% 70%, 100% 84%, 0 84%); }
  96%  { opacity: 0; transform: none; clip-path: none; }
}
.hero-sub {
  color: var(--text);
  font-size: clamp(.95rem, 2vw, 1.2rem);
  font-weight: 200;
  letter-spacing: .08em;
  margin-top: 26px;
}

/* --- Efecto Hacker en los títulos ---
   Cada carácter pasa a ser una caja con su ancho congelado: se mide el
   ancho del carácter real y se fija ese ancho. El descifrado sigue
   cambiando el glifo que se ve, pero como la caja no cambia de tamaño,
   el título no puede pasar de renglón ni de alto, y la página deja de
   expandirse y contraerse a medida que los títulos aparecen. */
.hx-char {
  display: inline-block;
  /* el ancho congelado puede sobrar en la ultima caja: el glifo va pegado
     a la izquierda para que ese resto quede al final y no como un hueco */
  text-align: left;
}
/* La palabra entera es la caja, y adentro van los caracteres. Si la caja
   fuera el carácter, el navegador podría cortar entre dos cajas
   cualesquiera y partir palabras por la mitad ("MA" / "S QUE..."). Con
   la palabra como caja, el corte solo cae en los espacios. El
   break-word es la red de seguridad para una palabra tan larga que no
   entra en una línea (una URL, un nombre): antes eso no pasaba nunca
   porque se cortaba en cualquier lado. */
.hx-word {
  display: inline-block;
  overflow-wrap: break-word;
}
.hx-live .hx-glitch {
  color: #6dff9c;
  text-shadow: 0 0 10px rgba(109,255,156,.7);
}
.hx-char.hx-on {
  color: #fff;
  opacity: 1;
  text-shadow: 0 0 8px rgba(109,255,156,.3);
}

/* --- Scroll hint --- */
.scroll-hint {
  position: absolute;
  bottom: 36px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  font-size: .62rem;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.scroll-hint .wheel {
  width: 1px; height: 46px;
  background: linear-gradient(#999, transparent);
  animation: drop 2s cubic-bezier(.22,1,.36,1) infinite;
  transform-origin: top;
}
@keyframes drop {
  0% { transform: scaleY(0); }
  55% { transform: scaleY(1); }
  56% { transform-origin: bottom; }
  100% { transform: scaleY(0); }
}

/* --- Tipografia general --- */
.num {
  font-size: .72rem;
  font-weight: 300;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: 18px;
}
.big-title {
  font-size: clamp(1.8rem, 5.5vw, 3.4rem);
  font-weight: 200;
  letter-spacing: .04em;
  text-transform: uppercase;
  line-height: 1.1;
  color: #fff;
  /* Los títulos display parten en varias líneas y, sin esto, la última
     palabra queda sola ("... COPIAR Y" / "PEGAR"). `balance` reparte el
     texto en dos líneas parecidas en lugar de llenando la primera. */
  text-wrap: balance;
}
.desc {
  color: #ddd;
  font-size: clamp(1rem, 2.2vw, 1.2rem);
  font-weight: 200;
  line-height: 1.7;
  margin-top: 24px;
}
.desc a { color: #fff; text-decoration: underline; text-underline-offset: 4px; }
.line {
  width: 60px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.25), transparent);
  margin: 40px auto 0;
}
.narrow .line { margin: 32px 0; }

/* --- Stats --- */
.stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 60px;
  margin-top: 60px;
}
.stat { min-width: 130px; }
.stat .value {
  font-size: clamp(1.8rem, 4.5vw, 2.8rem);
  font-weight: 200;
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  color: #fff;
}
.stat .cap {
  font-size: .68rem;
  font-weight: 300;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-top: 10px;
}

/* --- CTA --- */
.cta {
  display: inline-block;
  margin-top: 40px;
  padding: 16px 42px;
  font-size: .78rem;
  font-weight: 300;
  letter-spacing: .35em;
  text-transform: uppercase;
  color: #fff;
  border: 1px solid #fff;
  transition: background .3s, color .3s;
}
.cta:hover { background: #fff; color: #000; }
/* Estado de error de un botón que valida un formulario (el de
   /servicios/). No cambia el layout, solo el color, para que el
   mensaje de "faltó algo" se lea sin recargar. */
.cta.is-warn {
  color: var(--danger-soft);
  border-color: var(--danger-soft);
  text-transform: none;
  letter-spacing: .08em;
}
.cta.is-warn:hover { background: var(--danger-soft); color: #000; }

/* fila de CTAs (hero): wrappea sin saltar el margin default */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-top: 40px;
}
.cta-row .cta { margin-top: 0; }
.cta-solid { background: #fff; color: #000; }
.cta-solid:hover { background: #000; color: #fff; }

/* --- Tags (etiquetas de post) --- */
.tag {
  display: inline-block;
  font-size: .62rem;
  font-weight: 300;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #999;
  border: 1px solid var(--color-line);
  padding: 6px 14px;
}

/* --- Catálogo (proyectos y blog comparten el mismo componente) --- */
.post-list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin-top: 60px;
}
.card {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 32px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
  background: rgba(17,17,19,0.9);
  transition: border-color .3s, transform .3s, box-shadow .3s;
  position: relative;
  overflow: hidden;
  text-align: left;
  font-weight: 300;
  /* Una palabra larga (una URL, un nombre de cliente) partía la card y
     empujaba el resto de la grilla. Cortar la palabra es feo pero meter
     scroll horizontal en la página es peor. */
  overflow-wrap: break-word;
}
.card:hover {
  border-color: rgba(255,255,255,0.3);
  transform: translateY(-4px);
  box-shadow: 0 8px 32px -8px rgba(0,0,0,0.6);
}
.card .feature-heading { margin-bottom: 16px; }
.card .feature-title {
  font-size: 1.125rem;
  font-weight: 300;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: #fff;
  overflow-wrap: break-word;
  line-height: 1.3;
}
.card .feature-meta {
  font-size: .62rem;
  font-weight: 300;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: 6px;
}
/* Etiqueta que reemplaza la fecha en la tarjeta fijada de la home
   ("Destacado"). Sale en el color de acento y con tracking un poco más
   cerrado para que se lea como una marca y no como otra fecha. */
.card .post-badge {
  display: inline-block;
  padding: 3px 8px 2px;
  border: 1px solid rgba(0, 230, 138, .45);
  border-radius: 3px;
  background: rgba(0, 230, 138, .08);
  color: var(--accent);
  letter-spacing: .22em;
  margin-bottom: 8px;
}
.card .feature-desc {
  font-size: .9375rem;
  font-weight: 200;
  color: var(--color-soft);
  line-height: 1.7;
  /* Antes llevaba -webkit-line-clamp: 3 y la descripción se cortaba a los
     3 renglones: en escritorio una de 6 renglones se mostraba en 3 y
     terminaba a media frase, que es justo lo que se veía raro. La grilla
     iguala el alto de las cards de una misma fila por su cuenta, así que
     el recorte no hacía falta para que se vieran ordenadas. */
  overflow-wrap: break-word;
}
.card .feature-image-container {
  aspect-ratio: 16/9;
  border: 1px solid var(--color-line-soft);
  border-radius: 12px;
  overflow: hidden;
  background: #0a0a0b;
  margin-top: auto;
}
.card .feature-image {
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: .85;
  transition: opacity .3s, transform .3s;
}
.card:hover .feature-image { opacity: 1; transform: scale(1.02); }
.card-cta {
  margin-top: 4px;
  font-size: .7rem;
  font-weight: 300;
  letter-spacing: .25em;
  text-transform: uppercase;
  color: var(--color-accent);
}
.card .tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: auto;
  padding-top: 16px;
}

/* --- Search --- */
.search-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  max-width: 480px;
  margin: 48px auto 0;
}
.search-input {
  width: 100%;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
  padding: 14px 20px;
  font-size: .875rem;
  font-family: var(--font);
  color: #fff;
  font-weight: 300;
  letter-spacing: .04em;
  outline: none;
  transition: border-color .3s, background .3s;
}
.search-input::placeholder { color: #555; }
.search-input:focus { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.25); }

/* Dropdown nativo del <select> en tema oscuro (por si aparece alguno) */
select option {
  background: #121216;
  color: var(--text);
}
select option:checked { background: #1a1a20; color: var(--accent); }
.search-count {
  font-size: .65rem;
  font-weight: 300;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--color-muted);
  /* nowrap: el contador ("3 PROYECTOS") no puede partirse a la mitad, pero
     en un teléfono de 360px eso empujaba la barra de búsqueda fuera de
     pantalla. nowrap solo mientras haya lugar. */
  white-space: nowrap;
  max-width: 100%;
  overflow-wrap: break-word;
}
.empty {
  color: #555;
  font-weight: 200;
  text-align: center;
  padding: 70px 20px;
  letter-spacing: .1em;
}

/* --- Detalle de post/proyecto (plantilla moderna) --- */
.narrow { width: 100%; max-width: 1100px; margin: 0 auto; text-align: left; }
.label {
  font-size: .68rem; font-weight: 300; letter-spacing: .3em;
  text-transform: uppercase; color: var(--color-muted); margin-bottom: 14px;
}
.title {
  font-size: clamp(1.6rem, 4vw, 2.4rem); font-weight: 200;
  letter-spacing: .04em; text-transform: uppercase; line-height: 1.15; color: #fff;
}
.subtitle { color: var(--color-soft); font-weight: 200; margin-top: 18px; font-size: 1.05rem; line-height: 1.7; }

/* --- Portada del post (detalle) --- */
.post-cover {
  width: 100%;
  aspect-ratio: 16/9;
  overflow: hidden;
  border: 1px solid var(--color-line-soft);
  border-radius: var(--radius);
  background: #0a0a0b;
  margin: 0 0 36px;
}
.post-cover .post-cover-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* --- Entry (contenido de posts) --- */
.entry {
  text-align: left;
  color: #ddd;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  font-weight: 200;
  line-height: 1.8;
}
.entry h2 {
  font-size: 1.5rem;
  font-weight: 300;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #fff;
  margin: 48px 0 14px;
}
.entry h3 {
  font-size: 1.2rem;
  font-weight: 300;
  color: #fff;
  margin: 36px 0 12px;
}
.entry p { margin: 14px 0; }
.entry ul, .entry ol { margin: 14px 0; padding-left: 1.4em; }
.entry li { margin-bottom: 6px; }
.entry code {
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: .9em;
  background: rgba(255,255,255,0.07);
  padding: 2px 6px;
  border-radius: 4px;
}
.entry pre {
  border: 1px solid var(--color-line);
  background: #0a0a0a;
  border-radius: 8px;
  padding: 18px;
  overflow-x: auto;
  margin: 20px 0;
  font-size: .85rem;
  line-height: 1.6;
}
.entry pre code { background: none; padding: 0; }
.entry a { color: #fff; text-decoration: underline; text-underline-offset: 4px; }
.entry strong { color: #fff; font-weight: 400; }
.entry img:not(.post-cover-img) { border-radius: 8px; margin: 24px 0; }
.entry hr { border: none; border-top: 1px solid var(--color-line-soft); margin: 32px 0; }
.entry { overflow-wrap: break-word; }

/* Separaciones verticales reutilizables (reemplazan style="margin-top") */
.mt-18 { margin-top: 18px; }
.mt-30 { margin-top: 30px; }
.mt-40 { margin-top: 40px; }
.mt-48 { margin-top: 48px; }
.entry table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-collapse: collapse;
  margin: 24px 0;
  font-size: .9rem;
  line-height: 1.5;
}
.entry th, .entry td {
  border: 1px solid var(--color-line);
  padding: 8px 12px;
  text-align: left;
  vertical-align: top;
}
.entry th { color: #fff; font-weight: 400; background: rgba(255,255,255,.04); }
.entry blockquote {
  border-left: 2px solid rgba(255,255,255,0.15);
  padding-left: 20px;
  margin: 24px 0;
  color: var(--muted);
}

/* --- Footer --- */
footer {
  z-index: 2;
  text-align: center;
  letter-spacing: .25em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 40px 16px;
  font-size: .65rem;
  font-weight: 300;
  position: relative;
}
.footer-inner { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.footer-inner span { color: #666; }
/* Ícono de Instagram del pie: línea fina, apagado, se enciende al pasar. */
.footer-ig {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: #888;
  transition: color .25s ease, border-color .25s ease, box-shadow .25s ease;
}
.footer-ig:hover, .footer-ig:focus-visible {
  color: var(--accent);
  border-color: rgba(0, 230, 138, .5);
  box-shadow: 0 0 14px rgba(0, 230, 138, .18);
  outline: none;
}

/* --- Loader global de pagina --- */
#loader {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity .5s ease, visibility .5s ease;
}
#loader .loader-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30px;
}
#loader .loader-logo {
  width: 84px;
  height: 84px;
  opacity: .92;
  animation: loader-breathe 2.2s ease-in-out infinite;
}
#loader .loader-bar {
  width: 180px;
  height: 1px;
  background: rgba(255,255,255,.12);
  overflow: hidden;
  position: relative;
}
#loader .loader-bar i {
  position: absolute;
  top: 0; left: 0;
  width: 40%;
  height: 100%;
  background: linear-gradient(90deg, transparent, var(--color-accent), transparent);
  animation: loader-scan 1.3s cubic-bezier(.22,1,.36,1) infinite;
}
#loader.loader-done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
@keyframes loader-breathe {
  0%, 100% { opacity: .55; transform: scale(1); }
  50% { opacity: .95; transform: scale(1.05); }
}
@keyframes loader-scan {
  0% { left: -40%; }
  100% { left: 100%; }
}
html.pg-loading { overflow: hidden; }
html.pg-loading [data-reveal] { transition: none !important; }

/* --- Reveal on scroll --- */
[data-reveal] {
  opacity: 0;
  transform: translateY(36px);
  transition: opacity .9s cubic-bezier(.22,1,.36,1), transform .9s cubic-bezier(.22,1,.36,1);
}
[data-reveal].on { opacity: 1; transform: none; }

/* --- Responsive --- */
@media (max-width: 1024px) {
  .post-list { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 720px) {
  .post-list { grid-template-columns: 1fr; }
  .nav { padding: 22px 20px; }
  .nav.scrolled { padding: 14px 20px; }
  .nav .links, .nav .clock { display: none; }
  .burger { display: flex; }
  .section { padding: 84px 20px; }
  .kicker { font-size: clamp(1.6rem, 8vw, 2.4rem); letter-spacing: .03em; line-height: 1.15; }
  .hero-sub { font-size: .95rem; margin-top: 20px; line-height: 1.7; }
  .num { letter-spacing: .2em; }
  .big-title { font-size: clamp(1.6rem, 8vw, 2.4rem); letter-spacing: .03em; }
  .desc { font-size: 1rem; line-height: 1.65; }
  .cta { width: 100%; max-width: 340px; padding: 16px 24px; display: block; margin: 40px auto 0; }
  .menu a { font-size: clamp(1.1rem, 5.5vw, 1.4rem); letter-spacing: .18em; }
  .stat .cap { letter-spacing: .22em; }
  .stats { gap: 36px; margin-top: 48px; }
  .stat { min-width: 100px; }
  [data-reveal] { opacity: 1; transform: none; }
}

@media (max-height: 560px) { .scroll-hint { display: none; } }

/* Teléfono: la card de 32px de padding se comía la mitad del ancho y el
   texto de 3 renglones salía con la última línea a media palabra. Acá la
   card respira menos y el clamp se suelta: es preferible un renglón más
   de texto completo que uno cortado con puntos suspensivos. */
@media (max-width: 520px) {
  .card { padding: 22px 18px; gap: 16px; }
  .card .feature-heading { margin-bottom: 12px; }
  .card .feature-meta { letter-spacing: .18em; }
  /* En una sola columna el alto desigual de las cards no se nota, pero el
     recorte sí: las descripciones necesitan 6-7 renglones y a 3 (o 5)
     quedaban con la última línea partida por la mitad. En el teléfono la
     descripción se muestra entera. */
  .card .feature-desc {
    font-size: .875rem;
    line-height: 1.6;
  }
  .card-cta { letter-spacing: .16em; }
  .search-count { letter-spacing: .12em; }
}

/* 320px (iPhone SE): el roster queda con ~209px de texto y las
   descripciones más largas seguían cayendo a 2 renglones. Un punto menos
   de cuerpo alcanza para que entren en uno. */
@media (max-width: 380px) {
  .eqia-row-que { font-size: .74rem; }
  .eqia-member { font-size: .72rem; }
  .card { padding: 20px 15px; }
}
@media (max-width: 420px) { .stats { flex-direction: column; gap: 34px; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
}


/* ============================================================
   Pulido 2026-10-23 — legibilidad, accesibilidad, lectura de posts
   ============================================================ */

/* Foco visible para teclado (antes no había ninguno) */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
.search-input:focus-visible { outline-offset: 0; }
.skip-link {
  position: fixed;
  top: 10px; left: 10px;
  z-index: 200;
  padding: 10px 16px;
  background: #fff;
  color: #000;
  font-size: .8rem;
  letter-spacing: .08em;
  transform: translateY(-160%);
  transition: transform .2s;
}
.skip-link:focus { transform: none; }

/* Texto corrido más legible: peso 200 sobre negro se come los trazos */
.desc, .subtitle, .card .feature-desc, .hero-sub { font-weight: 300; }
.entry { font-weight: 300; color: #e0e0e0; }
.entry strong { font-weight: 500; }
.search-input::placeholder, .empty { color: #8a8a8a; }
.nav .clock-wrap { color: #8a8a8a; }
.footer-inner span { color: #8a8a8a; }

/* Detalle: columna de lectura (≈70 caracteres por línea, no 140) */
.section-post {
  align-items: flex-start;
  min-height: 100svh;
  padding-top: 140px;
}
.section-post .narrow { max-width: 760px; }
.section-post .entry { max-width: none; font-size: 1.0625rem; line-height: 1.85; }
.section-post .title { text-wrap: balance; }
.post-meta {
  margin-top: 20px;
  font-size: .7rem;
  font-weight: 300;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.entry h2 { text-wrap: balance; }
.entry img:not(.post-cover-img) { max-width: 100%; height: auto; }
.entry :is(h2, h3) { scroll-margin-top: 90px; }
.post-project { margin-top: 40px; }

/* Cards: hover más sobrio y foco claro */
.card:focus-visible { border-color: var(--accent); outline-offset: 4px; }
.card:hover .card-cta { letter-spacing: .3em; }
.card-cta { transition: letter-spacing .3s; }

/* Imprimir un post: fondo blanco, sin chrome */
@media print {
  body { background: #fff; color: #000; }
  .nav, .menu, footer, .progress-bar, #loader, .cta, canvas { display: none !important; }
  .section-post { padding-top: 0; }
  .entry, .title, .entry h2, .entry h3, .entry strong { color: #000; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* ============================================================
   Bloques para posts (se usan desde el HTML/Markdown del admin)
   Sobrios a propósito: un solo acento, líneas finas, sin cajas de colores.
     <figure class="jx-fig"><img …><figcaption>…</figcaption></figure>
     <div class="jx-list"><div><h3>Título</h3><p>Texto</p></div>…</div>   (2 columnas, numeradas)
     <p class="jx-quote">Frase destacada</p>
     <table class="jx-compare"> · <ol class="jx-steps">
   ============================================================ */
.entry .jx-fig { margin: 40px 0; }
.entry .jx-fig img {
  width: 100%; height: auto; margin: 0; border-radius: 10px;
  border: 1px solid var(--line); background: #0a0c0f;
}
.entry .jx-fig figcaption { margin-top: 12px; font-size: .8rem; letter-spacing: .02em; color: var(--muted); }
.entry .jx-fig figcaption a { color: var(--soft); }

.entry .jx-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 48px; margin: 28px 0 36px; counter-reset: jx; }
.entry .jx-list > div { counter-increment: jx; padding: 22px 0 24px; border-top: 1px solid var(--line); }
.entry .jx-list h3 { margin: 0 0 8px; font-size: 1.05rem; font-weight: 400; letter-spacing: .01em; text-transform: none; color: #fff; }
.entry .jx-list h3::before { content: counter(jx, decimal-leading-zero); margin-right: 12px; font-size: .7rem; letter-spacing: .14em; color: var(--accent); vertical-align: 2px; }
.entry .jx-list p { margin: 0; font-size: .98rem; line-height: 1.7; color: #c9c9c9; }

.entry .jx-quote {
  margin: 40px 0; padding: 4px 0 4px 22px; border-left: 2px solid var(--accent);
  font-size: 1.2rem; line-height: 1.6; font-weight: 300; color: #fff;
}

.entry .jx-steps { list-style: none; padding: 0; margin: 24px 0; counter-reset: jx; }
.entry .jx-steps li { counter-increment: jx; margin: 0; padding: 16px 0 16px 48px; position: relative; border-top: 1px solid var(--line-soft); line-height: 1.6; }
.entry .jx-steps li:last-child { border-bottom: 1px solid var(--line-soft); }
.entry .jx-steps li::before { content: counter(jx, decimal-leading-zero); position: absolute; left: 0; top: 18px; font-size: .75rem; letter-spacing: .14em; color: var(--accent); }
.entry .jx-steps strong { color: #fff; font-weight: 400; margin-right: 8px; }

.entry table.jx-compare { display: table; width: 100%; border-collapse: collapse; margin: 28px 0; }
.entry table.jx-compare th, .entry table.jx-compare td { border: 0; border-bottom: 1px solid var(--line-soft); padding: 14px 16px 14px 0; text-align: left; }
.entry table.jx-compare th { background: none; font-size: .68rem; letter-spacing: .2em; text-transform: uppercase; color: var(--muted); font-weight: 400; border-bottom-color: var(--line); }
.entry table.jx-compare td:first-child { color: #fff; }
.entry table.jx-compare td:nth-child(2) { color: var(--muted); }
.entry table.jx-compare td:last-child { color: #e8e8e8; }

@media (max-width: 720px) {
  .entry .jx-list { grid-template-columns: 1fr; }
  .entry table.jx-compare th, .entry table.jx-compare td { padding-right: 10px; font-size: .88rem; }
}
