/* ═══════════════════════════════════════════════════════════
   PROPUESTA DE REDISEÑO — KLPServers
   Paleta y secciones originales. Tipografía, superficies,
   composición y movimiento reconstruidos.
   ═══════════════════════════════════════════════════════════ */

/* ── Tipografía alojada localmente (Task 23 — arreglo del CLS) ──────
   Antes: Geist/Geist Mono/Orbitron se pedían a fonts.googleapis.com,
   que a su vez redirige a fonts.gstatic.com. A 697ms llegaba Geist y
   el héroe saltaba ~60px al recomponerse (medido: CLS 0.21 a 390px
   en producción). El archivo de Google es en realidad una fuente
   variable (un solo .woff2 cubre los pesos 400-800): se aloja ese
   mismo archivo aquí, sin descargar un archivo por peso.

   El salto se elimina con ascent-override/descent-override/
   size-adjust en una fuente de respaldo ('Geist Fallback' /
   'Geist Mono Fallback') calculados para que Arial/Liberation Sans
   (Windows/Linux) y Helvetica (Mac) — el respaldo real más común—
   ocupen exactamente la misma caja que Geist. Así, aunque la fuente
   definitiva tarde, el hueco del texto no cambia y no hay salto.
   Valores calculados con las tablas hhea/OS-2 reales de cada
   archivo (fontTools), no estimados a ojo:
     Geist:      ascent 1005/1000em, descent 295/1000em, avgWidth 581/1000em
     LiberationSans (proxy de Arial): ascent 1854/2048em, descent 434/2048em, avgWidth 1187/2048em
     GeistMono:  ascent 1005/1000em, descent 295/1000em, avgWidth 600/1000em
     LiberationMono (proxy de Courier New): ascent 1705/2048em, descent 615/2048em, avgWidth 1229/2048em
   size-adjust = avgWidth(web)/avgWidth(fallback); ascent/descent-override = ratio(web)/size-adjust. */
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/geist-variable-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/geistmono-variable-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Orbitron';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/orbitron-700-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Geist Fallback';
  src: local('Arial'), local('Liberation Sans'), local('Arimo'), local('Helvetica Neue'), local('Helvetica');
  ascent-override: 100.26%;
  descent-override: 29.43%;
  line-gap-override: 0%;
  size-adjust: 100.24%;
}
@font-face {
  font-family: 'Geist Mono Fallback';
  src: local('Courier New'), local('Liberation Mono'), local('Consolas'), local('Menlo'), local('Courier');
  ascent-override: 100.52%;
  descent-override: 29.5%;
  line-gap-override: 0%;
  size-adjust: 99.98%;
}

:root {
  /* Paleta original, con superficies derivadas */
  --cyan:    #00f5ff;
  --magenta: #ff00ff;
  --purple:  #7b2fff;
  --green:   #00ff88;

  --bg:      #08080f;
  --bg-2:    #0c0c16;
  --surface: rgba(255,255,255,0.028);
  --surface-2: rgba(255,255,255,0.045);
  --line:    rgba(255,255,255,0.07);
  --line-2:  rgba(255,255,255,0.12);

  --text:    #edf0f6;
  --muted:   #9aa3b8;
  --subtle:  #5b6479;

  --display: 'Geist', 'Geist Fallback', system-ui, sans-serif;
  --mono:    'Geist Mono', 'Geist Mono Fallback', ui-monospace, monospace;

  --dur:     260ms;
  --ease:    cubic-bezier(0.16, 1, 0.3, 1);
  --spring:  cubic-bezier(0.34, 1.4, 0.64, 1);

  --shell:   1280px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--display);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ── Fondo vivo: malla de gradientes + rejilla + grano ───── */
.fondo { position: fixed; inset: 0; z-index: 0; pointer-events: none; }

/* El desenfoque se "hornea" en el propio gradiente (paradas amplias que ya
   diluyen el color antes del borde) en vez de un filter:blur() en vivo: un
   filter sobre una capa con inset:-30% (gigante) recalculado en cada
   fotograma de la animación era el coste más caro de toda la página
   (medido: pico de 62,7 ms en un solo fotograma). Sin filter, el navegador
   solo compone transform/opacity en la GPU, sin repintar píxeles. */
.fondo::before {
  content: '';
  position: absolute; inset: -10%;
  background:
    radial-gradient(56% 62% at 18% 22%, rgba(0,245,255,0.13), transparent 74%),
    radial-gradient(52% 58% at 82% 30%, rgba(255,0,255,0.11), transparent 76%),
    radial-gradient(64% 68% at 50% 88%, rgba(123,47,255,0.13), transparent 78%);
  animation: deriva 26s ease-in-out infinite alternate;
}
@keyframes deriva {
  0%   { transform: translate3d(-2%, -1%, 0) scale(1); }
  50%  { transform: translate3d(2%, 2%, 0) scale(1.06); }
  100% { transform: translate3d(-1%, 1%, 0) scale(1.02); }
}
@media (min-width: 901px) {
  /* will-change puntual: solo en escritorio, que es donde el fondo sigue
     animado (en móvil se congela más abajo, ver @media max-width:900px). */
  .fondo::before { will-change: transform; }
}

/* Rejilla en perspectiva: da profundidad sin coste de render.
   Antes animaba `background-position`, que NO se compone en GPU: obliga a
   repintar el elemento completo (2161x238px reales) en cada fotograma.
   Ahora anima `transform` (translateY añadido al final de la lista, para
   que se aplique ANTES de perspective/rotateX — es decir, sobre el plano
   local sin rotar, igual que hacía background-position con la textura),
   así que el navegador solo compone, nunca repinta. */
.rejilla {
  position: absolute; left: 50%; bottom: -12vh;
  width: 240vw; height: 62vh;
  transform: translateX(-50%) perspective(52vh) rotateX(72deg) translateY(0);
  background-image:
    linear-gradient(to right,  rgba(0,245,255,0.11) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(0,245,255,0.11) 1px, transparent 1px);
  background-size: 68px 68px;
  mask-image: linear-gradient(to top, #000 0%, transparent 78%);
  animation: rejilla-avanza 9s linear infinite;
}
@keyframes rejilla-avanza {
  from { transform: translateX(-50%) perspective(52vh) rotateX(72deg) translateY(0); }
  to   { transform: translateX(-50%) perspective(52vh) rotateX(72deg) translateY(68px); }
}

/* Grano: rompe la planitud digital. Sin mix-blend-mode: ese blend obligaba
   al compositor a mezclar la pantalla completa contra el fotograma de
   abajo en cada scroll (coste alto, capa fixed a pantalla completa). Con
   blend normal y opacidad baja el grano sigue visible, solo que ya no
   exige recalcular el mezclado en cada frame: es una capa fixed simple,
   barata de componer. */
.grano {
  position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: 0.06;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.capa { position: relative; z-index: 2; }
.shell { width: min(100% - 2.5rem, var(--shell)); margin-inline: auto; }

/* ── Aviso del sitio ────────────────────────────────────────
   Vive en flujo normal, ANTES del nav (que es sticky): así nunca
   lo tapa ni lo cubre, y no hace falta calcular ni sincronizar
   ninguna altura por JS — el nav simplemente aparece debajo. */
.anuncio {
  position: relative; z-index: 40;
  /* Superficie sólida, no cristal esmerilado: solo el nav (fijo, siempre
     sobre contenido que se mueve debajo) necesita backdrop-filter de verdad. */
  background: var(--bg-2);
  border-bottom: 1px solid var(--line-2);
}
.anuncio-in {
  position: relative;
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 0.4rem 1rem; min-height: 2.75rem;
  padding: 0.65rem 2.75rem 0.65rem 1rem;
}
.anuncio-tag {
  display: inline-flex; align-items: center; flex-shrink: 0;
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--acento-anuncio, var(--cyan));
}
.anuncio-tag::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
  background: currentColor; margin-right: 0.5rem;
}
.anuncio-txt { margin: 0; font-size: 0.86rem; color: var(--text); text-align: center; text-wrap: pretty; }
.anuncio-cta {
  flex-shrink: 0; text-decoration: none; color: var(--acento-anuncio, var(--cyan));
  border: 1px solid currentColor; border-radius: 4px; padding: 0.25rem 0.7rem;
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.03em;
  transition: background-color var(--dur) var(--ease);
}
.anuncio-cta:hover { background-color: rgba(255,255,255,0.08); }
.anuncio-cerrar {
  position: absolute; right: 0.6rem; top: 50%; transform: translateY(-50%);
  border: 0; border-radius: 4px; background: transparent; color: var(--subtle);
  cursor: pointer; font-size: 0.85rem; line-height: 1; padding: 0.45rem;
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.anuncio-cerrar:hover { color: var(--text); background: rgba(255,255,255,0.07); }

.anuncio-info    { --acento-anuncio: var(--cyan); }
.anuncio-success { --acento-anuncio: var(--green); }
.anuncio-warning { --acento-anuncio: #ffb020; }
.anuncio-danger  { --acento-anuncio: #ff5c5c; }

/* ── Navegación ─────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 50;
  backdrop-filter: blur(18px) saturate(140%);
  background: rgba(8,8,15,0.72);
  border-bottom: 1px solid var(--line);
}
.nav-in { display: flex; align-items: center; gap: 2rem; height: 66px; }
.marca { display: inline-flex; align-items: center; gap: 0.6rem; text-decoration: none; flex-shrink: 0; }
.marca img { width: 30px; height: 30px; flex-shrink: 0; }
.marca b {
  font-family: 'Orbitron', var(--display); /* el logotipo conserva la fuente de marca */
  font-size: 0.98rem; letter-spacing: 0.06em; color: var(--text);
}
/* .nav-mob envuelve el <details> que controla el menú móvil. En
   escritorio es un simple contenedor (el <details> abierto o cerrado da
   igual: .nav-links se fuerza visible más abajo). En móvil, es el botón
   hamburguesa más el panel desplegable. */
.nav-mob { margin-left: auto; position: relative; }
/* Velo del menú móvil: oculto por defecto en cualquier ancho (incluido
   escritorio, donde el menú móvil no existe). La regla que lo activa
   vive dentro de @media (max-width: 900px) más abajo -- si esta línea
   estuviera solo ahí dentro, en escritorio el <div> caería al
   display:block de un <div> normal en vez de quedar oculto. */
.nav-velo { display: none; }
/* Chrome moderno anima el <details> metiendo su contenido en un
   ::details-content anónimo con content-visibility:hidden mientras está
   cerrado. Eso ignora nuestro display:flex de más abajo (content-visibility
   no es display), así que el panel entero quedaba en 0×0 hasta abrirlo.
   Lo neutralizamos aquí: la visibilidad real la sigue controlando
   .nav-links con display, como en el resto de navegadores. */
.nav-mob::details-content { content-visibility: visible; }
.nav-links { display: flex; gap: 1.6rem; align-items: center; }
.nav-links a {
  color: var(--muted); text-decoration: none; font-size: 0.9rem; font-weight: 500;
  position: relative; transition: color var(--dur) var(--ease);
}
.nav-links a::after {
  content: ''; position: absolute; left: 0; bottom: -6px; height: 1px; width: 100%;
  background: var(--cyan); transform: scaleX(0); transform-origin: right;
  transition: transform var(--dur) var(--ease);
}
.nav-links a:hover { color: var(--text); }
.nav-links a:hover::after { transform: scaleX(1); transform-origin: left; }
.nav-cta {
  padding: 0.5rem 1.05rem; border-radius: 4px;
  border: 1px solid var(--line-2); color: var(--text) !important;
  font-size: 0.85rem !important;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.nav-cta::after { display: none; }
.nav-cta:hover { border-color: rgba(0,245,255,0.55); background: rgba(0,245,255,0.07); }
.nav-cta:active { transform: scale(0.97); }

/* Botón hamburguesa: oculto en escritorio, el <summary> del <details>.
   list-style/marker se quitan porque <summary> trae una flecha nativa. */
.nav-burger {
  display: none;
  list-style: none;
  align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: 4px; flex-shrink: 0;
  border: 1px solid var(--line-2); background: var(--surface);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.nav-burger::-webkit-details-marker { display: none; }
.nav-burger::marker { content: ''; }
.nav-burger:hover { border-color: rgba(0,245,255,0.45); background: rgba(255,255,255,0.05); }
.nav-burger:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
/* Icono de 3 barras → X: solo transform/opacity, nunca background-color,
   para que el cambio de estado no dispare repintados costosos.
   Son 3 <span> hermanos (no pseudo-elementos de una barra central):
   opacity en un elemento también difumina sus ::before/::after, así que
   con pseudo-elementos la barra "central" se llevaba a las otras dos
   por delante al ocultarse. Como hermanos independientes, cada una
   anima su propia transformación sin arrastrar a las demás. */
.nav-burger-icon { position: relative; display: block; width: 18px; height: 14px; }
.nav-burger-barra {
  position: absolute; left: 0; width: 18px; height: 2px; border-radius: 2px; background: var(--text);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.nav-burger-barra:nth-child(1) { top: 0; }
.nav-burger-barra:nth-child(2) { top: 6px; }
.nav-burger-barra:nth-child(3) { top: 12px; }
.nav-mob[open] .nav-burger-barra:nth-child(2) { opacity: 0; }
.nav-mob[open] .nav-burger-barra:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-mob[open] .nav-burger-barra:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ── Héroe: composición asimétrica ──────────────────────── */
.hero { padding: clamp(4rem, 11vh, 8rem) 0 clamp(3.5rem, 8vh, 6rem); }
.hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
}

.hero h1 {
  margin: 0.8rem 0 0;
  /* Geist tiene una altura de x ~8% mayor que la tipografía anterior
     a igual tamaño (medido con canvas measureText), así que a igual
     clamp se ve más grande de lo calibrado. Se reduce ~5% para devolver la
     proporción original del héroe. */
  font-size: clamp(2.45rem, 6.8vw, 5.1rem);
  /* Tipografía pesada y ceñida a propósito: line-height ~0.94 y
     letter-spacing marcadamente negativo, para que el titular tenga
     presencia física en vez de flotar como texto genérico. */
  line-height: 0.94; letter-spacing: -0.045em; font-weight: 800;
  text-wrap: balance;
}
/* Bloque de color sólido tras la palabra clave del titular: nada de
   degradados en el texto (era el segundo cliché más delator del diseño
   anterior). El bloque se inclina con skewX(-6deg) y el texto interior se
   contra-inclina skewX(6deg) para leerse recto pese al bloque torcido.
   Por defecto usa magenta/texto oscuro (héroe, blog); .jhero lo sobreescribe
   con el acento de cada juego más abajo. */
/* El relleno vertical es imprescindible: sin él la caja se ajusta a la altura
   de línea y recorta los descendentes (la cola de la "g" de "gratis" quedaba
   cortada). El margen negativo compensa ese relleno para que el bloque no
   empuje las líneas del titular, que van muy ceñidas (line-height 0.94).
   box-decoration-break mantiene el relleno en ambos trozos si el titular
   envuelve y parte el bloque en dos líneas. */
.bloque {
  display: inline-block;
  padding: 0.06em 0.16em 0.14em;
  margin: -0.06em 0 -0.14em;
  transform: skewX(-6deg);
  background: var(--magenta);
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.bloque > span { display: inline-block; transform: skewX(6deg); color: var(--bg); }
.hero p.entrada {
  margin: 1.35rem 0 0; max-width: 52ch;
  font-size: clamp(1rem, 1.5vw, 1.12rem); color: var(--muted); text-wrap: pretty;
}
.hero-juegos {
  margin-top: 1.1rem; display: flex; flex-wrap: wrap; gap: 0.45rem 0.75rem;
  font-family: var(--mono); font-size: 0.76rem; color: var(--subtle);
}
.hero-juegos a { color: var(--subtle); text-decoration: none; transition: color var(--dur) var(--ease); }
.hero-juegos a:hover { color: var(--cyan); }

/* Línea de datos reales bajo el titular: ubicación, servidores totales,
   en línea y ping — todo renderizado por PHP salvo el ping, que llega por
   JS (mismo mecanismo que ya mide el panel). Nada decorativo. */
.hero-datos {
  margin-top: 1.1rem; display: flex; flex-wrap: wrap; gap: 0.35rem 0.9rem;
  font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.01em; color: var(--muted);
}
.hero-datos b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }

.acciones { margin-top: 2.1rem; display: flex; flex-wrap: wrap; gap: 0.75rem; }
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.85rem 1.5rem; border-radius: 3px;
  font-size: 0.92rem; font-weight: 700; text-decoration: none;
  border: 1px solid transparent; cursor: pointer;
  transition: transform var(--dur) var(--spring), box-shadow var(--dur) var(--ease),
              background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
/* Sólidos y de esquina viva: nada de degradados en los botones. El
   principal usa color plano de alto contraste (cian sobre fondo oscuro,
   14.7:1); el secundario es borde fino sobre transparente. */
.btn-p {
  color: var(--bg);
  background: var(--cyan);
}
.btn-p:hover  { transform: translateY(-2px); background: #33f8ff; box-shadow: 0 12px 28px -12px rgba(0,245,255,0.55); }
.btn-p:active { transform: translateY(0) scale(0.985); }
.btn-s { color: var(--text); border-color: var(--line-2); background: transparent; }
.btn-s:hover  { border-color: var(--cyan); background: rgba(0,245,255,0.08); transform: translateY(-2px); }
.btn-s:active { transform: translateY(0) scale(0.985); }

/* Panel de estado en vivo, junto al héroe — tratado como consola, no como
   tarjeta de cristal: marco de borde definido, superficie sólida (sin
   cristal esmerilado — eso se reserva para el nav fijo) y una barra
   superior tipo terminal con identificador + indicador de estado. */
.panel {
  border: 1px solid var(--line-2); border-radius: 6px;
  background: var(--bg-2);
  box-shadow: 0 26px 60px -32px rgba(0,0,0,0.9);
  padding: 0 1.4rem 1.4rem;
  overflow: hidden;
}
.panel-cab {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  margin: 0 -1.4rem 1.1rem; padding: 0.8rem 1.4rem;
  background: var(--bg); border-bottom: 1px solid var(--line-2);
}
.panel-id {
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.02em; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.panel-estado {
  display: inline-flex; align-items: center; gap: 0.45rem; flex-shrink: 0;
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--subtle);
}
/* Punto de estado estático (sin animación de pulso): es un indicador de
   consola, no la píldora palpitante que se quitó del héroe. */
.panel-punto { width: 6px; height: 6px; border-radius: 2px; background: var(--green); flex-shrink: 0; }
.metricas { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 1.2rem; }
.metrica-k {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--subtle);
}
.metrica-v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.65rem; font-weight: 700; line-height: 1.15; margin-top: 0.15rem;
}
.metrica-v small { font-size: 0.82rem; font-weight: 500; color: var(--subtle); margin-left: 0.12rem; }
.barra { height: 3px; border-radius: 2px; background: rgba(255,255,255,0.07); margin-top: 0.55rem; overflow: hidden; }
.barra i { display: block; height: 100%; width: 0; border-radius: 2px; transition: width 900ms var(--ease); }
.c-cyan    { color: var(--cyan); }    .f-cyan    { background: var(--cyan); }
.c-magenta { color: var(--magenta); } .f-magenta { background: var(--magenta); }
.c-purple  { color: var(--purple); }  .f-purple  { background: var(--purple); }
.c-green   { color: var(--green); }   .f-green   { background: var(--green); }

.panel-pie {
  margin-top: 1.2rem; padding-top: 0.9rem; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 0.35rem 1.1rem;
  font-family: var(--mono); font-size: 0.68rem; color: var(--subtle);
}

/* ── Secciones ──────────────────────────────────────────── */
.sec { padding: clamp(4rem, 9vh, 7rem) 0; }
.sec-cab { margin-bottom: 2.6rem; max-width: 62ch; }
.eyebrow {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--cyan); display: block; margin-bottom: 0.7rem;
}
.sec-cab h1, .sec-cab h2 {
  margin: 0; font-size: clamp(1.65rem, 3.2vw, 2.55rem); /* -5%: ver nota en .hero h1 */
  letter-spacing: -0.035em; line-height: 1.08; font-weight: 800; text-wrap: balance;
}
.sec-cab p { margin: 0.8rem 0 0; color: var(--muted); max-width: 58ch; text-wrap: pretty; }

/* Bento de juegos: tamaños distintos según cuántos servidores hay */
.bento { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0.9rem; }
.jcard {
  grid-column: span 2;
  position: relative; overflow: hidden;
  border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); padding: 1.25rem;
  text-decoration: none; color: inherit; display: flex; flex-direction: column;
  min-height: 132px;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.jcard.ancha { grid-column: span 3; }
/* Borde que se ilumina siguiendo el cursor */
.jcard::before {
  content: ''; position: absolute; inset: -1px; border-radius: inherit; padding: 1px;
  background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 0%), var(--acento), transparent 62%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity: 0; transition: opacity var(--dur) var(--ease);
}
/* Línea de acento superior por juego, siempre visible (mismo lenguaje que
   .jscard::before en la página de cada juego): identifica el juego incluso
   en las dos tarjetas sin foto (Teeworlds, ARK), que no tienen otra pista
   de color aparte del resalte al pasar el cursor. */
.jcard::after {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--acento), transparent);
  opacity: 0.55;
}
.jcard:hover { transform: translateY(-4px); border-color: var(--line-2); }
.jcard:hover::before { opacity: 1; }
.jcard:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
.jcard h3 { margin: 0; font-size: 1.12rem; letter-spacing: -0.015em; font-weight: 600; }
.jcard .n {
  margin-top: auto; font-family: var(--mono);
  font-variant-numeric: tabular-nums; font-size: 1.9rem; font-weight: 700; line-height: 1;
}
.jcard .etq { font-family: var(--mono); font-size: 0.68rem; color: var(--subtle); margin-top: 0.3rem; }
.jcard .mant { color: var(--purple); }

/* Tarjetas con foto (Minecraft, Counter Strike 1.6, TeamSpeak): la imagen
   ocupa una columna propia a la derecha, a sangre con el borde de la
   tarjeta (por eso el padding baja a 0 aquí y se traslada a .jcard-txt).
   Texto y foto quedan lado a lado, sin superponerse -> no hace falta
   ningún degradado de protección para que el texto se lea. */
.jcard-foto { flex-direction: row; padding: 0; align-items: stretch; }
.jcard-txt {
  display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0;
  padding: 1.25rem;
}
.jcard-img {
  flex: 0 0 auto; align-self: stretch;
  width: 132px; height: 100%;
  display: block; object-fit: cover; background: var(--bg-2);
}
.jcard-foto.ancha .jcard-img { width: 196px; }
/* Minecraft y TeamSpeak son arte/logo con transparencia, no una foto de
   escena: object-fit:cover los recortaría a lo tonto. Con contain se ve
   la pieza completa flotando sobre el fondo oscuro de la tarjeta, con
   un poco de aire alrededor para que no toque los bordes. */
.jcard-img--contain { object-fit: contain; padding: 0.85rem; box-sizing: border-box; background: none; }

/* Tarjetas sin foto (Teeworlds, ARK): en vez de un hueco vacío, la sigla
   del juego flota gigante y muy tenue al fondo -- mismo lenguaje mono del
   resto del sitio (números, etiquetas), sin fingir una imagen que no hay. */
.jcard-marca {
  position: absolute; right: -0.1rem; bottom: -0.55rem; z-index: -1;
  font-family: var(--mono); font-weight: 800; font-size: 4.2rem; line-height: 1;
  letter-spacing: -0.03em; color: var(--acento); opacity: 0.12;
  pointer-events: none; user-select: none;
}

/* Tarjetas de servidor */
.sgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 0.85rem; margin-top: 1.6rem; }
.scard {
  border: 1px solid var(--line); border-left: 2px solid var(--green);
  border-radius: 6px; background: var(--surface); padding: 1rem 1.1rem;
  transition: transform var(--dur) var(--ease), background-color var(--dur) var(--ease),
              border-top-color var(--dur) var(--ease), border-right-color var(--dur) var(--ease),
              border-bottom-color var(--dur) var(--ease);
}
.scard:hover { transform: translateY(-3px); background: var(--surface-2);
  border-top-color: var(--line-2); border-right-color: var(--line-2); border-bottom-color: var(--line-2); }
.scard.off  { border-left-color: rgba(255,70,70,0.6); opacity: 0.62; }
.scard.mant { border-left-color: var(--purple); opacity: 0.78; }
.scard-top { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.scard-nom { font-weight: 600; font-size: 0.94rem; letter-spacing: -0.01em; }
.estado {
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.09em;
  padding: 0.24rem 0.5rem; border-radius: 3px; white-space: nowrap;
}
.e-on   { color: var(--green);   background: rgba(0,255,136,0.1); }
.e-off  { color: #ff6b6b;        background: rgba(255,70,70,0.1); }
.e-mant { color: var(--purple);  background: rgba(123,47,255,0.14); }
.scard-ip {
  font-family: var(--mono); font-size: 0.78rem; color: var(--cyan);
  margin-top: 0.55rem; word-break: break-all;
}
.scard-meta { font-family: var(--mono); font-size: 0.68rem; color: var(--subtle); margin-top: 0.35rem; }

/* Cifras de comunidad */
.cifras { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; }
.cifra { border: 1px solid var(--line); border-radius: 6px; background: var(--surface); padding: 1.5rem; }
.cifra .v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: clamp(2rem, 4.4vw, 3rem); font-weight: 700; line-height: 1; letter-spacing: -0.03em;
}
.cifra .k {
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--subtle); margin-top: 0.6rem;
}

/* Nosotros: asimétrico */
.about { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: clamp(2rem, 5vw, 4rem); align-items: center; }
.perfil { border: 1px solid var(--line); border-radius: 8px; background: var(--surface); padding: 1.8rem; text-align: center; }
.perfil img {
  width: 116px; height: 116px; border-radius: 8px; object-fit: cover; object-position: center 22%;
  border: 1px solid var(--line-2);
}
.perfil h3 { margin: 1rem 0 0.2rem; font-size: 1.2rem; }
.perfil .rol { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.1em; color: var(--cyan); text-transform: uppercase; }

/* Cierre */
.cierre {
  border: 1px solid var(--line); border-radius: 8px; padding: clamp(2.2rem, 5vw, 3.6rem);
  background:
    radial-gradient(70% 130% at 12% 0%, rgba(0,245,255,0.1), transparent 60%),
    radial-gradient(70% 130% at 88% 100%, rgba(255,0,255,0.09), transparent 60%),
    var(--surface);
  text-align: center;
}
.cierre h2 { margin: 0 0 0.8rem; font-size: clamp(1.5rem, 3.4vw, 2.35rem); letter-spacing: -0.038em; font-weight: 800; text-wrap: balance; } /* -5%: ver nota en .hero h1 */
.cierre p { margin: 0 auto 1.8rem; color: var(--muted); max-width: 52ch; }

.pie { border-top: 1px solid var(--line); padding: 2.2rem 0 3rem; margin-top: 3rem; }
.pie-in { display: flex; flex-wrap: wrap; gap: 1.2rem; justify-content: space-between; align-items: center; }
.pie a { color: var(--muted); text-decoration: none; font-size: 0.85rem; transition: color var(--dur) var(--ease); }
.pie a:hover { color: var(--cyan); }
.pie small { color: var(--subtle); font-size: 0.78rem; }

/* Entradas al hacer scroll */
.rev { opacity: 0; transform: translateY(18px); transition: opacity 620ms var(--ease), transform 620ms var(--ease); }
.rev.visto { opacity: 1; transform: none; }

a:focus-visible, button:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; border-radius: 4px; }

@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; }
  .about { grid-template-columns: 1fr; }
  .bento { grid-template-columns: repeat(2, 1fr); }
  .jcard, .jcard.ancha { grid-column: span 1; }
  /* A 2 columnas no hay ancho para foto+texto lado a lado (~168px de
     tarjeta): se apilan, con el texto arriba (nombre y número son lo que
     importa primero) y la foto como franja decorativa debajo. */
  .jcard-foto, .jcard-foto.ancha { flex-direction: column; }
  .jcard-foto .jcard-txt { padding: 0.85rem 0.9rem 0.95rem; }
  .jcard-foto .jcard-img,
  .jcard-foto.ancha .jcard-img { width: 100%; height: 84px; }
  .jcard-img--contain { padding: 0.5rem; }
  .jcard-marca { font-size: 3.1rem; }

  /* En pantallas chicas el movimiento del fondo casi no se aprecia (la
     mancha ocupa casi toda la vista, el ojo no distingue el desplazamiento)
     y es justo donde más duele su coste durante el scroll. Se congela: el
     fondo sigue teniendo color y forma, solo deja de animarse. */
  .fondo::before, .rejilla { animation: none; }

  /* Menú móvil: botón hamburguesa + panel desplegable controlado por
     el atributo [open] nativo de <details>, sin depender de JS. */
  .nav-burger { display: inline-flex; }
  .nav-links { display: none; }
  .nav-mob[open] .nav-links {
    display: flex; flex-direction: column; align-items: stretch; gap: 0.15rem;
    position: absolute; top: calc(100% + 0.7rem); right: 0; z-index: 60;
    min-width: 230px; max-width: calc(100vw - 2.5rem);
    /* Panel opaco de verdad: un rgba(...,0.94) + blur (intento anterior)
       seguía dejando pasar ~6% del héroe de atrás, suficiente para que un
       h1 blanco enorme se transparentara y compitiera con los enlaces.
       --bg/--bg-2 son colores hex sólidos (sin alpha): 0% de fuga posible,
       sea cual sea el contenido detrás. Ya no hace falta backdrop-filter
       (no hay nada translúcido que difuminar). */
    background: linear-gradient(160deg, var(--bg-2), var(--bg));
    border: 1px solid var(--line); border-radius: 6px;
    padding: 0.6rem;
    box-shadow: 0 24px 50px -22px rgba(0,0,0,0.85);
  }
  .nav-mob[open] .nav-links a { padding: 0.78rem 0.9rem; border-radius: 4px; color: var(--text); }
  .nav-mob[open] .nav-links a::after { display: none; }
  .nav-mob[open] .nav-links a:not(.nav-cta):hover,
  .nav-mob[open] .nav-links a:not(.nav-cta):focus-visible { background: rgba(255,255,255,0.06); }
  .nav-mob[open] .nav-cta { margin-top: 0.3rem; text-align: center; }

  /* Velo oscuro tras el panel: separa el menú del resto de la página
     (patrón conocido) sin bloquear el scroll -- es position:fixed, no
     overflow:hidden en el body, así que el usuario sigue pudiendo
     desplazarse con el menú abierto.
     Es un <div class="nav-velo"> real, HERMANO de <header class="nav">
     (ver includes/nav.php), NO un ::before dentro de .nav-mob: .nav
     tiene backdrop-filter (línea ~140), y backdrop-filter en un
     ANCESTRO convierte a ese ancestro en el "containing block" de
     cualquier descendiente position:fixed -- un ::before fixed dentro
     de .nav-mob quedaría encerrado en los ~66px de la barra de nav en
     vez de cubrir el viewport. Al vivir fuera de <header>, el velo usa
     el viewport real como containing block.
     z-index 45: por debajo de .nav (50, con el panel del menú a 60 en
     su interior) para no taparlo nunca; por encima del contenido normal
     de <main> (z-index:auto) para separarlo del héroe de atrás. Como
     .nav-velo no es descendiente de .nav-mob, el listener de "click
     fuera cierra" en nav.php ya lo cubre sin necesidad de nada extra. */
  header.nav:has(.nav-mob[open]) ~ .nav-velo {
    display: block; position: fixed; inset: 0; z-index: 45;
    background: rgba(4,4,10,0.55);
    animation: velo-in 200ms var(--ease);
  }
  @keyframes velo-in { from { opacity: 0; } to { opacity: 1; } }

  /* Menos aire arriba/abajo de cada sección: en pantallas chicas el
     relleno vh-based de escritorio (76-93px) es aire desperdiciado.
     Se reduce, pero sin aplanar el ritmo entre secciones. */
  .hero  { padding: clamp(2.5rem, 7vh, 4rem) 0 clamp(2rem, 5vh, 3rem); }
  .sec   { padding: clamp(2.5rem, 6vh, 3.5rem) 0; }
  .jhero { padding: clamp(1.75rem, 4vh, 2.75rem) 0 clamp(1.25rem, 3vh, 2rem); }

  /* La cabecera de cada sección (eyebrow + título + texto) llevaba el
     mismo margen que en escritorio (2.6rem) antes de la rejilla de
     tarjetas: en pantallas chicas es más aire del que hace falta entre
     un título corto y las tarjetas justo debajo. */
  .sec-cab { margin-bottom: 1.8rem; }

  /* Tarjetas de servidor: dos por fila y más compactas. En escritorio
     no cambia nada (regla fuera de este media query). */
  .sgrid { grid-template-columns: repeat(2, 1fr); gap: 0.6rem; margin-top: 1.2rem; }
  .scard { padding: 0.7rem 0.75rem; }
  .scard-top { align-items: flex-start; gap: 0.5rem; }
  .scard-nom { font-size: 0.82rem; line-height: 1.28; }
  .estado { font-size: 0.56rem; padding: 0.22rem 0.4rem; }
  .scard-ip { font-size: 0.7rem; margin-top: 0.45rem; }
  .scard-meta { font-size: 0.62rem; margin-top: 0.3rem; }
}
@media (max-width: 420px) {
  .metricas { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  .rev { opacity: 1 !important; transform: none !important; }
  .fondo::before, .rejilla { animation: none; }
}

/* ═══════════════════════════════════════════════════════════
   PÁGINA DE JUEGO — /servidores/{slug}
   ═══════════════════════════════════════════════════════════ */

.ruta {
  font-family: var(--mono); font-size: 0.72rem; color: var(--subtle);
  display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;
}
.ruta a { color: var(--subtle); text-decoration: none; transition: color var(--dur) var(--ease); }
.ruta a:hover { color: var(--cyan); }

/* Cabecera del juego: título grande + resumen de estado a la derecha */
.jhero { padding: clamp(2.5rem, 6vh, 4.5rem) 0 clamp(1.5rem, 3vh, 2.5rem); }
.jhero-grid {
  display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem); align-items: end;
}
.jhero h1 {
  margin: 0; font-size: clamp(2rem, 4.9vw, 3.6rem); /* -5%: ver nota en .hero h1 */
  line-height: 0.96; letter-spacing: -0.045em; font-weight: 800; text-wrap: balance;
}
/* Mismo tratamiento de bloque que el héroe, con el acento propio de cada
   juego en vez de magenta fijo. --bloque-txt lo fija juego.php en línea,
   según el contraste real de cada acento (el púrpura necesita texto claro,
   el resto texto oscuro: ver nota en juego.php). */
.jhero h1 .bloque { background: var(--acento, var(--cyan)); }
.jhero h1 .bloque > span { color: var(--bloque-txt, var(--bg)); }
.jhero .entrada { margin: 1.1rem 0 0; color: var(--muted); max-width: 56ch; text-wrap: pretty; }

.resumen {
  border: 1px solid var(--line-2); border-radius: 6px; padding: 1.3rem;
  background: linear-gradient(160deg, var(--bg-2), var(--bg));
  display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;
}
.resumen .k {
  font-family: var(--mono); font-size: 0.63rem; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--subtle);
}
.resumen .v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.75rem; font-weight: 700; line-height: 1.1; margin-top: 0.15rem;
}

/* Tarjeta de servidor ampliada: la IP es lo que la gente viene a copiar */
.jsgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1rem; }
.jscard {
  position: relative; overflow: hidden;
  border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); padding: 1.35rem;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.jscard::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--acento, var(--cyan)), transparent);
  opacity: 0.65;
}
.jscard.off::before  { background: linear-gradient(90deg, transparent, #ff4646, transparent); }
.jscard.mant::before { background: linear-gradient(90deg, transparent, var(--purple), transparent); }
.jscard.off, .jscard.mant { opacity: 0.72; }
.jscard:hover { transform: translateY(-4px); border-color: var(--line-2); }

.jscard-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.jscard h3 { margin: 0; font-size: 1.05rem; font-weight: 600; letter-spacing: -0.015em; }

/* Campo de IP con botón de copiar: lo más útil de toda la página */
.ipbox {
  margin-top: 1rem; display: flex; align-items: stretch;
  border: 1px solid var(--line-2); border-radius: 4px; overflow: hidden;
  background: rgba(0,0,0,0.28);
}
.ipbox code {
  flex: 1; min-width: 0; padding: 0.62rem 0.8rem;
  font-family: var(--mono); font-size: 0.82rem; color: var(--cyan);
  overflow-x: auto; white-space: nowrap; scrollbar-width: none;
}
.ipbox code::-webkit-scrollbar { display: none; }
.copiar {
  flex-shrink: 0; padding: 0 0.9rem; border: 0; border-left: 1px solid var(--line-2);
  background: transparent; color: var(--muted); cursor: pointer;
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.copiar:hover { background: rgba(0,245,255,0.1); color: var(--cyan); }
.copiar.hecho { color: var(--green); }

.specs { display: flex; gap: 1.4rem; margin-top: 1rem; }
.specs div { font-family: var(--mono); font-size: 0.7rem; color: var(--subtle); }
.specs b {
  display: block; font-size: 0.95rem; color: var(--text);
  font-weight: 600; font-variant-numeric: tabular-nums; margin-top: 0.15rem;
}

/* Preguntas frecuentes, sin acordeón genérico */
.faq { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.3rem 2.4rem; }
.faq article { border-top: 1px solid var(--line); padding-top: 1.1rem; }
.faq h3 { margin: 0 0 0.5rem; font-size: 1rem; font-weight: 600; letter-spacing: -0.01em; text-wrap: balance; }
.faq p { margin: 0; color: var(--muted); font-size: 0.94rem; text-wrap: pretty; }

/* Otros juegos, al final */
.otros { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.otros a {
  border: 1px solid var(--line); border-radius: 4px; padding: 0.6rem 1rem;
  text-decoration: none; color: var(--muted); font-size: 0.9rem;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.otros a:hover { border-color: rgba(0,245,255,0.45); color: var(--text); transform: translateY(-2px); }

.vacio {
  border: 1px dashed var(--line-2); border-radius: 6px; padding: 2.2rem;
  text-align: center; color: var(--muted);
}

@media (max-width: 900px) {
  .jhero-grid { grid-template-columns: 1fr; align-items: start; }
}

/* ═══════════════════════════════════════════════════════════
   BLOG Y ARTÍCULOS — /blog.php, /post/{id}-{slug}
   ═══════════════════════════════════════════════════════════ */

/* Columna de lectura más angosta que el .shell general, para el
   listado del blog. Se combina con .shell: éste da el margen
   lateral fluido, .container solo topa el ancho máximo. */
.container { max-width: 900px; }

.filtros { display: flex; gap: 0.6rem; flex-wrap: wrap; margin: 1.7rem 0 2.2rem; }

.blog-list { display: flex; flex-direction: column; gap: 1rem; }
.blog-card {
  display: flex; gap: 1.1rem; align-items: flex-start;
  border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); padding: 1.1rem;
  text-decoration: none; color: inherit;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.blog-card:hover { transform: translateY(-3px); border-color: var(--line-2); background: var(--surface-2); }
.blog-card:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
.blog-card-img, .blog-card-img-placeholder {
  width: 128px; height: 86px; border-radius: 4px; flex-shrink: 0;
  border: 1px solid var(--line);
}
.blog-card-img { object-fit: cover; }
.blog-card-img-placeholder { background: linear-gradient(160deg, var(--surface-2), rgba(255,255,255,0.012)); }
.blog-card-etq {
  font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.1em;
  text-transform: uppercase; margin-bottom: 0.45rem;
}
.blog-card h2 { margin: 0 0 0.4rem; font-size: 1.05rem; font-weight: 600; letter-spacing: -0.015em; }
.blog-card p  { margin: 0; color: var(--muted); font-size: 0.88rem; line-height: 1.55; text-wrap: pretty; }

.pagination { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; margin-top: 2.4rem; }
.page-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.1rem; padding: 0.45rem 0.85rem;
  border: 1px solid var(--line); border-radius: 4px;
  color: var(--muted); text-decoration: none;
  font-family: var(--mono); font-size: 0.78rem;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.page-btn:hover { border-color: var(--line-2); color: var(--text); }
.page-btn.active { border-color: rgba(0,245,255,0.5); color: var(--cyan); background: rgba(0,245,255,0.08); }

/* Artículo: ancho de lectura cómodo, no el .shell completo */
.post-content { max-width: 68ch; margin: 0 auto; }
.post-etq {
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.1em;
  text-transform: uppercase; margin-bottom: 0.9rem;
}
.post-content h1 {
  margin: 0 0 1.2rem; font-size: clamp(1.8rem, 4vw, 2.45rem); /* -5%: ver nota en .hero h1 */
  letter-spacing: -0.035em; line-height: 1.08; font-weight: 800; text-wrap: balance;
}
.post-content img {
  width: 100%; border-radius: 6px; margin: 1.7rem 0;
  border: 1px solid var(--line);
}
.post-body { font-size: 1.02rem; color: var(--text); }
.post-body p, .post-body li { color: var(--muted); line-height: 1.8; margin-bottom: 1rem; }
.post-body h2 { margin: 2.1rem 0 0.8rem; font-size: 1.4rem; letter-spacing: -0.02em; }
.post-body h3 { margin: 1.7rem 0 0.6rem; font-size: 1.15rem; letter-spacing: -0.015em; }
.post-body a { color: var(--cyan); }
.post-body blockquote {
  border-left: 2px solid var(--line-2); margin: 1.3rem 0; padding: 0.2rem 0 0.2rem 1.1rem;
  color: var(--muted); font-style: italic;
}
.post-body code {
  font-family: var(--mono); background: rgba(255,255,255,0.06);
  padding: 0.15em 0.4em; border-radius: 4px; font-size: 0.88em;
}
.post-body img { max-width: 100%; border-radius: 4px; }
.post-volver { margin-top: 2.4rem; padding-top: 1.5rem; border-top: 1px solid var(--line); }
.post-volver a { color: var(--cyan); font-size: 0.85rem; text-decoration: none; }
.post-volver a:hover { text-decoration: underline; }

@media (max-width: 640px) {
  .blog-card { flex-direction: column; }
  .blog-card-img, .blog-card-img-placeholder { width: 100%; height: 160px; }
}

/* ── Destacado de KLPScape ──────────────────────────────────
   Enlace grande al proyecto propio, que vive en otro subdominio.
   Va antes de la lista de servidores porque es lo que diferencia
   a KLPServers de cualquier otro host gratuito. */
.destacado {
  display: grid; grid-template-columns: minmax(0,1.7fr) minmax(0,1fr);
  gap: clamp(1.5rem,4vw,3rem); align-items: center;
  border: 1px solid var(--line-2); border-radius: 8px;
  padding: clamp(1.6rem,4vw,2.8rem);
  background:
    radial-gradient(80% 140% at 8% 0%, rgba(255,215,0,0.10), transparent 62%),
    radial-gradient(70% 130% at 95% 100%, rgba(123,47,255,0.10), transparent 60%),
    var(--bg-2);
  text-decoration: none; color: inherit;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.destacado:hover { transform: translateY(-3px); border-color: rgba(255,215,0,0.45); }
.destacado:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
.destacado .eyebrow { color: #ffd700; }
.destacado h2 {
  margin: 0 0 0.9rem; font-size: clamp(1.5rem,3.1vw,2.3rem);
  font-weight: 800; letter-spacing: -0.035em; line-height: 1.06; text-wrap: balance;
}
.destacado p { margin: 0; color: var(--muted); max-width: 56ch; text-wrap: pretty; }
.destacado-cta {
  display: inline-block; margin-top: 1.3rem;
  font-weight: 600; color: #ffd700; font-size: 0.95rem;
}
.destacado-datos { display: grid; gap: 1.1rem; }
.destacado-datos div { border-left: 2px solid rgba(255,215,0,0.35); padding-left: 0.9rem; }
.destacado-datos b {
  display: block; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.9rem; font-weight: 700; line-height: 1; color: var(--text);
}
.destacado-datos small {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--subtle);
}
@media (max-width: 820px) {
  .destacado { grid-template-columns: 1fr; }
  .destacado-datos { grid-template-columns: repeat(3,1fr); gap: 0.9rem; }
}

/* ═══════════════════════════════════════════════════════════
   PÁGINAS DE CONFIANZA — /pedir-servidor, /privacidad, /contacto
   Comprobado antes de escribir estas reglas: `.pasos`, `.paso`,
   `.paso-n`, `.aviso-tienda`, `.canales` y `.canal` no existen en
   ningún otro sitio del proyecto (grep en assets/css y en todo *.php,
   Task 26).
   ═══════════════════════════════════════════════════════════ */

/* Los 4 pasos de /pedir-servidor: número en círculo + texto al lado.
   .critico marca el paso del ticket (el que pierde el servidor si se
   salta) con el mismo magenta que ya usa .bloque en el resto del sitio,
   para que destaque sin inventar un color nuevo. */
.pasos { display: flex; flex-direction: column; gap: 1.1rem; margin: 1.6rem 0; }
.paso {
  display: grid; grid-template-columns: auto 1fr; gap: 1rem; align-items: start;
  border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); padding: 1.3rem 1.4rem;
}
.paso.critico {
  border-color: rgba(255,0,255,0.35);
  background: linear-gradient(160deg, rgba(255,0,255,0.07), var(--surface));
}
.paso-n {
  display: flex; align-items: center; justify-content: center;
  width: 2.2rem; height: 2.2rem; border-radius: 50%; flex-shrink: 0;
  background: var(--cyan); color: var(--bg);
  font-family: var(--mono); font-weight: 700; font-size: 1rem;
}
.paso.critico .paso-n { background: var(--magenta); }
.paso h3 { margin: 0 0 0.4rem; font-size: 1.05rem; font-weight: 600; letter-spacing: -0.01em; }
.paso p { margin: 0; color: var(--muted); font-size: 0.94rem; line-height: 1.65; text-wrap: pretty; }
.paso p + p { margin-top: 0.6rem; }
.paso code {
  font-family: var(--mono); background: rgba(255,255,255,0.07);
  padding: 0.15em 0.45em; border-radius: 4px; font-size: 0.88em; color: var(--cyan);
}

/* Callout que explica el cargo de $1, antes de los 4 pasos */
.aviso-tienda {
  border: 1px solid rgba(0,245,255,0.3); border-radius: 6px;
  background: rgba(0,245,255,0.05); padding: 1.2rem 1.4rem; margin: 1.6rem 0;
}
.aviso-tienda p { margin: 0; color: var(--text); font-size: 0.94rem; line-height: 1.65; }
.aviso-tienda p + p { margin-top: 0.7rem; }

/* Tarjetas de canal en /contacto */
.canales { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; margin: 1.8rem 0 2.2rem; }
.canal {
  border: 1px solid var(--line); border-radius: 6px; background: var(--surface);
  padding: 1.4rem; display: flex; flex-direction: column; gap: 0.55rem;
}
.canal h3 { margin: 0; font-size: 1.02rem; font-weight: 600; letter-spacing: -0.01em; }
.canal p { margin: 0; color: var(--muted); font-size: 0.88rem; line-height: 1.6; }
.canal a { color: var(--cyan); font-size: 0.9rem; text-decoration: none; font-weight: 600; }
.canal a:hover { text-decoration: underline; }

@media (max-width: 480px) {
  .paso { grid-template-columns: auto 1fr; gap: 0.8rem; padding: 1.1rem; }
  .paso-n { width: 1.9rem; height: 1.9rem; font-size: 0.88rem; }
}
