diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5e49113 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +# Copiar a .env y ajustar +PORT=3000 +JWT_SECRET=cambia_esto_en_produccion + +# Backend Xtream (Dispatcharr en tu red) +# Ejemplo: http://10.10.10.101:9191 +# En la UI de KiraTV añades una fuente Xtream con la misma URL y usuario/contraseña de Dispatcharr. + +# Opcional: si usas balanceador dedicado solo para /api/transcode, la app debe generar URLs absolutas +# con ese host (requiere cambios en front); por defecto mismo origen vía reverse proxy en 10.10.10.115 diff --git a/package-lock.json b/package-lock.json index 3113d49..97970d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "nodecast-tv", - "version": "2.1.4", + "name": "kiratv", + "version": "2.1.4-kira1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "nodecast-tv", - "version": "2.1.4", + "name": "kiratv", + "version": "2.1.4-kira1", "license": "GPL-3.0-only", "dependencies": { "@ffprobe-installer/ffprobe": "^2.1.2", diff --git a/package.json b/package.json index 6bef281..4b1ff80 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "nodecast-tv", - "version": "2.1.4", - "description": "Modern IPTV Player", + "name": "kiratv", + "version": "2.1.4-kira1", + "description": "KiraTV — reproductor IPTV para el navegador (fork de NodeCast)", "license": "GPL-3.0-only", "main": "server/index.js", "scripts": { diff --git a/public/css/main.css b/public/css/main.css index dedba28..05fa26a 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -1,5 +1,5 @@ /* ===================================================== - * NodeCast TV - Dark Theme Design System + * KiraTV — tema oscuro (azul marino + oro) ===================================================== */ /* CSS Variables */ @@ -7,32 +7,37 @@ /* iOS Safari toolbar compensation (set dynamically by JS) */ --ios-ui-bottom: 0px; + /* Brand — logo hero (marino #000066 / blanco; acento arena para botones) */ + --color-brand-navy: #000066; + --color-brand-navy-mid: #050045; + --color-accent: #e8d5b5; + --color-accent-hover: #f5ead8; + --color-accent-muted: rgba(232, 213, 181, 0.14); + --color-on-accent: #000044; /* Colors */ - --color-bg-primary: #0a0a0f; - --color-bg-secondary: #12121a; - --color-bg-tertiary: #1a1a25; - --color-bg-hover: #22222f; - --color-bg-active: #2a2a3a; + --color-bg-primary: #000022; + --color-bg-secondary: #050038; + --color-bg-tertiary: #0a0a4d; + --color-bg-hover: #12125c; + --color-bg-active: #1a1a72; - --color-accent: #6366f1; - --color-accent-hover: #818cf8; - --color-accent-dim: rgba(99, 102, 241, 0.2); + --color-accent-dim: var(--color-accent-muted); - --color-success: #10b981; - --color-warning: #f59e0b; - --color-error: #ef4444; + --color-success: #34d399; + --color-warning: #fbbf24; + --color-error: #f87171; - --color-text-primary: #f1f1f5; - --color-text-secondary: #a1a1aa; - --color-text-muted: #71717a; + --color-text-primary: #f4f6fb; + --color-text-secondary: #a8b0c4; + --color-text-muted: #6b7389; - --color-border: #27272a; - --color-border-light: #3f3f46; + --color-border: #243047; + --color-border-light: #344062; /* Glass effect */ - --glass-bg: rgba(18, 18, 26, 0.8); - --glass-border: rgba(255, 255, 255, 0.1); + --glass-bg: rgba(0, 0, 102, 0.88); + --glass-border: rgba(255, 255, 255, 0.08); /* Spacing */ --space-xs: 4px; @@ -52,7 +57,7 @@ --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3); --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4); --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5); - --shadow-glow: 0 0 20px rgba(99, 102, 241, 0.3); + --shadow-glow: 0 4px 28px rgba(232, 213, 181, 0.16); /* Transitions */ --transition-fast: 150ms ease; @@ -83,11 +88,14 @@ html, body { height: 100%; - font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + font-family: 'DM Sans', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 14px; line-height: 1.5; color: var(--color-text-primary); - background: var(--color-bg-primary); + background: + radial-gradient(ellipse 120% 85% at 50% -30%, rgba(255, 255, 255, 0.04), transparent 52%), + radial-gradient(ellipse 90% 55% at 100% 35%, rgba(0, 0, 102, 0.45), transparent), + linear-gradient(185deg, var(--color-brand-navy) 0%, var(--color-bg-primary) 55%); overflow: hidden; /* Prevent pull-to-refresh and overscroll bounce on mobile */ overscroll-behavior: none; @@ -137,6 +145,9 @@ h6 { h2 { font-size: 1.5rem; + font-family: 'Montserrat', 'DM Sans', sans-serif; + font-weight: 700; + letter-spacing: -0.02em; } h3 { @@ -168,8 +179,9 @@ h4 { padding-left: max(var(--space-lg), var(--safe-area-inset-left)); padding-right: max(var(--space-lg), var(--safe-area-inset-right)); background: var(--glass-bg); - backdrop-filter: blur(12px); + backdrop-filter: blur(14px); border-bottom: 1px solid var(--glass-border); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06); z-index: 100; } @@ -190,12 +202,24 @@ h4 { fill: var(--color-accent); } +/* Logo imagen de marca (PNG/JPEG) */ +.navbar-logo-img { + display: block; + height: 42px; + width: auto; + max-width: 172px; + object-fit: contain; + object-position: left center; + border-radius: 10px; + box-shadow: 0 2px 14px rgba(0, 0, 0, 0.35); +} + .brand-text { - font-family: 'Century Gothic', sans-serif; - font-size: 1.5rem; - font-weight: 500; - letter-spacing: -0.03em; - color: #fff; + font-family: 'Montserrat', 'DM Sans', sans-serif; + font-size: 1.45rem; + font-weight: 600; + letter-spacing: -0.02em; + color: var(--color-text-primary); /* Visual correction: shift text slightly down to align optically with icon center */ padding-top: 2px; } @@ -207,8 +231,8 @@ h4 { .version-badge { font-size: 0.65rem; font-weight: 600; - background: var(--color-accent); - color: #fff; + background: linear-gradient(135deg, var(--color-accent) 0%, #c9a875 100%); + color: var(--color-on-accent); padding: 2px 6px; border-radius: 10px; margin-left: 8px; @@ -1492,13 +1516,15 @@ kbd { } .btn-primary { - background: var(--color-accent); - color: white; + background: linear-gradient(135deg, var(--color-accent) 0%, #c9a875 100%); + color: var(--color-on-accent); + font-weight: 600; } .btn-primary:hover { - background: var(--color-accent-hover); + background: linear-gradient(135deg, var(--color-accent-hover) 0%, var(--color-accent) 100%); box-shadow: var(--shadow-glow); + color: var(--color-on-accent); } .btn-secondary { @@ -4415,9 +4441,9 @@ kbd { } .user-badge-sso { - background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); - color: #fff; - box-shadow: 0 2px 4px rgba(99, 102, 241, 0.3); + background: linear-gradient(135deg, var(--color-accent) 0%, #c9a875 100%); + color: var(--color-on-accent); + box-shadow: 0 2px 4px rgba(232, 213, 181, 0.22); } .user-badge-local { @@ -4448,24 +4474,24 @@ kbd { gap: 8px; padding: 6px 14px; margin-right: var(--space-md); - background: linear-gradient(135deg, var(--color-accent) 0%, #8b5cf6 100%); + background: linear-gradient(135deg, var(--color-accent) 0%, #c9a875 100%); border-radius: var(--radius-full); - color: white; + color: var(--color-on-accent); text-decoration: none; font-size: 13px; - font-weight: 500; + font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; - box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4); + box-shadow: 0 2px 10px rgba(232, 213, 181, 0.22); transition: transform var(--transition-fast), box-shadow var(--transition-fast); animation: now-playing-pulse 2s ease-in-out infinite; } .now-playing-indicator:hover { transform: scale(1.05); - box-shadow: 0 4px 12px rgba(99, 102, 241, 0.5); + box-shadow: 0 4px 14px rgba(232, 213, 181, 0.28); } .now-playing-indicator.hidden { @@ -4819,4 +4845,45 @@ kbd { font-size: 0.7rem; max-width: 70px; } -} \ No newline at end of file +} +/* Electron Windows: mpv embutido (HWND) — ocultar overlays tras el vídeo nativo */ +body.kiratv-win-embedded #player-controls-overlay, +body.kiratv-win-embedded #watch-overlay { + visibility: hidden !important; +} + +/* WebView2 + panel vídeo Win32 — lista estrecha, reproductor fuera del motor web */ +body.kiratv-shell-wv2:not(.kiratv-shell-wv2-fullweb) #page-live .player-section { display: none !important; } +body.kiratv-shell-wv2:not(.kiratv-shell-wv2-fullweb) #page-live .home-layout { + display: block; +} +body.kiratv-shell-wv2:not(.kiratv-shell-wv2-fullweb) #page-live .channel-sidebar { + width: 100% !important; + max-width: none !important; +} +body.kiratv-shell-wv2-playing #player-controls-overlay, +body.kiratv-shell-wv2-playing #watch-overlay { + visibility: hidden !important; +} + +/* App de escritorio (Electron / WebView2): ancho completo; quita cajas centradas tipo max-width:1400px */ +body.kiratv-desktop-app #app { + max-width: none; + width: 100%; + margin: 0; +} + +body.kiratv-desktop-app .dashboard-content { + max-width: none !important; + width: 100%; + margin-left: 0 !important; + margin-right: 0 !important; +} + +body.kiratv-desktop-app .settings-container { + max-width: none !important; +} + +body.kiratv-desktop-app .watch-details-section { + max-width: none !important; +} diff --git a/public/favicon.svg b/public/favicon.svg index 9ac77a5..e5e1c8e 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1,3 +1,11 @@ - - Live TV + TV en directo - TV Guide + Guía TV - Movies + Películas - Settings + Ajustes @@ -97,7 +92,7 @@