/* ═══════════════════════════════════════════════════════════
   PTT Web App — Design System
   Tema oscuro premium con glassmorphism y micro-animaciones
   ═══════════════════════════════════════════════════════════ */

/* ── Fuentes Locales (sin CDN externo) ── */
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 300; font-display: swap; src: url('/fonts/inter-300-a473493e759c058118283b666046ef3d.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/inter-400-da03732a27e16543f09d6a6a62b0cdd4.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/inter-500-51205681a1ba304816fc629e8989256b.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap; src: url('/fonts/inter-600-2ede57db1a3a5f41f40467e7a43a1dd4.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 700; font-display: swap; src: url('/fonts/inter-700-8ca0a51552960933d0fd52c19175cbe9.woff2') format('woff2'); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/jetbrains-mono-400-caf0dfde4e448468f09b7bed230206a4.woff2') format('woff2'); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/jetbrains-mono-500-a21e038a03f709cf60aa1e2944048aef.woff2') format('woff2'); }

:root {
    --bg-primary: #0a0e17;
    --bg-secondary: #111827;
    --bg-card: rgba(17, 24, 39, 0.8);
    --bg-glass: rgba(255, 255, 255, 0.04);
    --border-glass: rgba(255, 255, 255, 0.08);
    --border-active: rgba(99, 179, 237, 0.4);

    --text-primary: #e2e8f0;
    --text-secondary: #94a3b8;
    --text-muted: #64748b;

    --accent-blue: #3b82f6;
    --accent-cyan: #06b6d4;
    --accent-emerald: #10b981;
    --accent-amber: #f59e0b;
    --accent-red: #ef4444;
    --accent-purple: #8b5cf6;

    --gradient-hero: linear-gradient(135deg, #1e3a5f 0%, #0a0e17 50%, #1a1a2e 100%);
    --gradient-card: linear-gradient(145deg, rgba(30, 58, 95, 0.3), rgba(10, 14, 23, 0.8));
    --gradient-btn: linear-gradient(135deg, #3b82f6, #2563eb);
    --gradient-btn-hover: linear-gradient(135deg, #60a5fa, #3b82f6);
    --gradient-success: linear-gradient(135deg, #10b981, #059669);
    --gradient-warning: linear-gradient(135deg, #f59e0b, #d97706);

    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.6);
    --shadow-glow-blue: 0 0 20px rgba(59, 130, 246, 0.3);
    --shadow-glow-cyan: 0 0 20px rgba(6, 182, 212, 0.3);

    --radius-sm: 8px;
    --radius-md: 12px;
    --radius-lg: 16px;
    --radius-xl: 24px;

    --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-mono: 'JetBrains Mono', 'Fira Code', monospace;

    --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-normal: 250ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-slow: 400ms cubic-bezier(0.4, 0, 0.2, 1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
    font-size: 16px;
    scroll-behavior: smooth;
}

body {
    font-family: var(--font-sans);
    background: var(--bg-primary);
    color: var(--text-primary);
    min-height: 100vh;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

/* ─── Layout ─── */

.app-container {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* ⚠ SIN backdrop-filter — y no es un descuido, es la corrección de un problema real.
   Esta barra es `position: sticky`, así que permanece encima del contenido que se
   desplaza. Un filtro de fondo sobre un elemento fijo obliga al navegador a releer y
   volver a desenfocar TODO lo que pasa por debajo en CADA fotograma del scroll: es la
   causa directa de que las tarjetas se vieran aparecer con retraso y de los destellos
   al desplazarse. El fondo ya era opaco al 90 %; subirlo al 96 % da el mismo aspecto
   de barra sólida oscura y libera al compositor por completo. */
.nav {
    background: rgba(10, 14, 23, 0.96);
    border-bottom: 1px solid var(--border-glass);
    padding: 0 2rem;
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 100;
}

.nav-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--accent-cyan);
    text-decoration: none;
    letter-spacing: -0.5px;
}

.nav-brand .icon {
    font-size: 1.5rem;
}

/* ── Alineación de la barra ──
   `align-items: center` NO estaba, así que regía el valor por defecto, `stretch`:
   cada <li> se estiraba a la altura del más alto de la fila —el hueco del traductor,
   con min-height:38px— pero su contenido se quedaba pegado ARRIBA. Como el chip del
   contador es más bajo que un enlace (6px de relleno vertical frente a 8px, y un
   cuerpo de letra menor), quedaba unos píxeles por encima del resto de la barra.
   Ese era el desalineado: no era el chip, era la fila entera sin eje común. */
.nav-links {
    display: flex;
    align-items: center;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Cada elemento centra su propio contenido, sea un enlace, el chip o el traductor
   (que inyecta su propio marcado y no se puede maquetar desde aquí). */
.nav-links > li {
    display: flex;
    align-items: center;
}

/* Altura ÚNICA para todo lo que se ve en la barra. Sin ella, cada pieza mide según
   su relleno y su cuerpo de letra, y la fila se lee como piezas sueltas a distintas
   alturas en vez de como una sola línea: es lo que hacía que la pastilla activa
   ("Dashboard") y el chip parecieran de tamaños distintos. */
.nav-links a,
.nav-links .online-chip {
    min-height: 34px;
}

.nav-links a {
    /* inline-flex + gap en lugar del margen del icono: en una caja flexible el
       espacio en blanco del HTML entre <span class="nav-ico">💳</span> y el texto NO
       se renderiza, así que la separación tiene que declararse aquí o "Pasarelas"
       quedaría pegado a su icono. */
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--text-secondary);
    text-decoration: none;
    padding: 8px 16px;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    font-weight: 500;
    /* El interlineado de 1.6 heredado del <body> hacía que la caja del enlace midiera
       38,4 px mientras la del chip medía 34,8: dos alturas distintas en la misma fila.
       Con 1.2 ambas caen por debajo del `min-height: 34px` común y todas las piezas de
       la barra miden EXACTAMENTE lo mismo. El texto no cambia: es de una sola línea. */
    line-height: 1.2;
    transition: color var(--transition-fast), background-color var(--transition-fast);
}

.nav-links a:hover {
    color: var(--text-primary);
    background: var(--bg-glass);
}

.nav-links a.active {
    color: var(--accent-cyan);
    background: rgba(6, 182, 212, 0.1);
}

.main-content {
    flex: 1;
    padding: 2rem;
    max-width: 1200px;
    margin: 0 auto;
    width: 100%;
}

/* ─── Tarjetas ─── */

/* ⚠ SIN backdrop-filter, por dos motivos concretos:
   1) NO SE VEÍA NADA. Lo que hay detrás de una tarjeta es `body { background:
      var(--bg-primary) }`, es decir el color plano #0a0e17. Desenfocar un color plano
      da exactamente el mismo color plano: el filtro no aportaba ni un píxel de efecto.
   2) SÍ SE PAGABA. Cada tarjeta con filtro de fondo es una capa de composición aparte
      cuyo fondo hay que releer y volver a desenfocar al desplazarse. El panel Admin
      tiene una decena de tarjetas (todo el bloque de Seguridad IP), así que al hacer
      scroll el navegador repetía ese trabajo una vez por recuadro y por fotograma:
      de ahí que los recuadros "tardaran en cargar" y parpadearan al desplazarse.
   El aspecto no cambia: --gradient-card ya lleva su propia transparencia sobre el
   fondo, que es lo que produce el efecto de cristal.

   La transición se acota a las DOS propiedades que realmente cambian en :hover. Con
   `transition: all`, cualquier recálculo de estilo durante el scroll podía animar
   también propiedades de tamaño o color heredadas y provocar el destello. */
.card {
    background: var(--gradient-card);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-lg);
    padding: 1.5rem;
    transition: border-color var(--transition-normal), box-shadow var(--transition-normal);
}

.card:hover {
    border-color: var(--border-active);
    box-shadow: var(--shadow-md);
}

.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1.25rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border-glass);
}

.card-title {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 8px;
}

/* ─── Formularios ─── */

.form-group {
    margin-bottom: 1.25rem;
}

.form-label {
    display: block;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-secondary);
    margin-bottom: 6px;
}

.form-input {
    width: 100%;
    padding: 12px 16px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 0.9375rem;
    transition: all var(--transition-fast);
    outline: none;
}

.form-input:focus {
    border-color: var(--accent-blue);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
    background: rgba(255, 255, 255, 0.06);
}

.form-input::placeholder {
    color: var(--text-muted);
}

/* ─── Botones ─── */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px 24px;
    border: none;
    border-radius: var(--radius-sm);
    font-family: var(--font-sans);
    font-size: 0.9375rem;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition-fast);
    text-decoration: none;
    letter-spacing: -0.2px;
}

.btn-primary {
    background: var(--gradient-btn);
    color: white;
    box-shadow: var(--shadow-sm);
}

.btn-primary:hover {
    background: var(--gradient-btn-hover);
    box-shadow: var(--shadow-glow-blue);
    transform: translateY(-1px);
}

.btn-success {
    background: var(--gradient-success);
    color: white;
}

.btn-success:hover {
    box-shadow: 0 0 20px rgba(16, 185, 129, 0.3);
    transform: translateY(-1px);
}

.btn-warning {
    background: var(--gradient-warning);
    color: #1a1a2e;
}

.btn-danger {
    background: linear-gradient(135deg, #ef4444, #dc2626);
    color: white;
}

.btn-ghost:hover {
    color: var(--text-primary);
    background: var(--bg-glass);
    border-color: var(--border-active);
}

.btn-outline {
    background: transparent;
    border: 1px solid currentColor;
}

.btn-outline:hover {
    background: rgba(255, 255, 255, 0.05);
}

.btn-full { width: 100%; }

.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none !important;
}

/* ─── Auth Pages ─── */

.auth-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--gradient-hero);
    padding: 2rem;
}

/* Sin filtro de fondo por la misma razón que .card: detrás solo hay un fondo estático,
   y desenfocar algo que no se mueve ni tiene detalle no produce ningún efecto visible.
   Aquí además la tarjeta ocupa media pantalla, así que era el filtro más caro de todos. */
.auth-card {
    width: 100%;
    max-width: 420px;
    background: var(--gradient-card);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-xl);
    padding: 2.5rem;
    box-shadow: var(--shadow-lg);
}

.auth-header {
    text-align: center;
    margin-bottom: 2rem;
}

.auth-header h1 {
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--accent-cyan);
    margin-bottom: 0.5rem;
    letter-spacing: -0.5px;
}

.auth-header p {
    color: var(--text-secondary);
    font-size: 0.9375rem;
}

.auth-footer {
    text-align: center;
    margin-top: 1.5rem;
    font-size: 0.875rem;
    color: var(--text-muted);
}

.auth-footer a {
    color: var(--accent-blue);
    text-decoration: none;
    font-weight: 500;
}

.auth-footer a:hover {
    text-decoration: underline;
}

/* ─── Dashboard Grid ─── */

.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 1.5rem;
    margin-top: 1.5rem;
}

.stat-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.stat-card {
    background: var(--gradient-card);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    padding: 1.25rem;
    text-align: center;
}

.stat-value {
    font-size: 2rem;
    font-weight: 700;
    font-family: var(--font-mono);
    color: var(--accent-cyan);
}

.stat-label {
    font-size: 0.8125rem;
    color: var(--text-muted);
    margin-top: 4px;
    text-transform: uppercase;
    letter-spacing: 1px;
}

/* ─── VHF Status ─── */

.vhf-panel {
    position: relative;
    overflow: hidden;
}

.vhf-panel::before {
    content: '';
    position: absolute;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(circle at center, rgba(6, 182, 212, 0.05) 0%, transparent 60%);
    animation: pulse-glow 4s ease-in-out infinite;
    pointer-events: none;
}

@keyframes pulse-glow {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 1; }
}

@keyframes pulse-red {
    0% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.5; transform: scale(1.05); }
    100% { opacity: 1; transform: scale(1); }
}

.recording-pulse {
    animation: pulse-red 1.5s ease-in-out infinite;
    color: var(--accent-red) !important;
    font-weight: 700;
}

.vhf-frequency {
    font-size: 2.5rem;
    font-weight: 700;
    font-family: var(--font-mono);
    color: var(--accent-cyan);
    text-shadow: var(--shadow-glow-cyan);
    letter-spacing: 2px;
}

.vhf-frequency span {
    font-size: 1rem;
    color: var(--text-muted);
    font-weight: 400;
}

.vhf-channel-name {
    font-size: 1.125rem;
    color: var(--accent-emerald);
    font-weight: 600;
    margin-top: 4px;
}

.signal-bar {
    width: 100%;
    height: 8px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 4px;
    margin-top: 12px;
    overflow: hidden;
}

.signal-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--accent-emerald), var(--accent-cyan));
    border-radius: 4px;
    transition: width 0.05s ease-out;
}

.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.status-active {
    background: rgba(16, 185, 129, 0.15);
    color: var(--accent-emerald);
    border: 1px solid rgba(16, 185, 129, 0.3);
}

.status-inactive {
    background: rgba(239, 68, 68, 0.15);
    color: var(--accent-red);
    border: 1px solid rgba(239, 68, 68, 0.3);
}

.status-pending {
    background: rgba(245, 158, 11, 0.15);
    color: var(--accent-amber);
    border: 1px solid rgba(245, 158, 11, 0.3);
}

/* ─── Channel Selector ─── */

.channel-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 10px;
    margin-top: 1rem;
}

.channel-btn {
    padding: 12px;
    background: var(--bg-glass);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: center;
    font-family: var(--font-sans);
}

.channel-btn:hover {
    border-color: var(--accent-cyan);
    color: var(--text-primary);
    background: rgba(6, 182, 212, 0.1);
}

.channel-btn.active {
    border-color: var(--accent-cyan);
    background: rgba(6, 182, 212, 0.15);
    color: var(--accent-cyan);
    box-shadow: var(--shadow-glow-cyan);
}

/* Canal con tráfico AHORA (channels_activity del relay), independiente de si este
   usuario lo tiene seleccionado (.active, cian) — se combinan sin chocar: el fondo
   cian sigue marcando "tu canal" y el pulso esmeralda marca "hay voz aquí ahora". */
.channel-btn.busy {
    border-color: var(--accent-emerald);
    animation: channelBusyPulse 1.6s ease-in-out infinite;
}

@keyframes channelBusyPulse {
    0%, 100% { box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.25); }
    50%      { box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.55); }
}

/* Barrita fina de nivel instantáneo por canal, dentro de cada .channel-btn — versión
   miniatura de .signal-bar/.signal-bar-fill, sin historial ni canvas. */
.channel-activity-bar {
    width: 100%;
    height: 3px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 2px;
    margin-top: 8px;
    overflow: hidden;
}

/* Estado POR DEFECTO (sin detección de voz): color neutro apagado. Se mantiene
   este color mientras NO haya actividad de voz en el canal, INCLUSO si el canal
   está desconectado (el relay mide los 6 canales y el poll de 1s siempre corre). */
.channel-activity-fill {
    height: 100%;
    width: 0%;
    background: var(--text-muted);
    border-radius: 2px;
    /* El ANCHO lo anima el motor de interpolación rAF (barSmoother) en dashboard.html a 60fps,
       con ataque vivo y caída suave; por eso NO se transiciona 'width' aquí (una transición CSS
       de ancho se solaparía con el rAF y produciría arrastre). Sí se suavizan color y halo. */
    transition: background-color 0.18s ease-out, box-shadow 0.18s ease-out;
    will-change: width;
}

/* Estado ACTIVO (hay detección de voz ahora, channels_activity[id].active=true):
   el relleno se pone VERDE con un leve halo. Lo alterna updateChannelButtonsActivity
   en dashboard.html según entry.active, sin depender de si este cliente está
   escuchando ese canal (funciona con el canal desconectado). */
.channel-activity-fill.voice-active {
    background: var(--accent-emerald);
    box-shadow: 0 0 6px rgba(16, 185, 129, 0.65);
}

.channel-btn .ch-num {
    font-size: 1.5rem;
    font-weight: 700;
    font-family: var(--font-mono);
    display: block;
}

.channel-btn .ch-desc {
    font-size: 0.6875rem;
    color: var(--text-muted);
    margin-top: 2px;
}

/* ─── Payment Cards ─── */

.payment-options {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1.5rem;
    margin-top: 1.5rem;
}

.payment-card {
    background: var(--gradient-card);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-lg);
    padding: 2rem;
    text-align: center;
    transition: all var(--transition-normal);
    cursor: pointer;
}

.payment-card:hover {
    border-color: var(--border-active);
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

.payment-card .provider-name {
    font-size: 1.25rem;
    font-weight: 700;
    margin: 1rem 0 0.5rem;
}

.payment-card .provider-desc {
    color: var(--text-muted);
    font-size: 0.875rem;
    margin-bottom: 1.5rem;
}

.price-tag {
    font-size: 2.25rem;
    font-weight: 800;
    font-family: var(--font-mono);
    color: var(--accent-emerald);
}

.price-tag .currency {
    font-size: 1rem;
    color: var(--text-muted);
    font-weight: 400;
}

.price-tag .period {
    font-size: 0.875rem;
    color: var(--text-muted);
    font-weight: 400;
}

/* ─── Table ─── */

.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.data-table th {
    text-align: left;
    padding: 10px 12px;
    color: var(--text-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-size: 0.75rem;
    border-bottom: 1px solid var(--border-glass);
}

.data-table td {
    padding: 10px 12px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.03);
    color: var(--text-secondary);
}

.data-table tr:hover td {
    background: var(--bg-glass);
    color: var(--text-primary);
}

/* ─── Alerts ─── */

.alert {
    padding: 12px 16px;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 8px;
}

.alert-success {
    background: rgba(16, 185, 129, 0.1);
    border: 1px solid rgba(16, 185, 129, 0.3);
    color: var(--accent-emerald);
}

.alert-error {
    background: rgba(239, 68, 68, 0.1);
    border: 1px solid rgba(239, 68, 68, 0.3);
    color: var(--accent-red);
}

.alert-info {
    background: rgba(59, 130, 246, 0.1);
    border: 1px solid rgba(59, 130, 246, 0.3);
    color: var(--accent-blue);
}

/* ─── Loader ─── */

.spinner {
    width: 20px;
    height: 20px;
    border: 2px solid rgba(255, 255, 255, 0.1);
    border-top-color: var(--accent-cyan);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* ─── Responsive ─── */

@media (max-width: 768px) {
    .nav { padding: 0 1rem; }
    .main-content { padding: 1rem; }
    .dashboard-grid { grid-template-columns: 1fr; }
    .stat-row { grid-template-columns: 1fr 1fr; }
    .auth-card { padding: 1.5rem; }
    .vhf-frequency { font-size: 1.75rem; }
    .payment-options { grid-template-columns: 1fr; }
}
/* ─── Compatibilidad con Google Translate ─── */
.goog-te-banner-frame.skiptranslate {
    display: none !important;
}
body {
    top: 0px !important;
}
.skiptranslate {
    font-family: var(--font-sans) !important;
}
/* Evita que el banner de Google empuje el nav sticky de forma incorrecta */
#google_translate_element select {
    background: var(--bg-glass);
    color: var(--text-primary);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-sm);
    padding: 4px;
    font-size: 0.75rem;
    outline: none;
}

/* ─── Mini Audio Player Flotante ─── */
/* Mismo caso que la barra de navegación: es `position: fixed`, se queda quieto sobre el
   contenido que se desplaza, y con filtro de fondo obligaba a redesenfocar lo que pasa
   por debajo en cada fotograma. El fondo ya estaba al 95 % de opacidad —el desenfoque
   apenas se intuía— así que al 97 % el reproductor se ve igual y el scroll deja de
   arrastrarlo. Se conserva `transform` en la transición porque el :hover lo usa. */
.mini-audio-player {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 999;
    background: rgba(10, 14, 23, 0.97);
    border: 1px solid var(--border-active);
    border-radius: var(--radius-md);
    padding: 10px 16px;
    box-shadow: var(--shadow-lg);
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    transition: transform var(--transition-normal), box-shadow var(--transition-normal);
}
.mini-audio-player:hover {
    box-shadow: var(--shadow-glow-cyan);
    transform: translateY(-2px);
}
.mini-audio-player .live-dot {
    color: var(--accent-emerald);
    font-size: 0.8rem;
    animation: pulse-glow 2s infinite;
}
.mini-audio-player .live-label {
    color: var(--text-primary);
    font-size: 0.8125rem;
    font-weight: 600;
}
.mini-audio-player .stop-btn {
    background: none;
    border: 1px solid var(--accent-red);
    color: var(--accent-red);
    border-radius: var(--radius-sm);
    padding: 4px 10px;
    font-size: 0.75rem;
    cursor: pointer;
    transition: all var(--transition-fast);
}
.mini-audio-player .stop-btn:hover {
    background: rgba(239, 68, 68, 0.15);
}

/* ══════════════════════════════════════════════════════════════════════════
   CONTADOR DE USUARIOS CONECTADOS (barra de navegación)
   Chip compacto con punto latiente. Vive dentro de .nav-links, así que evita
   heredar el padding de los enlaces (no es un enlace: no debe parecer pulsable).
   ══════════════════════════════════════════════════════════════════════════ */

.online-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    /* 7px y no 8: el chip tiene borde de 1px y los enlaces no, así que este relleno
       compensa esos 2px y deja ambas cajas en la misma altura total (34px con
       box-sizing: border-box). Es lo que pone la pastilla del contador a ras exacto
       de "Dashboard" y "Admin" en lugar de unos píxeles por encima. */
    padding: 7px 12px;
    border-radius: 999px;
    border: 1px solid var(--border-glass);
    background: rgba(16, 185, 129, 0.08);
    font-size: 0.8125rem;
    font-weight: 600;
    /* 1.2 y no 1: con interlineado exacto, la tilde de "en línea" puede quedar
       recortada por el borde superior de la caja en algunas fuentes. */
    line-height: 1.2;
    color: var(--text-secondary);
    white-space: nowrap;
    cursor: default;
    transition: border-color var(--transition-fast), background-color var(--transition-fast);
}

.online-chip:hover {
    border-color: rgba(16, 185, 129, 0.45);
    background: rgba(16, 185, 129, 0.14);
}

/* .is-live la añade presence.js tras el primer latido confirmado por el servidor:
   antes de eso el punto NO parpadea, para no dar por buena una cifra sin verificar. */
.online-chip .online-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--text-muted);
    flex: 0 0 auto;
}

.online-chip.is-live .online-dot {
    background: var(--accent-emerald);
    box-shadow: 0 0 8px rgba(16, 185, 129, 0.8);
    animation: pulse-glow 2s ease-in-out infinite;
}

.online-chip .online-value {
    font-family: var(--font-mono);
    font-size: 0.875rem;
    color: var(--accent-emerald);
    min-width: 1ch;
    text-align: right;
}

.online-chip .online-label {
    color: var(--text-muted);
    font-weight: 500;
    letter-spacing: 0.3px;
}

/* ── Hueco del traductor dentro de la barra ──
   El <li> del widget de Google Translate llevaba su maquetación EN LÍNEA en el HTML
   (margin-left, min-height:38px), repetida a mano en cuatro plantillas. Ese 38px era,
   además, el elemento más alto de la fila y el que estiraba a todos los demás.
   Aquí se centraliza, con la altura común del resto de la barra. */
.nav-links #google_translate_element {
    display: flex;
    align-items: center;
    min-height: 34px;
    margin-left: 4px;
}

/* Mientras el widget no se haya inyectado, su hueco deja un vano visible entre
   "Admin" y "Salir" que rompe el ritmo de la barra. Con el contenedor vacío, se
   colapsa el elemento entero (no solo el div: si no, el `gap` de 8px seguiría ahí).
   `:has()` está disponible en todos los navegadores actuales; donde no lo esté, el
   único efecto es conservar el comportamiento anterior. */
.nav-links > li:has(> #google_translate_element:empty) {
    display: none;
}

/* ══════════════════════════════════════════════════════════════════════════
   LANDING DE PASARELAS (hito de captación + MercadoPago "en construcción")
   ══════════════════════════════════════════════════════════════════════════ */

.landing-hero {
    text-align: center;
    padding: 2rem 1rem 0.5rem;
}

.landing-title {
    font-size: 2rem;
    font-weight: 700;
    letter-spacing: -0.6px;
    margin: 0.85rem 0 0.6rem;
    background: linear-gradient(120deg, var(--text-primary), var(--accent-cyan));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.landing-subtitle {
    max-width: 640px;
    margin: 0 auto;
    color: var(--text-secondary);
    font-size: 0.9375rem;
    line-height: 1.65;
}

.mp-showcase {
    margin: 2rem auto 0;
    max-width: 560px;
}

/* Marco del logotipo: la cinta "Próximamente" se ancla a él, por eso es relative
   y con overflow oculto (la cinta se rota 45° y debe recortarse en la esquina).

   El fondo es CLARO a propósito. El logotipo oficial de Mercado Pago lleva el nombre
   en azul #0A0080, que sobre el fondo oscuro de la app resultaría ilegible. La guía de
   marca prohíbe recolorear o alterar el archivo, así que la placa clara la pone el
   contenedor: el logotipo se reproduce exactamente como lo publica Mercado Pago. */
.mp-logo-frame {
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2.25rem 1.5rem;
    border-radius: var(--radius-lg);
    border: 1px solid rgba(255, 255, 255, 0.18);
    background: linear-gradient(160deg, #ffffff 0%, #eef4f9 100%);
    box-shadow: var(--shadow-lg);
}

.mp-logo-frame::after {
    /* Trama diagonal sutil = señalética de "obra en curso", sin tapar el logo. */
    content: '';
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        45deg,
        rgba(245, 158, 11, 0.12) 0px,
        rgba(245, 158, 11, 0.12) 12px,
        transparent 12px,
        transparent 24px
    );
    pointer-events: none;
}

.mp-logo {
    max-width: 100%;
    height: auto;
    position: relative;
    z-index: 1;
    /* Sombra neutra y suave: sobre la placa clara, un halo azul saturado ensuciaría
       los bordes del isotipo celeste del logotipo oficial. */
    filter: drop-shadow(0 4px 12px rgba(15, 23, 42, 0.18));
}

/* Placa clara mínima para el logotipo oficial cuando NO va dentro de .mp-logo-frame
   (por ejemplo, la tarjeta de pago operativa de /subscription, de fondo oscuro).
   Misma razón que el marco: el nombre de la marca es azul #0A0080 y no puede recolorearse. */
.mp-logo-plate {
    background: #ffffff;
    border-radius: var(--radius-md);
    padding: 0.75rem 1rem;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
}

.mp-ribbon {
    position: absolute;
    top: 18px;
    right: -46px;
    transform: rotate(45deg);
    background: var(--gradient-warning);
    color: #1a1a2e;
    font-size: 0.6875rem;
    font-weight: 800;
    letter-spacing: 1px;
    text-transform: uppercase;
    padding: 6px 56px;
    z-index: 2;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}

.mp-caption {
    margin-top: 0.9rem;
    font-size: 0.8125rem;
    color: var(--text-muted);
    line-height: 1.6;
}

/* ─── Contadores del hito ─── */

.gw-counter-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    margin: 0.5rem 0 1.25rem;
}

.gw-counter {
    text-align: center;
    padding: 0.85rem 0.5rem;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-glass);
    background: var(--bg-glass);
}

.gw-counter-value {
    font-family: var(--font-mono);
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--accent-cyan);
    line-height: 1.1;
}

.gw-counter-value.gw-counter-accent {
    color: var(--accent-amber);
}

.gw-counter-label {
    margin-top: 4px;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted);
}

.gw-progress {
    height: 14px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--border-glass);
    overflow: hidden;
}

.gw-progress-fill {
    height: 100%;
    width: 0;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--accent-blue), var(--accent-cyan));
    /* Transición generosa: el valor lo refresca presence.js por polling, y un salto
       seco delataría el intervalo de sondeo en vez de leerse como progreso continuo. */
    transition: width 900ms cubic-bezier(0.22, 1, 0.36, 1), background 400ms linear;
}

.gw-progress-fill.is-complete {
    background: var(--gradient-success);
    box-shadow: 0 0 14px rgba(16, 185, 129, 0.45);
}

.gw-progress-note {
    margin-top: 0.7rem;
    font-size: 0.75rem;
    color: var(--text-muted);
    line-height: 1.6;
}

/* ─── Llamadas a la acción ─── */

.gw-cta {
    margin-top: 1.25rem;
    padding: 1.1rem;
    border-radius: var(--radius-md);
    border: 1px dashed rgba(245, 158, 11, 0.35);
    background: rgba(245, 158, 11, 0.05);
}

.gw-cta.gw-cta-success {
    border: 1px solid rgba(16, 185, 129, 0.4);
    background: rgba(16, 185, 129, 0.07);
}

.gw-cta-text {
    font-size: 0.875rem;
    color: var(--text-secondary);
    line-height: 1.6;
}

.gw-cta-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 0.9rem;
}

/* ─── Listas de características ─── */

.feature-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}

.feature-list li {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    font-size: 0.8125rem;
    color: var(--text-secondary);
    line-height: 1.6;
}

.feature-list .feature-icon {
    font-size: 1.15rem;
    flex: 0 0 auto;
    line-height: 1.3;
}

.feature-list strong {
    color: var(--text-primary);
}

.landing-footnote {
    margin-top: 2rem;
    text-align: center;
    font-size: 0.75rem;
    color: var(--text-muted);
    line-height: 1.6;
}

/* ─── Adaptación a móvil ─── */

@media (max-width: 768px) {
    .landing-title { font-size: 1.5rem; }
    .gw-counter-row { grid-template-columns: 1fr; }
    .gw-counter { display: flex; align-items: baseline; justify-content: space-between; padding: 0.7rem 1rem; text-align: left; }
    .gw-counter-value { font-size: 1.375rem; }
    .gw-counter-label { margin-top: 0; }
    .mp-ribbon { right: -52px; padding: 5px 60px; font-size: 0.625rem; }
    /* El chip de conectados no debe empujar los enlaces fuera de la barra en pantallas
       estrechas: se compacta ocultando la etiqueta y conservando punto + número. */
    .online-chip { padding: 5px 9px; }
    .online-chip .online-label { display: none; }
}

/* Icono de un enlace de navegación. Tamaño reducido y línea base normalizada para que
   el emoji no desalinee el texto del enlace ni aumente la altura de la barra. */
/* La separación con el texto la da ahora el `gap` del enlace, y `vertical-align` no
   tiene efecto sobre un elemento de caja flexible: el centrado lo resuelve
   `align-items: center`. Se conserva solo el ajuste de tamaño del icono. */
.nav-links .nav-ico {
    font-size: 0.9em;
    line-height: 1;
}
