/* zx-vps.css — panel de VPS (vps.zentexnode.com) sobre el sistema visual común de la web
   (https://zentexnode.com/vendor/zx-design.css, v4 «arcade suave»). Maqueta 2026-10-23 (zx-dev-02).
   Solo aspecto: las clases e ids que consulta el JS del panel (.card[data-vmid], .fill, .m .v, .side .nav.on,
   #side.open, #scrim.open, .ov, .modal, .oscard.sel, .gtpl.on, .gperms input, .mtab.on, .btn, .toast, .spin…)
   se conservan tal cual y aquí reciben el estilo nuevo con los tokens --zx-*. Solo tema oscuro.
   Prefijo zxv- = propio de este panel; nada de aquí redefine una clase zx-* del sistema. */

/* ───────────── 0. Base del panel ───────────── */
:root { color-scheme: dark; }
.zx-page {
  --zxv-navh: 64px;          /* alto de la barra superior (el lateral se pega debajo) */
  --zxv-side: 224px;         /* ancho del lateral */
  --zxv-mem: #60a5fa;        /* colores de las gráficas (los mismos que usa drawSpark) */
  --zxv-disk: var(--zx-ok);
  --zxv-net: var(--zx-warn);
  --zxv-shared: #22d3ee;     /* «compartido contigo» */
}
/* El popup de un <select> lo pinta el navegador: con color-scheme:dark sale oscuro; estas reglas son la red de
   seguridad para los navegadores que lo ignoran. El resaltado va en un violeta más oscuro que el de marca (AA). */
.zx-page select option, .zx-page select optgroup { background-color: var(--zx-bg-2); color: var(--zx-text); }
.zx-page select option:checked, .zx-page select option:hover { background-color: #6d28d9; color: var(--zx-text); }
.zx-page select option:disabled { color: var(--zx-muted-2); }

/* ───────────── 1. Esqueleto: barra superior + lateral + contenido ───────────── */
.app { display: grid; grid-template-columns: var(--zxv-side) minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); min-height: 100vh; }

/* Barra superior, como la del área de cliente (web/dashboard): logo · píldora de enlaces · perfil */
.navbar {
  grid-column: 1 / -1; position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 14px; min-height: var(--zxv-navh); padding: 10px clamp(14px, 3vw, 28px);
  border-bottom: 1px solid var(--zx-line); background: rgba(18, 16, 28, .82);
  backdrop-filter: blur(16px) saturate(140%); -webkit-backdrop-filter: blur(16px) saturate(140%);
}
/* Marca: sin letter-spacing ni peso 800 (con Inter sin instalar, Segoe UI Black separaba «Zen tex»); fuente de texto explícita */
.navbar .logo { display: inline-flex; align-items: center; gap: 10px; font: 700 1.05rem/1 var(--zx-font); letter-spacing: 0; color: var(--zx-text); }
.navbar .logo img { width: 34px; height: 34px; border-radius: 9px; }
.navbar .logo span { font-family: var(--zx-font); letter-spacing: 0; white-space: nowrap; }
.navbar .logo b { color: var(--zx-brand-2); font-weight: 700; letter-spacing: 0; }
.nav-links { display: flex; gap: 2px; margin-left: 6px; padding: 5px; border: 1px solid var(--zx-line); border-radius: var(--zx-r-pill); background: rgba(255, 255, 255, .02); }
.nav-links a { display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: var(--zx-r-pill); font-size: .88rem; font-weight: 500; color: var(--zx-muted); white-space: nowrap; transition: color var(--zx-dur-fast), background var(--zx-dur-fast); }
.nav-links a:hover { color: var(--zx-text); background: rgba(255, 255, 255, .04); }
.nav-links a.active { color: var(--zx-text); background: var(--zx-surface-2); box-shadow: inset 0 0 0 1px var(--zx-line-2); }
.nav-profile { margin-left: auto; display: flex; align-items: center; gap: 8px; padding: 5px 6px; border: 1px solid var(--zx-line); border-radius: var(--zx-r-pill); background: var(--zx-surface); }
.who { display: inline-flex; align-items: center; gap: 9px; padding: 0 6px 0 2px; font-size: .88rem; font-weight: 600; color: var(--zx-text); }
.who .av { width: 30px; height: 30px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: .78rem; font-weight: 800; color: #fff; background: var(--zx-grad-fill); box-shadow: 0 0 0 1px var(--zx-line-2); }
.who .user-name:empty { display: none; }
.logout-btn { width: 34px; height: 34px; flex: none; border-radius: 50%; border: 1px solid var(--zx-line-2); background: transparent; color: var(--zx-muted); display: grid; place-items: center; cursor: pointer; transition: color var(--zx-dur-fast), border-color var(--zx-dur-fast); }
.logout-btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.9; }
.logout-btn:hover { color: var(--zx-bad); border-color: var(--zx-bad); }
.logout-btn.account-btn:hover { color: var(--zx-brand-2); border-color: var(--zx-brand-2); }
.menu-btn { display: none; width: 40px; height: 40px; flex: none; align-items: center; justify-content: center; border-radius: 12px; border: 1px solid var(--zx-line-2); background: transparent; color: var(--zx-text); cursor: pointer; }
.menu-btn svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 2; }

/* Lateral del panel (Mis VPS · Crear · IPs · Dashboard · Facturación · Salir) */
.side { position: sticky; top: var(--zxv-navh); height: calc(100vh - var(--zxv-navh)); overflow: auto; display: flex; flex-direction: column; gap: 4px; padding: 18px 12px; border-right: 1px solid var(--zx-line); background: rgba(23, 20, 36, .55); }
.brand { display: flex; align-items: center; gap: 8px; margin: 2px 12px 10px; font-family: var(--zx-font-pixel); font-size: var(--zx-fs-micro); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--zx-muted-2); }
.brand b { color: var(--zx-brand-2); font-weight: 700; }
.nav { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 10px; color: var(--zx-muted); font-size: .9rem; font-weight: 500; text-decoration: none; cursor: pointer; transition: background var(--zx-dur-fast), color var(--zx-dur-fast); }
.nav:hover { background: var(--zx-surface); color: var(--zx-text); }
.nav.on { background: var(--zx-surface-2); color: var(--zx-text); box-shadow: inset 2px 0 0 var(--zx-brand-2); }
.nav svg { width: 18px; height: 18px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.8; }
.side .sp { flex: 1; }
.scrim { display: none; position: fixed; inset: 0; z-index: 65; background: rgba(0, 0, 0, .55); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }

/* Contenido: sin fondo propio, el de zx-design se ve detrás */
.main { min-width: 0; padding: 28px clamp(16px, 3vw, 32px) 48px; }

/* ───────────── 2. Cabecera de cada vista ───────────── */
.topbar { display: flex; align-items: flex-end; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 22px; animation: zxv-in .5s var(--zx-ease) backwards; }
.topbar h1 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: clamp(1.5rem, 2.6vw, 2rem); font-weight: 800; letter-spacing: -.03em; }
.topbar p { margin-top: 5px; font-size: .88rem; color: var(--zx-muted); }
.badge { display: inline-flex; align-items: center; padding: 3px 8px; border-radius: 8px; font-size: .64rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--zx-brand-2); background: rgba(139, 92, 246, .14); border: 1px solid rgba(192, 132, 252, .4); vertical-align: middle; }
.badge.shared { color: #a5f3fc; background: rgba(34, 211, 238, .12); border-color: rgba(34, 211, 238, .35); }
.badge.ok { color: var(--zx-ok); background: color-mix(in srgb, var(--zx-ok) 12%, transparent); border-color: color-mix(in srgb, var(--zx-ok) 35%, transparent); }
.badge.bad { color: var(--zx-bad); background: color-mix(in srgb, var(--zx-bad) 12%, transparent); border-color: color-mix(in srgb, var(--zx-bad) 35%, transparent); }

/* ───────────── 3. Lista: tarjeta de cada VPS (.card = zx-card) ───────────── */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.zx-page .card { padding: 18px; border-radius: var(--zx-r); animation: zxv-in .55s var(--zx-ease) backwards; }
/* cascada: cada tarjeta entra un poco después que la anterior (solo al pintar la lista; softList no la repinta) */
.grid > .card:nth-child(2) { animation-delay: 60ms; } .grid > .card:nth-child(3) { animation-delay: 120ms; } .grid > .card:nth-child(4) { animation-delay: 180ms; }
.grid > .card:nth-child(5) { animation-delay: 240ms; } .grid > .card:nth-child(6) { animation-delay: 300ms; } .grid > .card:nth-child(n+7) { animation-delay: 360ms; }
/* brillo violeta suave al pasar (el foco que sigue al ratón de zx-design solo se engancha al cargar; aquí todo se pinta después) */
.zx-page .zx-card:hover { border-color: rgba(192, 132, 252, .38); box-shadow: 0 0 0 1px rgba(192, 132, 252, .10), 0 18px 40px -22px var(--zx-brand-glow); }
.ctop { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; }
.ctop > div { min-width: 0; }
.os { width: 38px; height: 38px; flex: none; border-radius: 11px; display: grid; place-items: center; font-size: 18px; border: 1px solid var(--zx-line-2); background: var(--zx-surface-2); }
.os.lg { width: 44px; height: 44px; font-size: 21px; border-radius: 13px; }
.ctop .nm { font-weight: 700; font-size: .98rem; letter-spacing: -.01em; overflow-wrap: anywhere; }
.ctop .id { margin-top: 2px; font-size: .76rem; color: var(--zx-muted-2); font-family: var(--zx-mono); overflow-wrap: anywhere; }
.ctop .id.dim { opacity: .8; font-family: var(--zx-font); }
.id.infra-warn { color: var(--zx-bad); font-family: var(--zx-font); }

/* Estado: etiqueta con punto. Encendido late (--zx-ok), detenido gris, ocupado/migrando ámbar, suspendido rojo */
.pill { margin-left: auto; flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: var(--zx-r-pill); font: 700 .66rem/1.5 var(--zx-font-pixel); letter-spacing: .05em; text-transform: uppercase; border: 1px solid currentColor; background: color-mix(in srgb, currentColor 10%, transparent); color: var(--zx-muted); white-space: nowrap; }
.pill.on { color: var(--zx-ok); }
.pill.off { color: var(--zx-muted); }
.pill.busy { color: var(--zx-warn); }
.pill.bad { color: var(--zx-bad); }
.pill .d { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.pill.on .d { animation: zxv-beat 1.8s ease-out infinite; }
.pill.busy .d { animation: zxv-blink 1.1s ease-in-out infinite; }
.pill.mig { color: var(--zx-warn); }

.specs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 14px; }
.specs span { font-size: .74rem; color: var(--zx-muted); background: var(--zx-bg-2); border: 1px solid var(--zx-line); padding: 3px 8px; border-radius: 7px; font-family: var(--zx-mono); }
.meters { display: grid; gap: 9px; margin-bottom: 16px; }
.m { display: grid; grid-template-columns: 46px 1fr 72px; align-items: center; gap: 10px; }
.m label { font-size: .66rem; font-weight: 600; color: var(--zx-muted-2); text-transform: uppercase; letter-spacing: .06em; font-family: var(--zx-font-pixel); }
.m .v { font-size: .76rem; color: var(--zx-muted); text-align: right; font-family: var(--zx-mono); font-variant-numeric: tabular-nums; }
.track { height: 6px; border-radius: var(--zx-r-pill); background: var(--zx-surface-2); overflow: hidden; }
.fill { display: block; height: 100%; border-radius: inherit; background: var(--zx-grad); transition: width .6s var(--zx-ease); }
.acts { display: flex; gap: 8px; }
.acts .btn { flex: 1; }

/* ───────────── 4. Botones (.btn = el zx-btn del sistema, en su tamaño pequeño) ─────────────
   Se estiliza la clase .btn y no zx-btn porque el JS reescribe className='btn primary' (migración); así todos salen iguales. */
body.zx-page .btn { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 9px 14px; border-radius: 12px; border: 1px solid var(--zx-line-2); font: 600 .86rem/1 var(--zx-font); color: var(--zx-text); background: transparent; cursor: pointer; text-decoration: none; box-shadow: 0 3px 0 rgba(255, 255, 255, .08); transition: transform .12s ease, box-shadow .12s ease, border-color var(--zx-dur-fast), background var(--zx-dur-fast), color var(--zx-dur-fast); }
body.zx-page .btn:hover { transform: translateY(-1px); border-color: rgba(255, 255, 255, .3); box-shadow: 0 4px 0 rgba(255, 255, 255, .12); }
body.zx-page .btn:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(255, 255, 255, .08); }
body.zx-page .btn.primary { border-color: transparent; background: var(--zx-grad-fill); color: #fff; box-shadow: 0 4px 0 var(--zx-brand-deep), 0 10px 24px -10px var(--zx-brand-glow); }
body.zx-page .btn.primary:hover { transform: translateY(-1px); box-shadow: 0 5px 0 var(--zx-brand-deep), 0 14px 30px -10px var(--zx-brand-glow); }
body.zx-page .btn.primary:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--zx-brand-deep), 0 4px 12px -6px var(--zx-brand-glow); }
body.zx-page .btn.warn { color: var(--zx-warn); border-color: color-mix(in srgb, var(--zx-warn) 40%, transparent); background: color-mix(in srgb, var(--zx-warn) 8%, transparent); box-shadow: 0 3px 0 color-mix(in srgb, var(--zx-warn) 22%, transparent); }
body.zx-page .btn.warn:hover { background: color-mix(in srgb, var(--zx-warn) 16%, transparent); border-color: var(--zx-warn); box-shadow: 0 4px 0 color-mix(in srgb, var(--zx-warn) 28%, transparent); }
body.zx-page .btn.danger { color: var(--zx-bad); border-color: color-mix(in srgb, var(--zx-bad) 40%, transparent); background: color-mix(in srgb, var(--zx-bad) 8%, transparent); box-shadow: 0 3px 0 color-mix(in srgb, var(--zx-bad) 22%, transparent); }
body.zx-page .btn.danger:hover { background: color-mix(in srgb, var(--zx-bad) 16%, transparent); border-color: var(--zx-bad); box-shadow: 0 4px 0 color-mix(in srgb, var(--zx-bad) 28%, transparent); }
body.zx-page .btn:disabled, body.zx-page .btn[disabled] { opacity: .5; cursor: not-allowed; transform: none; box-shadow: none; }
body.zx-page .btn.block { width: 100%; }
.btn svg { width: 15px; height: 15px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.8; }
.mini { font: 600 .74rem/1 var(--zx-font); padding: 7px 10px; border-radius: 9px; border: 1px solid var(--zx-line-2); background: var(--zx-surface-2); color: var(--zx-text); cursor: pointer; white-space: nowrap; transition: border-color var(--zx-dur-fast), background var(--zx-dur-fast); }
.mini:hover { border-color: rgba(255, 255, 255, .3); }
.mini.dg { color: var(--zx-bad); border-color: color-mix(in srgb, var(--zx-bad) 40%, transparent); background: color-mix(in srgb, var(--zx-bad) 8%, transparent); }
.mini.dg:hover { background: color-mix(in srgb, var(--zx-bad) 16%, transparent); }
.edit-name { display: inline-flex; cursor: pointer; color: var(--zx-muted-2); vertical-align: middle; margin: 0 2px; transition: color var(--zx-dur-fast); }
.edit-name svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 1.8; }
.edit-name:hover { color: var(--zx-text); }

/* ───────────── 5. Detalle de un VPS ───────────── */
.dtop { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; flex-wrap: wrap; animation: zxv-in .5s var(--zx-ease) backwards; }
.back { width: 36px; height: 36px; flex: none; border-radius: 11px; border: 1px solid var(--zx-line-2); background: var(--zx-surface); display: grid; place-items: center; cursor: pointer; transition: border-color var(--zx-dur-fast), background var(--zx-dur-fast); }
.back:hover { border-color: rgba(255, 255, 255, .3); background: var(--zx-surface-2); }
.back svg { width: 18px; height: 18px; stroke: var(--zx-text); fill: none; stroke-width: 2; }
.dtop .big { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 1.45rem; font-weight: 800; letter-spacing: -.03em; overflow-wrap: anywhere; }
.dtop .big .pill { margin-left: 0; }
.dtop .sub { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.dtop .sub.lead { color: var(--zx-muted); font-size: .88rem; margin-top: 4px; }
.mchip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--zx-r-pill); border: 1px solid var(--zx-line); background: rgba(255, 255, 255, .02); font-size: .76rem; font-weight: 500; color: var(--zx-muted); white-space: nowrap; }
.mchip svg { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 1.9; }
.pw { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.pw .btn { flex: 0 0 auto; padding: 10px 16px; }

/* Cifras (.tile = zx-kpi): la línea de abajo lleva el color de la gráfica */
.tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 16px; }
.zx-page .tile { min-width: 0; padding: 16px; gap: 4px; animation: zxv-in .55s var(--zx-ease) backwards; }
.tiles > .tile:nth-child(2) { animation-delay: 60ms; } .tiles > .tile:nth-child(3) { animation-delay: 120ms; } .tiles > .tile:nth-child(4) { animation-delay: 180ms; }
.tile--cpu { --zx-kpi-c: var(--zx-grad); } .tile--mem { --zx-kpi-c: var(--zxv-mem); } .tile--disk { --zx-kpi-c: var(--zxv-disk); } .tile--net { --zx-kpi-c: var(--zxv-net); }
.tile .tv { margin: 2px 0 4px; font-size: 1.5rem; font-weight: 800; letter-spacing: -.03em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.tile .tv small { font-size: .76rem; font-weight: 600; color: var(--zx-muted); letter-spacing: 0; }
.tile .tv.sm { font-size: .95rem; }
.tile.clk { cursor: pointer; transition: border-color var(--zx-dur-fast), transform var(--zx-dur-fast) var(--zx-ease), box-shadow var(--zx-dur-fast); }
.tile.clk:hover { border-color: rgba(192, 132, 252, .38); transform: translateY(-2px); box-shadow: 0 18px 40px -22px var(--zx-brand-glow); }
.sparkwrap { position: relative; height: 34px; margin-top: 2px; min-width: 0; }
/* Las gráficas (canvas de 300 px por dentro) no deben ensanchar la casilla. */
.sparkwrap canvas { max-width: 100%; }

.cols { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: 14px; align-items: start; }
/* Invitado solo-ver: la columna izquierda (consola, snapshots) queda sin paneles → se oculta y la otra ocupa todo */
.cols > div:not(:has(*)) { display: none; }
.cols:has(> div:not(:has(*))) { grid-template-columns: minmax(0, 1fr); }
.zx-page .panel { padding: 18px; margin-bottom: 14px; border-radius: var(--zx-r); animation: zxv-in .55s var(--zx-ease) backwards; }
.zx-page .panel:hover { transform: none; }
.cols > div > .panel:nth-child(2) { animation-delay: 80ms; } .cols > div > .panel:nth-child(3) { animation-delay: 160ms; }
.zx-page .panel h3 { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; font-size: .95rem; font-weight: 700; letter-spacing: -.01em; }
.panel h3 .r { margin-left: auto; font: 700 .64rem/1.5 var(--zx-font-pixel); letter-spacing: .06em; text-transform: uppercase; color: var(--zx-brand-2); }
.panel table { width: 100%; border-collapse: collapse; font-size: .86rem; }
.panel table td { padding: 9px 0; border-bottom: 1px solid var(--zx-line); vertical-align: top; }
.panel table tr:last-child td { border-bottom: 0; }
.panel table td.v { text-align: right; }
.k { color: var(--zx-muted-2); }
.mono { font-family: var(--zx-mono); color: var(--zx-text); }
.mono.hl { font-weight: 700; color: var(--zx-brand-2); }
.soon { color: var(--zx-muted); font-size: .86rem; line-height: 1.55; padding: 8px 0; }
.prow { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.prow .btn { flex: 1; min-width: 120px; }
.shared-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 0 0 14px; padding: 10px 14px; border-radius: 12px; font-size: .86rem; color: #cffafe; background: color-mix(in srgb, var(--zxv-shared) 8%, transparent); border: 1px solid color-mix(in srgb, var(--zxv-shared) 30%, transparent); }
.shared-bar .btn { flex: 0 0 auto; padding: 7px 12px; }
.shared-bar.infra-bar { color: #fecaca; background: color-mix(in srgb, var(--zx-bad) 8%, transparent); border-color: color-mix(in srgb, var(--zx-bad) 40%, transparent); }

/* Snapshots */
.snaplist { display: grid; gap: 8px; margin-bottom: 12px; }
.snap { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--zx-line); border-radius: 12px; background: var(--zx-bg-2); }
.snap > div { min-width: 0; }
.snap .sn { font-weight: 600; font-size: .86rem; overflow-wrap: anywhere; }
.snap .sd { font-size: .74rem; color: var(--zx-muted-2); font-family: var(--zx-mono); }
.sa { margin-left: auto; display: flex; gap: 6px; flex: none; flex-wrap: wrap; justify-content: flex-end; }
.snapform { display: flex; gap: 8px; }
.snapform .zx-input { flex: 1; min-width: 0; }
.snapform .btn { flex: 0 0 auto; }

/* Usuarios invitados */
.glist { display: grid; gap: 8px; }
.grow { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px; border: 1px solid var(--zx-line); border-radius: 12px; background: var(--zx-bg-2); }
.grow > div { min-width: 0; }
.grow .ge { font-weight: 600; font-size: .86rem; word-break: break-all; }
.grow .gt { font-size: .76rem; color: var(--zx-muted-2); margin-top: 2px; }
.gtpls { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 12px; }
.gtpl { display: grid; gap: 3px; text-align: left; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--zx-line); background: var(--zx-surface); color: var(--zx-text); cursor: pointer; font: inherit; transition: border-color var(--zx-dur-fast), background var(--zx-dur-fast); }
.gtpl b { font-size: .86rem; }
.gtpl span { font-size: .76rem; color: var(--zx-muted-2); line-height: 1.4; }
.gtpl:hover { border-color: var(--zx-line-2); }
.gtpl.on { border-color: var(--zx-brand-2); background: radial-gradient(120% 120% at 0% 0%, rgba(139, 92, 246, .18), transparent 60%), var(--zx-surface); }
.gtpl[disabled] { cursor: default; opacity: .55; }
.gtpl[disabled].on { opacity: 1; }
.gperms { display: grid; gap: 9px; font-size: .86rem; text-align: left; }
.gperms label { display: flex; gap: 10px; align-items: center; cursor: pointer; }
.gwarn { margin-top: 10px; padding: 9px 11px; border-radius: 10px; font-size: .8rem; text-align: left; color: #fecaca; background: color-mix(in srgb, var(--zx-bad) 10%, transparent); border: 1px solid color-mix(in srgb, var(--zx-bad) 35%, transparent); }
.gaudit { margin-top: 12px; font-size: .8rem; text-align: left; }
.gaudit summary { cursor: pointer; color: var(--zx-muted); margin-bottom: 6px; }
.gaudit .arow { padding: 6px 0; border-top: 1px solid var(--zx-line); overflow-wrap: anywhere; }
.gaudit .aw { color: var(--zx-muted-2); font-family: var(--zx-mono); font-size: .74rem; }

/* ───────────── 6. Ventanas (.ov > .modal: la estructura que busca el JS, con el aspecto de zx-dialog) ─────────────
   No llevan la clase zx-dialog a propósito: zx-design.js la cerraría con Esc o clic fuera sin pasar por el flujo del panel. */
.ov { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: var(--zx-gutter); background: rgba(8, 6, 16, .66); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); animation: zxv-fade .25s var(--zx-ease); }
.modal { position: relative; width: 100%; max-width: 400px; max-height: calc(100vh - 2 * var(--zx-gutter)); overflow: auto; padding: 26px; text-align: center; border: 1px solid var(--zx-line-2); border-radius: var(--zx-r-lg); background: var(--zx-surface); box-shadow: 0 40px 120px -40px var(--zx-brand-glow), 0 20px 60px rgba(0, 0, 0, .5); animation: zxv-pop .35s var(--zx-ease); }
.modal h3 { font-size: 1.15rem; font-weight: 800; letter-spacing: -.02em; margin-bottom: 8px; }
.modal p { color: var(--zx-muted); font-size: .9rem; line-height: 1.55; margin-bottom: 18px; }
.modal p b { color: var(--zx-text); }
.modal .mb { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.modal .mb .btn { flex: 1; min-width: 120px; }
.modal.wide { max-width: 680px; text-align: left; }
.modal .field { text-align: left; margin-bottom: 12px; }
.modal .zx-input, .modal .zx-select { margin-bottom: 14px; }
.modal .field .zx-input, .modal .field .zx-select, .modal .field input, .modal .field select { margin-bottom: 0; }
.modal .zx-input.center { text-align: center; }
.mtabs { margin-top: 10px; }
.mtabs .mtab.on { color: var(--zx-text); background: var(--zx-surface-2); box-shadow: inset 0 0 0 1px var(--zx-line-2); }
.chartbox { position: relative; height: 300px; margin-top: 14px; }
.chartbox canvas { max-width: 100%; }
.mig-prog { font-size: .86rem; color: var(--zx-muted); margin-bottom: 12px; line-height: 1.5; text-align: left; }
.mig-prog b { color: var(--zx-text); }

/* ───────────── 7. Formularios (Crear VPS, Recursos, Reasignar…) ───────────── */
.form { max-width: 820px; }
.fg { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 14px; }
/* min-width:0 en celdas y campos: sin esto los input type=number guardan su ancho intrínseco y «Crear VPS» desbordaba a 481 px en móvil */
.fg > *, .field, .cols > div, .zx-page .panel, .form { min-width: 0; }
.field { display: grid; gap: 7px; }
.field.full { grid-column: 1 / -1; }
.field label { font-size: .82rem; font-weight: 600; color: var(--zx-muted); }
.field label .hint { color: var(--zx-muted-2); font-weight: 400; }
.zx-page .zx-input, .zx-page .zx-select, .zx-page .field input, .zx-page .field select { width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box; padding: 11px 13px; border-radius: var(--zx-r-sm); border: 1px solid var(--zx-line-2); background: var(--zx-bg-2); color: var(--zx-text); font: 400 .92rem var(--zx-font); outline: none; transition: border-color var(--zx-dur-fast), box-shadow var(--zx-dur-fast); }
.zx-page .zx-input::placeholder, .zx-page .field input::placeholder { color: var(--zx-muted-2); }
.zx-page .zx-input:focus, .zx-page .zx-select:focus, .zx-page .field input:focus, .zx-page .field select:focus { border-color: var(--zx-brand-2); box-shadow: 0 0 0 4px rgba(139, 92, 246, .18); }
.formbar { display: flex; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.formbar .btn { flex: 0 0 auto; padding: 11px 20px; }

/* Selector de sistema (.oscard.sel = zx-choice marcado) */
.osgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 6px 0 4px; max-height: 46vh; overflow-y: auto; padding: 2px; }
.oscard { position: relative; text-align: left; padding: 12px; border-radius: 14px; border: 1px solid var(--zx-line); background: var(--zx-surface); cursor: pointer; transition: border-color var(--zx-dur-fast), background var(--zx-dur-fast), transform var(--zx-dur-fast) var(--zx-ease); }
.oscard:hover { border-color: var(--zx-line-2); transform: translateY(-1px); }
.oscard.sel { border-color: var(--zx-brand-2); background: radial-gradient(120% 120% at 0% 0%, rgba(139, 92, 246, .18), transparent 60%), var(--zx-surface); box-shadow: 0 0 0 1px var(--zx-brand-2); }
.oscard .oh { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.oscard .oh .lg { width: 26px; height: 26px; flex: 0 0 26px; }
.oscard .oh b { font-size: .86rem; font-weight: 700; }
.oscard .oh .kind { margin-left: auto; padding: 2px 7px; border-radius: 6px; font: 700 .6rem/1.5 var(--zx-font-pixel); letter-spacing: .06em; color: var(--zx-brand-2); background: rgba(139, 92, 246, .16); }
.zx-page .oscard select { padding: 8px 10px; font-size: .8rem; margin: 0; }
.dnote { font-size: .7rem; color: var(--zx-muted-2); margin-top: 4px; line-height: 1.3; }

/* ───────────── 8. IPs (admin): tabla del sistema ───────────── */
.zx-page .iptab td { vertical-align: top; }
.iptab td > div + div { margin-top: 2px; }
.iptab .k { color: var(--zx-muted-2); }
.ipchk { display: block; font-size: .78rem; line-height: 1.5; }
.ipchk.ok { color: var(--zx-ok); }
.ipchk.bad { color: var(--zx-bad); font-weight: 600; }
.ipsub { font-size: .78rem; color: var(--zx-muted-2); }
.ipsub.link { color: var(--zx-brand-2); }
.ipst { font-weight: 600; white-space: nowrap; }
.ipst.free { color: var(--zx-ok); }
.ipst.res { color: var(--zx-brand-2); }
.ipst.asg { color: var(--zx-muted-2); }
.ipok { color: var(--zx-ok); } .ipbad { color: var(--zx-bad); } .iphl { color: var(--zx-brand-2); }
.zx-page .zx-table-wrap { animation: zxv-in .55s var(--zx-ease) backwards; }
.zx-page .zx-table .btn { padding: 5px 10px; font-size: .76rem; }
.zx-page .zx-table th.r, .zx-page .zx-table td.r { text-align: right; }
/* Apilada en móvil (≤700 px, zx-table--stack): el sistema pone cada celda en flex (etiqueta a la izquierda, valor a la derecha),
   pero estas celdas tienen varios hijos (b, span, div, a, .ipchk) y salían repartidos en columnas. Aquí cada celda va en
   bloque: etiqueta en su línea y el contenido debajo, con cada comprobación/subtítulo en línea propia. */
@media (max-width: 700px) {
  .zx-page .iptab.zx-table--stack tr { padding: 12px 6px; }
  .zx-page .iptab.zx-table--stack td { display: block; text-align: left; padding: 6px 8px; }
  .zx-page .iptab.zx-table--stack td::before { display: block; margin-bottom: 3px; text-align: left; }
  .zx-page .iptab.zx-table--stack td[data-label=""]::before { display: none; }
  .zx-page .iptab.zx-table--stack td.r { text-align: left; padding-top: 8px; }
  .zx-page .iptab.zx-table--stack td:empty, .zx-page .iptab.zx-table--stack td.r:not(:has(*)) { display: none; }
  .zx-page .iptab.zx-table--stack td .ipchk, .zx-page .iptab.zx-table--stack td .ipsub, .zx-page .iptab.zx-table--stack td a, .zx-page .iptab.zx-table--stack td > div { display: block; overflow-wrap: anywhere; }
  .zx-page .iptab.zx-table--stack td > b, .zx-page .iptab.zx-table--stack td > .mono { display: inline-block; margin-right: 6px; overflow-wrap: anywhere; }
}

/* ───────────── 9. Acceso, vacío, espera y avisos ───────────── */
.center { min-height: 60vh; display: grid; place-items: center; text-align: center; padding: 24px 0; }
.zx-page .authc { width: 100%; max-width: 400px; padding: 36px 32px 30px; border-radius: var(--zx-r-lg); border-color: var(--zx-line-2); text-align: center; animation: zxv-in .6s var(--zx-ease) backwards; }
.zx-page .authc:hover { transform: none; }
.authc .logo { width: 64px; height: 64px; margin: 0 auto 16px; border-radius: 18px; }
.zx-page .authc h2 { font-size: 1.4rem; font-weight: 800; margin-bottom: 6px; }
.zx-page .authc p { font-size: .92rem; margin-bottom: 22px; }
.muted { color: var(--zx-muted-2); font-size: .88rem; }
.spin { width: 40px; height: 40px; margin: 60px auto; border: 3px solid rgba(139, 92, 246, .2); border-top-color: var(--zx-brand); border-radius: 50%; animation: zxv-sp 1s linear infinite; }
.toast { position: fixed; bottom: 22px; left: 50%; z-index: 1100; transform: translateX(-50%); max-width: calc(100vw - 32px); padding: 12px 18px; border-radius: 12px; border: 1px solid var(--zx-line-2); background: var(--zx-surface-2); color: var(--zx-text); font-size: .88rem; box-shadow: 0 12px 30px rgba(0, 0, 0, .5), 0 0 0 1px rgba(192, 132, 252, .15); animation: zxv-toast .35s var(--zx-ease); }

/* ───────────── 10. Animaciones propias (prefers-reduced-motion las quita zx-design) ───────────── */
@keyframes zxv-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes zxv-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes zxv-pop { from { opacity: 0; transform: translateY(14px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes zxv-toast { from { opacity: 0; transform: translate(-50%, 10px); } to { opacity: 1; transform: translateX(-50%); } }
@keyframes zxv-sp { to { transform: rotate(360deg); } }
@keyframes zxv-beat { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 55%, transparent); } 80%, 100% { box-shadow: 0 0 0 7px transparent; } }
@keyframes zxv-blink { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@keyframes zxpulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

/* ───────────── 11. Tableta y móvil ───────────── */
@media (max-width: 1100px) { .nav-links a { padding: 8px 11px; } }
@media (max-width: 980px) {
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cols { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) { .nav-links { display: none; } }
@media (max-width: 760px) {
  .zx-page { --zxv-navh: 56px; }
  .app { grid-template-columns: minmax(0, 1fr); }
  .navbar { padding: 8px 14px; gap: 10px; }
  .navbar .logo img { width: 30px; height: 30px; }
  .nav-profile .user-name { display: none; }
  .menu-btn { display: inline-flex; }
  /* cajón lateral: fuera de pantalla hasta que #side lleva .open (toggleSide) */
  .side { position: fixed; top: 0; left: 0; bottom: 0; height: auto; width: min(84vw, 280px); z-index: 70; padding-top: 18px; transform: translateX(-102%); transition: transform .3s var(--zx-ease); background: rgba(23, 20, 36, .98); box-shadow: 0 18px 50px rgba(0, 0, 0, .55); }
  .side.open { transform: none; }
  .scrim.open { display: block; }
  .main { padding: 18px 16px 40px; }
  .grid { grid-template-columns: minmax(0, 1fr); }
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pw { margin-left: 0; width: 100%; }
  .pw .btn { flex: 1; padding: 10px 12px; }
  .fg, .gtpls, .osgrid { grid-template-columns: minmax(0, 1fr); }
  .osgrid { max-height: 40vh; }
  .modal { padding: 20px 16px; }
  .modal .mb .btn { min-width: 0; }
  .snapform { flex-wrap: wrap; }
  .snapform .zx-input { flex: 1 1 100%; }
  .snapform .btn { flex: 1; }
  .toast { bottom: 16px; }
}
@media (max-width: 420px) {
  .m { grid-template-columns: 40px 1fr 64px; gap: 8px; }
  .acts { flex-wrap: wrap; }
  .acts .btn { min-width: 44%; }
  .grow, .snap { flex-wrap: wrap; }
  .grow .sa, .snap .sa { margin-left: 0; width: 100%; justify-content: flex-start; }
}
