PageSourceSearch

https://nativafmbauru.com.br/

html nativafmbauru.com.br collected 2026-10-02 00:26:22 UTC 284,545 bytes, 6,082 lines download raw bytes

1<!DOCTYPE html>
2<html lang="pt-BR">
3
4<head>
5    <meta charset="UTF-8">
6    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
7        <title>Nativa FM Bauru - A Nativa é tudo e muito mais! — Nativa FM Bauru</title>
8    <meta name="description"  content="A Nativa é tudo e muito mais!">
9    <meta name="keywords" content="radio, online, musica, streaming">
10            <meta name="robots"       content="index, follow">
11    
12        <link rel="canonical" href="https://nativafmbauru.com.br/">
13    
14    <!-- Open Graph (WhatsApp, Facebook, Telegram, LinkedIn, Discord, Teams, iMessage) -->
15    <meta property="og:type"        content="website">
16    <meta property="og:title"       content="Nativa FM Bauru - A Nativa é tudo e muito mais!">
17    <meta property="og:description" content="A Nativa é tudo e muito mais!">
18    <meta property="og:url"         content="https://nativafmbauru.com.br/">
19    <meta property="og:site_name"   content="Nativa FM Bauru">
20    <meta property="og:locale"      content="pt_BR">
21    <meta property="og:image"       content="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
22    <meta property="og:image:secure_url" content="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
23    <meta property="og:image:alt"   content="Nativa FM Bauru - A Nativa é tudo e muito mais!">
24    <meta property="og:image:width"  content="192">
25    <meta property="og:image:height" content="192">
26    <meta property="og:image:type"   content="image/webp">
27    
28    <!-- Twitter / X -->
29    <meta name="twitter:card"        content="summary_large_image">
30    <meta name="twitter:title"       content="Nativa FM Bauru - A Nativa é tudo e muito mais!">
31    <meta name="twitter:description" content="A Nativa é tudo e muito mais!">
32    <meta name="twitter:image"       content="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
33    <meta name="twitter:image:alt"   content="Nativa FM Bauru - A Nativa é tudo e muito mais!">
34
35    <!-- LCP Preload (Logo) com WebP fallback -->
36                    <link rel="preload" as="image" href="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
37    
38    <link rel="stylesheet" href="https://nativafmbauru.com.br/themes/neon/style.css?v=1790900780">
39
40
41    <!-- Custom CSS (Admin) -->
42    
43    <!-- External Fonts (Google Fonts) -->
44    <link rel="preconnect" href="https://fonts.googleapis.com">
45    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
46    <link
47        href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@400;500;700&family=Roboto:ital,wght@0,300;0,400;0,500;0,700;1,400&family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,700;1,9..40,400&display=swap"
48        rel="stylesheet">
49    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
50
51    <!-- Lucide Icons (Ajuste 8 — ícones modernos) -->
52    
52<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js" defer></script>
52
53
54    <!-- Global CSS — Seções e Cookie Banner (Ajustes 6 e 3) -->
55    <link rel="stylesheet" href="https://nativafmbauru.com.br/assets/css/section-header.css?v=1790900780">
56    <link rel="stylesheet" href="https://nativafmbauru.com.br/assets/css/cookie-banner.css?v=1790900780">
57    <!-- Global Slider CSS — carregado para todos os temas -->
58    <link rel="stylesheet" href="https://nativafmbauru.com.br/assets/css/slider.css?v=1784297539">
59    <!-- Top Músicas: marquee de título/artista. Depois do CSS de tema de
60         propósito — precisa vencer o `text-overflow: ellipsis` dos temas. -->
61    <link rel="stylesheet" href="https://nativafmbauru.com.br/assets/css/chart-marquee.css?v=1790785599">
62        <!-- App Rádio 3.0: camada de segurança escopada em html.radio30-app. Carregada
63         sempre, porque a classe também é injetada pelo próprio app — cobre o HTML
64         servido sem a detecção no servidor (cache, service worker). -->
65    <link rel="stylesheet" href="https://nativafmbauru.com.br/assets/css/radio30-app.css?v=1790785599">
66    
67    <!-- Favicon -->
68            <link rel="icon" type="image/png" sizes="32x32" href="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
69        <link rel="shortcut icon" href="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
70    
71    <!-- PWA Meta Tags -->
72    <link rel="manifest" href="/?manifest=1">
73        <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
74    <meta name="theme-color" content="#000000"  media="(prefers-color-scheme: dark)">
75        <meta name="theme-color" content="#ffffff">
76    
77    <meta name="mobile-web-app-capable" content="yes">
78    <meta name="apple-mobile-web-app-capable" content="yes">
79    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
80    <meta name="apple-mobile-web-app-title" content="Nativa FM Bauru">
81
82    <!-- Apple Touch Icons — usa o ícone de Configurações Gerais; PWA como fallback -->
83        <link rel="apple-touch-icon" href="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
84    <link rel="apple-touch-icon" sizes="152x152" href="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
85    <link rel="apple-touch-icon" sizes="180x180" href="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
86    <link rel="apple-touch-icon" sizes="167x167" href="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp">
87    
88    
88<script>
89    const SITE_URL = "https://nativafmbauru.com.br";
90    const STREAM_URL = ""; /* carregado via /api/stream-config.php */
91    const SITE_NAME = "Nativa FM Bauru";
92    const PLAYER_DEFAULT_IMAGE = "https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp";
93</script>
93
94
95<!-- Font Awesome -->
96<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
97<!-- Material Icons + Symbols (Stitch uses Material Symbols Outlined) -->
98<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
99<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,[email protected],0..1&display=swap" rel="stylesheet">
100<!-- Space Grotesk — Fonte principal do design Stitch NEON -->
101<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap" rel="stylesheet">
102
103<link rel="preconnect" href="https://fonts.googleapis.com">
104<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
105<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Poppins:wght@300;400;500;600;700;800&family=Space+Grotesk:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
106    <!-- Dynamic Theme CSS — carregado APÓS o head.php do tema para garantir que o admin sempre prevaleça -->
107    <style>
108        @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
109
110            :root {
111                --primary-color: #7911b0;
112                --secondary-color: #903ff3;
113                --tertiary-color: #e100ff;
114                --accent-color: #ff00ea;
115                --primary-rgb: 121, 17, 176;
116                --secondary-rgb: 144, 63, 243;
117                --tertiary-rgb: 225, 0, 255;
118                --accent-rgb: 255, 0, 234;
119                /* Aliases semânticos */
120                --color-primary: #7911b0;
121                --color-secondary: #903ff3;
122                --color-tertiary: #e100ff;
123            }
124        
125            :root {
126                /* Light Theme - Background Colors */
127                --bg-primary: #ffffff;
128                --bg-primary-rgb: 255, 255, 255;
129                --bg-secondary: #f5f5f7;
130                --bg-secondary-rgb: 245, 245, 247;
131                --bg-tertiary: #e9ecef;
132                --bg-card: #ffffff;
133                --bg-card-rgb: 255, 255, 255;
134                --bg-card-hover: #f8f9fa;
135                --bg-input: #ffffff;
136
137                /* === Header/Nav background (sincronizado com theme_color do PWA) === */
138                --site-header-bg: #ffffff;
139                --header-bg: var(--site-header-bg);
140
141                --glass-bg: rgba(255, 255, 255, 0.95);
142                --glass-border: rgba(0, 0, 0, 0.08);
143                --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
144
145                --text-primary: #1a1a2e;
146                --text-primary-rgb: 26, 26, 46;
147                --text-secondary: #4a4a5a;
148                --text-muted: #6c757d;
149
150                --border-color: rgba(0, 0, 0, 0.08);
151                --border-light: rgba(0, 0, 0, 0.05);
152
153                --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.06);
154                --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.08);
155                --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.1);
156                --shadow-glow: 0 0 30px rgba(121, 17, 176, 0.12);
157
158                --gradient-dark: linear-gradient(180deg, #ffffff 0%, #f5f5f7 100%);
159
160                /* === WAVE Brutalism — Borda/Sombra (Light) === */
161                --brut-border-color: #000000;
162                --brut-border-light: #333333;
163                --brut-shadow-color:  #000000;
164                --brut-shadow-hover:  #000000;
165            }
166            
167            :root {
168                --nav-font-family: 'Inter', sans-serif;
169                --nav-font-size: 14px;
170                --nav-font-weight: normal;
171                --nav-font-style: normal;
172                --nav-color: #111111;
173            }
174        
175                .nav, .nav-link, .header nav, .header .nav-link, nav a,
176                #mainNav a, #mainNav a.nav-link {
177                    font-family: var(--nav-font-family);
178                    font-size: var(--nav-font-size);
179                    font-weight: var(--nav-font-weight);
180                    font-style: var(--nav-font-style);
181                    color: var(--nav-color);
182                }
183            
184            :root {
185                --page-title-font-family: 'Inter', sans-serif;
186                --page-title-font-weight: bold;
187                --page-title-font-style: normal;
188                --page-title-color: #1a1a1a;
189                --page-title-font-size-base: 39px;
190
191                /* Aliases legados — mantém compatibilidade com head.php dos temas */
192                --title-font-family: 'Inter', sans-serif;
193                --title-font-weight: bold;
194                --title-font-style: normal;
195                --title-color: #1a1a1a;
196                --title-font-size-base: 39px;
197            }
198        
199                /* === FONTE DOS TÍTULOS DAS PÁGINAS (somente front-end) === */
200                body h1, body h2, body h3, body h4, body h5, body h6,
201                body .section-title, body .page-title, body .pd-page-hero__title,
202                /* Single pages — títulos principais de página */
203                body .ns-title,
204                body .pr-title,
205                body .ep-title,
206                body .on-air-title,
207                body .page-hero__title {
208                    font-family: var(--page-title-font-family) !important;
209                    font-weight: var(--page-title-font-weight) !important;
210                    font-style: var(--page-title-font-style) !important;
211                    color: var(--page-title-color) !important;
212                }
213                body h1, body .ns-title, body .pr-title, body .ep-title, body .on-air-title, body .page-hero__title { font-size: var(--page-title-font-size-base) !important; }
214                body h2 { font-size: calc(var(--page-title-font-size-base) * 0.85) !important; }
215                body h3 { font-size: calc(var(--page-title-font-size-base) * 0.7) !important; }
216                body h4, body h5, body h6 { font-size: calc(var(--page-title-font-size-base) * 0.6) !important; }
217            
218            :root {
219                --card-title-font-family: 'Inter', sans-serif;
220                --card-title-font-weight: bold;
221                --card-title-font-style: normal;
222                --card-title-color: #222222;
223                --card-title-font-size: 20px;
224            }
225        
226                /* === FONTE DOS CARDS (home + páginas internas + single pages) (somente front-end) === */
227                /* ── Notícias ── */
228                body .hn-card__title, body .hn-hero__title, body .d5-news-card__title,
229                body .d5-news-featured__title, body .s-news-card__title, body .news-title,
230                /* ── Sidebar de notícia single ── */
231                body .ns-sidebar-card-title, body .ns-sidebar-title,
232                body .pulse-sidebar-card-title, body .pulse-sidebar-title,
233                /* ── Eventos ── */
234                body .d5-event-card__title, body .s-event-card__title, body .event-title,
235                /* ── Promoções ── */
236                body .d5-promo-card__title, body .s-promo-card__title, body .promo-title,
237                /* ── Podcasts / Episódios ── */
238                body .pod-card__title, body .sp-title, body .ep-sidebar-title, body .ep-more-title, body .podcast-title,
239                /* ── Programação / Shows ── */
240                body .d5-prog-card__name, body .schedule-name, body .on-air-name, body .spsc-name, body .s-show-card__name,
241                /* ── Equipe ── */
242                body .team-name, body .team-member-name,
243                /* ── Listagens ── */
244                body .s-section-title,
245                /* ── Genéricos ── */
246                body .card-title, body .font-display {
247                    font-family: var(--card-title-font-family) !important;
248                    font-weight: var(--card-title-font-weight) !important;
249                    font-style: var(--card-title-font-style) !important;
250                    color: var(--card-title-color) !important;
251                    font-size: var(--card-title-font-size) !important;
252                }
253            
254            :root {
255                --body-font-family: 'Poppins', sans-serif;
256                --body-font-weight: normal;
257                --body-font-style: normal;
258                --body-font-color: #333333;
259                --body-font-size: 15px;
260            }
261        
262                /* ── Parágrafos e listas genéricas (somente front-end) ── */
263                p:not(.font-preview), li {
264                    font-family: var(--body-font-family) !important;
265                    font-weight: var(--body-font-weight) !important;
266                    font-style: var(--body-font-style) !important;
267                    font-size: var(--body-font-size) !important;
268                    color: var(--body-font-color) !important;
269                }
270
271                /* ── Single de Notícia (ns-*) ── */
272                .ns-body-content, .ns-body-content p, .ns-body-content li, .ns-lead {
273                    font-family: var(--body-font-family) !important;
274                    font-weight: var(--body-font-weight) !important;
275                    font-style: var(--body-font-style) !important;
276                    font-size: var(--body-font-size) !important;
277                    color: var(--body-font-color) !important;
278                }
279
280                /* ── Single de Evento (ev-*) ── */
281                .ev-description, .ev-description p, .ev-description li {
282                    font-family: var(--body-font-family) !important;
283                    font-weight: var(--body-font-weight) !important;
284                    font-style: var(--body-font-style) !important;
285                    font-size: var(--body-font-size) !important;
286                    color: var(--body-font-color) !important;
287                }
288
289                /* ── Single de Promoção (pr-*) ── */
290                .pr-description, .pr-description p, .pr-description li,
291                .pr-rules-body, .pr-rules-body p, .pr-rules-body li {
292                    font-family: var(--body-font-family) !important;
293                    font-weight: var(--body-font-weight) !important;
294                    font-style: var(--body-font-style) !important;
295                    font-size: var(--body-font-size) !important;
296                    color: var(--body-font-color) !important;
297                }
298
299                /* ── Single de Podcast (ep-*) ── */
300                .ep-desc-content, .ep-desc-content p, .ep-desc-content li {
301                    font-family: var(--body-font-family) !important;
302                    font-weight: var(--body-font-weight) !important;
303                    font-style: var(--body-font-style) !important;
304                    font-size: var(--body-font-size) !important;
305                    color: var(--body-font-color) !important;
306                }
307
308                /* ── Page Builder / Páginas dinâmicas ── */
309                .bloco-texto, .bloco-texto p, .bloco-texto li,
310                .pd-compat-text, .pd-compat-rich, .pd-compat-rich p, .pd-compat-rich li,
311                .pd-page-content p, .pd-page-content li {
312                    font-family: var(--body-font-family) !important;
313                    font-weight: var(--body-font-weight) !important;
314                    font-style: var(--body-font-style) !important;
315                    font-size: var(--body-font-size) !important;
316                    color: var(--body-font-color) !important;
317                }
318
319                /* ── Cards e seções da Home ── */
320                .card-description, .card-text, .card-excerpt,
321                .news-excerpt, .news-description,
322                .event-description, .event-excerpt,
323                .team-description, .team-bio,
324                .promo-description, .promotion-description,
325                .podcast-description, .podcast-excerpt,
326                .section-description, .section-text,
327                .about-text, .about-description,
328                .hero-description, .hero-text,
329                .slider-description, .slide-text {
330                    font-family: var(--body-font-family) !important;
331                    font-weight: var(--body-font-weight) !important;
332                    font-style: var(--body-font-style) !important;
333                    font-size: var(--body-font-size) !important;
334                    color: var(--body-font-color) !important;
335                }
336            
337            :root {
338                --player-bg: linear-gradient(135deg, #31004c 0%, #7b15b2 100%);
339                --player-text-color: #ffffff;
340            }
341
342            /* =========================================================
343               GLOBAL PLAYER CONTROLS (SOLID ROUND BUTTONS)
344               ========================================================= */
345            /* Garante herança da cor base do texto no container */
346            #player, .d5-player, .neon-player {
347                color: var(--player-text-color, #ffffff) !important;
348            }
349
350            /* Textos padronizados */
351            #playerArtist, #playerTitle, #playerStatusText, .live-text, .neon-player__title, .neon-player__artist,
352            .d5-player-title, .d5-player-artist {
353                color: var(--player-text-color, #ffffff) !important;
354                -webkit-text-stroke: 0 !important;
355                text-shadow: none !important;
356            }
357            .neon-player__artist, .d5-player-artist {
358                opacity: 0.8 !important;
359            }
360
361            /* 
362               BOTÕES SÓLIDOS (Exemplo Anexo)
363               O fundo do botão herda a Cor dos Elementos.
364               O ícone corta a cor, usando a cor de fundo original do player (ou escala de cinza/preta).
365            */
366            #playBtn, #liveBtn, #videoBtn, #volumeBtn,
367            .d5-play-btn, .neon-player__play-btn, .neon-player__live-btn, .neon-player__vol-btn {
368                background-color: var(--player-text-color, #ffffff) !important;
369                border: none !important;
370                box-shadow: 0 4px 10px rgba(0,0,0,0.15) !important;
371                display: flex !important;
372                align-items: center !important;
373                justify-content: center !important;
374                border-radius: 50% !important; /* Sempre redondo */
375            }
376
377            /* Ajuste de Preenchimento para garantir que todos os botões fiquem proporcionais */
378            #liveBtn, #videoBtn, #volumeBtn, .neon-player__live-btn, .neon-player__vol-btn {
379                width: 36px !important;
380                height: 36px !important;
381                min-width: 36px !important;
382            }
383            #playBtn, .d5-play-btn, .neon-player__play-btn {
384                width: 48px !important;
385                height: 48px !important;
386            }
387
388            /* Ícones dentro dos botões (Cor contrastante) */
389            #playBtn i, #liveBtn i, #volumeBtn i, #videoBtn i, .d5-vol-icon,
390            #playBtn svg, #liveBtn svg, #volumeBtn svg, #videoBtn svg,
391            #svgPlay, #svgPause,
392            .d5-play-btn i, .d5-play-btn svg, .d5-vol-icon svg,
393            .neon-player__play-btn svg, .neon-player__controls button svg, .neon-player__vol-btn svg,
394            .neon-player__controls button i {
395                color: var(--player-bg, #222) !important;
396                fill: var(--player-bg, #222) !important;
397                filter: none !important;
398                -webkit-text-stroke: 0 !important;
399                text-shadow: none !important;
400                /* Adicionando um mixin de preto para garantir contraste na inversão */
401                color: color-mix(in srgb, var(--player-bg, #222) 80%, black) !important;
402                fill: color-mix(in srgb, var(--player-bg, #222) 80%, black) !important;
403            }
404            /* Exceção para o spinner de loading preservar stroke e não ter fill */
405            #svgLoading {
406                color: color-mix(in srgb, var(--player-bg, #222) 80%, black) !important;
407                fill: none !important;
408            }
409
410            /* Remove margens estranhas dos ícones centralizados que alguns SVGs tem por padrão */
411            .neon-player__play-btn svg, .d5-play-btn i {
412                margin: 0 !important;
413                transform: translateX(2px); /* Ajuste visual do triângulo de play ficar centralizado visualmente */
414            }
415            .neon-player__controls button svg {
416                transform: none;
417            }
418
419            /* Trilho do Slider de Volume */
420            .d5-volume-slider, .neon-player__vol-slider {
421                background: color-mix(in srgb, var(--player-text-color, #ffffff) 20%, transparent) !important;
422            }
423
424            /* Controle de Volume: Destaque na bolinha (Thumb) combinando com o botão sólido */
425            #volumeSlider::-webkit-slider-thumb, 
426            .d5-volume-slider::-webkit-slider-thumb,
427            .neon-player__vol-slider::-webkit-slider-thumb {
428                background: var(--player-text-color, #ffffff) !important;
429                box-shadow: 0 2px 5px rgba(0,0,0,0.3) !important;
430                border: none !important;
431            }
432            #volumeSlider::-moz-range-thumb, 
433            .d5-volume-slider::-moz-range-thumb,
434            .neon-player__vol-slider::-moz-range-thumb {
435                background: var(--player-text-color, #ffffff) !important;
436                box-shadow: 0 2px 5px rgba(0,0,0,0.3) !important;
437                border: none !important;
438            }
439
440            /* Elementos secundários (Badges informativos) */
441            #playerArtwork, .d5-player-artwork {
442                background-color: color-mix(in srgb, var(--player-text-color, #ffffff) 10%, transparent) !important;
443                border: 1px solid color-mix(in srgb, var(--player-text-color, #ffffff) 15%, transparent) !important;
444                border-radius: 8px !important;
445            }
446            .live-badge {
447                background-color: color-mix(in srgb, var(--player-text-color, #ffffff) 15%, transparent) !important;
448                border: 1px solid color-mix(in srgb, var(--player-text-color, #ffffff) 30%, transparent) !important;
449                color: var(--player-text-color, #ffffff) !important;
450            }
451            .live-dot, .neon-player__live-dot {
452                background-color: var(--player-text-color, #ffffff) !important;
453            }
454        
455            /* =========================================================
456               PADRONIZAÇÃO TIPOGRÁFICA MOBILE (FIXED SIZES)
457               As definições abaixo forçam tamanhos fixos no mobile,
458               ignorando os tamanhos definidos pelo painel para desktop.
459               Escala baseada em boas práticas para UI Mobile.
460               ========================================================= */
461            @media (max-width: 768px) {
462                :root {
463                    --page-title-font-size-base: 24px !important;
464                    --card-title-font-size: 18px !important;
465                    --body-font-size: 14px !important;
466                    --nav-font-size: 16px !important;
467                }
468
469                /* Título Principal (H1) */
470                body h1, body .ns-title, body .pr-title, body .ep-title, body .on-air-title, body .page-hero__title { 
471                    font-size: 24px !important; 
472                    line-height: 1.4 !important;
473                }
474
475                /* Título Secundário (H2) */
476                body h2, body .section-title { 
477                    font-size: 20px !important; 
478                    line-height: 1.4 !important;
479                }
480
481                /* Título Terciário (H3) / Cards Principais */
482                body h3, 
483                body .hn-card__title, body .hn-hero__title, body .d5-news-card__title,
484                body .d5-news-featured__title, body .s-news-card__title, body .news-title,
485                body .ns-sidebar-card-title, body .ns-sidebar-title,
486                body .pulse-sidebar-card-title, body .pulse-sidebar-title,
487                body .d5-event-card__title, body .s-event-card__title, body .event-title,
488                body .d5-promo-card__title, body .s-promo-card__title, body .promo-title,
489                body .pod-card__title, body .sp-title, body .ep-sidebar-title, body .ep-more-title, body .podcast-title,
490                body .d5-prog-card__name, body .schedule-name, body .on-air-name, body .spsc-name, body .s-show-card__name,
491                body .tea
491m-name, body .team-member-name,
492                body .s-section-title,
493                body .card-title, body .font-display,
494                body .neon-news-header__title {
495                    font-size: 18px !important;
496                    line-height: 1.4 !important;
497                }
498
499                /* Subtítulo (H4-H6 / Nav) */
500                body h4, body h5, body h6,
501                body .nav, body .nav-link, body .header nav, body .header .nav-link, body nav a,
502                body #mainNav a, body #mainNav a.nav-link { 
503                    font-size: 16px !important; 
504                    line-height: 1.4 !important;
505                }
506
507                /* Corpo do Texto (Body) */
508                body p:not(.font-preview), body li,
509                body .ns-body-content, body .ns-body-content p, body .ns-body-content li, body .ns-lead,
510                body .ev-description, body .ev-description p, body .ev-description li,
511                body .pr-description, body .pr-description p, body .pr-description li,
512                body .pr-rules-body, body .pr-rules-body p, body .pr-rules-body li,
513                body .ep-desc-content, body .ep-desc-content p, body .ep-desc-content li,
514                body .bloco-texto, body .bloco-texto p, body .bloco-texto li,
515                body .pd-compat-text, body .pd-compat-rich, body .pd-compat-rich p, body .pd-compat-rich li,
516                body .pd-page-content p, body .pd-page-content li {
517                    font-size: 14px !important;
518                    line-height: 1.6 !important;
519                }
520
521                /* Descrições / Texto Auxiliar */
522                body .card-description, body .card-text, body .card-excerpt,
523                body .news-excerpt, body .news-description,
524                body .event-description, body .event-excerpt,
525                body .team-description, body .team-bio,
526                body .promo-description, body .promotion-description,
527                body .podcast-description, body .podcast-excerpt,
528                body .section-description, body .section-text,
529                body .about-text, body .about-description,
530                body .hero-description, body .hero-text,
531                body .slider-description, body .slide-text,
532                body .neon-slide__desc {
533                    font-size: 12px !important;
534                    line-height: 1.5 !important;
535                }
536
537                /* Legendas / Caption */
538                body figcaption, body .caption, body .date-badge, body .d5-news-date, body .category-badge, 
539                body .neon-news-header__label span, body .neon-news-header__label {
540                    font-size: 11px !important;
541                    line-height: 1.4 !important;
542                }
543            }
544            
545/* === CONTROLE DE TAMANHO DO LOGOTIPO === */
546@media (min-width: 769px) {
547    .site-logo img, .navbar-brand img, .navbar-logo img, header .logo img, nav .logo img, header img[src*='uploads/media'], header img[src*='uploads/logo'], header a[href='./'] > img, .wave-header__logo img, .pulse-header__logo img, .neon-header__logo img, .header-logo img {
548        width: 120px !important;
549        max-width: 100% !important;
550        height: auto !important;
551        object-fit: contain !important;
552        display: block !important;
553        transition: width 0.2s, height 0.2s !important;
554    }
555    header, .site-header, nav.navbar, .navbar, .navbar-inner, .header-inner, .wave-header, .pulse-header, .neon-header {
556        height: auto !important;
557        min-height: 68px !important;
558        padding-top: 16px !important;
559        padding-bottom: 16px !important;
560        display: flex !important;
561        align-items: center !important;
562        box-sizing: border-box !important;
563    }
564}
565@media (max-width: 768px) {
566    .site-logo img, .navbar-brand img, .navbar-logo img, header .logo img, nav .logo img, header img[src*='uploads/media'], header img[src*='uploads/logo'], header a[href='./'] > img, .wave-header__logo img, .pulse-header__logo img, .neon-header__logo img, .header-logo img, #mobileNav img[src*='uploads/media'], #mobileNav img[src*='uploads/logo'], #mobileNav a[href='./'] > img, [data-ag-drawer] img[src*='uploads/media'], [data-ag-drawer] img[src*='uploads/logo'], [data-ag-drawer] a[href='./'] > img, .wave-mobile__logo img, .pulse-mobile__logo img, .neon-mobile__logo img, .mobile-logo img {
567        width: 50px !important;
568        max-width: 100% !important;
569        height: auto !important;
570        object-fit: contain !important;
571        display: block !important;
572        transition: width 0.2s, height 0.2s !important;
573    }
574    header, .site-header, nav.navbar, .navbar, .navbar-inner, .header-inner, .wave-header, .pulse-header, .neon-header {
575        height: auto !important;
576        min-height: 39px !important;
577        padding-top: 12px !important;
578        padding-bottom: 12px !important;
579    }
580}
581.navbar-brand, .site-logo, nav .logo, .wave-header__logo, .pulse-header__logo, .neon-header__logo, .header-logo {
582    display: flex !important;
583    align-items: center !important;
584    overflow: visible !important;
585    flex-shrink: 0 !important;
586    height: auto !important;
587}
588    </style>
589
590    <!-- Google Analytics -->
591        
592    <!-- Google Search Console -->
593        
594    <!-- Código Personalizado — <head> (raw, escopo do tenant; ver /?page=integrations) -->
595        </head>
596
597<body class="theme-light page-home">
598
599
600    <!-- Código Personalizado — início do <body> (raw, escopo do tenant) -->
601        
602    
603<header class="neon-header" id="header">
604    <div class="neon-header__inner">
605        <!-- Logo -->
606        <a href="./" class="neon-header__logo">
607                            <img src="https://nativafmbauru.com.br/uploads/media/6a2974fa436ab_1781101818.png"
608                     alt="Nativa FM Bauru">
609                    </a>
610
611        <!-- Desktop Nav -->
612        <nav class="ag-eic neon-nav ag-eic--neon" id="mainNav" aria-label="Menu principal">
613    <ul class="ag-eic__list">
614                <li class="ag-eic__item is-active">
615                        <a
616                class="ag-eic__link"
617                href="https://nativafmbauru.com.br/"
618                                aria-current="page"                aria-expanded="false"
619                            >
620                <span class="ag-eic__icon"><svg class="ag-eic__icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
620<path d="M4 11 12 4l8 7"/><path d="M6 10v9a1 1 0 0 0 1 1h3v-6h4v6h3a1 1 0 0 0 1-1v-9"/></svg></span>
621                <span class="ag-eic__label-wrap"><span class="ag-eic__label">Home</span></span>
622            </a>
623                    </li>
624                <li class="ag-eic__item">
625                        <a
626                class="ag-eic__link"
627                href="noticias"
628                                                aria-expanded="false"
629                            >
630                <span class="ag-eic__icon"><svg class="ag-eic__icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M7 3h7l4 4v13a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/><path d="M14 3v4h4"/><line x1="8.5" y1="12" x2="15.5" y2="12"/><line x1="8.5" y1="15.5" x2="15.5" y2="15.5"/></svg></span>
631                <span class="ag-eic__label-wrap"><span class="ag-eic__label">Notícias</span></span>
632            </a>
633                    </li>
634                <li class="ag-eic__item">
635                        <a
636                class="ag-eic__link"
637                href="equipe"
638                                                aria-expanded="false"
639                            >
640                <span class="ag-eic__icon"><svg class="ag-eic__icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="9" cy="8" r="3.5"/><path d="M2.5 20a6.5 6.5 0 0 1 13 0"/><circle cx="17" cy="9" r="3"/><path d="M15.5 13.5c2.9.3 5 2.5 5.5 6.3"/></svg></span>
641                <span class="ag-eic__label-wrap"><span class="ag-eic__label">Equipe</span></span>
642            </a>
643                    </li>
644                <li class="ag-eic__item">
645                        <a
646                class="ag-eic__link"
647                href="promocoes"
648                                                aria-expanded="false"
649                            >
650                <span class="ag-eic__icon"><svg class="ag-eic__icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="3" y="8.5" width="18" height="4" rx="1"/><path d="M5 12.5V20a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-7.5"/><line x1="12" y1="8.5" x2="12" y2="21"/><path d="M12 8.5S10.8 3.5 8.4 3.5a2.2 2.2 0 0 0 0 5zM12 8.5s1.2-5 3.6-5a2.2 2.2 0 0 1 0 5z"/></svg></span>
651                <span class="ag-eic__label-wrap"><span class="ag-eic__label">Promoções</span></span>
652            </a>
653                    </li>
654                <li class="ag-eic__item">
655                        <a
656                class="ag-eic__link"
657                href="programacao"
658                                                aria-expanded="false"
659                            >
660                <span class="ag-eic__icon"><svg class="ag-eic__icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M12 7v5.2l3.4 2"/></svg></span>
661                <span class="ag-eic__label-wrap"><span class="ag-eic__label">Programação</span></span>
662            </a>
663                    </li>
664                <li class="ag-eic__item">
665                        <a
666                class="ag-eic__link"
667                href="contato"
668                                                aria-expanded="false"
669                            >
670                <span class="ag-eic__icon"><svg class="ag-eic__icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg></span>
671                <span class="ag-eic__label-wrap"><span class="ag-eic__label">Contato</span></span>
672            </a>
673                    </li>
674            </ul>
675</nav>
676
677<style>
678/* Menu Horizontal Expansível com Ícones — estilos globais (emitidos uma única vez por página) */
679.ag-eic {
680    --ag-eic-radius: 14px;
681    --ag-eic-height: 44px;
682    --ag-eic-gap: 8px;
683    --ag-eic-pad: 14px;
684    --ag-eic-font-size: var(--nav-font-size, 14px);
685    --ag-eic-bg: var(--bg-secondary, #eef0f3);
686    --ag-eic-bg-hover: var(--bg-hover, var(--bg-tertiary, #e2e5ea));
687    --ag-eic-text: var(--text-secondary, #52525b);
688    --ag-eic-text-hover: var(--text-primary, #18181b);
689    --ag-eic-accent: var(--color-primary, var(--primary-color, #2563eb));
690    --ag-eic-bg-active: rgba(37, 99, 235, .12);
691    --ag-eic-bg-active: color-mix(in srgb, var(--ag-eic-accent) 14%, transparent);
692    --ag-eic-border: 0 solid transparent;
693    --ag-eic-shadow: none;
694    max-width: 100%;
695    overflow-x: auto;
696    scrollbar-width: none;
697    -ms-overflow-style: none;
698}
699.ag-eic::-webkit-scrollbar { display: none; }
700
701.ag-eic__list {
702    display: flex;
703    align-items: center;
704    flex-wrap: nowrap;
705    gap: var(--ag-eic-gap);
706    margin: 0;
707    padding: 2px;
708    list-style: none;
709}
710
711.ag-eic__item {
712    position: relative;
713    flex: 0 0 auto;
714}
715
716/* O <a> não carrega `color` de propósito — ver "NOTA DE CASCATA" no topo
717   deste arquivo. Quem pinta é .ag-eic__icon / .ag-eic__label. */
718.ag-eic__link {
719    display: grid;
720    grid-template-columns: auto 0fr;
721    align-items: center;
722    height: var(--ag-eic-height);
723    border: var(--ag-eic-border);
724    border-radius: var(--ag-eic-radius);
725    background: var(--ag-eic-bg);
726    box-shadow: var(--ag-eic-shadow);
727    text-decoration: none;
728    cursor: pointer;
729    -webkit-tap-highlight-color: transparent;
730    transition: grid-template-columns 260ms cubic-bezier(.4, 0, .2, 1),
731                background-color 200ms ease,
732                box-shadow 200ms ease;
733}
734
735.ag-eic__icon {
736    width: calc(var(--ag-eic-height) - 2px);
737    height: 100%;
738    display: flex;
739    align-items: center;
740    justify-content: center;
741    flex-shrink: 0;
742    color: var(--ag-eic-text);
743    transition: color 200ms ease;
744}
745
746.ag-eic__icon-svg {
747    width: 20px;
748    height: 20px;
749}
750
751.ag-eic__label-wrap {
752    min-width: 0;
753    overflow: hidden;
754}
755
756.ag-eic__label {
757    display: block;
758    white-space: nowrap;
759    font-family: var(--nav-font-family, inherit);
760    font-size: var(--ag-eic-font-size);
761    font-weight: 600;
762    line-height: 1;
763    color: var(--ag-eic-text);
764    padding-right: 0;
765    opacity: 0;
766    transform: translateX(-4px);
767    transition: opacity 180ms ease, transform 180ms ease, color 200ms ease,
768                padding-right 260ms cubic-bezier(.4, 0, .2, 1);
769}
770
771/* Expansão no hover — só em dispositivos com mouse/trackpad de fato */
772@media (hover: hover) and (pointer: fine) {
773    .ag-eic__item:hover .ag-eic__link {
774        grid-template-columns: auto 1fr;
775        background: var(--ag-eic-bg-hover);
776    }
777    .ag-eic__item:hover .ag-eic__icon,
778    .ag-eic__item:hover .ag-eic__label {
779        color: var(--ag-eic-text-hover);
780    }
781    .ag-eic__item:hover .ag-eic__label {
782        opacity: 1;
783        transform: none;
784        padding-right: var(--ag-eic-pad);
785    }
786}
787
788/* Expansão por teclado (foco) ou por toque em mobile (classe .is-expanded via JS) */
789.ag-eic__item:focus-within .ag-eic__link,
790.ag-eic__item.is-expanded .ag-eic__link {
791    grid-template-columns: auto 1fr;
792    background: var(--ag-eic-bg-hover);
793}
794.ag-eic__item:focus-within .ag-eic__icon,
795.ag-eic__item:focus-within .ag-eic__label,
796.ag-eic__item.is-expanded .ag-eic__icon,
797.ag-eic__item.is-expanded .ag-eic__label {
798    color: var(--ag-eic-text-hover);
799}
800.ag-eic__item:focus-within .ag-eic__label,
801.ag-eic__item.is-expanded .ag-eic__label {
802    opacity: 1;
803    transform: none;
804    padding-right: var(--ag-eic-pad);
805}
806
807/* Item ativo (página atual) */
808.ag-eic__item.is-active .ag-eic__link {
809    background: var(--ag-eic-bg-active);
810}
811.ag-eic__item.is-active .ag-eic__icon,
812.ag-eic__item.is-active .ag-eic__label {
813    color: var(--ag-eic-accent);
814}
815.ag-eic__item.is-active .ag-eic__link::after {
816    content: '';
817    position: absolute;
818    left: 10px;
819    right: 10px;
820    bottom: 3px;
821    height: 3px;
822    border-radius: 2px;
823    background: var(--ag-eic-accent);
824}
825
826/* Item desabilitado */
827.ag-eic__item.is-disabled .ag-eic__link {
828    opacity: .45;
829    cursor: not-allowed;
830    pointer-events: none;
831}
832
833/* Foco visível no teclado */
834.ag-eic__link:focus-visible {
835    outline: 2px solid var(--ag-eic-accent);
836    outline-offset: 2px;
837}
838
839@media (max-width: 768px) {
840    .ag-eic {
841        --ag-eic-height: 40px;
842        --ag-eic-gap: 6px;
843        --ag-eic-pad: 12px;
844    }
845    .ag-eic__icon-svg {
846        width: 18px;
847        height: 18px;
848    }
849}
850
851@media (prefers-reduced-motion: reduce) {
852    .ag-eic__link,
853    .ag-eic__label,
854    .ag-eic__icon {
855        transition: none !important;
856    }
857}
858</style>
859<script>
860(function () {
861    // Comportamento mínimo: em telas sem hover (touch), o primeiro toque
862    // expande o item e o segundo navega. No desktop tudo é CSS.
863    function hasHover() {
864        return window.matchMedia('(hover: hover) and (pointer: fine)').matches;
865    }
866
867    function collapseAll(except) {
868        document.querySelectorAll('.ag-eic__item.is-expanded').forEach(function (el) {
869            if (el === except) return;
870            el.classList.remove('is-expanded');
871            const link = el.querySelector('.ag-eic__link');
872            if (link) link.setAttribute('aria-expanded', 'false');
873        });
874    }
875
876    document.addEventListener('click', function (e) {
877        const link = e.target.closest('.ag-eic__link');
878        if (link && !hasHover()) {
879            const item = link.closest('.ag-eic__item');
880            if (item && !item.classList.contains('is-expanded')) {
881                e.preventDefault();
882                collapseAll(item);
883                item.classList.add('is-expanded');
884                link.setAttribute('aria-expanded', 'true');
885                return;
886            }
887        }
888        if (!e.target.closest('.ag-eic')) collapseAll(null);
889    });
890
891    document.addEventListener('keydown', function (e) {
892        if (e.key === 'Escape') collapseAll(null);
893    });
894
895    document.addEventListener('focusin', function (e) {
896        const link = e.target.closest('.ag-eic__link');
897        if (link) link.setAttribute('aria-expanded', 'true');
898    });
899
900    document.addEventListener('focusout', function (e) {
901        const link = e.target.closest('.ag-eic__link');
902        const item = link ? link.closest('.ag-eic__item') : null;
903        if (link && item && !item.classList.contains('is-expanded')) {
904            link.setAttribute('aria-expanded', 'false');
905        }
906    });
907
908    /**
909     * Re-sincroniza o item ativo no cliente. Os headers dos temas já marcam
910     * o ativo no PHP; isto cobre bfcache / service worker cache / popstate,
911     * substituindo o que as funções sync*NavActive() faziam com os links de
912     * texto antigos.
913     */
914    window.agEicSyncActive = function () {
915        // NFD decompoe os acentos e o filtro [^a-z0-9-] abaixo ja descarta as
916        // marcas combinantes resultantes -- por isso nao ha replace dedicado
917        // a elas (evita caracteres invisiveis no fonte).
918        const norm = (s) => s.toLowerCase()
919            .normalize('NFD')
920            .replace(/[^a-z0-9-]/g, '');
921
922        const slugFromHref = (href) => {
923            try {
924                const url = new URL(href, window.location.origin);
925                const sp = url.searchParams.get('page');
926                if (sp) return sp;
927                const p = url.pathname.replace(/^\//, '').replace(/\/$/, '');
928                return p ? p.split('/').pop() : 'home';
929            } catch (e) {
930                const s = href.replace(/^\//, '').replace(/\/$/, '');
931                return s || 'home';
932            }
933        };
934
935        const current = norm(window.location.pathname.replace(/^\//, '').replace(/\/$/, '') || 'home');
936
937        document.querySelectorAll('.ag-eic__link[href]').forEach(function (link) {
938            const on = norm(slugFromHref(link.getAttribute('href') || '')) === current;
939            const item = link.closest('.ag-eic__item');
940            if (item) item.classList.toggle('is-active', on);
941            if (on) {
942                link.setAttribute('aria-current', 'page');
943            } else {
944                link.removeAttribute('aria-current');
945            }
946        });
947    };
948
949    window.agEicSyncActive();
950    window.addEventListener('pageshow', function (e) { if (e.persisted) window.agEicSyncActive(); });
951    window.addEventListener('popstate', function () { window.agEicSyncActive(); });
952})();
953</script>
953
954
955        <!-- Right Actions -->
956        <div class="neon-header__actions">
957            <!-- Seletor de Praça (multi-praça; inerte com <2 praças) -->
958            
959            <!-- On Air Widget -->
960            
961            <!-- Search -->
962            <form action="https://nativafmbauru.com.br/" method="GET" class="neon-search" id="neonDesktopSearchForm">
963                <input type="hidden" name="page" value="busca">
964                <button type="submit" class="neon-search__btn">
965                    <!-- Lucide: search -->
966                    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
967                </button>
968                <input type="text" name="q" placeholder="Buscar..." class="neon-search__input" id="neonDesktopSearchInput" autocomplete="off">
969                <div class="neon-search-spinner" style="display: none;">
970                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="spin"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>
971                </div>
972                <!-- Resultado Desktop -->
973                <div class="neon-live-search-results" id="neonDesktopSearchDropdown"></div>
974            </form>
975
976        </div>
977
978        <!-- NEW: Mobile Actions (App Style Spotify) -->
979        <div class="neon-header__mobile-actions">
980            <!-- Mobile Toggle (drawer) -->
981            <button type="button" class="neon-header__mobile-btn neon-header__mobile-action" id="neonMobileBtn" data-ag-drawer-toggle aria-label="Abrir menu" aria-expanded="false" aria-controls="neonMobile">
982                <!-- Lucide: menu -->
983                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>
984            </button>
985                        <a href="https://wa.me/5514997350454" target="_blank" rel="noopener" class="neon-header__mobile-action header-icon-whatsapp" aria-label="WhatsApp" style="display: flex; align-items: center;">
986                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" style="width: 22px; height: 22px; min-width: 22px; min-height: 22px;">
987                    <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
988                </svg>
989            </a>
990                        <button type="button" class="neon-header__mobile-action" onclick="NeonMobileSearch.open()" aria-label="Buscar" style="display: flex; align-items: center;">
991                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width: 22px; height: 22px; min-width: 22px; min-height: 22px;"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
992            </button>
993        </div>
994    </div>
995</header>
996
997<!-- Mobile Expandable Search -->
998<div class="neon-mobile-search-overlay" id="neonMobileSearchOverlay">
999    <div class="neon-mobile-search-dialog">
1000        <div class="neon-mobile-search-topbar">
1001            <h3 class="neon-mobile-search-title">Pesquisar</h3>
1002            <button type="button" class="neon-mobile-search-close" onclick="NeonMobileSearch.close()" aria-label="Fechar Busca">
1003                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
1004            </button>
1005        </div>
1006        <form action="https://nativafmbauru.com.br/" method="GET" class="neon-mobile-search-form" id="neonMobileSearchForm">
1007            <input type="hidden" name="page" value="busca">
1008            <button type="submit" class="neon-mobile-search-submit">
1009                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
1010            </button>
1011            <input type="text" name="q" placeholder="O que você quer ouvir?" class="neon-mobile-search-input" id="neonMobileSearchInput" autocomplete="off">
1012            <div class="neon-search-spinner" id="neonMobileSearchSpinner" style="display: none;">
1013                <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="spin"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>
1014            </div>
1015        </form>
1016        <!-- Resultado Mobile -->
1017        <div class="neon-mobile-live-results" id="neonMobileSearchDropdown"></div>
1018    </div>
1019</div>
1020
1021<!-- Menu Mobile Drawer (partial compartilhado — markup+JS únicos) -->
1022
1023<!-- Backdrop / Overlay do Drawer -->
1024<div class="neon-mobile-overlay" id="neonOverlay" data-ag-drawer-overlay></div>
1025
1026<!-- Drawer / Painel Lateral -->
1027<aside class="neon-mobile" id="neonMobile" data-ag-drawer aria-hidden="true">
1028    <div class="neon-mobile__header">
1029        <div class="neon-mobile__logo">
1030                            <img src="https://nativafmbauru.com.br/uploads/media/6a2974fa436ab_1781101818.png"
1031                     alt="Nativa FM Bauru">
1032                    </div>
1033        <button type="button" class="neon-mobile__close" data-ag-drawer-close aria-label="Fechar menu">
1034            <!-- Lucide: x -->
1035            <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
1036        </button>
1037    </div>
1038
1039    
1040    
1041    <nav class="neon-mobile__nav">
1042                    <a href="https://nativafmbauru.com.br/" data-ag-drawer-link
1043               class="neon-mobile__link neon-mobile__link--active">
1044                Home                <!-- Lucide: chevron-right -->
1045                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewB
1045ox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
1046            </a>
1047                    <a href="noticias" data-ag-drawer-link
1048               class="neon-mobile__link ">
1049                Notícias                <!-- Lucide: chevron-right -->
1050                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
1051            </a>
1052                    <a href="equipe" data-ag-drawer-link
1053               class="neon-mobile__link ">
1054                Equipe                <!-- Lucide: chevron-right -->
1055                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
1056            </a>
1057                    <a href="promocoes" data-ag-drawer-link
1058               class="neon-mobile__link ">
1059                Promoções                <!-- Lucide: chevron-right -->
1060                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
1061            </a>
1062                    <a href="programacao" data-ag-drawer-link
1063               class="neon-mobile__link ">
1064                Programação                <!-- Lucide: chevron-right -->
1065                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
1066            </a>
1067                    <a href="contato" data-ag-drawer-link
1068               class="neon-mobile__link ">
1069                Contato                <!-- Lucide: chevron-right -->
1070                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
1071            </a>
1072            </nav>
1073
1074    <div class="neon-mobile__footer">
1075        <p>Nativa FM Bauru</p>
1076    </div>
1077</aside>
1078
1079<script>
1080/* Controlador ÚNICO do drawer mobile (compartilhado por Pulse/Wave/Neon/Glow).
1081   Como só um tema renderiza por página, há um único [data-ag-drawer]. */
1082(function () {
1083    if (window.AgDrawer) return;
1084
1085    const panel = document.querySelector('[data-ag-drawer]');
1086    if (!panel) return;
1087    const overlay = document.querySelector('[data-ag-drawer-overlay]');
1088    const toggles = document.querySelectorAll('[data-ag-drawer-toggle]');
1089    let lastFocus = null;
1090
1091    const AgDrawer = {
1092        open() {
1093            panel.classList.add('is-open');
1094            if (overlay) overlay.classList.add('is-open');
1095            document.body.style.overflow = 'hidden';
1096            panel.setAttribute('aria-hidden', 'false');
1097            toggles.forEach(t => t.setAttribute('aria-expanded', 'true'));
1098            // Acessibilidade: guarda o foco anterior e move para o botão de fechar.
1099            lastFocus = document.activeElement;
1100            const closeBtn = panel.querySelector('[data-ag-drawer-close]');
1101            if (closeBtn) closeBtn.focus();
1102        },
1103        close() {
1104            panel.classList.remove('is-open');
1105            if (overlay) overlay.classList.remove('is-open');
1106            document.body.style.overflow = '';
1107            panel.setAttribute('aria-hidden', 'true');
1108            toggles.forEach(t => t.setAttribute('aria-expanded', 'false'));
1109            // Devolve o foco a quem abriu o drawer.
1110            if (lastFocus && typeof lastFocus.focus === 'function') lastFocus.focus();
1111        },
1112        toggle() {
1113            panel.classList.contains('is-open') ? this.close() : this.open();
1114        }
1115    };
1116    window.AgDrawer = AgDrawer;
1117
1118    toggles.forEach(t => {
1119        t.setAttribute('aria-expanded', 'false');
1120        t.addEventListener('click', (e) => { e.preventDefault(); AgDrawer.toggle(); });
1121    });
1122    if (overlay) overlay.addEventListener('click', () => AgDrawer.close());
1123    panel.querySelectorAll('[data-ag-drawer-close]').forEach(b => b.addEventListener('click', () => AgDrawer.close()));
1124    panel.querySelectorAll('[data-ag-drawer-link]').forEach(a => a.addEventListener('click', () => AgDrawer.close()));
1125    document.addEventListener('keydown', (e) => {
1126        if (e.key === 'Escape' && panel.classList.contains('is-open')) AgDrawer.close();
1127    });
1128})();
1129</script>
1129
1130
1131<!-- Header spacer removido: #mainContent já tem padding-top:72px via style.css -->
1132
1133<script>
1134// ── Active nav state sync (JS) ──────────────────────────────────────────
1135function syncNeonNavActive() {
1136    const raw = window.location.pathname.replace(/^\//, '').replace(/\/$/, '');
1137    const currentPage = raw || 'home';
1138    const normalizeSlug = (s) => s.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^a-z0-9-]/g, '');
1139    const getSlug = (href) => {
1140        try {
1141            const url = new URL(href, window.location.origin);
1142            const sp = url.searchParams.get('page');
1143            if (sp) return sp;
1144            const p = url.pathname.replace(/^\//, '').replace(/\/$/, '');
1145            return p ? p.split('/').pop() : 'home';
1146        } catch(e) { return href.replace(/^\//, '').replace(/\/$/, '') || 'home'; }
1147    };
1148    const pn = normalizeSlug(currentPage);
1149    // Menu de ícones: o componente mantém o próprio sync (.is-active no <li> +
1150    // aria-current no link). Menu de texto: a lista abaixo fica vazia quando o
1151    // estilo de ícones está ativo, então as duas linhas convivem.
1152    if (typeof window.agEicSyncActive === 'function') window.agEicSyncActive();
1153    document.querySelectorAll('.neon-nav__link').forEach(l => l.classList.toggle('neon-nav__link--active', normalizeSlug(getSlug(l.getAttribute('href')||'')) === pn));
1154    document.querySelectorAll('.neon-mobile__link').forEach(l => l.classList.toggle('neon-mobile__link--active', normalizeSlug(getSlug(l.getAttribute('href')||'')) === pn));
1155}
1156syncNeonNavActive();
1157window.addEventListener('pageshow', (e) => { if (e.persisted) syncNeonNavActive(); });
1158window.addEventListener('popstate', syncNeonNavActive);
1159// ────────────────────────────────────────────────────────────────────────
1160
1161// ESC fecha a busca mobile. O drawer é controlado pelo AgDrawer (partial compartilhado).
1162document.addEventListener('keydown', e => {
1163    if (e.key === 'Escape' && typeof NeonMobileSearch !== 'undefined') NeonMobileSearch.close();
1164});
1165
1166const NeonMobileSearch = {
1167    open() {
1168        document.getElementById('neonMobileSearchOverlay').classList.add('is-active');
1169        document.body.style.overflow = 'hidden';
1170        setTimeout(() => {
1171            const input = document.getElementById('neonMobileSearchInput');
1172            if(input) input.focus();
1173        }, 300);
1174    },
1175    close() {
1176        document.getElementById('neonMobileSearchOverlay').classList.remove('is-active');
1177        document.body.style.overflow = '';
1178    },
1179    toggle() {
1180        document.getElementById('neonMobileSearchOverlay').classList.contains('is-active') ? this.close() : this.open();
1181    }
1182};
1183</script>
1183
1184    <!-- Page Content -->
1185    <div id="mainContent">
1186                
1187<!-- ═══════════ NEON HERO SLIDER ═══════════ -->
1188<section class="neon-slider neon-slider--contained neon-slider--rounded"
1189    style="margin-top:20px;">
1190        <div class="neon-slider__container" style="height:500px;min-height:260px;border-radius:var(--neon-radius-lg, 24px);overflow:hidden;position:relative;">
1191    
1192        <div id="neon-hero-slider" class="neon-slider__track slider-transition-vertical slider-align-left"
1193            style="height:100%;width:100%;border-radius:var(--neon-radius-lg, 24px);">
1194
1195                            <div class="neon-slider__carousel">
1196                                        <div class="neon-slide active"
1197                        style="opacity:1; ">
1198
1199                        <!-- Imagem de fundo -->
1200                        <img alt=""
1201                            class="neon-slide__img"
1202                            src="https://nativafmbauru.com.br/uploads/sliders/6a18a61ad4146_1780000282.webp"
1203                            loading="eager">
1204
1205                        <!-- Overlay gradiente -->
1206                        
1207                        <!-- Conteúdo textual -->
1208                        <div class="neon-slide__content" style="padding-bottom:5rem;">
1209                            
1210                            
1211                                                    </div>
1212                    </div>
1213                                        <div class="neon-slide "
1214                        style="opacity:0; cursor: pointer;" data-slide-link="noticia/radio-liga-sozinho-e-toca-rick-renner-apos-morte-do-cantor-bruno-se-surpreende-nao-tem-explicacao" data-slide-target="_self">
1215
1216                        <!-- Imagem de fundo -->
1217                        <img alt="Rádio liga sozinho e toca Rick &amp; Renner após morte do cantor; Bruno se surpreende: “Não tem explicação”"
1218                            class="neon-slide__img"
1219                            src="https://nativafmbauru.com.br/uploads/rss_6abd3945bc294.png"
1220                            loading="lazy">
1221
1222                        <!-- Overlay gradiente -->
1223                                                    <div class="neon-slide__overlay" style="--ov-r: 0; --ov-g: 0; --ov-b: 0; --ov-a: 0.5; background:linear-gradient(to right, rgba(0,0,0,0.83) 0%, rgba(0,0,0,0.65) 35%, rgba(0,0,0,0.30) 55%, rgba(0,0,0,0) 100%);"></div>
1224                        
1225                        <!-- Conteúdo textual -->
1226                        <div class="neon-slide__content" style="padding-bottom:5rem;">
1227                                                            <h1 style="--sl-title-fs:clamp(1.8rem, 3.5vw, 2.8rem);font-size:clamp(1.8rem, 3.5vw, 2.8rem);color:#ffffff !important;line-height:1.2;font-weight:bold;" class="neon-slide__title">
1228                                    Rádio liga sozinho e toca Rick &amp; Renner após morte do cantor; Bruno se surpreende: “Não tem explicação”                                </h1>
1229                            
1230                                                            <p style="--sl-desc-fs:clamp(0.9rem, 1.4vw, 1.1rem);font-size:clamp(0.9rem, 1.4vw, 1.1rem);color:#ffffff !important;line-height:1.6;" class="neon-slide__desc">
1231                                    Sertanejo contou que aparelho começou a tocar música da dupla sem que ninguém o acionasse e interpretou o episódio como…                                </p>
1232                            
1233                                                    </div>
1234                    </div>
1235                                        <div class="neon-slide "
1236                        style="opacity:0; ">
1237
1238                        <!-- Imagem de fundo -->
1239                        <img alt=""
1240                            class="neon-slide__img"
1241                            src="https://nativafmbauru.com.br/uploads/sliders/6a18a620ee2ff_1780000288.webp"
1242                            loading="lazy">
1243
1244                        <!-- Overlay gradiente -->
1245                        
1246                        <!-- Conteúdo textual -->
1247                        <div class="neon-slide__content" style="padding-bottom:5rem;">
1248                            
1249                            
1250                                                    </div>
1251                    </div>
1252                                        <div class="neon-slide "
1253                        style="opacity:0; cursor: pointer;
1253" data-slide-link="promocao/musica-da-semana" data-slide-target="_self">
1254
1255                        <!-- Imagem de fundo -->
1256                        <img alt="Música da Semana"
1257                            class="neon-slide__img"
1258                            src="https://nativafmbauru.com.br/uploads/media/6a18a95f5c211_1780001119.png"
1259                            loading="lazy">
1260
1261                        <!-- Overlay gradiente -->
1262                        
1263                        <!-- Conteúdo textual -->
1264                        <div class="neon-slide__content" style="padding-bottom:5rem;">
1265                            
1266                            
1267                                                    </div>
1268                    </div>
1269                                        <div class="neon-slide "
1270                        style="opacity:0; cursor: pointer;" data-slide-link="promocao/pix-surpresa-da-nativa-1780000428" data-slide-target="_self">
1271
1272                        <!-- Imagem de fundo -->
1273                        <img alt="PIX surpresa da Nativa"
1274                            class="neon-slide__img"
1275                            src="https://nativafmbauru.com.br/uploads/media/6a18a945650f2_1780001093.png"
1276                            loading="lazy">
1277
1278                        <!-- Overlay gradiente -->
1279                        
1280                        <!-- Conteúdo textual -->
1281                        <div class="neon-slide__content" style="padding-bottom:5rem;">
1282                            
1283                            
1284                                                    </div>
1285                    </div>
1286                                    </div>
1287
1288                <!-- Dots -->
1289                                <div class="neon-slider__dots">
1290                                            <button onclick="neonGoToSlide(0)"
1291                            class="neon-slider__dot active"
1292                            data-slide="0"
1293                            aria-label="Ir para slide 1"></button>
1294                                            <button onclick="neonGoToSlide(1)"
1295                            class="neon-slider__dot "
1296                            data-slide="1"
1297                            aria-label="Ir para slide 2"></button>
1298                                            <button onclick="neonGoToSlide(2)"
1299                            class="neon-slider__dot "
1300                            data-slide="2"
1301                            aria-label="Ir para slide 3"></button>
1302                                            <button onclick="neonGoToSlide(3)"
1303                            class="neon-slider__dot "
1304                            data-slide="3"
1305                            aria-label="Ir para slide 4"></button>
1306                                            <button onclick="neonGoToSlide(4)"
1307                            class="neon-slider__dot "
1308                            data-slide="4"
1309                            aria-label="Ir para slide 5"></button>
1310                                    </div>
1311
1312                <!-- Arrows -->
1313                <div class="neon-slider__arrows">
1314                    <button class="neon-slider__arrow neon-slider__arrow--prev" onclick="neonPrevSlide()" aria-label="Slide anterior">
1315                        <!-- Lucide: chevron-left -->
1316                        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
1317                    </button>
1318                    <button class="neon-slider__arrow neon-slider__arrow--next" onclick="neonNextSlide()" aria-label="Próximo slide">
1319                        <!-- Lucide: chevron-right -->
1320                        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
1321                    </button>
1322                </div>
1323                
1324                    </div>
1325
1326        </div><!-- /.neon-slider__container -->
1327    </section>
1328
1329<!-- ═══════════ NEON SLIDER STYLES ═══════════ -->
1330<style>
1331/* ── Container ── */
1332.neon-slider {
1333    position   : relative;
1334    width      : 100%;
1335    overflow   : hidden;
1336    background : var(--neon-bg-deep, #0e0c20);
1337    margin-top : 20px; /* respiro entre o header e o slider */
1338    margin-bottom: 0;
1339}
1340
1341.neon-slider--contained {
1342    max-width  : var(--container-width, 1280px);
1343    margin     : 20px auto 0;
1344}
1345
1346.neon-slider--rounded,
1347.neon-slider--contained .neon-slider__container {
1348    border-radius: var(--neon-radius-lg, 24px);
1349    overflow: hidden;
1350}
1351
1352.neon-slider__track {
1353    position: relative;
1354    width: 100%;
1355    overflow: hidden;
1356    background: var(--neon-bg-deep, #0e0c20);
1357}
1358
1359.neon-slider__carousel {
1360    position: relative;
1361    width: 100%;
1362    height: 100%;
1363}
1364
1365/* ── Slides ── */
1366.neon-slide {
1367    position: absolute;
1368    inset: 0;
1369    width: 100%;
1370    height: 100%;
1371    transition: opacity 0.8s ease, visibility 0.8s ease;
1372    visibility: hidden;
1373}
1374
1375.neon-slide.active {
1376    opacity: 1 !important;
1377    visibility: visible !important;
1378    z-index: 2;
1379}
1380
1381.neon-slide__img {
1382    position: absolute;
1383    inset: 0;
1384    width: 100%;
1385    height: 100%;
1386    object-fit: cover;
1387    object-position: center;
1388}
1389
1390.neon-slide__overlay {
1391    position: absolute;
1392    inset: 0;
1393    z-index: 1;
1394}
1395
1396/* ── Alinhamento Global de Conteúdo ── */
1397/* Torna o slide um flex-row para poder posicionar o bloco de conteúdo */
1398.slider-align-left  .neon-slide,
1399.slider-align-center .neon-slide,
1400.slider-align-right .neon-slide {
1401    display         : flex;
1402    flex-direction  : row;
1403    align-items     : stretch; /* conteúdo estica 100% da altura */
1404}
1405.slider-align-left   .neon-slide { justify-content: flex-start; }
1406.slider-align-center .neon-slide { justify-content: center; }
1407.slider-align-right  .neon-slide { justify-content: flex-end; }
1408
1409/* Ajustes de texto e espaçamento por alinhamento */
1410.slider-align-left .neon-slide__content {
1411    align-items : flex-start;
1412    text-align  : left;
1413}
1414.slider-align-center .neon-slide__content {
1415    align-items : center;
1416    text-align  : center;
1417    max-width   : 70%;
1418}
1419.slider-align-right .neon-slide__content {
1420    align-items  : flex-end;
1421    text-align   : right;
1422    padding-left : 0;
1423    padding-right: 5rem;
1424}
1425
1426/* ── Content ── */
1427.neon-slide__content {
1428    position      : relative;
1429    z-index       : 3;
1430    display       : flex;
1431    flex-direction: column;
1432    justify-content: center;
1433    height        : 100%;
1434    padding       : 3rem 5rem 8rem !important; /* Maior respiro no bottom (8rem) e laterais (5rem) */
1435    max-width     : 55%;
1436    box-sizing    : border-box;
1437}
1438
1439.neon-slide__title {
1440    font-family: var(--font-family, sans-serif);
1441    font-weight: 700;
1442    margin: 0 0 1rem;
1443    line-height: 1.2;
1444    letter-spacing: -0.01em;
1445}
1446
1447.neon-slide__desc {
1448    font-family: var(--font-family, sans-serif);
1449    font-weight: 400;
1450    margin: 0 0 1.5rem;
1451    max-width: 500px;
1452    opacity: 0.9;
1453}
1454
1455/* ── Tamanho de título/descrição vindos do painel (Aparência Global) ──
1456   Somente desktop (≥769px). O mobile mantém os tamanhos fixos definidos
1457   nos blocos @media (max-width: 767px/768px) e não é afetado aqui.
1458   Especificidade elevada de propósito: o CSS dinâmico de models/Settings.php
1459   gera `body h1 { font-size: ... !important }` (0,0,2) e
1460   `p:not(.font-preview) { font-size: ... !important }` (0,1,1), que venceriam
1461   `.neon-slide__title` (0,1,0) e o font-size inline. */
1462@media (min-width: 769px) {
1463    .neon-slide__content .neon-slide__title {
1464        font-size: var(--sl-title-fs) !important;
1465    }
1466    .neon-slide__content p.neon-slide__desc {
1467        font-size: var(--sl-desc-fs) !important;
1468    }
1469}
1470
1471.neon-slide__cta-wrap {
1472    display: flex;
1473}
1474
1475.neon-slide__cta {
1476    display: inline-flex;
1477    align-items: center;
1478    gap: 8px;
1479    padding: 12px 32px;
1480    background: var(--neon-pink, #ff7cf5);
1481    color: #fff;
1482    font-family: var(--font-family, sans-serif);
1483    font-size: 0.9rem;
1484    font-weight: 600;
1485    text-decoration: none;
1486    border-radius: var(--neon-radius-pill, 9999px);
1487    border: none;
1488    cursor: pointer;
1489    transition: all 0.3s ease;
1490    box-shadow: 0 0 20px rgba(var(--neon-pink-rgb, 255, 124, 245), 0.4);
1491    letter-spacing: 0.02em;
1492}
1493
1494.neon-slide__cta:hover {
1495    background: var(--neon-cyan, #00e3fd);
1496    color: #fff;
1497    transform: translateY(-2px);
1498    box-shadow: 0 0 30px rgba(var(--neon-cyan-rgb, 0, 227, 253), 0.5);
1499}
1500
1501/* ── Dots ── */
1502.neon-slider__dots {
1503    position : absolute;
1504    bottom   : 2rem;     /* Mais próximo da base do slider e afastado do texto */
1505    left     : 50%;
1506    transform: translateX(-50%);
1507    display  : flex;
1508    gap      : 12px;     /* Aumentando levemente o gap para um look mais sofisticado */
1509    z-index  : 10;
1510}
1511
1512.neon-slider__dot {
1513    width: 10px;
1514    height: 10px;
1515    border-radius: 50%;
1516    background: rgba(255, 255, 255, 0.3);
1517    border: none;
1518    cursor: pointer;
1519    transition: all 0.3s ease;
1520    padding: 0;
1521}
1522
1523.neon-slider__dot:hover {
1524    background: rgba(255, 255, 255, 0.6);
1525}
1526
1527.neon-slider__dot.active {
1528    background: var(--neon-pink, #ff7cf5);
1529    width: 28px;
1530    border-radius: 5px;
1531    box-shadow: 0 0 12px rgba(var(--neon-pink-rgb, 255, 124, 245), 0.6);
1532}
1533
1534/* ── Arrows ── */
1535.neon-slider__arrows {
1536    position: absolute;
1537    top: 50%;
1538    transform: translateY(-50%);
1539    width: 100%;
1540    display: flex;
1541    justify-content: space-between;
1542    padding: 0 1rem;
1543    pointer-events: none;
1544    z-index: 10;
1545}
1546
1547.neon-slider__arrow {
1548    width: 48px;
1549    height: 48px;
1550    border-radius: 50%;
1551    background: rgba(var(--neon-pink-rgb, 255, 124, 245), 0.15);
1552    backdrop-filter: blur(12px);
1553    -webkit-backdrop-filter: blur(12px);
1554    border: 1px solid rgba(var(--neon-pink-rgb, 255, 124, 245), 0.3);
1555    color: #fff;
1556    font-size: 1rem;
1557    cursor: pointer;
1558    transition: all 0.3s ease;
1559    pointer-events: auto;
1560    display: flex;
1561    align-items: center;
1562    justify-content: center;
1563}
1564
1565.neon-slider__arrow:hover {
1566    background: var(--neon-pink, #ff7cf5);
1567    border-color: var(--neon-pink, #ff7cf5);
1568    box-shadow: 0 0 20px rgba(var(--neon-pink-rgb, 255, 124, 245), 0.5);
1569}
1570
1571/* ── Empty fallback ── */
1572.neon-slide__empty {
1573    display: flex;
1574    align-items: center;
1575    justify-content: center;
1576    background: radial-gradient(ellipse at 30% 50%,
1577        rgba(var(--neon-pink-rgb, 255, 124, 245), 0.12) 0%, transparent 60%),
1578        var(--neon-bg-deep, #0e0c20);
1579    height: 100%;
1580    min-height: 400px;
1581}
1582
1583/* ── Mobile ── */
1584@media (max-width: 767px) {
1585/* Removido o override fixo .neon-slider, usando .slider-fullscreen / .neon-slider--contained do slider.css global */
1586
1587    /* Centralização vertical correta — garante que a cadeia de altura funcione mesmo quando
1588       o global slider.css resolve o carousel via position:absolute */
1589    .neon-slide__content {
1590        position: absolute !important;
1591        top: 0 !important;
1592        bottom: 0 !important;
1593        left: 0 !important;
1594        right: 0 !important;
1595        height: 100% !important;
1596        max-width: 100% !important;
1597        display: flex !important;
1598        flex-direction: column !important;
1599        justify-content: center !important;
1600        align-items: center !important;
1601        text-align: center !important;
1602        padding: 16px !important;
1603        box-sizing: border-box !important;
1604    }
1605
1606    /* Preservar alinhamento global configurado no painel */
1607    .slider-align-left  .neon-slide__content { align-items: flex-start !important; text-align: left !important; }
1608    .slider-align-center .neon-slide__content { align-items: center !important; text-align: center !important; }
1609    .slider-align-right  .neon-slide__content { align-items: flex-end !important; text-align: right !important; padding-right: 1.5rem !important; }
1610
1611    .neon-slide__desc {
1612        display: none !important;
1613    }
1614
1615    .neon-slide__cta-wrap {
1616        display: none !important;
1617    }
1618
1619    .neon-slide__title {
1620        font-size: 1.1rem !important;
1621        line-height: 1.3 !important;
1622    }
1623
1624    .neon-slider__arrows {
1625        display: none;
1626    }
1627
1628    .neon-slider__dots {
1629        bottom: 12px;
1630    }
1631
1632    .neon-slider__dot {
1633        width: 8px;
1634        height: 8px;
1635    }
1636
1637    .neon-slider__dot.active {
1638        width: 22px;
1639    }
1640}
1641</style>
1642
1643<!-- ═══════════ NEON SLIDER SCRIPT ═══════════ -->
1644<script>
1645(function () {
1646    'use strict';
1647
1648    var NEON_SLIDER = {
1649        currentSlide: 0,
1650        slides: [],
1651        dots: [],
1652        interval: null,
1653        autoplay: true,
1654        speed: 5000,
1655        isPaused: false,
1656        swipedAt: 0,
1657
1658        init: function () {
1659            this.slides = document.querySelectorAll('.neon-slide');
1660            this.dots   = document.querySelectorAll('.neon-slider__dot');
1661
1662            // Antes do early return: a área clicável do slide existe mesmo
1663            // quando há um slide só e não há navegação entre slides.
1664            this.bindSlideLinks();
1665
1666            if (this.slides.length <= 1) return;
1667
1668            var self = this;
1669
1670            // Hover pause
1671            var track = document.getElementById('neon-hero-slider');
1672            if (track) {
1673                track.addEventListener('mouseenter', function () { self.isPaused = true; });
1674                track.addEventListener('mouseleave', function () { self.isPaused = false; });
1675            }
1676
1677            // Touch/swipe
1678            var touchStartX = 0;
1679            if (track) {
1680                track.addEventListener('touchstart', function (e) {
1681                    touchStartX = e.changedTouches[0].screenX;
1682                }, { passive: true });
1683                track.addEventListener('touchend', function (e) {
1684                    var diff = touchStartX - e.changedTouches[0].screenX;
1685                    if (Math.abs(diff) > 50) {
1686                        // Arrastar troca de slide e NÃO conta como clique no slide
1687                        // (o toque ainda gera um 'click' logo depois do 'touchend').
1688                        self.swipedAt = Date.now();
1689                        diff > 0 ? self.next() : self.prev();
1690                    }
1691                }, { passive: true });
1692            }
1693
1694            // Autoplay
1695            if (this.autoplay) {
1696                this.startAutoplay();
1697            }
1698        },
1699
1700        /**
1701         * Clique na área do slide (fora de <a> e <button>) navega pela SPA.
1702         * Navegação dura recarregaria o documento e pararia o player ao vivo.
1703         * Delegado no track, que é recriado a cada render — sem listener órfão.
1704         */
1705        bindSlideLinks: function () {
1706            var self  = this;
1707            var track = document.getElementById('neon-hero-slider');
1708            if (!track || track.getAttribute('data-slide-links-bound') === '1') return;
1709            track.setAttribute('data-slide-links-bound', '1');
1710
1711            track.addEventListener('click', function (e) {
1712                if (e.target.closest('a') || e.target.closest('button')) return;
1713
1714                var slide = e.target.closest('.neon-slide[data-slide-link]');
1715                if (!slide) return;
1716
1717                // Fim de um arraste não é clique.
1718                if (self.swipedAt && Date.now() - self.swipedAt < 500) return;
1719
1720                var url = slide.getAttribute('data-slide-link');
1721                if (!url) return;
1722
1723                var target = slide.getAttribute('data-slide-target');
1724                e.preventDefault();
1725
1726                if (typeof window.spaNavigate === 'function') {
1727                    window.spaNavigate(url, target);
1728                } else if (target === '_blank') {
1729                    window.open(url, '_blank', 'noopener,noreferrer');
1730                } else {
1731                    window.location.href = url;
1732                }
1733            });
1734        },
1735
1736        show: function (index) {
1737            var self = this;
1738            var track = document.getElementById('neon-hero-slider');
1739            var isVertical = track && track.classList.contains('slider-transition-vertical');
1740            var oldSlide = this.currentSlide;
1741
1742            if (isVertical && index !== oldSlide) {
1743                var current = this.slides[oldSlide];
1744                var next = this.slides[index];
1745
1746                // PASSO 1 - Prepara
1747                next.style.transition = 'none';
1748                next.style.transform = 'translateY(100%)';
1749                next.style.opacity = '0';
1750                next.style.visibility = 'visible';
1751                next.style.zIndex = '3';
1752                
1753                current.style.visibility = 'visible';
1754                current.style.zIndex = '2';
1755
1756                // Classes puramente de estado
1757                current.classList.add('is-leaving');
1758                current.classList.remove('active');
1759                next.classList.add('active');
1760                next.classList.remove('is-leaving');
1761
1762                // PASSO 2 - Reflow
1763                next.getBoundingClientRect(); 
1764
1765                // PASSO 3 - Religar transitioes
1766                next.style.transition = 'opacity 600ms ease-in-out, transform 600ms ease-in-out';
1767                current.style.transition = 'opacity 600ms ease-in-out, transform 600ms ease-in-out';
1768
1769                // PASSO 4 - Despachar simultaneamente
1770                requestAnimationFrame(function() {
1771                    next.style.transform = 'translateY(0)';
1772                    next.style.opacity = '1';
1773                    current.style.transform = 'translateY(-100%)';
1774                    current.style.opacity = '0';
1775                });
1776
1777                // PASSO 5 - Cleanup
1778                setTimeout(function() {
1779                    current.style.transition = 'none';
1780                    current.style.transform = 'translateY(100%)';
1781                    current.style.opacity = '0';
1782                    current.style.zIndex = '';
1783                    current.style.visibility = '';
1784                    next.style.zIndex = '';
1785                    next.style.visibility = '';
1786                    current.classList.remove('is-leaving');
1787                }, 620);
1788            } else {
1789                this.slides.forEach(function (s) {
1790                    s.classList.remove('active');
1791                    s.style.opacity = '0';
1792                });
1793                this.slides[index].style.opacity = '1';
1794                this.slides[index].classList.add('active');
1795            }
1796
1797            this.dots.forEach(function (d, i) {
1798                if (i === index) {
1799                    d.classList.add('active');
1800                } else {
1801                    d.classList.remove('active');
1802                }
1803            });
1804
1805            this.currentSlide = index;
1806        },
1807
1808        next: function () {
1809            this.goTo((this.currentSlide + 1) % this.slides.length);
1810        },
1811
1812        prev: function () {
1813            this.goTo((this.currentSlide - 1 + this.slides.length) % this.slides.length);
1814        },
1815
1816        goTo: function (index) {
1817            this.show(index);
1818            if (this.autoplay) {
1819                this.stopAutoplay();
1820                this.startAutoplay();
1821            }
1822        },
1823
1824        startAutoplay: function () {
1825            if (!this.autoplay) return;
1826            this.stopAutoplay();
1827            var self = this;
1828            this.interval = setInterval(function () {
1829                if (!self.isPaused) {
1830                    self.show((self.currentSlide + 1) % self.slides.length);
1831                }
1832            }, this.speed);
1833        },
1834
1835        stopAutoplay: function () {
1836            if (this.interval) {
1837                clearInterval(this.interval);
1838                this.interval = null;
1839            }
1840        }
1841    };
1842
1843    // Global functions for onclick
1844    window.neonGoToSlide = function (i) { NEON_SLIDER.goTo(i); };
1845    window.neonNextSlide = function () { NEON_SLIDER.next(); };
1846    window.neonPrevSlide = function () { NEON_SLIDER.prev(); };
1847
1848    if (document.readyState === 'loading') {
1849        document.addEventListener('DOMContentLoaded', function () { NEON_SLIDER.init(); });
1850    } else {
1851        NEON_SLIDER.init();
1852    }
1853})();
1854</script>
1854
1855
1856
1857<section class="section neon-promo-section ">
1858    <div class="container">
1859        <div class="neon-news-header">
1860            <div class="neon-news-header__bar"></div>
1861            <div class="neon-news-header__text">
1862                <div class="neon-news-header__label">
1863                    <!-- Lucide: gift -->
1864                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 12 20 22 4 22 4 12"/><rect width="22" height="5" x="1" y="7"/><line x1="12" x2="12" y1="22" y2="7"/><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></svg>
1865                    <span>Do seu jeito!</span>
1866                </div>
1867                <h2 class="neon-news-header__title">Promoções</h2>
1868            </div>
1869        </div>
1870
1871        <div class="neon-promo-layout-wrapper">
1872            <div class="neon-promo-grid shelf-row shelf-82">
1873                
1874                    <div class="neon-promo-card">
1875                        <!-- Image -->
1876                        <div class="neon-promo-card__img">
1877                                                            <img src="https://nativafmbauru.com.br/uploads/media/6a18a945650f2_1780001093.png"
1878                                     alt="PIX surpresa da Nativa" loading="lazy">
1879                            
1880                        </div>
1881
1882                        <!-- Body -->
1883                        <div class="neon-promo-card__body">
1884                            <h4 class="neon-promo-card__title">PIX surpresa da Nativa</h4>
1885
1886                                                            <p class="neon-promo-card__desc">Promoção PIX SURPRESA da Nativa
1887
1888O ouvinte deverá mandar uma mensagem de texto para o whatsapp da Promoção da Nativa (...</p>
1889                            
1890                            <!-- Footer: linha separadora + CTA -->
1891                            <hr class="neon-promo-card__divider">
1892                            <div class="neon-promo-card__footer">
1893                                                                    <a href="https://nativafmbauru.com.br/promocao/pix-surpresa-da-nativa-1780000428"
1894                                       class="neon-promo-card__cta neon-promo-card__cta--primary">
1895                                        Participar
1896                                        <!-- Lucide: arrow-right -->
1897                                        <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1898                                    </a>
1899                                                            </div>
1900                        </div>
1901                    </div>
1902                
1903                    <div class="neon-promo-card">
1904                        <!-- Image -->
1905                        <div class="neon-promo-card__img">
1906                                                            <img src="https://nativafmbauru.com.br/uploads/media/6a18a95f5c211_1780001119.png"
1907                                     alt="Música da Semana" loading="lazy">
1908                            
1909                        </div>
1910
1911                        <!-- Body -->
1912                        <div class="neon-promo-card__body">
1913                            <h4 class="neon-promo-card__title">Música da Semana</h4>
1914
1915                                                            <p class="neon-promo-card__desc">Toda semana com um sucesso que vai te dar R$ 500,00, até sexta-feira no programa “A Nativa entrou no grupo”. Envie seu n...</p>
1916                            
1917                            <!-- Footer: linha separadora + CTA -->
1918                            <hr class="neon-promo-card__divider">
1919                            <div class="neon-promo-card__footer">
1920                                                                    <a href="https://nativafmbauru.com.br/promocao/musica-da-semana"
1921                                       class="neon-promo-card__cta neon-promo-card__cta--primary">
1922                                        Participar
1923                                        <!-- Lucide: arrow-right -->
1924                                        <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1925                                    </a>
1926                                                            </div>
1927                        </div>
1928                    </div>
1929                            </div>
1930
1931                    </div>
1932
1933        <!-- Shelf pagination dots (apenas mobile) -->
1934        <div class="shelf-dots"></div>
1935    </div>
1936</section>
1937
1938<!-- Últimas Notícias — Neon Theme -->
1939<section class="neon-news-section">
1940    <div class="container">
1941        <!-- Header Stitch-style -->
1942        <div class="neon-news-header">
1943            <div class="neon-news-header__bar"></div>
1944            <div class="neon-news-header__text">
1945                <div class="neon-news-header__label">
1946                    <!-- Lucide: newspaper -->
1947                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-2 2Zm0 0a2 2 0 0 1-2-2v-9c0-1.1.9-2 2-2h2"/><path d="M18 14h-8"/><path d="M15 18h-5"/><path d="M10 6h8v4h-8V6Z"/></svg>
1948                    <span>Em destaque</span>
1949                </div>
1950                <h2 class="neon-news-header__title">Últimas Notícias</h2>
1951            </div>
1952        </div>
1953
1954                <!-- Tabs de categorias -->
1955        <div class="neon-news-tabs" role="tablist" data-news-tabs="neon">
1956            <button class="neon-news-tab active" data-category="0" role="tab" aria-selected="true">Todas</button>
1957                            <button class="neon-news-tab" data-category="4" role="tab" aria-selected="false">
1958                    Notícias                </button>
1959                    </div>
1960        
1961        
1962        <!-- Layout Wrapper (grid + banner lateral) -->
1963        <div class="neon-news-layout-wrapper">
1964
1965        <!-- News Grid -->
1966        <div id="neon-home-news-grid" class="neon-news-grid shelf-row shelf-72">
1967                            <div class="neon-promo-card neon-news-card-item">
1968                    <!-- Imagem com badge sobrepost no canto superior esquerdo -->
1969                    <div class="neon-promo-card__img">
1970                        <img src="uploads/rss_6abd3945bc294.png"
1971                             alt="Rádio liga sozinho e toca Rick &amp; Renner após morte do cantor; Bruno se surpreende: “Não tem explicação”"
1972                             onerror="this.parentElement.classList.add('no-thumb'); this.remove();" loading="lazy">
1973                                                    <div class="neon-promo-badge neon-promo-badge--primary neon-news-badge">
1974                                <span>Notícias</span>
1975                            </div>
1976                                            </div>
1977
1978                    <!-- Corpo -->
1979                    <div class="neon-promo-card__body">
1980                        <h4 class="neon-promo-card__title">Rádio liga sozinho e toca Rick &amp; Renner após morte do cantor; Bruno se surpreende: “Não tem explicação”</h4>
1981                                                    <p class="neon-promo-card__desc">Sertanejo contou que aparelho começou a tocar música da dupla sem que ninguém o acionasse e interpretou o episódio como...</p>
1982                        
1983                        <hr class="neon-promo-card__divider">
1984                        <div class="neon-promo-card__footer neon-news-card__footer">
1985                                                            <time class="neon-news-card__date" datetime="2026-09-28 16:06:33">
1986                                    28/09/2026                                </time>
1987                                                        <a href="noticia/radio-liga-sozinho-e-toca-rick-renner-apos-morte-do-cantor-bruno-se-surpreende-nao-tem-explicacao"
1988                               class="neon-promo-card__cta neon-promo-card__cta--primary">
1989                                Saiba Mais
1990                                <!-- Lucide: arrow-right -->
1991                                <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1992                            </a>
1993                        </div>
1994                    </div>
1995                </div>
1996                
1997                            <div class="neon-promo-card neon-news-card-item">
1998                    <!-- Imagem com badge sobrepost no canto superior esquerdo -->
1999                    <div class="neon-promo-card__img">
2000                        <img src="uploads/rss_6abd3945c0b48.png"
2001                             alt="Rick, da dupla Rick &amp; Renner, morre aos 59 anos em acidente de helicóptero em Santa Catarina"
2002                             onerror="this.parentElement.classList.add('no-thumb'); this.remove();" loading="lazy">
2003                                                    <div class="neon-promo-badge neon-promo-badge--primary neon-news-badge">
2004                                <span>Notícias</span>
2005                            </div>
2006                                            </div>
2007
2008                    <!-- Corpo -->
2009                    <div class="neon-promo-card__body">
2010                        <h4 class="neon-promo-card__title">Rick, da dupla Rick &amp; Renner, morre aos 59 anos em acidente de helicóptero em Santa Catarina</h4>
2011                                                    <p class="neon-promo-card__desc">Cantor sertanejo estava entre as cinco pessoas que viajavam na aeronave; destroços foram localizados nesta terça-feira...</p>
2012                        
2013                        <hr class="neon-promo-card__divider">
2014                        <div class="neon-promo-card__footer neon-news-card__footer">
2015                                                            <time class="neon-news-card__date" datetime="2026-09-22 15:49:26">
2016                                    22/09/2026                                </time>
2017                                                        <a href="noticia/rick-da-dupla-rick-renner-morre-aos-59-anos-em-acidente-de-helicoptero-em-santa-catarina"
2018                               class="neon-promo-card__cta neon-promo-card__cta--primary">
2019                                Saiba Mais
2020                                <!-- Lucide: arrow-right -->
2021                                <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
2022                            </a>
2023                        </div>
2024                    </div>
2025                </div>
2026                
2027                            <div class="neon-promo-card neon-news-card-item">
2028                    <!-- Imagem com badge sobrepost no canto superior esquerdo -->
2029                    <div class="neon-promo-card__img">
2030                        <img src="uploads/rss_6abd3945c50f1.png"
2031                             alt="‘Só vejo essa menina com roupa de 50 reais’: filha de Neymar, Helena é alvo de comentário polêmico sobre pensão e Amanda Kimberlly rebate. ‘Até a etiqueta…’"
2032                             onerror="this.parentElement.classList.add('no-thumb'); this.remove();" loading="lazy">
2033                                                    <div class="neon-promo-badge neon-promo-badge--primary neon-news-badge">
2034                                <span>Notícias</span>
2035                            </div>
2036                                            </div>
2037
2038                    <!-- Corpo -->
2039                    <div class="neon-promo-card__body">
2040                        <h4 class="neon-promo-card__title">‘Só vejo essa menina com roupa de 50 reais’: filha de Neymar, Helena é alvo de comentário polêmico sobre pensão e Amanda Kimberlly rebate. ‘Até a etiqueta…’</h4>
2041                                                    <p class="neon-promo-card__desc">Influenciadora usou o bom humor para responder seguidora que questionou os looks e a pensão da pequena Helena. Amanda...</p>
2042                        
2043                        <hr class="neon-promo-card__divider">
2044                        <div class="neon-promo-card__footer neon-news-card__footer">
2045                                                            <time class="neon-news-card__date" datetime="2026-08-25 15:45:43">
2046                                    25/08/2026                                </time>
2047                                                        <a href="noticia/so-vejo-essa-menina-com-roupa-de-50-reais-filha-de-neymar-helena-e-alvo-de-comentario-polemico-sobre-pensao-e-amanda-kimberlly-rebate-ate-a-etiqueta"
2048                               class="neon-promo-card__cta neon-promo-card__cta--primary">
2049                                Saiba Mais
2050                                <!-- Lucide: arrow-right -->
2051                                <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
2052                            </a>
2053                        </div>
2054                    </div>
2055                </div>
2056                
2057                    </div>
2058
2059                </div><!-- /.neon-news-layout-wrapper -->
2060        
2061        <div class="neon-news-more">
2062            <a href="noticias" class="neon-news-more__btn">
2063                <i class="fas fa-newspaper"></i>
2064                Ver outras notícias
2065            </a>
2066        </div>
2067
2068        <div class="shelf-dots"></div>
2069    </div>
2070</section>
2071
2072<script>
2073(function () {
2074    const grid = document.getElementById('neon-home-news-grid');
2075    const tabs = document.querySelectorAll('[data-news-tabs="neon"] .neon-news-tab');
2076    const limit = 3;
2077
2078    if (!grid || !tabs.length) return;
2079
2080    function esc(str) {
2081        if (!str) return '';
2082        const d = document.createElement('div');
2083        d.textContent = str;
2084        return d.innerHTML;
2085    }
2086
2087    function truncate(str, max) {
2088        if (!str) return '';
2089        str = str.replace(/<[^>]*>/g, '');
2090        return str.length > max ? str.slice(0, max) + '...' : str;
2091    }
2092
2093    function fmtDate(dateStr) {
2094        if (!dateStr) return '';
2095        return new Date(dateStr).toLocaleDateString('pt-BR');
2096    }
2097
2098    const svgArrow = '<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>';
2099
2100    function buildCard(news, idx) {
2101        const excerpt = esc(truncate(news.summary || news.content, 120));
2102        const imgSrc = news.featured_image ? SITE_URL + '/uploads/' + news.featured_image : '';
2103        const slug = esc(news.slug || String(news.id));
2104
2105        return `<div class="neon-promo-card neon-news-card-item">
2106            <div class="neon-promo-card__img">
2107                ${imgSrc ? `<img src="${esc(imgSrc)}" alt="${esc(news.title)}" onerror="this.parentElement.classList.add('no-thumb');this.remove();" loading="lazy">` : ''}
2108                ${news.category_name ? `<div class="neon-promo-badge neon-promo-badge--primary neon-news-badge"><span>${esc(news.category_name)}</span></div>` : ''}
2109            </div>
2110            <div class="neon-promo-card__body">
2111                <h4 class="neon-promo-card__title">${esc(news.title)}</h4>
2112                ${excerpt ? `<p class="neon-promo-card__desc">${excerpt}</p>` : ''}
2113                <hr class="neon-promo-card__divider">
2114                <div class="neon-promo-card__footer neon-news-card__footer">
2115                    ${news.published_at ? `<time class="neon-news-card__date" datetime="${esc(news.published_at)}">${fmtDate(news.published_at)}</time>` : ''}
2116                    <a href="noticia/${slug}" class="neon-promo-card__cta neon-promo-card__cta--primary">Saiba Mais ${svgArrow}</a>
2117                </div>
2118            </div>
2119        </div>`;
2120    }
2121
2122    tabs.forEach(function (tab) {
2123        tab.addEventListener('click', function () {
2124            const categoryId = parseInt(this.dataset.category) || 0;
2125
2126            tabs.forEach(function (t) {
2127                t.classList.remove('active');
2128                t.setAttribute('aria-selected', 'false');
2129            });
2130            this.classList.add('active');
2131            this.setAttribute('aria-selected', 'true');
2132
2133            grid.classList.add('neon-news-grid--loading');
2134
2135            let url = SITE_URL + '/api/news.php?limit=' + limit + '&page=1';
2136            if (categoryId > 0) url += '&category=' + categoryId;
2137
2138            fetch(url)
2139                .then(function (r) { return r.json(); })
2140                .then(function (data) {
2141                    grid.classList.remove('neon-news-grid--loading');
2142                    grid.innerHTML = '';
2143                    if (data.news && data.news.length > 0) {
2144                        data.news.forEach(function (item, idx) {
2145                            grid.insertAdjacentHTML('beforeend', buildCard(item, idx));
2146                        });
2147                    } else {
2148                        grid.innerHTML = '<p class="neon-news-empty">Nenhuma notícia encontrada nesta categoria.</p>';
2149                    }
2150                })
2151                .catch(function () {
2152                    grid.classList.remove('neon-news-grid--loading');
2153                });
2154        });
2155    });
2156})();
2157</script>
2157
2158
2159
2160<!-- Top Músicas — Neon Theme -->
2161<section class="neon-chart-section">
2162    <div class="container">
2163        <!-- Header: Stitch-style (gradient bar + fire icon) -->
2164        <div class="neon-chart-header" style="display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 2rem;">
2165            <div class="neon-news-header" style="margin-bottom: 0;">
2166                <div class="neon-news-header__bar"></div>
2167                <div class="neon-news-header__text">
2168                    <div class="neon-news-header__label">
2169                        <span class="material-symbols-outlined" style="font-size:14px; font-variation-settings: 'FILL' 1">local_fire_department</span>
2170                        <span>As mais tocadas </span>
2171                    </div>
2172                    <h2 class="neon-news-header__title">Top Músicas</h2>
2173                </div>
2174            </div>
2175                        <a href="paradas" class="neon-chart-header__cta">
2176                Ver Todas → <span class="material-symbols-outlined" style="font-size:16px">arrow_forward</span>
2177            </a>
2178                    </div>
2179
2180        <!-- Grid 2 colunas + banner lateral -->
2181        <div class="neon-chart-layout-wrapper">
2182        <div class="neon-chart-grid" id="chart-list">
2183                        <div class="neon-chart-track neon-chart-track--pink" id="track-0"
2184                 data-track-id="28"
2185                 onclick="toggleChartTrack(0)">
2186
2187                <!-- Row: Rank + Cover + Info + Votes -->
2188                <div class="neon-chart-track__row">
2189                    <!-- Rank number -->
2190                    <span class="neon-chart-track__rank">01</span>
2191
2192                    <!-- Cover art -->
2193                    <div class="neon-chart-track__cover"
2194                         >
2195                        <img class="neon-chart-track__cover-img" id="img-0"
2196                             src="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/3b/d8/a6/3bd8a697-f495-6018-689f-e9b505278bf5/196874116920.jpg/600x600bb.jpg"
2197                             alt="Retrovisor"
2198                             onerror="this.src='https://nativafmbauru.com.br/assets/img/default-cover.svg'">
2199                                                <button class="neon-chart-track__play-overlay" id="play-btn-0"
2200                                data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/8b/38/00/8b3800d0-e962-9f5b-a806-dc2588e54da6/mzaf_576454498965197282.plus.aac.p.m4a"
2201                                onclick="event.stopPropagation(); playChartTrack(0)">
2202                            <span class="material-symbols-outlined" id="play-icon-0" style="font-size:22px; font-variation-settings:'FILL' 1">play_arrow</span>
2203                        </button>
2204                                            </div>
2205
2206                    <!-- Title + Artist -->
2207                    <div class="neon-chart-track__info">
2208                        <p class="neon-chart-track__title">Retrovisor</p>
2209                        <p class="neon-chart-track__artist">Gusttavo Lima</p>
2210                    </div>
2211
2212                    <!-- Vote buttons -->
2213                                        <div class="neon-chart-track__votes">
2214                        <button class="neon-vote-btn neon-vote-up" id="like-0"
2215                                onclick="event.stopPropagation(); vote(0, 'like')" title="Curtir">
2216                            <span class="material-symbols-outlined" style="font-size:18px">thumb_up</span>
2217                        </button>
2218                        <span class="neon-vote-count" id="vote-count-0">
2219                            36                        </span>
2220                        <button class="neon-vote-btn neon-vote-down" id="dislike-0"
2221                                onclick="event.stopPropagation(); vote(0, 'dislike')" title="Não curtir">
2222                            <span class="material-symbols-outlined" style="font-size:18px">thumb_down</span>
2223                        </button>
2224                    </div>
2225                                    </div><!-- /.neon-chart-track__row -->
2226
2227                <!-- Inline player (hidden, shown on click) -->
2228                <div class="neon-inline-player" id="player-ui-0"
2229                     data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/8b/38/00/8b3800d0-e962-9f5b-a806-dc2588e54da6/mzaf_576454498965197282.plus.aac.p.m4a"
2230                     data-title="Retrovisor"
2231                     data-artist="Gusttavo Lima"
2232                     data-cover="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/3b/d8/a6/3bd8a697-f495-6018-689f-e9b505278bf5/196874116920.jpg/600x600bb.jpg"
2233                                          style="display:none;">
2234                    <button class="neon-inline-player__btn" id="pplay-0"
2235                            data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/8b/38/00/8b3800d0-e962-9f5b-a806-dc2588e54da6/mzaf_576454498965197282.plus.aac.p.m4a"
2236                            onclick="event.stopPropagation(); playChartTrack(0)">
2237                        <span class="material-symbols-outlined" style="font-size:18px; font-variation-settings:'FILL' 1">play_arrow</span>
2238                    </button>
2239                    <div style="flex:1; min-width:0;">
2240                        <div class="neon-inline-player__bar" onclick="seekTrack(event,0)">
2241                            <div class="neon-inline-player__progress" id="progress-bar-0"></div>
2242                        </div>
2243                        <div class="neon-inline-player__times">
2244                            <span id="current-time-0">0:00</span>
2245                            <span id="total-time-0">--:--</span>
2246                        </div>
2247                    </div>
2248                </div><!-- /.neon-inline-player -->
2249
2250            </div><!-- /.neon-chart-track -->
2251                        <div class="neon-chart-track neon-chart-track--cyan" id="track-1"
2252                 data-track-id="30"
2253                 onclick="toggleChartTrack(1)">
2254
2255                <!-- Row: Rank + Cover + Info + Votes -->
2256                <div class="neon-chart-track__row">
2257                    <!-- Rank number -->
2258                    <span class="neon-chart-track__rank">02</span>
2259
2260                    <!-- Cover art -->
2261                    <div class="neon-chart-track__cover"
2262                         >
2263                        <img class="neon-chart-track__cover-img" id="img-1"
2264                             src="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/3d/06/16/3d0616e9-7841-e64f-01f0-a60a98ce11c7/25UMGIM33948.rgb.jpg/600x600bb.jpg"
2265                             alt="Saudade Proibida (Ao Vivo)"
2266                             onerror="this.src='https://nativafmbauru.com.br/assets/img/default-cover.svg'">
2267                                                <button class="neon-chart-track__play-overlay" id="play-btn-1"
2268                                data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/27/81/07/2781075e-c6a3-1008-e078-14d68f5b02a9/mzaf_2490608400725389767.plus.aac.p.m4a"
2269                                onclick="event.stopPropagation(); playChartTrack(1)">
2270                            <span class="material-symbols-outlined" id="play-icon-1" style="font-size:22px; font-variation-settings:'FILL' 1">play_arrow</span>
2271                        </button>
2272                                            </div>
2273
2274                    <!-- Title + Artist -->
2275                    <div class="neon-chart-track__info">
2276                        <p class="neon-chart-track__title">Saudade Proibida (Ao Vivo)</p>
2277                        <p class="neon-chart-track__artist">Simone Mendes</p>
2278                    </div>
2279
2280                    <!-- Vote buttons -->
2281                                        <div class="neon-chart-track__votes">
2282                        <button class="neon-vote-btn neon-vote-up" id="like-1"
2283                                onclick="event.stopPropagation(); vote(1, 'like')" title="Curtir">
2284                            <span class="material-symbols-outlined" style="font-size:18px">thumb_up</span>
2285                        </button>
2286                        <span class="neon-vote-count" id="vote-count-1">
2287                            29                        </span>
2288                        <button class="neon-vote-btn neon-vote-down" id="dislike-1"
2289                                onclick="event.stopPropagation(); vote(1, 'dislike')" title="Não curtir">
2290                            <span class="material-symbols-outlined" style="font-size:18px">thumb_down</span>
2291                        </button>
2292                    </div>
2293                                    </div><!-- /.neon-chart-track__row -->
2294
2295                <!-- Inline player (hidden, shown on click) -->
2296                <div class="neon-inline-player" id="player-ui-1"
2297                     data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/27/81/07/2781075e-c6a3-1008-e078-14d68f5b02a9/mzaf_2490608400725389767.plus.aac.p.m4a"
2298                     data-title="Saudade Proibida (Ao Vivo)"
2299                     data-artist="Simone Mendes"
2300                     data-cover="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/3d/06/16/3d0616e9-7841-e64f-01f0-a60a98ce11c7/25UMGIM33948.rgb.jpg/600x600bb.jpg"
2301                                          style="display:none;">
2302                    <button class="neon-inline-player__btn" id="pplay-1"
2303                            data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/27/81/07/2781075e-c6a3-1008-e078-14d68f5b02a9/mzaf_2490608400725389767.plus.aac.p.m4a"
2304                            onclick="event.stopPropagation(); playChartTrack(1)">
2305                        <span class="material-symbols-outlined" style="font-size:18px; font-variation-settings:'FILL' 1">play_arrow</span>
2306                    </button>
2307                    <div style="flex:1; min-width:0;">
2308                        <div class="neon-inline-player__bar" onclick="seekTrack(event,1)">
2309                            <div class="neon-inline-player__progress" id="progress-bar-1"></div>
2310                        </div>
2311                        <div class="neon-inline-player__times">
2312                            <span id="current-time-1">0:00</span>
2313                            <span id="total-time-1">--:--</span>
2314                        </div>
2315                    </div>
2316                </div><!-- /.neon-inline-player -->
2317
2318            </div><!-- /.neon-chart-track -->
2319                        <div class="neon-chart-track neon-chart-track--pink" id="track-2"
2320                 data-track-id="29"
2321                 onclick="toggleChartTrack(2)">
2322
2323                <!-- Row: Rank + Cover + Info + Votes -->
2324                <div class="neon-chart-track__row">
2325                    <!-- Rank number -->
2326                    <span class="neon-chart-track__rank">03</span>
2327
2328                    <!-- Cover art -->
2329                    <div class="neon-chart-track__cover"
2330                         >
2331                        <img class="neon-chart-track__cover-img" id="img-2"
2332                             src="https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/f4/74/7b/f4747b8e-2913-e3eb-fe21-7b1f2823c52f/196874366028.jpg/600x600bb.jpg"
2333                             alt="Cadeira Cativa (Ao Vivo)"
2334                             onerror="this.src='https://nativafmbauru.com.br/assets/img/default-cover.svg'">
2335                                                <button class="neon-chart-track__play-overlay" id="play-btn-2"
2336                                data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/27/05/4b/27054b7a-c17f-b0c6-c6fc-c4417dfba626/mzaf_9835988559387151635.plus.aac.p.m4a"
2337                                onclick="event.stopPropagation(); playChartTrack(2)">
2338                            <span class="material-symbols-outlined" id="play-icon-2" style="font-size:22px; font-variation-settings:'FILL' 1">play_arrow</span>
2339                        </button>
2340                                            </div>
2341
2342                    <!-- Title + Artist -->
2343                    <div class="neon-chart-track__info">
2344                        <p class="neon-chart-track__title">Cadeira Cativa (Ao Vivo)</p>
2345                        <p class="neon-chart-track__artist">Zé Neto &amp; Cristiano</p>
2346                    </div>
2347
2348                    <!-- Vote buttons -->
2349                                        <div class="neon-chart-track__votes">
2350                        <button class="neon-vote-btn neon-vote-up" id="like-2"
2351                                onclick="event.stopPropagation(); vote(2, 'like')" title="Curtir">
2352                            <span class="material-symbols-outlined" style="font-size:18px">thumb_up</span>
2353                        </button>
2354                        <span class="neon-vote-count" id="vote-count-2">
2355                            21                        </span>
2356                        <button class="neon-vote-btn neon-vote-down" id="dislike-2"
2357                                onclick="event.stopPropagation(); vote(2, 'dislike')" title="Não curtir">
2358                            <span class="material-symbols-outlined" style="font-size:18px">thumb_down</span>
2359                        </button>
2360                    </div>
2361                                    </div><!-- /.neon-chart-track__row -->
2362
2363                <!-- Inline player (hidden, shown on click) -->
2364                <div class="neon-inline-player" id="player-ui-2"
2365                     data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/27/05/4b/27054b7a-c17f-b0c6-c6fc-c4417dfba626/mzaf_9835988559387151635.plus.aac.p.m4a"
2366                     data-title="Cadeira Cativa (Ao Vivo)"
2367                     data-artist="Zé Neto &amp; Cristiano"
2368                     data-cover="https://is1-ssl.mzstatic.com/image/thumb/Music221/v4/f4/74/7b/f4747b8e-2913-e3eb-fe21-7b1f2823c52f/196874366028.jpg/600x600bb.jpg"
2369                                          style="display:none;">
2370                    <button class="neon-inline-player__btn" id="pplay-2"
2371                            data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/27/05/4b/27054b7a-c17f-b0c6-c6fc-c4417dfba626/mzaf_9835988559387151635.plus.aac.p.m4a"
2372                            onclick="event.stopPropagation(); playChartTrack(2)">
2373                        <span class="material-symbols-outlined" style="font-size:18px; font-variation-settings:'FILL' 1">play_arrow</span>
2374                    </button>
2375                    <div style="flex:1; min-width:0;">
2376                        <div class="neon-inline-player__bar" onclick="seekTrack(event,2)">
2377                            <div class="neon-inline-player__progress" id="progress-bar-2"></div>
2378                        </div>
2379                        <div class="neon-inline-player__times">
2380                            <span id="current-time-2">0:00</span>
2381                            <span id="total-time-2">--:--</span>
2382                        </div>
2383                    </div>
2384                </div><!-- /.neon-inline-player -->
2385
2386            </div><!-- /.neon-chart-track -->
2387                        <div class="neon-chart-track neon-chart-track--cyan" id="track-3"
2388                 data-track-id="31"
2389                 onclick="toggleChartTrack(3)">
2390
2391                <!-- Row: Rank + Cover + Info + Votes -->
2392                <div class="neon-chart-track__row">
2393                    <!-- Rank number -->
2394                    <span class="neon-chart-track__rank">04</span>
2395
2396                    <!-- Cover art -->
2397                    <div class="neon-chart-track__cover"
2398                         >
2399                        <img class="neon-chart-track__cover-img" id="img-3"
2400                             src="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/54/20/ff/5420ff9a-e8d3-4546-fc1a-99d8cae88062/26UMGIM45423.rgb.jpg/600x600bb.jpg"
2401                             alt="Estranho De Novo (Ao Vivo)"
2402                             onerror="this.src='https://nativafmbauru.com.br/assets/img/default-cover.svg'">
2403                                                <button class="neon-chart-track__play-overlay" id="play-btn-3"
2404                                data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/07/1e/c3/071ec3f0-40ee-3947-9e5f-64aa8786c6ca/mzaf_9100846059423630688.plus.aac.p.m4a"
2405                                onclick="event.stopPropagation(); playChartTrack(3)">
2406                            <span class="material-symbols-outlined" id="play-icon-3" style="font-size:22px; font-variation-settings:'FILL' 1">play_arrow</span>
2407                        </button>
2408                                            </div>
2409
2410                    <!-- Title + Artist -->
2411                    <div class="neon-chart-track__info">
2412                        <p class="neon-chart-track__title">Estranho De Novo (Ao Vivo)</p>
2413                        <p class="neon-chart-track__artist">Felipe Araújo</p>
2414                    </div>
2415
2416                    <!-- Vote buttons -->
2417                                        <div class="neon-chart-track__votes">
2418                        <button class="neon-vote-btn neon-vote-up" id="like-3"
2419                                onclick="event.stopPropagation(); vote(3, 'like')" title="Curtir">
2420                            <span class="material-symbols-outlined" style="font-size:18px">thumb_up</span>
2421                        </button>
2422                        <span class="neon-vote-count" id="vote-count-3">
2423                            11                        </span>
2424                        <button class="neon-vote-btn neon-vote-down" id="dislike-3"
2425                                onclick="event.stopPropagation(); vote(3, 'dislike')" title="Não curtir">
2426                            <span class="material-symbols-outlined" style="font-size:18px">thumb_down</span>
2427                        </button>
2428                    </div>
2429                                    </div><!-- /.neon-chart-track__row -->
2430
2431                <!-- Inline player (hidden, shown on click) -->
2432                <div class="neon-inline-player" id="player-ui-3"
2433                     data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/07/1e/c3/071ec3f0-40ee-3947-9e5f-64aa8786c6ca/mzaf_9100846059423630688.plus.aac.p.m4a"
2434                     data-title="Estranho De Novo (Ao Vivo)"
2435                     data-artist="Felipe Araújo"
2436                     data-cover="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/54/20/ff/5420ff9a-e8d3-4546-fc1a-99d8cae88062/26UMGIM45423.rgb.jpg/600x600bb.jpg"
2437                                          style="display:none;">
2438                    <button class="neon-inline-player__btn" id="pplay-3"
2439                            data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/07/1e/c3/071ec3f0-40ee-3947-9e5f-64aa8786c6ca/mzaf_9100846059423630688.plus.aac.p.m4a"
2440                            onclick="event.stopPropagation(); playChartTrack(3)">
2441                        <span class="material-symbols-outlined" style="font-size:18px; font-variation-settings:'FILL' 1">play_arrow</span>
2442                    </button>
2443                    <div style="flex:1; min-width:0;">
2444                        <div class="neon-inline-player__bar" onclick="seekTrack(event,3)">
2445                            <div class="neon-inline-player__progress" id="progress-bar-3"></div>
2446                        </div>
2447                        <div class="neon-inline-player__times">
2448                            <span id="current-time-3">0:00</span>
2449                            <span id="total-time-3">--:--</span>
2450                        </div>
2451                    </div>
2452                </div><!-- /.neon-inline-player -->
2453
2454            </div><!-- /.neon-chart-track -->
2455                        <div class="neon-chart-track neon-chart-track--pink" id="track-4"
2456                 data-track-id="32"
2457                 onclick="toggleChartTrack(4)">
2458
2459                <!-- Row: Rank + Cover + Info + Votes -->
2460                <div class="neon-chart-track__row">
2461                    <!-- Rank number -->
2462                    <span class="neon-chart-track__rank">05</span>
2463
2464                    <!-- Cover art -->
2465                    <div class="neon-chart-track__cover"
2466                         >
2467                        <img class="neon-chart-track__cover-img" id="img-4"
2468                             src="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/b3/cf/da/b3cfdac4-2fc7-31da-4d5e-f716cc978868/196873612935.jpg/600x600bb.jpg"
2469                             alt="OLHO MARROM - Ao Vivo em Lisboa"
2470                             onerror="this.src='https://nativafmbauru.com.br/assets/img/default-cover.svg'">
2471                                                <button class="neon-chart-track__play-overlay" id="play-btn-4"
2472                                data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/c2/61/fd/c261fd07-f12a-270c-49c9-8978c85926f5/mzaf_17332012605388868844.plus.aac.p.m4a"
2473                                onclick="event.stopPropagation(); playChartTrack(4)">
2474                            <span class="material-symbols-outlined" id="play-icon-4" style="font-size:22px; font-variation-settings:'FILL' 1">play_arrow</span>
2475                        </button>
2476                                            </div>
2477
2478                    <!-- Title + Artist -->
2479                    <div class="neon-chart-track__info">
2480                        <p class="neon-chart-track__title">OLHO MARROM - Ao Vivo em Lisboa</p>
2481                        <p class="neon-chart-track__artist">Luan Santana</p>
2482                    </div>
2483
2484                    <!-- Vote buttons -->
2485                                        <div class="neon-chart-track__votes">
2486                        <button class="neon-vote-btn neon-vote-up" id="like-4"
2487                                onclick="event.stopPropagation(); vote(4, 'like')" title="Curtir">
2488                            <span class="material-symbols-outlined" style="font-size:18px">thumb_up</span>
2489                        </button>
2490                        <span class="neon-vote-count" id="vote-count-4">
2491                            25                        </span>
2492                        <button class="neon-vote-btn neon-vote-down" id="dislike-4"
2493                                onclick="event.stopPropagation(); vote(4, 'dislike')" title="Não curtir">
2494                            <span class="material-symbols-outlined" style="font-size:18px">thumb_down</span>
2495                        </button>
2496                    </div>
2497                                    </div><!-- /.neon-chart-track__row -->
2498
2499                <!-- Inline player (hidden, shown on click) -->
2500                <div class="neon-inline-player" id="player-ui-4"
2501                     data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/c2/61/fd/c261fd07-f12a-270c-49c9-8978c85926f5/mzaf_17332012605388868844.plus.aac.p.m4a"
2502                     data-title="OLHO MARROM - Ao Vivo em Lisboa"
2503                     data-artist="Luan Santana"
2504                     data-cover="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/b3/cf/da/b3cfdac4-2fc7-31da-4d5e-f716cc978868/196873612935.jpg/600x600bb.jpg"
2505                                          style="display:none;">
2506                    <button class="neon-inline-player__btn" id="pplay-4"
2507                            data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview211/v4/c2/61/fd/c261fd07-f12a-270c-49c9-8978c85926f5/mzaf_17332012605388868844.plus.aac.p.m4a"
2508                            onclick="event.stopPropagation(); playChartTrack(4)">
2509                        <span class="material-symbols-outlined" style="font-size:18px; font-variation-settings:'FILL' 1">play_arrow</span>
2510                    </button>
2511                    <div style="flex:1; min-width:0;">
2512                        <div class="neon-inline-player__bar" onclick="seekTrack(event,4)">
2513                            <div class="neon-inline-player__progress" id="progress-bar-4"></div>
2514                        </div>
2515                        <div class="neon-inline-player__times">
2516                            <span id="current-time-4">0:00</span>
2517                            <span id="total-time-4">--:--</span>
2518                        </div>
2519                    </div>
2520                </div><!-- /.neon-inline-player -->
2521
2522            </div><!-- /.neon-chart-track -->
2523                        <div class="neon-chart-track neon-chart-track--cyan" id="track-5"
2524                 data-track-id="27"
2525                 onclick="toggleChartTrack(5)">
2526
2527                <!-- Row: Rank + Cover + Info + Votes -->
2528                <div class="neon-chart-track__row">
2529                    <!-- Rank number -->
2530                    <span class="neon-chart-track__rank">06</span>
2531
2532                    <!-- Cover art -->
2533                    <div class="neon-chart-track__cover"
2534                         >
2535                        <img class="neon-chart-track__cover-img" id="img-5"
2536                             src="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/0d/c2/23/0dc223e8-0f7e-b188-1f8a-f2b4e576b0dc/dj.esvmgkxr.jpg/600x600bb.jpg"
2537                             alt="Vagabundo"
2538                             onerror="this.src='https://nativafmbauru.com.br/assets/img/default-cover.svg'">
2539                                                <button class="neon-chart-track__play-overlay" id="play-btn-5"
2540                                data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/32/0e/48/320e481f-2331-266f-de6f-71c4f5707519/mzaf_13393668534680992445.plus.aac.p.m4a"
2541                                onclick="event.stopPropagation(); playChartTrack(5)">
2542                            <span class="material-symbols-outlined" id="play-icon-5" style="font-size:22px; font-variation-settings:'FILL' 1">play_arrow</span>
2543                        </button>
2544                                            </div>
2545
2546                    <!-- Title + Artist -->
2547                    <div class="neon-chart-track__info">
2548                        <p class="neon-chart-track__title">Vagabundo</p>
2549                        <p class="neon-chart-track__artist">Gusttavo Lima &amp; Luis Fonsi</p>
2550                    </div>
2551
2552                    <!-- Vote buttons -->
2553                                        <div class="neon-chart-track__votes">
2554                        <button class="neon-vote-btn neon-vote-up" id="like-5"
2555                                onclick="event.stopPropagation(); vote(5, 'like')" title="Curtir">
2556                            <span class="material-symbols-outlined" style="font-size:18px">thumb_up</span>
2557                        </button>
2558                        <span class="neon-vote-count" id="vote-count-5">
2559                            16                        </span>
2560                        <button class="neon-vote-btn neon-vote-down" id="dislike-5"
2561                                onclick="event.stopPropagation(); vote(5, 'dislike')" title="Não curtir">
2562                            <span class="material-symbols-outlined" style="font-size:18px">thumb_down</span>
2563                        </button>
2564                    </div>
2565                                    </div><!-- /.neon-chart-track__row -->
2566
2567                <!-- Inline player (hidden, shown on click) -->
2568                <div class="neon-inline-player" id="player-ui-5"
2569                     data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/32/0e/48/320e481f-2331-266f-de6f-71c4f5707519/mzaf_13393668534680992445.plus.aac.p.m4a"
2570                     data-title="Vagabundo"
2571                     data-artist="Gusttavo Lima &amp; Luis Fonsi"
2572                     data-cover="https://is1-ssl.mzstatic.com/image/thumb/Music211/v4/0d/c2/23/0dc223e8-0f7e-b188-1f8a-f2b4e576b0dc/dj.esvmgkxr.jpg/600x600bb.jpg"
2573                                          style="display:none;">
2574                    <button class="neon-inline-player__btn" id="pplay-5"
2575                            data-url="https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/32/0e/48/320e481f-2331-266f-de6f-71c4f5707519/mzaf_13393668534680992445.plus.aac.p.m4a"
2576                            onclick="event.stopPropagation(); playChartTrack(5)">
2577                        <span class="material-symbols-outlined" style="font-size:18px; font-variation-settings:'FILL' 1">play_arrow</span>
2578                    </button>
2579                    <div style="flex:1; min-width:0;">
2580                        <div class="neon-inline-player__bar" onclick="seekTrack(event,5)">
2581                            <div class="neon-inline-player__progress" id="progress-bar-5"></div>
2582                        </div>
2583                        <div class="neon-inline-player__times">
2584                            <span id="current-time-5">0:00</span>
2585                            <span id="total-time-5">--:--</span>
2586                        </div>
2587                    </div>
2588                </div><!-- /.neon-inline-player -->
2589
2590            </div><!-- /.neon-chart-track -->
2591                    </div><!-- /.neon-chart-grid -->
2592
2593                </div><!-- /.neon-chart-layout-wrapper -->
2594    </div>
2595</section>
2596
2597<script>
2598(function () {
2599    'use strict';
2600
2601    /* ── Estado ── */
2602    var _activeIdx   = -1;
2603    var _isPlaying   = false;
2604    var _rpAudio     = null;
2605    var _progressBound = false;
2606    var _updateInterval = null;
2607
2608    /* ── Cookie helpers para persistir votos ── */
2609    var VOTE_COOKIE_KEY  = 'chart_votes';
2610    var VOTE_COOKIE_DAYS = 30;
2611
2612    function getVoteCookie() {
2613        var match = document.cookie.match(new RegExp('(?:^|; )' + VOTE_COOKIE_KEY + '=([^;]*)'));
2614        if (!match) return {};
2615        try { return JSON.parse(decodeURIComponent(match[1])); } catch(e) { return {}; }
2616    }
2617    function setVoteCookie(hash, voteType) {
2618        var data = getVoteCookie();
2619        if (voteType === null) { delete data[hash]; } else { data[hash] = voteType; }
2620        var expires = new Date(Date.now() + VOTE_COOKIE_DAYS * 864e5).toUTCString();
2621        document.cookie = VOTE_COOKIE_KEY + '=' + encodeURIComponent(JSON.stringify(data))
2622            + '; expires=' + expires + '; path=/; SameSite=Lax';
2623    }
2624
2625    /* ── Track data (injected from PHP) ── */
2626    var trackData   = {};
2627    var hashToIndex = {};
2628
2629        trackData[0] = {
2630        likes: 32,
2631        dislikes: 4,
2632        voted: null
2633    };
2634            trackData[1] = {
2635        likes: 27,
2636        dislikes: 2,
2637        voted: null
2638    };
2639            trackData[2] = {
2640        likes: 18,
2641        dislikes: 3,
2642        voted: null
2643    };
2644            trackData[3] = {
2645        likes: 11,
2646        dislikes: 0,
2647        voted: null
2648    };
2649            trackData[4] = {
2650        likes: 17,
2651        dislikes: 8,
2652        voted: null
2653    };
2654            trackData[5] = {
2655        likes: 12,
2656        dislikes: 4,
2657        voted: null
2658    };
2659        
2660    /* Restaurar votos do cookie */
2661    (function restoreVotesFromCookie() {
2662        var saved = getVoteCookie();
2663        Object.keys(saved).forEach(function(hash) {
2664            var idx = hashToIndex[hash];
2665            if (idx === undefined || !trackData[idx]) return;
2666            trackData[idx].voted = saved[hash];
2667            updateVoteUI(idx);
2668        });
2669    })();
2670
2671    var activeChartId = '1';
2672
2673    /* ── Toggle card (expand/collapse inline player) ── */
2674    window.toggleChartTrack = function (idx) {
2675        var playerUI = document.getElementById('player-ui-' + idx);
2676        var trackItem = document.getElementById('track-' + idx);
2677        if (!playerUI || !trackItem) return;
2678
2679        var isActive = trackItem.classList.contains('neon-chart-active');
2680
2681        /* Close all cards */
2682        document.querySelectorAll('.neon-chart-track').forEach(function(el) {
2683            el.classList.remove('neon-chart-active');
2684            var p = el.querySelector('.neon-inline-player');
2685            if (p) p.style.display = 'none';
2686        });
2687
2688        if (!isActive) {
2689            trackItem.classList.add('neon-chart-active');
2690            playerUI.style.display = 'flex';
2691            playChartTrack(idx);
2692        } else {
2693            _activeIdx = -1;
2694            _isPlaying = false;
2695            if (window.radioPlayer) {
2696                if (window.radioPlayer.stopPlayback) window.radioPlayer.stopPlayback();
2697                else if (window.radioPlayer.audio) window.radioPlayer.audio.pause();
2698            }
2699            _resetIcons();
2700            /* Resume live after 500ms */
2701            setTimeout(function() {
2702                if (window.radioPlayer) {
2703                    if (typeof window.radioPlayer.returnToLive === 'function') window.radioPlayer.returnToLive();
2704                    else if (typeof window.radioPlayer.startPlayback === 'function') window.radioPlayer.startPlayback();
2705                }
2706            }, 500);
2707        }
2708    };
2709
2710    /* ── Play chart track via radioPlayer ── */
2711    window.playChartTrack = async function (idx) {
2712        var playerUI = document.getElementById('player-ui-' + idx);
2713        var extBtn   = document.getElementById('play-btn-' + idx);
2714        var dataSource = playerUI || extBtn;
2715        if (!dataSource) return;
2716
2717        var url    = playerUI ? playerUI.dataset.url    : (extBtn ? extBtn.dataset.url : '');
2718        var title  = playerUI ? playerUI.dataset.title  : (extBtn ? extBtn.dataset.title : '');
2719        var artist = playerUI ? playerUI.dataset.artist : (extBtn ? extBtn.dataset.artist : '');
2720        var imgTag = document.getElementById('img-' + idx);
2721        var cover  = (imgTag ? imgTag.src : '') || (playerUI ? playerUI.dataset.cover : '');
2722        var needPreview = playerUI ? playerUI.dataset.needPreview === 'true' : false;
2723        var pplayBtn = document.getElementById('pplay-' + idx);
2724
2725        if (_activeIdx === idx) { _stopAndResume(idx); return; }
2726
2727        /* Fetch preview if needed */
2728        if (!url && needPreview) {
2729            if (pplayBtn) {
2730                var origIcon = pplayBtn.innerHTML;
2731                pplayBtn.innerHTML = '<span class="material-symbols-outlined" style="font-size:18px;animation:spin 1s linear infinite">refresh</span>';
2732                try {
2733                    var res  = await fetch('https://nativafmbauru.com.br/api/track_info.php?artist=' + encodeURIComponent(artist) + '&title=' + encodeURIComponent(title));
2734                    var data = await res.json();
2735                    if (data.success && data.preview_url) {
2736                        url = data.preview_url;
2737                        if (playerUI) { playerUI.dataset.url = url; playerUI.dataset.needPreview = 'false'; }
2738                        if (extBtn) extBtn.dataset.url = url;
2739                        if (pplayBtn) pplayBtn.dataset.url = url;
2740                        if (data.artwork) { cover = data.artwork; if (imgTag) imgTag.src = data.artwork; }
2741                    } else { pplayBtn.innerHTML = origIcon; return; }
2742                } catch(e) { pplayBtn.innerHTML = origIcon; return; }
2743                pplayBtn.innerHTML = origIcon;
2744            }
2745        } else if (!url) { return; }
2746
2747        /* Close previous */
2748        if (_activeIdx >= 0 && _activeIdx !== idx) {
2749            _setIcon(_activeIdx, 'play_arrow');
2750            var prevItem = document.getElementById('track-' + _activeIdx);
2751            if (prevItem) {
2752                prevItem.classList.remove('neon-chart-active');
2753                var prevPlayer = prevItem.querySelector('.neon-inline-player');
2754                if (prevPlayer) prevPlayer.style.display = 'none';
2755            }
2756        }
2757
2758        _activeIdx = idx;
2759        _resetIcons();
2760        _setIcon(idx, 'pause');
2761
2762        var trackItem = document.getElementById('track-' + idx);
2763        if (trackItem) {
2764            trackItem.classList.add('neon-chart-active');
2765            var playerEl = trackItem.querySelector('.neon-inline-player');
2766            if (playerEl) playerEl.style.display = 'flex';
2767        }
2768
2769        /* Play via radioPlayer */
2770        if (window.radioPlayer) {
2771            if (typeof window.radioPlayer.playTrack === 'function') {
2772                window.radioPlayer.playTrack(url, { title: title, artist: artist, artwork: cover });
2773            } else if (window.radioPlayer.audio) {
2774                window.radioPlayer.audio.src = url;
2775                window.radioPlayer.audio.play();
2776            }
2777            _startProgressUpdate(idx);
2778        }
2779
2780        _isPlaying = true;
2781    };
2782
2783    /* ── Seek ── */
2784    window.seekTrack = function (e, idx) {
2785        if (_activeIdx !== idx || !window.radioPlayer || !window.radioPlayer.audio) return;
2786        e.stopPropagation();
2787        var bar  = e.currentTarget;
2788        var pct  = e.offsetX / bar.clientWidth;
2789        var audio = window.radioPlayer.audio;
2790        if (!isNaN(audio.duration)) audio.currentTime = audio.duration * pct;
2791    };
2792
2793    /* ── Votação ── */
2794    window.vote = function (idx, type) {
2795        if (!activeChartId) return;
2796        var t = trackData[idx];
2797        if (!t) return;
2798        var trackEl = document.getElementById('track-' + idx);
2799        if (!trackEl) return;
2800        var trackId = trackEl.dataset.trackId;
2801        if (!trackId) return;
2802
2803        var oldState = { likes: t.likes, dislikes: t.dislikes, voted: t.voted };
2804
2805        /* Optimistic toggle */
2806        if (t.voted === type) {
2807            t.voted = null;
2808            type === 'like' ? t.likes-- : t.dislikes--;
2809        } else {
2810            if (t.voted) { t.voted === 'like' ? t.likes-- : t.dislikes--; }
2811            t.voted = type;
2812            type === 'like' ? t.likes++ : t.dislikes++;
2813        }
2814        updateVoteUI(idx);
2815
2816        var fd = new FormData();
2817        fd.append('action', 'vote');
2818        fd.append('chart_id', activeChartId);
2819        fd.append('track_id', trackId);
2820        fd.append('type', type === 'like' ? 'up' : 'down');
2821
2822        fetch('https://nativafmbauru.com.br/api/charts.php', { method: 'POST', body: fd })
2823            .then(function(r) { return r.json(); })
2824            .then(function(data) {
2825                if (data.success) {
2826                    t.likes    = parseInt(data.counts.votes_up);
2827                    t.dislikes = parseInt(data.counts.votes_down);
2828                    updateVoteUI(idx);
2829                    setVoteCookie(trackId, t.voted);
2830                    if (data.ranked_tracks && data.ranked_tracks.length > 0) _reorderChart(data.ranked_tracks);
2831                } else {
2832                    Object.assign(t, oldState); updateVoteUI(idx);
2833                }
2834            })
2835            .catch(function() { Object.assign(t, oldState); updateVoteUI(idx); });
2836    };
2837
2838    function updateVoteUI(idx) {
2839        var t  = trackData[idx];
2840        var lb = document.getElementById('like-'       + idx);
2841        var db = document.getElementById('dislike-'    + idx);
2842        var ce = document.getElementById('vote-count-' + idx);
2843        if (lb) lb.classList.toggle('voted', t.voted === 'like');
2844        if (db) db.classList.toggle('voted', t.voted === 'dislike');
2845        if (ce) {
2846            var total = t.likes + t.dislikes;
2847            var fmt = function(n) { return n >= 1000 ? (n/1000).toFixed(1).replace('.0','')+'K' : String(n); };
2848            ce.textContent = total > 0 ? fmt(total) : '';
2849        }
2850    }
2851
2852    function _reorderChart(rankedTracks) {
2853        var list = document.getElementById('chart-list');
2854        if (!list) return;
2855        var posMap = {};
2856        rankedTracks.forEach(function(rt) { posMap[rt.track_hash] = rt.position; });
2857        var items = Array.from(list.querySelectorAll('.neon-chart-track'));
2858        items.sort(function(a,b) { return (posMap[a.dataset.trackId]||999) - (posMap[b.dataset.trackId]||999); });
2859        list.style.transition = 'opacity 0.25s ease';
2860        list.style.opacity = '0.5';
2861        setTimeout(function() {
2862            items.forEach(function(el, i) {
2863                var rs = el.querySelector('.neon-chart-track__rank');
2864                if (rs) rs.textContent = String(i+1).padStart(2,'0');
2865                list.appendChild(el);
2866            });
2867            list.style.opacity = '1';
2868        }, 260);
2869    }
2870
2871    /* ── Progress update ── */
2872    function _startProgressUpdate(idx) {
2873        if (_updateInterval) clearInterval(_updateInterval);
2874        if (!window.radioPlayer || !window.radioPlayer.audio) return;
2875        var audio = window.radioPlayer.audio;
2876
2877        function onTimeUpdate() {
2878            if (_activeIdx !== idx) return;
2879            var pb = document.getElementById('progress-bar-' + idx);
2880            var ct = document.getElementById('current-time-' + idx);
2881            var tt = document.getElementById('total-time-' + idx);
2882            if (pb && audio.duration) pb.style.width = (audio.currentTime / audio.duration * 100) + '%';
2883            if (ct) ct.textContent = _fmt(audio.currentTime);
2884            if (tt && audio.duration) tt.textContent = _fmt(audio.duration);
2885            if (audio.ended) _stopAndResume(idx);
2886        }
2887        function onPlay()  { _setIcon(idx, 'pause');      }
2888        function onPause() { _setIcon(idx, 'play_arrow'); }
2889
2890        audio.removeEventListener('timeupdate', audio._neonTimeUpdate);
2891        audio.removeEventListener('play',       audio._neonPlay);
2892        audio.removeEventListener('pause',      audio._neonPause);
2893        audio._neonTimeUpdate = onTimeUpdate;
2894        audio._neonPlay       = onPlay;
2895        audio._neonPause      = onPause;
2896        audio.addEventListener('timeupdate', onTimeUpdate);
2897        audio.addEventListener('play',       onPlay);
2898        audio.addEventListener('pause',      onPause);
2899
2900        _updateInterval = setInterval(function() {
2901            if (_activeIdx !== idx || !audio || audio.paused) return;
2902            onTimeUpdate();
2903        }, 250);
2904    }
2905
2906    function _stopAndResume(idx) {
2907        _setIcon(idx, 'play_arrow');
2908        if (_updateInterval) clearInterval(_updateInterval);
2909        _activeIdx = -1;
2910        _isPlaying = false;
2911        var trackItem = document.getElementById('track-' + idx);
2912        if (trackItem) {
2913            trackItem.classList.remove('neon-chart-active');
2914            var p = trackItem.querySelector('.neon-inline-player');
2915            if (p) p.style.display = 'none';
2916        }
2917        if (window.radioPlayer) {
2918            if (typeof window.radioPlayer.returnToLive === 'function') window.radioPlayer.returnToLive();
2919            else { setTimeout(function() { if (typeof window.radioPlayer.startPlayback === 'function') window.radioPlayer.startPlayback(); }, 300); }
2920        }
2921    }
2922
2923    function _setIcon(idx, name) {
2924        var overlay = document.getElementById('play-icon-' + idx);
2925        if (overlay) overlay.textContent = name;
2926        var pplay = document.getElementById('pplay-' + idx);
2927        if (pplay) {
2928            var ic = pplay.querySelector('.material-symbols-outlined');
2929            if (ic) ic.textContent = name;
2930        }
2931    }
2932
2933    function _resetIcons() {
2934        document.querySelectorAll('.neon-inline-player__btn .material-symbols-outlined').forEach(function(icon) {
2935            icon.textContent = 'play_arrow';
2936        });
2937    }
2938
2939    function _fmt(s) {
2940        s = Math.floor(s || 0);
2941        var m = Math.floor(s / 60), sec = s % 60;
2942        return m + ':' + (sec < 10 ? '0' : '') + sec;
2943    }
2944
2945    /* ── Auto-fetch artwork for tracks without cover ── */
2946    (function loadMissingArtwork() {
2947        var items = document.querySelectorAll('.neon-chart-track__cover[data-need-art="true"]');
2948        items.forEach(function(item) {
2949            var artist = item.dataset.trackArtist;
2950            var title  = item.dataset.trackTitle;
2951            var idx    = item.dataset.trackIndex;
2952            fetch('https://nativafmbauru.com.br/api/track_info.php?artist=' + encodeURIComponent(artist) + '&title=' + encodeURIComponent(title))
2953                .then(function(r) { return r.json(); })
2954                .then(function(data) {
2955                    if (data.success) {
2956                        if (data.artwork) {
2957                            var img = document.getElementById('img-' + idx);
2958                            if (img) img.src = data.artwork;
2959                        }
2960                        if (data.preview_url) {
2961                            var pui = document.getElementById('player-ui-' + idx);
2962                            var btn = document.getElementById('play-btn-' + idx);
2963                            if (pui) { pui.dataset.url = data.preview_url; pui.dataset.needPreview = 'false'; }
2964                            if (btn) { btn.dataset.url = data.preview_url; btn.dataset.needPreview = 'false'; }
2965                        }
2966                    }
2967                })
2968                .catch(function(e) { console.error('Auto artwork fetch error', e); });
2969        });
2970    })();
2971
2972})();
2973</script>
2973
2974
2975<!-- Equipe — Neon Theme -->
2976<section class="neon-team-section" style="overflow:visible!important;">
2977    <div class="container" style="overflow:visible!important;">
2978        <!-- Header Stitch-style -->
2979        <!-- Header Stitch-style with custom buttons -->
2980        <div style="display:flex; justify-content: space-between; align-items: flex-end; margin-bottom: 32px; flex-wrap: wrap; gap: 16px;">
2981            <div class="neon-news-header" style="margin-bottom: 0;">
2982                <div class="neon-news-header__bar"></div>
2983                <div class="neon-news-header__text">
2984                    <div class="neon-news-header__label">
2985                        <!-- Lucide: users -->
2986                        <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
2987                        <span></span>
2988                    </div>
2989                    <h2 class="neon-news-header__title">Equipe</h2>
2990                </div>
2991            </div>
2992                        <div style="display:flex;gap:10px;">
2993                <button class="team-carousel-prev" aria-label="Anterior"
2994                        style="width:44px;height:44px;border-radius:50%;border:2px solid var(--color-primary);background:transparent;color:var(--color-primary);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.25s;">
2995                    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
2996                </button>
2997                <button class="team-carousel-next" aria-label="Próximo"
2998                        style="width:44px;height:44px;border-radius:50%;border:none;background:var(--color-primary);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.25s;">
2999                    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
3000                </button>
3001            </div>
3002                    </div>
3003
3004        <!-- Team Grid + banner lateral -->
3005        <div class="neon-team-layout-wrapper">
3006        <div class="team-carousel-wrapper" style="overflow:hidden; position:relative;">
3007            <div class="team-carousel-inner shelf-72" style="display:flex; gap:24px;">
3008                            <div class="team-card neon-team-card neon-team-card--var-1"
3009                     data-nome="André"
3010                     data-cargo="Locutor"
3011                     data-descricao="O André faz parte da programação da Nativa, levando boa música, alto astral e muita interação para os ouvintes. Com seu jeito único, acompanha o público e deixa o dia ainda mais animado."
3012                     data-foto="https://nativafmbauru.com.br/uploads/media/6a18a3318ddae_1779999537.webp"
3013                     data-facebook=""
3014                     data-instagram="https://www.instagram.com/andreluizcosta88/"
3015                     data-twitter=""
3016                     data-tiktok="">
3017                    
3018                    <!-- Avatar com glow -->
3019                    <div class="neon-team-card__avatar-wrap">
3020                        <div class="neon-team-card__avatar-glow"></div>
3021                                                    <img class="neon-team-card__avatar"
3022                                 src="https://nativafmbauru.com.br/uploads/media/6a18a3318ddae_1779999537.webp"
3023                                 alt="André" loading="lazy">
3024                                            </div>
3025
3026                    <!-- Info -->
3027                    <div class="neon-team-card__info">
3028                        <h3 class="neon-team-card__name">André</h3>
3029                        
3030                                                    <p class="neon-team-card__role" style="color: var(--color-secondary);">
3031                                Locutor                            </p>
3032                                                
3033                                                    <p class="neon-team-card__bio">
3034                                O André faz parte da programação da Nativa, levando boa música, alto astral e muita interação para os ouvintes. Com seu...                            </p>
3035                                                
3036                        <!-- Social Links -->
3037                                                <div class="neon-team-card__socials">
3038                                                            <a href="https://www.instagram.com/andreluizcosta88/" target="_blank" rel="noopener" class="neon-team-social-btn" title="Instagram">
3039                                    <i class="fab fa-instagram"></i>
3040                                </a>
3041                                                                                                                                        </div>
3042                                            </div>
3043                </div>
3044                            <div class="team-card neon-team-card neon-team-card--var-2"
3045                     data-nome="Cleiton"
3046                     data-cargo="Coordenador Artístico"
3047                     data-descricao="À frente da coordenação artística da Nativa, o Cleiton trabalha para que a programação esteja sempre em sintonia com os ouvintes. Com dedicação e criatividade, contribui para levar música, entretenimento e conteúdo de qualidade para o ar todos os dias."
3048                     data-foto="https://nativafmbauru.com.br/uploads/media/6a18a330d75c7_1779999536.webp"
3049                     data-facebook=""
3050                     data-instagram="https://www.instagram.com/cleiton.carioca/"
3051                     data-twitter=""
3052                     data-tiktok="">
3053                    
3054                    <!-- Avatar com glow -->
3055                    <div class="neon-team-card__avatar-wrap">
3056                        <div class="neon-team-card__avatar-glow"></div>
3057                                                    <img class="neon-team-card__avatar"
3058                                 src="https://nativafmbauru.com.br/uploads/media/6a18a330d75c7_1779999536.webp"
3059                                 alt="Cleiton" loading="lazy">
3060                                            </div>
3061
3062                    <!-- Info -->
3063                    <div class="neon-team-card__info">
3064                        <h3 class="neon-team-card__name">Cleiton</h3>
3065                        
3066                                                    <p class="neon-team-card__role" style="color: var(--color-primary);">
3067                                Coordenador Artístico                            </p>
3068                                                
3069                                                    <p class="neon-team-card__bio">
3070                                À frente da coordenação artística da Nativa, o Cleiton trabalha para que a programação esteja sempre em sintonia com os...                            </p>
3071                                                
3072                        <!-- Social Links -->
3073                                                <div class="neon-team-card__socials">
3074                                                            <a href="https://www.instagram.com/cleiton.carioca/" target="_blank" rel="noopener" class="neon-team-social-btn" title="Instagram">
3075                                    <i class="fab fa-instagram"></i>
3076                                </a>
3077                                                                                                                                        </div>
3078                                            </div>
3079                </div>
3080                            <div class="team-card neon-team-card neon-team-card--var-3"
3081                     data-nome="Day Quarenta"
3082                     data-cargo="Apresentadora"
3083                     data-descricao="Diariamente a Day leva muita alegria e alto astral com o programa “A Nativa entrou no grupo” Vem que tem alegria, vem que tem Nativa!"
3084                     data-foto="https://nativafmbauru.com.br/uploads/media/6a18a33033f04_1779999536.webp"
3085                     data-facebook=""
3086                     data-instagram=""
3087                     data-twitter=""
3088                     data-tiktok="">
3089                    
3090                    <!-- Avatar com glow -->
3091                    <div class="neon-team-card__avatar-wrap">
3092                        <div class="neon-team-card__avatar-glow"></div>
3093                                                    <img class="neon-team-card__avatar"
3094                                 src="https://nativafmbauru.com.br/uploads/media/6a18a33033f04_1779999536.webp"
3095                                 alt="Day Quarenta" loading="lazy">
3096                                            </div>
3097
3098                    <!-- Info -->
3099                    <div class="neon-team-card__info">
3100                        <h3 class="neon-team-card__name">Day Quarenta</h3>
3101                        
3102                                                    <p class="neon-team-card__role" style="color: var(--color-secondary);">
3103                                Apresentadora                            </p>
3104                                                
3105                                                    <p class="neon-team-card__bio">
3106                                Diariamente a Day leva muita alegria e alto astral com o programa “A Nativa entrou no grupo” Vem que tem alegria, vem...                            </p>
3107                                                
3108                        <!-- Social Links -->
3109                                            </div>
3110                </div>
3111                        </div>
3112        </div>
3113        
3114                </div><!-- /.neon-team-layout-wrapper -->
3115
3116                <div class="team-carousel-dots" style="display:flex;justify-content:center;gap:8px;margin-top:20px;"></div>
3117        
3118        <!-- Ver Toda a Equipe -->
3119                <div class="neon-team-viewall">
3120            <a href="https://nativafmbauru.com.br/equipe" class="neon-team-viewall__btn">
3121                <!-- Lucide: users-2 -->
3122                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewB
3122ox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 19a6 6 0 0 0-12 0"/><circle cx="8" cy="9" r="4"/><path d="M22 19a6 6 0 0 0-6-6 4 4 0 0 0 0-8"/></svg>
3123                Ver Toda a Equipe            </a>
3124        </div>
3125            </div>
3126</section>
3127<script src="https://nativafmbauru.com.br/assets/js/team-module.js?v=1790900781"></script>
3127
3128
3129
3130<script>
3131    // ── Podcast Player Integration ──────────────────────────────
3132    // Delega ao radioPlayer.playPodcast() — método nativo que seta currentSong,
3133    // chama updateSongInfo() e dispara o MutationObserver do mini player mobile.
3134    function playPodcastEpisode(audioUrl, title, coverUrl, artist) {
3135        if (!audioUrl) {
3136            alert('Este episódio não possui áudio disponível.');
3137            return;
3138        }
3139        var rp = window.radioPlayer;
3140        if (!rp) {
3141            window.open(audioUrl, '_blank');
3142            return;
3143        }
3144
3145        // Usar o método nativo playPodcast() que já configura currentSong,
3146        // chama updateSongInfo() e dispara radioPlayerStateChange corretamente.
3147        if (typeof rp.playPodcast === 'function') {
3148            rp.playPodcast(
3149                audioUrl,
3150                title   || 'Podcast',
3151                artist  || '',
3152                coverUrl || rp.defaultArtwork || ''
3153            );
3154            return;
3155        }
3156
3157        // Fallback legado caso playPodcast não exista
3158        rp.audio.pause();
3159        rp.audio.src = '';
3160        rp.isStream = false;
3161        rp.userIntendedPlay = true;
3162        if (rp.playerTitle)  rp.playerTitle.textContent  = title  || 'Podcast';
3163        if (rp.playerArtist) rp.playerArtist.textContent = artist || '';
3164        if (coverUrl && rp.playerArtwork) {
3165            rp.playerArtwork.classList.add('has-image');
3166            var img = rp.playerArtwork.querySelector('img');
3167            if (!img) { img = document.createElement('img'); rp.playerArtwork.appendChild(img); }
3168            img.src = coverUrl;
3169            img.alt = title || 'Capa do Podcast';
3170        }
3171        rp.audio.src = audioUrl;
3172        rp.audio.load();
3173        rp.audio.play().catch(function (e) {
3174            console.warn('Autoplay blocked:', e);
3175            rp.setState && rp.setState('connecting');
3176        });
3177        rp.setState && rp.setState('transmitting');
3178    }
3179
3180    // Global Audio Handling: Mutex (Stop others) + UI Sync
3181
3182    document.addEventListener('play', function (e) {
3183        // 1. Stop all other audios
3184        var audios = document.getElementsByTagName('audio');
3185        for (var i = 0, len = audios.length; i < len; i++) {
3186            if (audios[i] != e.target) {
3187                audios[i].pause();
3188                audios[i].currentTime = 0; // Reset others
3189            }
3190        }
3191
3192        // 2. Update UI for the playing audio (if it's a chart player)
3193        if (e.target.classList.contains('chart-audio-player')) {
3194            const container = e.target.closest('.chart-track-player');
3195            if (container) {
3196                const icon = container.querySelector('.player-control-icon i');
3197                if (icon) {
3198                    icon.classList.remove('fa-play');
3199                    icon.classList.add('fa-pause');
3200                }
3201            }
3202        }
3203    }, true);
3204
3205    document.addEventListener('pause', function (e) {
3206        // Update UI when paused
3207        if (e.target.classList.contains('chart-audio-player')) {
3208            const container = e.target.closest('.chart-track-player');
3209            if (container) {
3210                const icon = container.querySelector('.player-control-icon i');
3211                if (icon) {
3212                    icon.classList.remove('fa-pause');
3213                    icon.classList.add('fa-play');
3214                }
3215            }
3216        }
3217    }, true);
3218
3219    function toggleChartPlayer(element) {
3220        // Find the parent chart-track (supports generic + neon theme)
3221        const trackCard = element.closest('.chart-track, .neon-chart-track');
3222        if (!trackCard) return;
3223
3224        // Check if this card is currently active
3225        const isActive = trackCard.classList.contains('active');
3226
3227        // Close ALL other tracks first (Accordion effect)
3228        document.querySelectorAll('.chart-track.active, .neon-chart-track.active').forEach(card => {
3229            card.classList.remove('active');
3230            const audio = card.querySelector('audio');
3231            if (audio) {
3232                audio.pause();
3233                audio.currentTime = 0;
3234            }
3235        });
3236
3237        // If it wasn't active, open it now
3238        if (!isActive) {
3239            // STOP MAIN RADIO when opening a preview
3240            if (window.radioPlayer && typeof window.radioPlayer.stopPlayback === 'function') {
3241                window.radioPlayer.stopPlayback();
3242            }
3243
3244            trackCard.classList.add('active');
3245            const audio = trackCard.querySelector('audio');
3246            if (audio) {
3247                audio.play().catch(e => console.log("Autoplay blocked usually ok", e));
3248            }
3249        }
3250    }
3251
3252    // New Function to handle the inner player interaction (Custom Player Click)
3253    function toggleTrackPlayback(element) {
3254        // Element is .custom-player-ui
3255        const playerContainer = element.closest('.chart-track-player');
3256        if (!playerContainer) return;
3257
3258        const audio = playerContainer.querySelector('audio.chart-audio-player');
3259        const icon = playerContainer.querySelector('.player-control-icon i');
3260
3261        if (audio) {
3262            if (audio.paused) {
3263                // Stop main radio
3264                if (window.radioPlayer && typeof window.radioPlayer.stopPlayback === 'function') {
3265                    window.radioPlayer.stopPlayback();
3266                }
3267
3268                // Stop other chart players
3269                document.querySelectorAll('audio.chart-audio-player').forEach(otherAudio => {
3270                    if (otherAudio !== audio) {
3271                        otherAudio.pause();
3272                        otherAudio.currentTime = 0;
3273                        // Reset other icons/bars
3274                        const otherContainer = otherAudio.closest('.chart-track-player');
3275                        if (otherContainer) {
3276                            const otherIcon = otherContainer.querySelector('.player-control-icon i');
3277                            const otherBar = otherContainer.querySelector('.player-progress-fill');
3278                            if (otherIcon) {
3279                                otherIcon.classList.remove('fa-pause');
3280                                otherIcon.classList.add('fa-play');
3281                            }
3282                            if (otherBar) otherBar.style.width = '0%';
3283                        }
3284                    }
3285                });
3286
3287                audio.play();
3288                if (icon) {
3289                    icon.classList.remove('fa-play');
3290                    icon.classList.add('fa-pause');
3291                }
3292            } else {
3293                audio.pause();
3294                if (icon) {
3295                    icon.classList.remove('fa-pause');
3296                    icon.classList.add('fa-play');
3297                }
3298            }
3299        }
3300    }
3301
3302    // Attach listeners to update Progress Bars
3303    document.addEventListener('DOMContentLoaded', function () {
3304        // Use event delegation or attach to existing audios? 
3305        // Since we have multiple, let's attach to all present
3306        const chartAudios = document.querySelectorAll('audio.chart-audio-player');
3307        chartAudios.forEach(audio => {
3308
3309            // Update Progress Bar
3310            audio.addEventListener('timeupdate', function () {
3311                const container = this.closest('.chart-track-player');
3312                if (!container) return;
3313                const bar = container.querySelector('.player-progress-fill');
3314
3315                if (bar && this.duration) {
3316                    const percent = (this.currentTime / this.duration) * 100;
3317                    bar.style.width = percent + '%';
3318                }
3319            });
3320
3321            // Reset on End — and resume main radio stream
3322            audio.addEventListener('ended', function () {
3323                const container = this.closest('.chart-track-player');
3324                if (!container) return;
3325
3326                const bar = container.querySelector('.player-progress-fill');
3327                const icon = container.querySelector('.player-control-icon i');
3328                if (bar) bar.style.width = '0%';
3329                if (icon) { icon.classList.remove('fa-pause'); icon.classList.add('fa-play'); }
3330                this.currentTime = 0;
3331
3332                // Close the accordion panel (supports generic + neon)
3333                const trackCard = container.closest('.chart-track, .neon-chart-track');
3334                if (trackCard) trackCard.classList.remove('active');
3335
3336                // Resume main streaming player
3337                setTimeout(function () {
3338                    if (window.radioPlayer && typeof window.radioPlayer.startPlayback === 'function') {
3339                        window.radioPlayer.startPlayback();
3340                    } else if (window.radioPlayer && typeof window.radioPlayer.play === 'function') {
3341                        window.radioPlayer.play();
3342                    }
3343                }, 400);
3344            });
3345        });
3346    });
3347
3348
3349
3350    async function voteTrack(chartId, trackId, voteType, btn) {
3351        if (btn.disabled) return;
3352
3353        // Get the parent container (supports generic + neon theme)
3354        const voteContainer = btn.closest('.vote-column, .neon-chart-track__votes');
3355        if (!voteContainer) return;
3356
3357        // Disable both buttons (supports generic + neon btn classes)
3358        const allBtns = voteContainer.querySelectorAll('.vote-mini-btn, .neon-vote-btn');
3359        allBtns.forEach(b => b.disabled = true);
3360
3361        const formData = new FormData();
3362        formData.append('action', 'vote');
3363        formData.append('vote_type', voteType);
3364
3365        // Auto mode: trackId is 0, use track_hash instead
3366        const trackCard = btn.closest('.chart-track, .neon-chart-track, [data-track-hash]');
3367        const trackHash = trackCard ? trackCard.dataset.trackHash : '';
3368
3369        if (trackId === 0 && trackHash) {
3370            // Auto mode — send track_hash, no chart_id/track_id
3371            formData.append('track_hash', trackHash);
3372            formData.append('chart_id', '');
3373            formData.append('track_id', '');
3374        } else {
3375            // Manual mode — send chart_id + track_id
3376            formData.append('chart_id', chartId);
3377            formData.append('track_id', trackId);
3378        }
3379
3380        try {
3381            const response = await fetch(SITE_URL + '/api/vote.php', {
3382                method: 'POST',
3383                body: formData
3384            });
3385            const data = await response.json();
3386
3387            if (data.success) {
3388                voteContainer.classList.add('voted');
3389
3390                // Update the vote count display in real-time
3391                const voteCountEl = voteContainer.querySelector('.vote-net-count');
3392                if (voteCountEl) {
3393                    let currentCount = parseInt(voteCountEl.textContent) || 0;
3394                    if (voteType === 'up') {
3395                        currentCount += 1;
3396                    } else if (voteType === 'down') {
3397                        currentCount -= 1;
3398                    }
3399                    voteCountEl.textContent = currentCount;
3400
3401                    voteCountEl.style.transform = 'scale(1.2)';
3402                    setTimeout(() => {
3403                        voteCountEl.style.transform = 'scale(1)';
3404                    }, 200);
3405                }
3406
3407                // Visual feedback on the clicked button
3408                btn.style.opacity = '0.5';
3409
3410                if (typeof showToast === 'function') {
3411                    showToast(data.message || 'Voto registrado!', 'success');
3412                }
3413            } else {
3414                allBtns.forEach(b => b.disabled = false);
3415                if (typeof showToast === 'function') {
3416                    showToast(data.message, 'info');
3417                } else {
3418                    console.log("Voting info: " + data.message);
3419                    const msg = document.createElement('div');
3420                    msg.style.cssText = 'position:fixed;bottom:20px;right:20px;background:#333;color:white;padding:10px 20px;border-radius:5px;z-index:9999;animation:fadeIn 0.3s;';
3421                    msg.textContent = data.message;
3422                    document.body.appendChild(msg);
3423                    setTimeout(() => msg.remove(), 3000);
3424                }
3425            }
3426        } catch (error) {
3427            allBtns.forEach(b => b.disabled = false);
3428            console.error('Vote error:', error);
3429        }
3430    }
3431</script>
3431
3432    </div>
3433
3434    <!-- Persistent Audio Player -->
3435    <!-- Theme: NEON — Glassmorphism + Neon Glow — Audio Player -->
3436<div id="player" class="neon-player">
3437    <div class="neon-player__inner">
3438
3439        <!-- ──── GRUPO ESQUERDO: Artwork + Info + Controles + Volume ──── -->
3440        <div class="neon-player__left-group">
3441
3442            <!-- Artwork + Info -->
3443            <div class="neon-player__info">
3444                <div class="neon-player__artwork" id="playerArtwork">
3445                    <img src="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp"
3446                         alt="Album Art"
3447                         onerror="this.src = PLAYER_DEFAULT_IMAGE || 'https://nativafmbauru.com.br/assets/img/default-cover.png'">
3448                </div>
3449                <div class="neon-player__meta">
3450                    <div class="neon-player__status" data-player-status>
3451                    </div>
3452                    <div class="neon-player__title" id="playerTitle">Carregando...</div>
3453                    <div class="neon-player__artist" id="playerArtist">Nativa FM Bauru</div>
3454                </div>
3455            </div>
3456
3457            <!-- NOVOS CONTROLES (NATIVOS) -->
3458            <div class="zmp-player-controls-wrapper">
3459
3460                <!-- PLAY / PAUSE -->
3461                <button id="playBtn" class="zmp-btn zmp-play-size" title="Play/Pause">
3462                    <svg id="playIcon" class="zmp-svg zmp-show" xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" style="max-width: 22px; max-height: 22px;">
3463                        <path fill="currentColor" d="M6 3.5a1.5 1.5 0 0 1 2.3-.8l11.5 8a1.5 1.5 0 0 1 0 2.6l-11.5 8A1.5 1.5 0 0 1 6 20.5v-17z"/>
3464                    </svg>
3465                </button>
3466
3467                <!-- AO VIVO -->
3468                <button id="zmpLiveBtn" class="zmp-btn zmp-aux-size" title="Voltar ao Vivo" onclick="if(window.radioPlayer) window.radioPlayer.returnToLive()">
3469                    <svg class="zmp-svg zmp-show" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="currentColor" style="max-width: 18px; max-height: 18px;">
3470                        <circle cx="12" cy="12" r="2.5" />
3471                        <path d="M7.74 16.26a6 6 0 0 1 0-8.52l1.42 1.42a4 4 0 0 0 0 5.68z" />
3472                        <path d="M16.26 16.26a6 6 0 0 0 0-8.52l-1.42 1.42a4 4 0 0 1 0 5.68z" />
3473                        <path d="M4.91 19.09a10 10 0 0 1 0-14.18l1.42 1.42a8 8 0 0 0 0 11.34z" />
3474                        <path d="M19.09 19.09a10 10 0 0 0 0-14.18l-1.42 1.42a8 8 0 0 1 0 11.34z" />
3475                    </svg>
3476                </button>
3477
3478                <!-- VOLUME -->
3479                <button id="volumeBtn" class="zmp-btn zmp-aux-size" title="Volume">
3480                    <svg id="volumeIcon" class="zmp-svg zmp-show" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
3481                        <path fill="currentColor" d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/>
3482                    </svg>
3483                </button>
3484                <input type="range" id="volumeSlider" class="zmp-volume-slider" min="0" max="100" value="90" />
3485            
3486            </div> <!-- /zmp-player-controls-wrapper -->
3487
3488            <!-- CSS BLINDADO DOS CONTROLES -->
3489            <style>
3490            .zmp-player-controls-wrapper {
3491                display: flex;
3492                align-items: center;
3493                gap: 16px;
3494                margin-left: 20px;
3495            }
3496            .zmp-btn {
3497                appearance: none !important;
3498                background: transparent !important;
3499                color: var(--player-text-color, #ffffff);
3500                border: none !important;
3501                border-radius: 50% !important;
3502                display: flex !important;
3503                align-items: center !important;
3504                justify-content: center !important;
3505                cursor: pointer;
3506                box-shadow: none !important;
3507                transition: opacity 0.2s ease, transform 0.15s ease;
3508                padding: 0 !important;
3509            }
3510            .zmp-btn:hover {
3511                opacity: 0.7;
3512                transform: scale(1.08);
3513            }
3514            .zmp-play-size {
3515                width: 48px !important;
3516                height: 48px !important;
3517                min-width: 48px !important;
3518            }
3519            .zmp-aux-size {
3520                width: 36px !important;
3521                height: 36px !important;
3522                min-width: 36px !important;
3523            }
3524            /* ── BLINDAGEM MÁXIMA PARA SVG E DESIGN NEON ──
3525               Garante que os controles respondam à "COR DOS ELEMENTOS" do painel,
3526               independentemente do fundo, restaurando o estilo Neon sem fills hardcoded. */
3527               
3528            /* 1. Cores e Fills dos Ícones (SVGs e FontAwesome) */
3529            html body #player #playBtn svg,
3530            html body #player #zmpLiveBtn svg,
3531            html body #player #volumeBtn svg,
3532            html body #player .zmp-svg,
3533            html body #player .zmp-btn i {
3534                display: block;
3535                color: var(--player-text-color, #ffffff) !important;
3536                fill: var(--player-text-color, #ffffff) !important;
3537                stroke: none !important;
3538                margin: 0 auto !important;
3539                pointer-events: none;
3540                width: 20px !important;
3541                height: auto !important;
3542                filter: none !important;
3543            }
3544            
3545            /* Ajuste de tamanho específico para Live e Volume */
3546            html body #player #zmpLiveBtn svg,
3547            html body #player #volumeBtn svg,
3548            html body #player #volumeBtn i,
3549            html body #player #zmpLiveBtn i {
3550                width: 18px !important;
3551            }
3552            
3553            /* Textos padronizados de AO VIVO */
3554            html body #player .neon-player__live-text,
3555            html body #player .neon-watch-label {
3556                color: var(--player-text-color, #ffffff) !important;
3557            }
3558            html body #player .neon-player__live-dot {
3559                background: var(--player-text-color, #ffffff) !important;
3560                box-shadow: 0 0 6px color-mix(in srgb, var(--player-text-color, #ffffff) 60%, transparent) !important;
3561            }
3562
3563            html body #player #zmpIconLoad {
3564                fill: none !important;
3565                stroke: currentColor !important;
3566            }
3567
3568            /* 2. Formato e Glow dos Botões Principais (Restaurando o Neon) */
3569            html body #player, html body .neon-player {
3570                background: var(--player-bg, rgba(20, 16, 33, 0.95)) !important;
3571            }
3572
3573            html body #player #playBtn,
3574            html body #player #zmpLiveBtn,
3575            html body #player #volumeBtn,
3576            html body #player .zmp-btn {
3577                background-color: transparent !important;
3578                box-shadow: none !important;
3579                display: flex;
3580                align-items: center;
3581                justify-content: center;
3582                cursor: pointer;
3583                transition: all 0.3s ease;
3584                border: none !important; /* Limpa bordas extras e heranças do themes/neon/style.css */
3585            }
3586
3587            /* Play Button - Anel Neon Principal */
3588            html body #player #playBtn {
3589                width: 48px !important;
3590                height: 48px !important;
3591                border-radius: 50% !important;
3592                border: 1.5px solid color-mix(in srgb, var(--player-text-color, #ffffff) 50%, transparent) !important;
3593                background: color-mix(in srgb, var(--player-text-color, #ffffff) 5%, transparent) !important;
3594            }
3595            html body #player #playBtn:hover {
3596                background: color-mix(in srgb, var(--player-text-color, #ffffff) 15%, transparent) !important;
3597                border-color: var(--player-text-color, #ffffff) !important;
3598                transform: scale(1.05);
3599                box-shadow: 0 0 15px color-mix(in srgb, var(--player-text-color, #ffffff) 30%, transparent) !important;
3600            }
3601
3602            /* Correção visual do play center gap (o triângulo engana o olho) */
3603            html body #player #playBtn svg {
3604                transform: translateX(1.5px);
3605            }
3606            /* Quando está pausado, o SVG muda para pause/spinner, então removemos o shift */
3607            html body #player #playBtn svg.animate-spin,
3608            html body #player #playBtn svg[class*="fa-pause"] {
3609                transform: translateX(0);
3610            }
3611
3612            /* Live/Volume Buttons - Anéis Menores */
3613            html body #player #zmpLiveBtn,
3614            html body #player #volumeBtn {
3615                width: 36px !important;
3616                height: 36px !important;
3617                border-radius: 50% !important;
3618                border: 1.5px solid color-mix(in srgb, var(--player-text-color, #ffffff) 30%, transparent) !important;
3619                background: transparent !important;
3620            }
3621            html body #player #zmpLiveBtn:hover,
3622            html body #player #volumeBtn:hover {
3623                border-color: color-mix(in srgb, var(--player-text-color, #ffffff) 80%, transparent) !important;
3624                background: color-mix(in srgb, var(--player-text-color, #ffffff) 10%, transparent) !important;
3625            }
3626
3627            /* Slider de Volume */
3628            .zmp-volume-slider {
3629                width: 80px;
3630                height: 4px;
3631                border-radius: 4px;
3632                appearance: none;
3633                background: color-mix(in srgb, var(--player-text-color, #ffffff) 20%, transparent);
3634                outline: none;
3635                cursor: pointer;
3636            }
3637            .zmp-volume-slider::-webkit-slider-thumb {
3638                appearance: none;
3639                width: 12px;
3640                height: 12px;
3641                border-radius: 50%;
3642                background: var(--player-text-color, #ffffff);
3643                cursor: pointer;
3644                box-shadow: 0 1px 4px rgba(0,0,0,0.3);
3645            }
3646            
3647            /* Responsive Hiding se a tela for mto pequena pro volume (inclui celular em paisagem) */
3648            @media (max-width: 1024px), (pointer: coarse) and (max-width: 1366px) {
3649                #zmpVolBtn, .zmp-volume-slider { display: none !important; }
3650                .zmp-player-controls-wrapper { margin-left: auto; gap: 12px; }
3651            }
3652            </style>
3653
3654
3655        </div><!-- /.neon-player__left-group -->
3656
3657        <!-- ──── GRUPO DIREITO: Botão ASSISTIR AO VIVO ──── -->
3658        <!-- Aparece apenas quando o widget de vídeo existe no DOM (JS controla) -->
3659        <div class="neon-player__video-btn-wrap" id="neonVideoWatchBtn" style="display:none;">
3660            <button class="neon-player__watch-btn" id="btnAssistirAoVivo" title="Assistir transmissão ao vivo">
3661                <span class="neon-watch-dot"></span>
3662                <span class="neon-watch-label">ASSISTIR AO VIVO</span>
3663            </button>
3664        </div>
3665
3666    </div><!-- /.neon-player__inner -->
3667    <div id="visualizer" style="display:none;"></div>
3668</div>
3669
3670<style>
3671/* ════════════════════════════════════════════════
3672   NEON PLAYER — Layout: Left-group + Right-button
3673   ════════════════════════════════════════════════ */
3674
3675/* O inner agora é: left-group flex-1 | btn-wrap flex-shrink-0 */
3676.neon-player__inner {
3677    display        : flex;
3678    align-items    : center;
3679    justify-content: space-between;
3680    max-width      : 1440px;
3681    margin         : 0 auto;
3682    padding        : 12px 32px;
3683    gap            : 24px;
3684}
3685
3686/* Grupo esquerdo: agrupa artwork, controles e volume numa fileira */
3687.neon-player__left-group {
3688    display    : flex;
3689    align-items: center;
3690    gap        : 24px;
3691    flex       : 1;
3692    min-width  : 0;
3693}
3694
3695/* Fix: info não cresce mais (ocupa apenas o que precisa) */
3696.neon-player__info {
3697    display    : flex;
3698    align-items: center;
3699    gap        : 14px;
3700    min-width  : 0;
3701    /* Remove o flex:1 antigo — agora o left-group controla o crescimento */
3702}
3703
3704/* ── Botão ASSISTIR AO VIVO (direita) ── */
3705.neon-player__video-btn-wrap {
3706    flex-shrink: 0;
3707    margin-left: auto; /* empurra para a extrema direita */
3708}
3709
3710.neon-player__watch-btn {
3711    display        : flex;
3712    align-items    : center;
3713    gap            : 8px;
3714    background     : transparent;
3715    color          : var(--player-text-color, #ffffff);
3716    border         : 1px solid color-mix(in srgb, var(--player-text-color, #ffffff) 40%, transparent);
3717    font-size      : 11px;
3718    font-weight    : 800;
3719    letter-spacing : 0.8px;
3720    text-transform : uppercase;
3721    padding        : 9px 20px;
3722    border-radius  : 999px;
3723    cursor         : pointer;
3724    white-space    : nowrap;
3725    transition     : all 0.2s ease;
3726    font-family    : 'Space Grotesk', 'Inter', sans-serif;
3727    box-shadow     : none;
3728}
3729
3730.neon-player__watch-btn:hover {
3731    background: color-mix(in srgb, var(--player-text-color, #ffffff) 10%, transparent);
3732    transform: scale(1.02);
3733}
3734
3735.neon-watch-dot {
3736    width        : 7px;
3737    height       : 7px;
3738    border-radius: 50%;
3739    background   : var(--player-text-color, #ffffff);
3740    flex-shrink  : 0;
3741    animation    : neon-watch-pulse 1.5s ease-in-out infinite;
3742}
3743
3744@keyframes neon-watch-pulse {
3745    0%, 100% { opacity: 1;   transform: scale(1); }
3746    50%      { opacity: 0.3; transform: scale(0.85); }
3747}
3748
3749/* Estado: vídeo aberto → botão muda para "FECHAR VÍDEO" */
3750.neon-player__watch-btn.is-open {
3751    background : color-mix(in srgb, var(--player-text-color, #ffffff) 15%, transparent);
3752    color      : var(--player-text-color, #ffffff);
3753    border     : 1px solid color-mix(in srgb, var(--player-text-color, #ffffff) 40%, transparent);
3754    box-shadow : none;
3755}
3756
3757.neon-player__watch-btn.is-open .neon-watch-dot {
3758    animation: none;
3759    opacity  : 1;
3760}
3761
3762/* Mobile: ocultar botão de vídeo (não aplicável) — inclui celular em paisagem */
3763@media (max-width: 1024px), (pointer: coarse) and (max-width: 1366px) {
3764    .neon-player__video-btn-wrap { display: none !important; }
3765    .neon-player__inner { padding: 10px 16px; gap: 12px; }
3766    .neon-player__left-group { gap: 12px; }
3767}
3768</style>
3769
3770<script>
3771(function() {
3772    function initWatchBtn() {
3773        var btn     = document.getElementById('btnAssistirAoVivo');
3774        var btnWrap = document.getElementById('neonVideoWatchBtn');
3775        var widget  = document.getElementById('vmpWidget');
3776        var label   = btn ? btn.querySelector('.neon-watch-label') : null;
3777
3778        // Só exibe o botão se o widget de vídeo existir no DOM
3779        if (!widget || !btn || !label) return;
3780        btnWrap.style.display = '';
3781
3782        function syncLabel() {
3783            var isOpen = widget.style.display !== 'none';
3784            btn.classList.toggle('is-open', isOpen);
3785            label.textContent = isOpen ? 'FECHAR VÍDEO' : 'ASSISTIR AO VIVO';
3786        }
3787
3788        btn.addEventListener('click', function() {
3789            var isOpen = widget.style.display !== 'none';
3790            widget.style.display = isOpen ? 'none' : 'block';
3791            syncLabel();
3792        });
3793
3794        // Sincronizar quando o botão × interno do mini player for clicado
3795        var closeBtn = document.getElementById('vmpCloseBtn');
3796        if (closeBtn) {
3797            closeBtn.addEventListener('click', function() {
3798                setTimeout(syncLabel, 50);
3799            });
3800        }
3801
3802        syncLabel(); // estado inicial
3803    }
3804
3805    if (document.readyState === 'loading') {
3806        document.addEventListener('DOMContentLoaded', initWatchBtn);
3807    } else {
3808        setTimeout(initWatchBtn, 200);
3809    }
3810
3811})();
3812</script>
3812
3813    <!-- Video Player Global: movido para dentro do #mainContent (topo) — Fix 3 -->
3814    <!-- O singleton define('VIDEO_PLAYER_GLOBAL_RENDERED') previne dupla renderização -->
3815
3816    
3817<footer class="neon-footer">
3818    <div class="neon-footer__accent-line"></div>
3819    <div class="neon-footer__inner">
3820
3821        <!-- Col 1: Marca / About -->
3822        <div class="neon-footer__col">
3823            <a href="home" class="neon-footer__logo">
3824                                    <img src="https://nativafmbauru.com.br/uploads/media/6a2974fa436ab_1781101818.png"
3825                         alt="Nativa FM Bauru">
3826                            </a>
3827            <p class="neon-footer__site-name">Nativa FM Bauru</p>
3828            <p class="neon-footer__desc">A Nativa é tudo e muito mais!</p>
3829            <div class="neon-footer__social">
3830                                    <a href="https://www.instagram.com/nativafmbauru/" target="_blank" rel="noopener" class="neon-footer__social-btn" title="Instagram">
3831                        <i class="fab fa-instagram"></i>
3832                    </a>
3833                                                    <a href="https://www.facebook.com/nativafmbauru" target="_blank" rel="noopener" class="neon-footer__social-btn" title="Facebook">
3834                        <i class="fab fa-facebook-f"></i>
3835                    </a>
3836                                                    <a href="https://www.youtube.com/@nativafm_bauru" target="_blank" rel="noopener" class="neon-footer__social-btn" title="YouTube">
3837                        <i class="fab fa-youtube"></i>
3838                    </a>
3839                                                                                                    <a href="https://play.google.com/store/apps/details?id=br.com.nativafmbauru.twa&amp;hl=pt_BR" target="_blank" rel="noopener" class="neon-footer__social-btn" title="Android">
3840                        <i class="fab fa-android"></i>
3841                    </a>
3842                                                    <a href="https://apps.apple.com/us/app/nativa-fm-bauru/id6467184660" target="_blank" rel="noopener" class="neon-footer__social-btn" title="iOS">
3843                        <i class="fab fa-apple"></i>
3844                    </a>
3845                                                    <a href="https://wa.me/5514997350454" target="_blank" rel="noopener" class="neon-footer__social-btn" title="WhatsApp">
3846                        <i class="fab fa-whatsapp"></i>
3847                    </a>
3848                            </div>
3849        </div>
3850
3851        <!-- Col 2 e 3: Navegação (2 colunas) -->
3852        <div class="neon-footer__col neon-footer__col--nav">
3853            <h4 class="neon-footer__heading">Navegação</h4>
3854            <ul class="neon-footer__links neon-footer__links--two-cols">
3855                                    <li><a href="https://nativafmbauru.com.br/s">Home</a></li>
3856                                    <li><a href="promocoes">Promoções</a></li>
3857                                    <li><a href="programacao">Programação</a></li>
3858                                    <li><a href="noticias">Notícias</a></li>
3859                                    <li><a href="equipe">Equipe</a></li>
3860                                    <li><a href="contato">Contato</a></li>
3861                            </ul>
3862        </div>
3863
3864        <!-- Col 4: Contato -->
3865        <div class="neon-footer__col">
3866            <h4 class="neon-footer__heading">Contato</h4>
3867            <ul class="neon-footer__contact">
3868                                    <li>
3869                        <!-- WhatsApp (mantido FA Brands) -->
3870                        <i class="fab fa-whatsapp"></i>
3871                        <a href="https://wa.me/5514997350454" target="_blank" rel="noopener">
3872                            (14) 997350454                        </a>
3873                    </li>
3874                                                                        <li>
3875                        <!-- Lucide: phone -->
3876                        <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.69 12a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.56 1.2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
3877                        <span>(14) 3232-3572</span>
3878                    </li>
3879                                                                                </ul>
3880        </div>
3881    </div>
3882
3883    <!-- Barra de Copyright -->
3884    <div class="neon-footer__bottom">
3885        <div class="neon-footer__bottom-inner">
3886            <div class="neon-footer__b-left">
3887                <p class="neon-footer__copyright">
3888                    Todos os Direito Reservados - uHost                     &middot; <a href="politica-de-privacidade" class="neon-footer__privacy-link">Política de Privacidade</a>
3889                </p>
3890            </div>
3891            <div class="neon-footer__b-right">
3892                                    <a href="https://uhost.com.br/" target="_blank" rel="noopener" class="neon-footer__dev-link">
3893                        <img src="https://nativafmbauru.com.br/uploads/media/69c33a45ac364_1774402117.png"
3894                             alt="Site e app para rádio - UHOST"
3895                             class="neon-footer__dev-logo"
3896                             onerror="this.closest('.neon-footer__dev-link').style.display='none'">
3897                    </a>
3898                            </div>
3899        </div>
3900    </div>
3901</footer>
3902
3903<script>
3904document.addEventListener('DOMContentLoaded', () => {
3905    const handleShelves = () => {
3906        if (window.innerWidth > 768) {
3907            document.querySelectorAll('.shelf-dots').forEach(d => d.style.display = 'none');
3908            return;
3909        } else {
3910            document.querySelectorAll('.shelf-dots').forEach(d => d.style.display = 'flex');
3911        }
3912
3913        const shelves = document.querySelectorAll('.shelf-row');
3914        shelves.forEach(shelf => {
3915            // Touch handler aplicado SEMPRE — independente de haver dots
3916            let _tx = 0, _tl = 0;
3917            shelf.addEventListener('touchstart', e => {
3918                _tx = e.touches[0].clientX;
3919                _tl = shelf.scrollLeft;
3920            }, { passive: true });
3921            shelf.addEventListener('touchmove', e => {
3922                shelf.scrollLeft = _tl + (_tx - e.touches[0].clientX);
3923            }, { passive: true });
3924
3925            // Encontra o container dos dots (pode estar fora do layout-wrapper, dentro do .container)
3926            const dotContainer = shelf.closest('.container')?.querySelector('.shelf-dots') ?? null;
3927
3928            if (!dotContainer) return;
3929
3930            const cards = Array.from(shelf.children);
3931            if (cards.length === 0) return;
3932
3933            // Evitar duplicações
3934            if (dotContainer.children.length === cards.length) return;
3935
3936            // Criar dots
3937            dotContainer.innerHTML = '';
3938            cards.forEach((_, i) => {
3939                const dot = document.createElement('div');
3940                dot.classList.add('dot');
3941                if (i === 0) dot.classList.add('active');
3942                dotContainer.appendChild(dot);
3943            });
3944
3945            const dots = Array.from(dotContainer.children);
3946
3947            // Observer para atualizar estado ativo
3948            const observer = new IntersectionObserver((entries) => {
3949                entries.forEach(entry => {
3950                    if (entry.isIntersecting) {
3951                        const index = cards.indexOf(entry.target);
3952                        if (index !== -1 && dots[index]) {
3953                            dots.forEach(d => d.classList.remove('active'));
3954                            dots[index].classList.add('active');
3955                        }
3956                    }
3957                });
3958            }, {
3959                root: shelf,
3960                threshold: 0.6 // pelo menos 60% visível para ativar
3961            });
3962
3963            cards.forEach(card => observer.observe(card));
3964        });
3965    };
3966
3967    handleShelves();
3968    window.addEventListener('resize', handleShelves);
3969});
3970</script>
3970
3971
3972    
3973    <!-- ===== WHATSAPP WIDGET (Global — todos os temas) ===== -->
3974    <!-- Oculto automaticamente se nenhum número estiver configurado -->
3975    <!-- Oculto em mobile via CSS (max-width: 768px) -->
3976    <link rel="stylesheet" href="https://nativafmbauru.com.br/assets/css/whatsapp-widget.css?v=1779829714">
3977    
3977<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js" defer></script>
3977
3978    
3978<script src="https://nativafmbauru.com.br/assets/js/whatsapp-widget.js" defer></script>
3978
3979    
3980<!-- ===== WHATSAPP WIDGET (Global) ===== -->
3981
3982<!-- Botão Flutuante -->
3983<button id="wa-fab"
3984        aria-label="Fale conosco pelo WhatsApp"
3985        title="Fale conosco pelo WhatsApp">
3986    <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
3987        <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
3988    </svg>
3989</button>
3990
3991<!-- Overlay -->
3992<div id="wa-overlay" aria-hidden="true"></div>
3993
3994<!-- Painel lateral (Drawer) -->
3995<aside id="wa-panel" role="dialog" aria-modal="true" aria-label="WhatsApp">
3996
3997    <!-- Cabeçalho -->
3998    <div id="wa-panel-header">
3999        <p class="wa-ph-title">
4000            <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
4001                <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
4002            </svg>
4003            WhatsApp
4004        </p>
4005        <button id="wa-close-btn" aria-label="Fechar">&#x2715;</button>
4006    </div>
4007
4008    <!-- Corpo -->
4009    <div id="wa-panel-body">
4010
4011        <p class="wa-body-title">Escaneie o QR Code e fale conosco pelo WhatsApp</p>
4012
4013        <!-- QR Code gerado via whatsapp-widget.js -->
4014        <div id="wa-qr-wrap" aria-label="QR Code WhatsApp"></div>
4015
4016        <p class="wa-body-hint">
4017            Aponte a câmera do celular para o código acima
4018        </p>
4019
4020    </div>
4021</aside>
4022
4023<!-- Variáveis injetadas para o JS -->
4024<script>
4025var WA_NUMBER  = "5514997350454";
4026var WA_BTN_POS = "bottom-left";
4027</script>
4027
4028
4029    <!-- Cookie Banner Global (Ajuste 3) -->
4030    <!-- ===== COOKIE BANNER — Bottom Sheet Nativo ===== -->
4031<div
4032    id="cookieBanner"
4033    class="cookie-banner"
4034    role="alertdialog"
4035    aria-live="polite"
4036    aria-label="Aviso de privacidade"
4037    aria-describedby="cookieBannerDesc"
4038    style="display:none;"
4039>
4040    <!-- Handle pill (drag indicator nativo) -->
4041    <div class="cookie-banner__handle" aria-hidden="true"></div>
4042
4043    <!-- Cabeçalho estilo app nativo -->
4044    <div class="cookie-banner__header">
4045                <div class="cookie-banner__app-icon" aria-hidden="true">
4046            <img src="https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp" alt="" width="46" height="46" loading="lazy">
4047        </div>
4048                <div class="cookie-banner__app-info">
4049            <p class="cookie-banner__app-name">Sua privacidade</p>
4050            <p class="cookie-banner__app-host">Nativa FM Bauru · nativafmbauru.com.br</p>
4051        </div>
4052    </div>
4053
4054    <!-- Separador -->
4055    <div class="cookie-banner__divider" aria-hidden="true"></div>
4056
4057    <!-- Texto explicativo -->
4058    <p class="cookie-banner__desc" id="cookieBannerDesc">
4059        Usamos cookies para manter o app funcionando e melhorar sua experiência. Nenhum dado é vendido a terceiros.
4060        <a href="https://nativafmbauru.com.br/?page=politica-de-privacidade" target="_blank" rel="noopener" class="cookie-banner__privacy-link">Política de privacidade</a>
4061    </p>
4062
4063    <!-- Ações empilhadas (estilo nativo) -->
4064    <div class="cookie-banner__actions">
4065        <button
4066            id="cookieBannerAccept"
4067            class="cookie-banner__btn cookie-banner__btn--primary"
4068            type="button"
4069            aria-label="Aceitar todos os cookies"
4070        >
4071            Aceitar todos
4072        </button>
4073        <button
4074            id="cookieBannerDecline"
4075            class="cookie-banner__btn cookie-banner__btn--secondary"
4076            type="button"
4077            aria-label="Aceitar apenas cookies essenciais"
4078        >
4079            Apenas essenciais
4080        </button>
4081    </div>
4082</div>
4083
4084<script>
4085/* ── Cookie Banner JS (IIFE) ── */
4086(function () {
4087    'use strict';
4088
4089    var STORAGE_KEY = 'cookie_consent';
4090    var banner      = document.getElementById('cookieBanner');
4091    if (!banner) return;
4092
4093    /* Se o usuário já escolheu, não mostrar novamente */
4094    try {
4095        if (localStorage.getItem(STORAGE_KEY)) return;
4096    } catch (e) {
4097        return;
4098    }
4099
4100    /* ── Animação de entrada (slide-up) ── */
4101    function showBanner() {
4102        banner.style.display = 'flex';
4103        void banner.offsetHeight;
4104        banner.classList.add('cookie-banner--visible');
4105    }
4106
4107    function hideBanner(callback) {
4108        banner.classList.remove('cookie-banner--visible');
4109        banner.classList.add('cookie-banner--hiding');
4110        setTimeout(function () {
4111            banner.style.display = 'none';
4112            banner.classList.remove('cookie-banner--hiding');
4113            if (typeof callback === 'function') callback();
4114        }, 400);
4115    }
4116
4117    function saveChoice(choice) {
4118        try { localStorage.setItem(STORAGE_KEY, choice); } catch (e) {}
4119    }
4120
4121    /* ── Mostrar após 1.2s ── */
4122    setTimeout(showBanner, 1200);
4123
4124    /* ── Botão Aceitar todos ── */
4125    var acceptBtn = document.getElementById('cookieBannerAccept');
4126    if (acceptBtn) {
4127        acceptBtn.addEventListener('click', function () {
4128            saveChoice('accepted');
4129            hideBanner(function () {
4130                document.dispatchEvent(new CustomEvent('cookie:accepted'));
4131            });
4132        });
4133    }
4134
4135    /* ── Botão Apenas essenciais ── */
4136    var declineBtn = document.getElementById('cookieBannerDecline');
4137    if (declineBtn) {
4138        declineBtn.addEventListener('click', function () {
4139            saveChoice('essential');
4140            hideBanner(function () {
4141                document.dispatchEvent(new CustomEvent('cookie:declined'));
4142            });
4143        });
4144    }
4145
4146    /* ── Fechar com Escape ── */
4147    document.addEventListener('keydown', function (e) {
4148        if (e.key === 'Escape' && banner.classList.contains('cookie-banner--visible')) {
4149            saveChoice('essential');
4150            hideBanner();
4151        }
4152    });
4153})();
4154</script>
4154
4155
4156    <!-- Smart App Install Banner (global — CTA de loja, prompt PWA ou instruções iOS).
4157         Dentro do app Rádio 3.0 não faz sentido convidar a instalar o app. -->
4158            
4159    <!-- Popup de Abertura (global — campanha cadastrada em /?page=banners).
4160         Sem campanha ativa não emite CSS, JS nem markup. -->
4161    
4162    <!-- Menu Mobile Global (Apenas Mobile via CSS). Também traz o estilo de mini
4163         player e o player expandido — nada disso existe dentro do app Rádio 3.0. -->
4164        
4165<nav class="mobile-bottom-nav">
4166  <!-- Item 1: fixo (Página Inicial) -->
4167  <a class="nav-item" href="https://nativafmbauru.com.br">
4168    <div class="nav-icon-box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9.5L12 3l9 6.5V20a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9.5z"/><path d="M9 21V12h6v9"/></svg></div>
4169  </a>
4170
4171  <!-- Itens 2-5: dinâmicos -->
4172              <a class="nav-item" href="/promocoes">
4173        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 12 20 22 4 22 4 12"/><rect x="2" y="7" width="20" height="5"/><line x1="12" y1="22" x2="12" y2="7"/><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></svg>        <span>Promoções</span>
4174      </a>
4175            <a class="nav-item" href="/noticias">
4176        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><circle cx="3" cy="6" r="1"/><circle cx="3" cy="12" r="1"/><circle cx="3" cy="18" r="1"/></svg>        <span>Notícias</span>
4177      </a>
4178            <a class="nav-item" href="/programacao">
4179        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>        <span>Programação</span>
4180      </a>
4181            <a class="nav-item" href="/contato">
4182        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>        <span>Contato</span>
4183      </a>
4184        </nav>
4185
4186<style>
4187.mobile-bottom-nav {
4188  display: none;
4189}
4190@media (max-width: 1024px), (pointer: coarse) and (max-width: 1366px) {
4191  .mobile-bottom-nav {
4192    position: fixed;
4193    bottom: 0; left: 0; right: 0;
4194    background: var(--bg-card, #ffffff);
4195    border-top: 1px solid var(--border-color, #e0e0e0);
4196    display: flex;
4197    justify-content: space-around;
4198    align-items: flex-start;
4199    padding: 12px 0 calc(12px + env(safe-area-inset-bottom));
4200    z-index: 9999;
4201  }
4202}
4203
4204html[data-theme="dark"] .mobile-bottom-nav,
4205body.dark-mode .mobile-bottom-nav {
4206    background: var(--bg-card, #121214);
4207    border-top: 1px solid var(--border-color, rgba(255, 255, 255, 0.08));
4208}
4209
4210.mobile-bottom-nav .nav-item {
4211  all: unset;
4212  display: flex !important;
4213  flex-direction: column !important;
4214  align-items: center !important;
4215  gap: 5px !important;
4216  cursor: pointer !important;
4217  padding: 4px 10px !important;
4218  text-decoration: none !important;
4219  box-sizing: border-box !important;
4220}
4221
4222.mobile-bottom-nav .nav-item svg { stroke: #9e9e9e; width: 24px; height: 24px; transition: all 0.2s; }
4223.mobile-bottom-nav .nav-item span { font-size: 11px; color: #9e9e9e; font-weight: 500; transition: all 0.2s; }
4224
4225/* Hover — feedback visual ao toque */
4226.mobile-bottom-nav .nav-item:hover svg,
4227.mobile-bottom-nav .nav-item:focus svg { stroke: var(--primary-color, #1B1464); opacity: 0.7; }
4228.mobile-bottom-nav .nav-item:hover span,
4229.mobile-bottom-nav .nav-item:focus span { color: var(--primary-color, #1B1464); opacity: 0.7; }
4230
4231/* Ativo — página atual */
4232.mobile-bottom-nav .nav-item.active svg { stroke: var(--primary-color, #1B1464); opacity: 1; }
4233.mobile-bottom-nav .nav-item.active span { color: var(--primary-color, #1B1464); font-weight: 500; opacity: 1; }
4234
4235.mobile-bottom-nav .nav-icon-box {
4236  width: 48px; height: 48px;
4237  border-radius: 14px;
4238  background: var(--primary-color, #1B1464);
4239  display: flex; align-items: center; justify-content: center;
4240  margin-top: -6px; /* Para alinhar opticamente a caixa maior com os outros ícones */
4241  transition: all 0.2s;
4242}
4243
4244/* Ícone box do item 1 quando ativo */
4245.mobile-bottom-nav .nav-item.active .nav-icon-box { background: var(--primary-color, #1B1464); }
4246
4247/* Ícone box do item 1 quando inativo */
4248.mobile-bottom-nav .nav-item:not(.active) .nav-icon-box { background: var(--border-color, #e0e0e0); }
4249.mobile-bottom-nav .nav-item:not(.active) .nav-icon-box svg { stroke: #9e9e9e !important; opacity: 1; }
4250
4251/* Home icon should be white inside the active solid box */
4252.mobile-bottom-nav .nav-item.active .nav-icon-box svg { stroke: #ffffff !important; }
4253
4254/* Prevent overrides from global player svg rule modifying this one if any */
4255
4256/* Para não sobrepor o footer em sites mobile, adicione padding bottom global body via classe */
4257@media (max-width: 1024px), (pointer: coarse) and (max-width: 1366px) {
4258    body {
4259        padding-bottom: calc(148px + env(safe-area-inset-bottom)) !important;
4260    }
4261    
4262    /* =========================================
4263       REESTILIZAÇÃO GLOBAL DO PLAYER MOBILE
4264       ESTILO DEEZER (PÍLULA FLUTUANTE LIMPA)
4265       ========================================= */
4266    #player, .radio-player, .neon-player, .d5-player, .app-player, .player-container, .global-player {
4267        position: fixed !important;
4268        bottom: calc(85px + env(safe-area-inset-bottom)) !important;
4269        left: 12px !important;
4270        right: 12px !important;
4271        width: auto !important;
4272        height: 64px !important;
4273        min-height: 64px !important;
4274        max-height: 64px !important;
4275        box-sizing: border-box !important;
4276        align-items: center !important;
4277        overflow: hidden !important; /* garante que nada vaze para fora */
4278        border-radius: 12px !important;
4279        background: var(--player-bg, #181818) !important;
4280        box-shadow: 0 8px 25px rgba(0,0,0,0.4) !important;
4281        border: 1px solid var(--border-color, rgba(255,255,255,0.06)) !important;
4282        padding: 0 12px !important;
4283        z-index: 9998 !important;
4284    }
4285
4286    /* Container global - forçar flex row */
4287    #player > div,
4288    .neon-player__inner, 
4289    .d5-player-inner {
4290        display: flex !important;
4291        flex-direction: row !important;
4292        align-items: center !important;
4293        justify-content: flex-start !important;
4294        padding: 0 !important;
4295        height: 100% !important;
4296        gap: 10px !important;
4297        width: 100% !important;
4298        border: none !important;
4299    }
4300
4301    /* Ocultar elementos desnecessários (Artwork e Status Badge agora são visíveis) */
4302    .neon-player__video-btn-wrap,
4303    .wave-player__video-btn-wrap,
4304    .pulse-player__video-btn-wrap,
4305    .glow-player__video-btn-wrap,
4306    .d5-volume-ctrl,
4307    .zmp-volume-slider,
4308    #volumeBtn,
4309    #liveBtn,
4310    #zmpLiveBtn,
4311    #videoBtn,
4312    .d5-play-ring,
4313    #visualizer,
4314    .neon-player__watch-btn,
4315    .wave-player__watch-btn,
4316    .pulse-player__watch-btn,
4317    .glow-player__watch-btn {
4318        display: none !important;
4319    }
4320
4321    /* ==== Ajuste: Alinhamento exato da Capa e Botão Play (Tamanho fixo 48x48) ====
4322       Cada tema pode redefinir o tamanho da capa com especificidade maior
4323       (ex.: WAVE usa 52px no brutalism_override.css). O que importa aqui é que
4324       o slot NUNCA saia do fluxo e não mude de tamanho entre estados. */
4325    .neon-player__artwork,
4326    .d5-player-artwork,
4327    .player-artwork,
4328    #playerArtwork,
4329    .wave-player__artwork,
4330    .pulse-player__artwork,
4331    .glow-player__artwork,
4332    .play-btn,
4333    .neon-player__play-btn,
4334    .d5-play-btn,
4335    #playBtn,
4336    .global-play-btn,
4337    .wave-player__play-btn {
4338        width: 48px !important;
4339        height: 48px !important;
4340        min-width: 48px !important;
4341        max-width: 48px !important;
4342        flex-shrink: 0 !important;
4343        align-self: center !important;
4344        display: flex !important;
4345        align-items: center !important;
4346        justify-content: center !important;
4347        box-sizing: border-box !important;
4348        margin: 0 !important;
4349        padding: 0 !important;
4350    }
4351
4352    .neon-player__artwork,
4353    .d5-player-artwork,
4354    .player-artwork,
4355    #playerArtwork,
4356    .wave-player__artwork,
4357    .pulse-player__artwork,
4358    .glow-player__artwork {
4359        border-radius: 6px !important; /* Capa quadrada com cantos suaves no mobile */
4360        overflow: hidden !important;
4361        display: block !important;
4362    }
4363
4364    .neon-player__artwork img,
4365    .d5-player-artwork img,
4366    .player-artwork img,
4367    #playerArtwork img,
4368    .wave-player__artwork img,
4369    .pulse-player__artwork img,
4370    .glow-player__artwork img {
4371        width: 48px !important;
4372        height: 48px !important;
4373        object-fit: cover !important;
4374        display: block !important;
4375    }
4376
4377    /* ════════════════════════════════════════════════════════════════
4378       ESQUELETO ÚNICO DO MINI PLAYER (NEON / WAVE / PULSE / GLOW)
4379       ────────────────────────────────────────────────────────────────
4380       Regra de ouro: o layout NÃO depende do conteúdo. A ordem e a
4381       distribuição são as mesmas com ou sem metadados — só o texto e a
4382       imagem mudam. Ordem fixa:
4383           capa → badge → título → artista → play (colado na direita)
4384       IMPORTANTE: usamos #player como prefixo para ter especificidade
4385       maior que as regras inline no @media do player.php. --- */
4386    #player .neon-player__left-group,
4387    #player .wave-player__left-group,
4388    #player .pulse-player__left-group,
4389    #player .glow-player__left-group {
4390        display: flex !important;
4391        flex-direction: row !important;
4392        align-items: center !important;
4393        justify-content: flex-start !important; /* sobrescreve qualquer space-between herdado */
4394        gap: 10px !important;
4395        flex: 1 1 0 !important;
4396        width: 100% !important;
4397        min-width: 0 !important;
4398        overflow: hidden !important;
4399    }
4400
4401    /* Bloco capa + texto: ocupa TODA a sobra, sempre. É esse flex:1 1 0 que
4402       impede o botão play de escorregar para o meio quando o texto é curto. */
4403    #player .neon-player__info,
4404    #player .wave-player__info,
4405    #player .pulse-player__info,
4406    #player .glow-player__info {
4407        display: flex !important;
4408        flex-direction: row !important;
4409        align-items: center !important;
4410        justify-content: flex-start !important;
4411        flex: 1 1 0 !important;
4412        min-width: 0 !important;
4413        gap: 10px !important;
4414        order: 1 !important; /* capa + texto primeiro */
4415        overflow: hidden !important;
4416    }
4417
4418    /* Coluna de texto: min-width:0 é obrigatório para o ellipsis funcionar
4419       dentro de um flex item (sem ele o texto empurra o container). */
4420    #player .wave-player__meta,
4421    #player .neon-player__meta,
4422    #player .pulse-player__meta,
4423    #player .glow-player__meta,
4424    #player .d5-player-meta,
4425    #player .player-meta,
4426    #player .nmp-meta-wrap {
4427        display: flex !important;
4428        flex-direction: column !important;
4429        justify-content: center !important;
4430        gap: 0 !important;
4431        line-height: 1 !important;
4432        overflow: hidden !important;
4433        min-width: 0 !important;
4434        flex: 1 1 0 !important;
4435    }
4436
4437    /* Play ancorado na borda direita em TODOS os estados.
4438       margin-left:auto + order:2 = sempre o último, sempre colado à direita.
4439       (o margin-left:20px do player.php perde: 0,2,0 vs 0,1,0) */
4440    #player .zmp-player-controls-wrapper {
4441        margin: 0 0 0 auto !important;
4442        padding: 0 !important;
4443        order: 2 !important;
4444        flex: 0 0 auto !important;
4445        gap: 0 !important;
4446        width: auto !important;
4447    }
4448
4449    /* ---- LÓGICA DEMO 05 ---- */
4450    .d5-player-inner > div:nth-child(2) {
4451        order: -1 !important; /* Bloco do Play vai para a esquerda */
4452        margin: 0 !important;
4453        margin-right: -4px !important;
4454        flex: 0 0 auto !important;
4455        width: auto !important;
4456    }
4457    .d5-player-left {
4458        order: 2 !important; /* Bloco de Info vai para a direita do Play */
4459        flex: 1 !important;
4460        width: auto !important;
4461        gap: 0 !important;
4462    }
4463    .d5-player-inner > div:nth-child(3) {
4464        display: none !important; /* Esconde botões extras estendidos */
4465    }
4466    .d5-player-meta {
4467        justify-content: center !important;
4468        min-height: 0 !important;
4469        gap: 0 !important;
4470    }
4471
4472    /* ---- TIPOGRAFIA COMUM (TITULO / ARTISTA) ----
4473       As três linhas têm ALTURA RESERVADA (badge 10px, título 16px,
4474       artista 12px). Linha vazia continua ocupando o mesmo espaço, então
4475       trocar de estado não causa reflow nem salto de altura. */
4476    .player-status-badge,
4477    .neon-player__status,
4478    .wave-player__status,
4479    .pulse-player__status,
4480    .glow-player__status,
4481    .live-badge,
4482    .wave-player__live-text {
4483        display: block !important;
4484        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
4485        font-size: 10px !important;
4486        font-weight: 700 !important;
4487        text-transform: uppercase !important;
4488        letter-spacing: 0.08em !important;
4489        margin-bottom: 3px !important;
4490        line-height: 1 !important;
4491        height: 10px !important;
4492        flex: 0 0 10px !important;
4493        color: var(--player-text-color, #ffffff) !important;
4494    }
4495
4496    .neon-player__title,
4497    .d5-player-title,
4498    .wave-player__title,
4499    .pulse-player__title,
4500    .glow-player__title,
4501    .player-title {
4502        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
4503        font-size: 13px !important;
4504        font-weight: 800 !important;
4505        color: var(--player-text-color, #ffffff) !important;
4506        text-transform: uppercase !important;
4507        width: 100% !important;
4508        text-shadow: none !important;
4509        -webkit-text-stroke: 0 !important;
4510        line-height: 16px !important;
4511        height: 16px !important;
4512        flex: 0 0 16px !important;
4513        display: block; /* sem !important: o JS do marquee precisa poder ocultar */
4514        padding: 0 !important;
4515        margin: 0 0 2px 0 !important;
4516        white-space: nowrap !important;
4517        overflow: hidden !important;
4518        text-overflow: ellipsis !important;
4519    }
4520
4521    /* Oculta os elementos originais quando o marquee está ativo — usa !important
4522       para sobrescrever regras de tema (ex: wave-player__title tem display:block !important) */
4523    #player .nmp-src-hidden {
4524        display: none !important;
4525    }
4526
4527    .neon-player__artist,
4528    .d5-player-artist,
4529    .wave-player__artist,
4530    .pulse-player__artist,
4531    .glow-player__artist,
4532    .player-artist {
4533        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
4534        font-size: 11px !important;
4535        font-weight: 400 !important;
4536        color: var(--player-text-color, #ffffff) !important;
4537        opacity: 0.8 !important;
4538        text-transform: uppercase !important;
4539        white-space: nowrap !important;
4540        overflow: hidden !important;
4541        text-overflow: ellipsis !important;
4542        width: 100% !important;
4543        line-height: 12px !important;
4544        height: 12px !important;
4545        flex: 0 0 12px !important;
4546        display: block;
4547        padding: 0 !important;
4548        margin: 0 !important;
4549    }
4550
4551    /* ---- AJUSTE 3: ANIMAÇÃO MARQUEE ---- */
4552    --marquee-duration: 10s;
4553
4554    /* Wrapper de texto do mini player mobile.
4555       Nenhum tema gera .nmp-meta-wrap hoje; mantido para compatibilidade.
4556       order:1 para acompanhar o esqueleto (capa+texto antes do play). */
4557    .nmp-meta-wrap {
4558        flex: 1 1 0 !important;
4559        min-width: 0 !important;
4560        overflow: hidden !important;
4561        display: flex !important;
4562        flex-direction: column !important;
4563        justify-content: center !important;
4564        gap: 0 !important;
4565        line-height: 1 !important;
4566        order: 1 !important;
4567    }
4568
4569    /* O antigo bloco .nmp-fallback (logo + nome do site) foi removido: ele
4570       trocava a subárvore inteira do mini player quando não havia metadados,
4571       com markup, tamanhos e ordem próprios — a causa do layout embaralhado.
4572       Agora o esqueleto é sempre o mesmo e só o texto muda. */
4573
4574    /* Linha de texto com suporte a marquee.
4575       O <span> só vira inline-block quando o marquee está ativo. Enquanto for
4576       inline, o text-overflow do pai consegue aplicar o ellipsis — um filho
4577       inline-block seria cortado a seco, sem reticências. */
4578    .mini-player-text {
4579        white-space: nowrap !important;
4580        overflow: hidden !important;
4581        text-overflow: ellipsis !important;
4582        display: block !important;
4583        width: 100% !important;
4584        position: relative !important;
4585    }
4586    .mini-player-text span {
4587        display: inline;
4588        white-space: nowrap !important; /* Impede que o texto duplicado (marquee) quebre linha */
4589        padding-right: 0;
4590    }
4591    /* Estado rolando: o span passa a conter DUAS cópias idênticas (.nmp-run),
4592       cada uma com o intervalo já embutido no próprio padding-right. Assim
4593       metade da largura total é exatamente uma cópia + intervalo, e o
4594       translateX(-50%) emenda o fim no começo sem salto. Se o intervalo
4595       ficasse solto entre as cópias (ou no padding do span), 50% cairia no
4596       meio do vão e a volta daria um pulo visível. */
4597    .mini-player-text span.scrolling {
4598        display: inline-block;
4599        padding-right: 0;
4600        will-change: transform;
4601        animation: nmp-marquee-scroll 12s linear infinite; /* duração real vem do JS */
4602    }
4603    .mini-player-text span.scrolling .nmp-run {
4604        display: inline-block;
4605        white-space: nowrap;
4606        padding-right: 48px; /* intervalo entre o fim de uma cópia e o início da outra */
4607        font-style: normal;
4608    }
4609    @keyframes nmp-marquee-scroll {
4610        0%   { transform: translateX(0); }
4611        100% { transform: translateX(-50%); }
4612    }
4613    /* Respeita quem pediu menos animação no sistema: em vez de rolar, volta ao
4614       texto estático com reticências — a segunda cópia sai de cena para não
4615       aparecer texto repetido cortado no meio. */
4616    @media (prefers-reduced-motion: reduce) {
4617        .mini-player-text span.scrolling {
4618            display: inline;
4619            animation: none !important;
4620            transform: none !important;
4621        }
4622        .mini-player-text span.scrolling .nmp-run {
4623            padding-right: 0 !important;
4624        }
4625        .mini-player-text span.scrolling .nmp-run + .nmp-run {
4626            display: none !important;
4627        }
4628        #player.nmp-one-line #nmpDisplayTitle {
4629            text-overflow: ellipsis !important;
4630        }
4631    }
4632
4633    /* ════════════════════════════════════════════════════════
4634       LAYOUT GLOBAL — Mini Player Mobile (TODOS OS TEMAS)
4635       Abordagem: seletores de CLASSE e nth-child apenas.
4636       SEM :has() — compatível com qualquer browser.
4637       ════════════════════════════════════════════════════════ */
4638
4639    /* --- Container direto do #player: força flex-start em TUDO --- */
4640    #player > div,
4641    #player > .neon-player__inner,
4642    #player > .wave-player__inner,
4643    #player > .pulse-player__inner,
4644    #player > .glow-player__inner,
4645    #player > .d5-player-inner {
4646        flex-wrap: nowrap !important;
4647        gap: 10px !important;
4648        padding: 0 !important;
4649        overflow: hidden !important;
4650        justify-content: flex-start !important;
4651        align-items: center !important;
4652    }
4653
4654    /* Nota: as regras de #player .neon-player__left-group, .neon-player__info e
4655       .zmp-player-controls-wrapper com prefixo #player estão na seção LÓGICA FLEX acima. */
4656
4657    /* ════════════════════════════════════════════════════════
4658       DEMO 01 — Inner: .max-w-screen-2xl
4659       Estrutura: [1:Left=info] [2:Center=play] [3:Right=extras]
4660       ════════════════════════════════════════════════════════ */
4661    /* Centro (playBtn) → vai para a ESQUERDA */
4662    #player > div.max-w-screen-2xl > div:nth-child(2) {
4663        order: 1 !important;
4664        flex: 0 0 auto !important;
4665        width: auto !important;
4666        margin: 0 !important;
4667        gap: 0 !important;
4668        align-items: center !important;
4669    }
4670    /* Esquerda (artwork + info) → expande para preencher */
4671    #player > div.max-w-screen-2xl > div:nth-child(1) {
4672        order: 2 !important;
4673        flex: 1 1 0 !important;
4674        min-width: 0 !important;
4675        overflow: hidden !important;
4676        width: auto !important;
4677    }
4678    /* Direita (extras/volume) → oculto */
4679    #player > div.max-w-screen-2xl > div:nth-child(3) {
4680        display: none !important;
4681    }
4682    /* Container de texto dentro do bloco de info do Demo01 */
4683    #player > div.max-w-screen-2xl > div:nth-child(1) > div:last-child {
4684        flex: 1 1 0 !important;
4685        min-width: 0 !important;
4686        overflow: hidden !important;
4687    }
4688
4689    /* --- Containers de meta-info internos --- */
4690    .neon-player__info,
4691    .wave-player__info,
4692    .pulse-player__info,
4693    .glow-player__info,
4694    .d5-player-meta {
4695        flex: 1 1 0 !important;
4696        min-width: 0 !important;
4697        overflow: hidden !important;
4698    }
4699
4700    /* --- Título e Artista: sempre truncados com ellipsis ---
4701       IMPORTANTE: NÃO adicionar display:block !important aqui —
4702       o JS do marquee precisa conseguir ocultar esses elementos
4703       via element.style.display = 'none' para mostrar os
4704       substitutos #nmpDisplayTitle / #nmpDisplayArtist no lugar. --- */
4705    #player #playerTitle,
4706    #player #playerArtist,
4707    #player .neon-player__title,
4708    #player .wave-player__title,
4709    #player .pulse-player__title,
4710    #player .glow-player__title,
4711    #player .d5-player-title,
4712    #player .player-title,
4713    #player .neon-player__artist,
4714    #player .wave-player__artist,
4715    #player .pulse-player__artist,
4716    #player .glow-player__artist,
4717    #player .d5-player-artist,
4718    #player .player-artist {
4719        max-width: 100% !important;
4720        overflow: hidden !important;
4721        text-overflow: ellipsis !important;
4722        white-space: nowrap !important;
4723        /* display intencionalmente ausente — controlado pelo JS do marquee */
4724    }
4725
4726    /* Garante que playerTitle/Artist aparecem (desfaz 'hidden' do Tailwind/temas)
4727       SEM !important para não bloquear o display:none que o marquee-JS coloca */
4728    #player #playerTitle { display: block; }
4729    #player #playerArtist { display: block; }
4730
4731    /* Elementos de display do marquee (substitutos).
4732       Tipografia e altura reservada IDÊNTICAS às do título/artista originais —
4733       o fallback é troca de string, nunca troca de estilo. */
4734    #nmpDisplayTitle {
4735        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
4736        font-size: 13px !important;
4737        font-weight: 800 !important;
4738        color: var(--player-text-color, #ffffff) !important;
4739        text-transform: uppercase !important;
4740        letter-spacing: 0.02em !important;
4741        line-height: 16px !important;
4742        height: 16px !important;
4743        flex: 0 0 16px !important;
4744        margin: 0 0 2px 0 !important;
4745    }
4746    #nmpDisplayArtist {
4747        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
4748        font-size: 11px !important;
4749        font-weight: 400 !important;
4750        color: var(--player-text-color, #ffffff) !important;
4751        opacity: 0.8 !important;
4752        text-transform: uppercase !important;
4753        line-height: 12px !important;
4754        height: 12px !important;
4755        flex: 0 0 12px !important;
4756    }
4757
4758    /* ═══════════════════════════════════════════════════════════════════
4759       ESTADO COM METADADOS — LINHA ÚNICA (classe .nmp-one-line)
4760       ───────────────────────────────────────────────────────────────────
4761       Com faixa tocando, música e artista deixam de ocupar duas linhas
4762       estreitas e passam a formar UMA linha só:  MÚSICA • ARTISTA.
4763       A coluna de texto do mini player tem ~150px; dividir isso em duas
4764       linhas de 13px/11px espremia os dois textos e cortava os dois.
4765       Em uma linha só, o texto ganha o dobro de largura útil e o que não
4766       couber rola em marquee contínuo (nunca reticências, nunca fonte menor).
4767
4768       O slot do artista continua existindo no DOM — apenas fica vazio e sai
4769       do fluxo — para o esqueleto (capa → badge → texto → play) não mudar.
4770       ═══════════════════════════════════════════════════════════════════ */
4771
4772    /* Linha vazia (o slot do artista) sai do fluxo: nada de 12px em branco. */
4773    #player.nmp-one-line .nmp-empty {
4774        display: none !important;
4775    }
4776
4777    /* Bloco de texto opticamente centrado com a capa de 48px. */
4778    #player.nmp-one-line .neon-player__meta,
4779    #player.nmp-one-line .wave-player__meta,
4780    #player.nmp-one-line .pulse-player__meta,
4781    #player.nmp-one-line .glow-player__meta,
4782    #player.nmp-one-line .d5-player-meta,
4783    #player.nmp-one-line .player-meta,
4784    #player.nmp-one-line .nmp-meta-wrap {
4785        justify-content: center !important;
4786        gap: 0 !important;
4787    }
4788
4789    /* A linha única. Mesmo corpo de fonte do título antigo (13px) — o gan
4789ho de
4790       leitura vem da largura, não de encolher a tipografia.
4791       text-overflow: clip (e não ellipsis) porque o overflow aqui é tratado
4792       pelo marquee; reticências só voltam em prefers-reduced-motion. */
4793    #player.nmp-one-line #nmpDisplayTitle {
4794        font-size: 13px !important;
4795        font-weight: 700 !important;
4796        letter-spacing: 0.01em !important;
4797        line-height: 18px !important;
4798        height: 18px !important;
4799        flex: 0 0 18px !important;
4800        margin: 0 !important;
4801        overflow: hidden !important;
4802        text-overflow: clip !important;
4803    }
4804
4805    /* Nome da música em destaque; separador e artista recuam em peso/opacidade
4806       para a linha ter hierarquia mesmo sendo uma só. */
4807    #player.nmp-one-line #nmpDisplayTitle .nmp-track {
4808        font-weight: 800 !important;
4809    }
4810    #player.nmp-one-line #nmpDisplayTitle .nmp-sep {
4811        font-weight: 400 !important;
4812        opacity: 0.55 !important;
4813        padding: 0 2px !important;
4814    }
4815    #player.nmp-one-line #nmpDisplayTitle .nmp-artist {
4816        font-weight: 400 !important;
4817        opacity: 0.8 !important;
4818    }
4819
4820    /* ═══════════════════════════════════════════════
4821       BADGE "● AO VIVO" — Mini Player Mobile Integrado
4822       ═══════════════════════════════════════════════ */
4823    .wave-player__meta [data-player-status],
4824    .neon-player__meta [data-player-status],
4825    .pulse-player__meta [data-player-status],
4826    .glow-player__meta [data-player-status],
4827    .d5-player-meta [data-player-status],
4828    .player-meta [data-player-status],
4829    .nmp-meta-wrap [data-player-status] {
4830        display: block !important;
4831        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
4832        font-size: 10px !important;
4833        font-weight: 700 !important;
4834        text-transform: uppercase !important;
4835        letter-spacing: 0.08em !important;
4836        white-space: nowrap !important;
4837        overflow: hidden !important;
4838        text-overflow: ellipsis !important;
4839        line-height: 1 !important;
4840        margin-bottom: 2px !important;
4841    }
4842
4843    /* ═══════════════════════════════════════════════════════════
4844       STATUS DO MINI PLAYER — apenas "Ao Vivo", sem avisos offline
4845       O estado de conexão é responsabilidade exclusiva da pílula
4846       flutuante (connection-status.php). Aqui sempre mostramos "Ao Vivo".
4847       Especificidade #player + attr > classe + attr — sobrescreve o bloco acima.
4848       ═══════════════════════════════════════════════════════════ */
4849
4850    /* Zera o texto dinâmico injetado pelo player.js */
4851    #player [data-player-status] {
4852        font-size: 0 !important;
4853        letter-spacing: 0 !important;
4854        color: transparent !important;
4855        margin-bottom: 3px !important;
4856    }
4857
4858    /* Injeta "● Ao Vivo" fixo via pseudo-elemento */
4859    #player [data-player-status]::before {
4860        content: "● Ao Vivo";
4861        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
4862        font-size: 9px !important;
4863        font-weight: 500 !important;
4864        color: var(--player-text-color, #ffffff) !important;
4865        opacity: 0.7 !important;
4866        text-transform: none !important;
4867        letter-spacing: normal !important;
4868        line-height: 1 !important;
4869    }
4870
4871    /* Quando em modo podcast/música, oculta "Ao Vivo" também */
4872    #player [data-player-status][data-is-stream="false"]::before {
4873        content: "" !important;
4874    }
4875
4876    /* ═══════════════════════════════════════════════════════════════════
4877       ESTADO FALLBACK — streaming SEM metadados (classe .nmp-no-track)
4878       ───────────────────────────────────────────────────────────────────
4879       Estado próprio, com design fechado: não existe faixa para anunciar,
4880       então a hierarquia passa a ser
4881           [selo AO VIVO] → [nome da emissora] → [praça que está tocando]
4882       em um bloco de texto ÚNICO e compacto (entrelinhas apertadas), em vez
4883       de linhas soltas com altura reservada em branco.
4884
4885       O esqueleto NÃO muda (capa → texto → play, mesma ordem, mesmos slots) —
4886       apenas as alturas reservadas das linhas vazias são liberadas e a
4887       tipografia é redistribuída. Ver o histórico em assets/css/style.css:
4888       o fallback antigo tirava a capa do fluxo e sangrava o texto.
4889       ═══════════════════════════════════════════════════════════════════ */
4890
4891    /* Linha sem conteúdo sai do fluxo — nada de 12/16px vazios entre os textos.
4892       Vale SÓ no fallback; com metadados o esqueleto de altura fixa é mantido. */
4893    #player.nmp-no-track .nmp-empty {
4894        display: none !important;
4895    }
4896
4897    /* Coluna de texto: bloco coeso, opticamente centrado com a capa de 48px. */
4898    #player.nmp-no-track .neon-player__meta,
4899    #player.nmp-no-track .wave-player__meta,
4900    #player.nmp-no-track .pulse-player__meta,
4901    #player.nmp-no-track .glow-player__meta,
4902    #player.nmp-no-track .d5-player-meta,
4903    #player.nmp-no-track .player-meta,
4904    #player.nmp-no-track .nmp-meta-wrap {
4905        justify-content: center !important;
4906        gap: 0 !important;
4907    }
4908
4909    /* Selo "AO VIVO" — chip translúcido que ancora o topo do bloco.
4910       align-self: flex-start é obrigatório: sem ele o chip esticaria por toda a
4911       largura da coluna (align-items: stretch do flex) e o fundo viraria faixa.
4912       Cor derivada de --player-text-color → acompanha o painel de cores. */
4913    #player.nmp-no-track [data-player-status] {
4914        display: inline-flex !important;
4915        align-items: center !important;
4916        gap: 5px !important;
4917        align-self: flex-start !important;
4918        width: auto !important;
4919        max-width: 100% !important;
4920        height: auto !important;
4921        flex: 0 0 auto !important;
4922        padding: 3px 8px 3px 7px !important;
4923        margin: 0 0 5px 0 !important;
4924        border-radius: 999px !important;
4925        background: rgba(255, 255, 255, 0.16) !important;
4926        background: color-mix(in srgb, var(--player-text-color, #ffffff) 18%, transparent) !important;
4927        color: var(--player-text-color, #ffffff) !important;
4928        font-size: 0 !important; /* silencia o texto dinâmico do player.js */
4929        line-height: 1 !important;
4930        overflow: visible !important;
4931    }
4932
4933    #player.nmp-no-track [data-player-status]::before {
4934        content: "AO VIVO" !important;
4935        font-size: 9px !important;
4936        font-weight: 700 !important;
4937        letter-spacing: 0.1em !important;
4938        line-height: 1 !important;
4939        color: inherit !important;
4940        opacity: 1 !important;
4941        text-transform: uppercase !important;
4942    }
4943
4944    /* Ponto do "ao vivo" com pulso — order:-1 coloca o pseudo depois no código
4945       à ESQUERDA do texto, sem precisar de elemento extra no DOM. */
4946    #player.nmp-no-track [data-player-status]::after {
4947        content: "" !important;
4948        order: -1 !important;
4949        width: 5px !important;
4950        height: 5px !important;
4951        flex: 0 0 5px !important;
4952        border-radius: 50% !important;
4953        background: currentColor !important;
4954        animation: nmp-live-pulse 1.9s ease-in-out infinite !important;
4955    }
4956
4957    /* Podcast/música sob demanda não é "ao vivo" → chip inteiro sai. */
4958    #player.nmp-no-track [data-player-status][data-is-stream="false"] {
4959        display: none !important;
4960    }
4961
4962    @keyframes nmp-live-pulse {
4963        0%, 100% { opacity: 1; transform: scale(1); }
4964        50%      { opacity: 0.45; transform: scale(0.8); }
4965    }
4966
4967    /* Nome da emissora — linha dominante do estado. Caixa natural (não força
4968       maiúsculas): respeita como o nome foi cadastrado no painel. */
4969    #player.nmp-no-track #nmpDisplayTitle {
4970        font-size: 14px !important;
4971        font-weight: 700 !important;
4972        letter-spacing: 0 !important;
4973        text-transform: none !important;
4974        line-height: 17px !important;
4975        height: 17px !important;
4976        flex: 0 0 17px !important;
4977        margin: 0 !important;
4978        opacity: 1 !important;
4979    }
4980
4981    /* Praça em transmissão ("Você está ouvindo X") — linha de apoio, colada ao
4982       nome da emissora. Reaproveita o slot do artista, então herda o marquee
4983       quando o nome da praça não cabe. */
4984    #player.nmp-no-track #nmpDisplayArtist {
4985        font-size: 11px !important;
4986        font-weight: 500 !important;
4987        letter-spacing: 0 !important;
4988        text-transform: none !important;
4989        line-height: 13px !important;
4990        height: 13px !important;
4991        flex: 0 0 13px !important;
4992        margin: 1px 0 0 0 !important;
4993        opacity: 0.72 !important;
4994    }
4995
4996    /* O elemento do seletor de praças vira redundante no fallback: seu texto já
4997       está na linha de apoio acima (com marquee). Só aqui — no desktop e no
4998       estado com metadados ele continua intacto. */
4999    #player.nmp-no-track #agNowPlaying {
5000        display: none !important;
5001    }
5002
5003    /* Instalação sem nome de emissora configurado: a praça assume o papel de
5004       linha principal em vez de sobrar uma linha pequena e solta. */
5005    #player.nmp-no-track.nmp-no-name #nmpDisplayArtist {
5006        font-size: 13px !important;
5007        font-weight: 600 !important;
5008        line-height: 16px !important;
5009        height: 16px !important;
5010        flex: 0 0 16px !important;
5011        margin: 0 !important;
5012        opacity: 0.92 !important;
5013    }
5014
5015    /* LÓGICA DO BOTÃO VOLTAR AO VIVO NO MOBILE (Quando toca Podcast) */
5016    #player.is-playing-ext #zmpLiveBtn {
5017        display: flex !important;
5018        position: absolute !important;
5019        right: 12px !important;
5020        top: 50% !important;
5021        transform: translateY(-50%) !important;
5022        width: 40px !important;
5023        height: 40px !important;
5024        background: var(--color-primary) !important;
5025        border: 2px solid var(--border-color, transparent) !important;
5026        border-radius: 0 !important; /* Estilo Brutalista Quadrado */
5027        color: var(--player-text-color, #ffffff) !important;
5028        align-items: center !important;
5029        justify-content: center !important;
5030        z-index: 99 !important;
5031        cursor: pointer !important;
5032        box-sizing: border-box !important;
5033        padding: 0 !important;
5034    }
5035    #player.is-playing-ext #zmpLiveBtn svg {
5036        width: 18px !important;
5037        height: 18px !important;
5038        margin: 0 !important;
5039        display: block !important;
5040    }
5041    #player.is-playing-ext .neon-player__info,
5042    #player.is-playing-ext .wave-player__info,
5043    #player.is-playing-ext .pulse-player__info,
5044    #player.is-playing-ext .glow-player__info {
5045        padding-right: 48px !important; /* Evitar que o texto fique debaixo do botão */
5046    }
5047
5048    /* ---- ESTILO DO BOTÃO DE PLAY ---- */
5049    #playBtn, .zmp-btn, .d5-play-btn, .neon-player__play-btn {
5050        background: transparent !important;
5051        border: none !important;
5052        box-shadow: none !important;
5053        width: auto !important;
5054        height: auto !important;
5055        padding: 0 !important;
5056        display: flex !important;
5057        align-items: center !important;
5058        justify-content: center !important;
5059        border-radius: 0 !important;
5060        transform: none !important; 
5061        pointer-events: auto !important;
5062        cursor: pointer !important;
5063        z-index: 10 !important;
5064    }
5065    
5066    #playBtn svg, .zmp-svg, .d5-play-btn i, .neon-player__play-btn svg {
5067        width: 28px !important;
5068        height: 28px !important;
5069        fill: var(--player-text-color, #ffffff) !important;
5070        color: var(--player-text-color, #ffffff) !important;
5071        filter: none !important;
5072    }
5073    
5074    /* Outros widgets fixos de rodapé (WhatsApp / Video aberto) sobem para escapar da pílula */
5075    .vmp-widget, #vmpWidget, #waWidget, .wa-widget {
5076        bottom: calc(145px + env(safe-area-inset-bottom)) !important;
5077        z-index: 9998 !important;
5078    }
5079
5080    /* Garantir que o player__inner não clippe os elementos filhos.
5081       O recorte final é do #player (overflow:hidden na pílula). */
5082    .neon-player__inner,
5083    .wave-player__inner,
5084    .pulse-player__inner,
5085    .glow-player__inner {
5086        overflow: visible !important;
5087    }
5088}
5089</style>
5090
5091
5092<script src="https://cdnjs.cloudflare.com/ajax/libs/color-thief/2.3.0/color-thief.umd.js"></script>
vendor: 1 bytes, line 5092
5092
5093<script>
5094document.addEventListener('DOMContentLoaded', function () {
5095  const items = document.querySelectorAll('.mobile-bottom-nav .nav-item');
5096  const currentPath = window.location.pathname;
5097
5098  items.forEach(item => {
5099    const href = item.getAttribute('href');
5100    if (!href) return;
5101    
5102    try {
5103      // Parse full URLs perfectly by using the current origin as base
5104      const urlObj = new URL(href, window.location.origin);
5105      const itemPath = urlObj.pathname;
5106      
5107      // Match if exact path, or if current starts with itemPath (except for root '/')
5108      if (itemPath === currentPath || (currentPath.startsWith(itemPath) && itemPath !== '/')) {
5109        item.classList.add('active');
5110      }
5111    } catch (e) {
5112      console.warn("Invalid Mobile Nav URL: ", href);
5113    }
5114  });
5115
5116  // Special case: Ensure Home acts correctly when at exact root
5117  const homeItems = document.querySelectorAll('.mobile-bottom-nav .nav-item');
5118  homeItems.forEach(item => {
5119      const href = item.getAttribute('href');
5120      if (href) {
5121          try {
5122              const urlObj = new URL(href, window.location.origin);
5123              if (urlObj.pathname === '/' && currentPath === '/') {
5124                  item.classList.add('active');
5125              } else if (urlObj.pathname === '/') {
5126                  item.classList.remove('active');
5127              }
5128          } catch(e){}
5129      }
5130  });
5131
5132  // =========================================
5133  // LOGIC FOR EXPANDED PLAYER
5134  // =========================================
5135  const miniPlayers = document.querySelectorAll('#player, .radio-player, .neon-player, .d5-player, .app-player, .player-container, .global-player');
5136  const epCard = document.getElementById('expandedPlayerCard');
5137  const epHandle = document.getElementById('epHandle');
5138  const epPlayBtn = document.getElementById('epPlayBtn');
5139
5140  // Synchronizing the UI
5141  let observerActivated = false;
5142  
5143  // Waveform logic
5144  const epWaveform = document.getElementById('epWaveform');
5145  const waveCtx = epWaveform ? epWaveform.getContext('2d') : null;
5146  let waveAnimId;
5147  let waveBars = [];
5148  const NUM_BARS = 18;
5149  const BAR_WIDTH = 3;
5150  const BAR_GAP = 3;
5151  let isPlayingAudio = false;
5152
5153  if (waveCtx) {
5154      for(let i=0; i<NUM_BARS; i++) {
5155          waveBars.push({ height: 2, phase: Math.random() * Math.PI * 2, speed: 0.05 + Math.random() * 0.06 });
5156      }
5157  }
5158
5159  function renderWaveform() {
5160      if(!waveCtx) return;
5161      waveCtx.clearRect(0, 0, epWaveform.width, epWaveform.height);
5162      const isCardOpen = epCard && epCard.classList.contains('active');
5163      let allSettled = true;
5164      const centerY = epWaveform.height; // Bars from bottom up
5165
5166      for(let i=0; i<NUM_BARS; i++) {
5167          const bar = waveBars[i];
5168          let targetHeight = 2; // Idle state
5169          
5170          if(isPlayingAudio && isCardOpen) {
5171              bar.phase += bar.speed;
5172              targetHeight = 4 + Math.abs(Math.sin(bar.phase)) * (epWaveform.height - 6);
5173              allSettled = false;
5174          }
5175          
5176          bar.height += (targetHeight - bar.height) * 0.2;
5177          if(Math.abs(bar.height - targetHeight) > 0.5) {
5178              allSettled = false;
5179          }
5180
5181          const isLight = document.body.classList.contains('theme-light');
5182          waveCtx.fillStyle = isLight ? 'rgba(26,23,48,0.7)' : 'rgba(255,255,255,0.7)';
5183          const startX = (epWaveform.width / 2) - ((NUM_BARS * (BAR_WIDTH + BAR_GAP)) / 2) + i * (BAR_WIDTH + BAR_GAP);
5184          waveCtx.fillRect(startX, Math.max(0, centerY - bar.height), BAR_WIDTH, bar.height);
5185      }
5186
5187      if(!allSettled || (isPlayingAudio && isCardOpen)) {
5188          if (waveAnimId) cancelAnimationFrame(waveAnimId);
5189          waveAnimId = requestAnimationFrame(renderWaveform);
5190      }
5191  }
5192
5193  // Background ColorLogic
5194  const epBgLayer1 = document.getElementById('epBgLayer1');
5195  const epBgLayer2 = document.getElementById('epBgLayer2');
5196  let currentBgLayer = 1;
5197  let lastArtworkSrc = '';
5198  let colorThief = null;
5199  try { colorThief = new ColorThief(); } catch(e) {}
5200
5201  function applyColors(imageUrl) {
5202      if (!colorThief || !imageUrl || imageUrl === lastArtworkSrc) return;
5203      lastArtworkSrc = imageUrl;
5204      
5205      const img = new Image();
5206      img.crossOrigin = 'Anonymous';
5207      img.src = imageUrl;
5208      img.onload = () => {
5209          let palette = null;
5210          try { palette = colorThief.getPalette(img, 3); } catch(e) { return; }
5211          if(palette && palette.length >= 2) {
5212              const c1 = `rgb(${palette[0][0]}, ${palette[0][1]}, ${palette[0][2]})`;
5213              const c2 = `rgb(${palette[1][0]}, ${palette[1][1]}, ${palette[1][2]})`;
5214              const gradient = `linear-gradient(135deg, ${c1} 0%, ${c2} 100%)`;
5215              
5216              if(currentBgLayer === 1 && epBgLayer2) {
5217                  epBgLayer2.style.backgroundImage = gradient;
5218                  epBgLayer2.style.opacity = '1';
5219                  if(epBgLayer1) epBgLayer1.style.opacity = '0';
5220                  currentBgLayer = 2;
5221              } else if (currentBgLayer === 2 && epBgLayer1) {
5222                  epBgLayer1.style.backgroundImage = gradient;
5223                  epBgLayer1.style.opacity = '1';
5224                  if(epBgLayer2) epBgLayer2.style.opacity = '0';
5225                  currentBgLayer = 1;
5226              }
5227          }
5228      };
5229  }
5230
5231  window.syncAllPlayerUI = function() {
5232      const epTitle = document.getElementById('epTitle');
5233      const epArtist = document.getElementById('epArtist');
5234      const epArtworkImg = document.getElementById('epArtworkImg');
5235      const epPlayIcon = document.getElementById('epPlayIcon');
5236      
5237      const pTitle = document.getElementById('playerTitle') || document.querySelector('.player-title');
5238      const pArtist = document.getElementById('playerArtist') || document.querySelector('.player-artist');
5239      const pArtwork = document.getElementById('playerArtwork') || document.querySelector('.player-artwork');
5240      const pPlayIcon = document.getElementById('playIcon') || document.querySelector('.play-icon, #playBtn svg, .global-play-btn svg');
5241      
5242      const doSync = () => {
5243          if(pTitle && epTitle) epTitle.textContent = pTitle.textContent;
5244          if(pArtist && epArtist) epArtist.textContent = pArtist.textContent;
5245          
5246          if(pArtwork && epArtworkImg) {
5247              const img = pArtwork.querySelector('img');
5248              if(img && img.src) {
5249                  epArtworkImg.removeAttribute('crossorigin');
5250                  epArtworkImg.src = img.src;
5251                  applyColors(img.src);
5252              } else if (pArtwork.tagName === 'IMG') {
5253                  epArtworkImg.removeAttribute('crossorigin');
5254                  epArtworkImg.src = pArtwork.src;
5255                  applyColors(pArtwork.src);
5256              }
5257          }
5258          
5259          let wasPlaying = isPlayingAudio;
5260          if(pPlayIcon && epPlayIcon) {
5261              const htmlStr = pPlayIcon.tagName.toLowerCase() === 'svg' ? pPlayIcon.outerHTML : pPlayIcon.innerHTML;
5262              // Remove inner IDs to avoid DOM conflicts
5263              const cleanHtmlStr = htmlStr.replace(/id="[^"]*"/g, '');
5264              epPlayIcon.innerHTML = cleanHtmlStr;
5265              
5266              if (htmlStr.includes('M7 ') || htmlStr.includes('M7,')) {
5267                  isPlayingAudio = true;
5268              } else if (htmlStr.includes('M6 3.5') || htmlStr.includes('M6,')) {
5269                  isPlayingAudio = false;
5270              } else {
5271                  isPlayingAudio = window.radioPlayer && window.radioPlayer.state === 'transmitting';
5272              }
5273          }
5274          if (wasPlaying !== isPlayingAudio) {
5275              renderWaveform();
5276          }
5277      };
5278      
5279      doSync();
5280      
5281      if(!observerActivated) {
5282          observerActivated = true;
5283          const observer = new MutationObserver(() => doSync());
5284          if(pTitle) observer.observe(pTitle, { childList: true, characterData: true, subtree: true });
5285          if(pArtist) observer.observe(pArtist, { childList: true, characterData: true, subtree: true });
5286          if(pArtwork) observer.observe(pArtwork, { childList: true, attributes: true, subtree: true, attributeFilter: ['src'] });
5287          if(pPlayIcon) observer.observe(pPlayIcon, { childList: true, subtree: true, attributes: true });
5288      }
5289  };
5290
5291  // Listen to global changes from RadioPlayer
5292  document.addEventListener('radioPlayerStateChange', window.syncAllPlayerUI);
5293
5294  // Bind Open/Toggle actions explicitly
5295  miniPlayers.forEach(p => {
5296      p.addEventListener('click', (e) => {
5297          // Card expandido é exclusivo do mobile (inclui celular em paisagem) — ignorar em desktop/tablet
5298          if (!window.matchMedia('(max-width: 1024px), (pointer: coarse) and (max-width: 1366px)').matches) return;
5299
5300          const isPlayBtn = e.target.closest('#playBtn') || e.target.closest('.d5-play-btn') ||
5301              e.target.closest('.neon-player__play-btn') || e.target.closest('.global-btn') ||
5302              e.target.closest('.global-play') || e.target.closest('#volumeBtn') ||
5303              e.target.closest('#zmpLiveBtn') || e.target.closest('#liveBtn') ||
5304              e.target.closest('.zmp-volume-slider') || e.target.closest('.zmp-player-controls-wrapper') ||
5305              e.target.closest('#btnAssistirAoVivo') || e.target.closest('.neon-player__video-btn-wrap');
5306
5307          if (isPlayBtn) {
5308              e.stopPropagation();
5309              return;
5310          }
5311
5312          if (epCard) {
5313              epCard.style.display = 'flex';
5314              void epCard.offsetWidth; // Force Reflow
5315              epCard.classList.add('active');
5316              document.body.style.overflow = 'hidden'; 
5317              window.syncAllPlayerUI(); 
5318              renderWaveform();
5319          }
5320      });
5321  });
5322
5323  // Expanded Play Btn
5324  if(epPlayBtn) {
5325      epPlayBtn.addEventListener('click', (e) => {
5326          e.stopPropagation();
5327          e.preventDefault();
5328          if (window.radioPlayer && typeof window.radioPlayer.togglePlay === 'function') {
5329              window.radioPlayer.togglePlay();
5330          } else {
5331              // Fallback
5332              const nativePlayBtn = document.getElementById('playBtn') || document.querySelector('.neon-player__play-btn, .d5-play-btn, .global-play');
5333              if(nativePlayBtn) nativePlayBtn.click();
5334          }
5335          setTimeout(window.syncAllPlayerUI, 50);
5336      });
5337  }
5338
5339  // Swipe capabilities
5340  if(epCard && epHandle) {
5341      function closeExpandedPlayer() {
5342          epCard.classList.remove('active');
5343          epCard.style.transform = ''; 
5344          document.body.style.overflow = '';
5345          renderWaveform(); // Jump start fade out
5346          setTimeout(() => {
5347              if(!epCard.classList.contains('active')) {
5348                  epCard.style.display = 'none';
5349              }
5350          }, 450);
5351      }
5352      
5353      let startY = 0;
5354      let currentY = 0;
5355      let isDragging = false;
5356
5357      // Click to close
5358      epHandle.addEventListener('click', (e) => {
5359          e.stopPropagation();
5360          closeExpandedPlayer();
5361      });
5362      epHandle.addEventListener('touchstart', (e) => {
5363          e.stopPropagation(); 
5364      }, {passive: true});
5365      epHandle.addEventListener('touchend', (e) => {
5366          e.stopPropagation();
5367          e.preventDefault();
5368          closeExpandedPlayer();
5369      }, {passive: false});
5370
5371      epCard.addEventListener('touchstart', (e) => {
5372          startY = e.touches[0].clientY;
5373          isDragging = true;
5374          epCard.style.transition = 'none'; 
5375      }, {passive: true});
5376
5377      epCard.addEventListener('touchmove', (e) => {
5378          if(!isDragging) return;
5379          currentY = e.touches[0].clientY;
5380          const diff = currentY - startY;
5381          if(diff > 0) { 
5382              epCard.style.transform = `translateY(${diff}px)`;
5383          }
5384      }, {passive: true});
5385
5386      epCard.addEventListener('touchend', (e) => {
5387          if(!isDragging) return;
5388          isDragging = false;
5389          const diff = currentY - startY;
5390          epCard.style.transition = 'transform 0.4s cubic-bezier(0.32, 0.72, 0, 1)';
5391          
5392          if(diff > 150) { 
5393              closeExpandedPlayer();
5394          } else {
5395              epCard.style.transform = '';
5396          }
5397      });
5398  }
5399
5400
5401  // ======================================================
5402  // Filtro de Metadados + Marquee do mini player mobile
5403  //
5404  // ESQUELETO ÚNICO: a estrutura, a ordem e a distribuição são as mesmas em
5405  // todos os estados. Sem metadados, só o TEXTO muda — nada é removido do DOM
5406  // e nada troca de lugar. Por isso não existe mais bloco de fallback próprio.
5407  // CORREÇÃO: flag de reentrância para evitar loop infinito
5408  // ======================================================
5409  (function initMetadataFilterAndMarquee() {
5410    if (!window.matchMedia('(max-width: 1024px), (pointer: coarse) and (max-width: 1366px)').matches) return; // Apenas mobile (inclui celular em paisagem)
5411
5412    // Palavras que indicam player em modo não-música. 'live' foi removido
5413    // para não bloquear podcasts como "Live Sessions" — 'ao vivo'/'aovivo' bastam.
5414    var BLOCKLIST = ['vinheta','trilha','break','off','locu\u00e7\u00e3o','locutor','intervalo','comercial','patroc\u00ednio','jingle','spot','ao vivo','aovivo'];
5415    var FALLBACK_NAME  = "Nativa FM Bauru";
5416    // Deploy em que o include roda fora do escopo de $siteName: cai na constante
5417    // que o head.php do tema publica, em vez de deixar a linha do nome vazia.
5418    if (!FALLBACK_NAME && typeof SITE_NAME !== 'undefined') FALLBACK_NAME = SITE_NAME || '';
5419
5420    // O texto de "carregando" só faz sentido nos primeiros segundos. Passada a
5421    // carência, se ainda não chegou metadado, a linha de título passa a exibir o
5422    // nome da emissora (configuração do tenant) em vez de mentir "carregando".
5423    var LOADING_GRACE_MS = 3000;
5424    var _startedAt = Date.now();
5425
5426    // FLAG: evitar loop infinito (observer -> DOM change -> observer...)
5427    var _busy = false;
5428
5429    function isMusicMetadata(title, artist) {
5430      var str = (title + ' ' + artist).toLowerCase();
5431      return !BLOCKLIST.some(function(w){ return str.indexOf(w) !== -1; });
5432    }
5433
5434    // Título que não representa uma faixa: vazio ou placeholder de carregamento
5435    // já fora da janela de carência.
5436    function isPlaceholderTitle(title) {
5437      if (!title) return true;
5438      return /^carregando/i.test(title) && (Date.now() - _startedAt) > LOADING_GRACE_MS;
5439    }
5440
5441    // Cria elementos de EXIBIÇÃO dedicados para o marquee.
5442    // Os elementos originais (#playerTitle/#playerArtist) NÃO são tocados —
5443    // apenas ocultados. Assim o MutationObserver não entra em loop.
5444    function getOrCreateDisplayEl(sourceEl, displayId) {
5445      var existing = document.getElementById(displayId);
5446      if (existing) return existing;
5447      var d = document.createElement('div');
5448      d.id = displayId;
5449      d.className = 'mini-player-text';
5450      d.appendChild(document.createElement('span'));
5451      sourceEl.parentNode.insertBefore(d, sourceEl.nextSibling);
5452      return d;
5453    }
5454
5455    // Velocidade do marquee em px/s. Duração fixa fazia texto curto se arrastar
5456    // e texto longo passar voando; com velocidade constante a leitura tem sempre
5457    // o mesmo ritmo — só o tempo de volta muda.
5458    var MARQUEE_SPEED  = 45;
5459    var MARQUEE_MIN_S  = 8;
5460    var MARQUEE_MAX_S  = 45;
5461
5462    // Monta uma "passada" do texto. `parts` é uma lista de trechos {text, cls} —
5463    // é o que permite música, separador e artista terem pesos diferentes dentro
5464    // da MESMA linha. wrapAsRun envolve tudo em .nmp-run (usado só no estado
5465    // rolando, onde existem duas cópias iguais).
5466    function buildRun(parts, wrapAsRun) {
5467      var frag = document.createDocumentFragment();
5468      var host = frag;
5469      if (wrapAsRun) {
5470        host = document.createElement('i');
5471        host.className = 'nmp-run';
5472        frag.appendChild(host);
5473      }
5474      for (var i = 0; i < parts.length; i++) {
5475        var p = parts[i];
5476        if (!p.text) continue;
5477        if (p.cls) {
5478          var s = document.createElement('span');
5479          s.className = p.cls;
5480          s.textContent = p.text; // textContent: metadado do streaming não é markup
5481          host.appendChild(s);
5482        } else {
5483          host.appendChild(document.createTextNode(p.text));
5484        }
5485      }
5486      return frag;
5487    }
5488
5489    // Ativa o marquee SÓ quando o texto realmente estoura o container.
5490    // A medição é SÍNCRONA: ler clientWidth já força o cálculo de layout, então
5491    // não dependemos de requestAnimationFrame — que fica suspenso quando a aba
5492    // está em segundo plano. Era essa dependência (mais a medição num único
5493    // frame, quando o elemento ainda podia ter largura 0) que deixava título
5494    // longo cortado sem nunca rolar. O retry usa setTimeout pelo mesmo motivo.
5495    function applyMarqueeOnDisplay(displayEl, parts) {
5496      if (!displayEl) return;
5497      var span = displayEl.querySelector('span');
5498      if (!span) return;
5499
5500      span.classList.remove('scrolling');
5501      span.style.animationDuration = '';
5502      span.textContent = '';
5503      span.appendChild(buildRun(parts, false));
5504
5505      var tries = 0;
5506      function decide() {
5507        // Container ainda sem largura medível (acabou de entrar no DOM, ou a
5508        // pílula ainda não foi posicionada) → tenta de novo em 100ms.
5509        if (displayEl.clientWidth === 0 && tries++ < 20) {
5510          setTimeout(decide, 100);
5511          return;
5512        }
5513        // Medir no CONTAINER, não no <span>: fora do estado de rolagem o span é
5514        // inline (para o ellipsis do pai funcionar) e inline não expõe scrollWidth.
5515        if (displayEl.scrollWidth <= displayEl.clientWidth + 1) return; // cabe: fica parado
5516
5517        // Duas cópias idênticas, cada uma com o intervalo embutido no próprio
5518        // padding — metade da largura total vira exatamente uma cópia, então o
5519        // translateX(-50%) emenda o fim no começo sem salto.
5520        span.textContent = '';
5521        span.appendChild(buildRun(parts, true));
5522        span.appendChild(buildRun(parts, true));
5523        span.classList.add('scrolling');
5524
5525        // A distância percorrida por ciclo é UMA cópia (texto + intervalo) —
5526        // é ela que define a duração, não a largura total do span.
5527        var run = span.querySelector('.nmp-run');
5528        var dist = run ? run.offsetWidth : 0;
5529        if (dist > 0) {
5530          var secs = Math.min(MARQUEE_MAX_S, Math.max(MARQUEE_MIN_S, dist / MARQUEE_SPEED));
5531          span.style.animationDuration = secs.toFixed(1) + 's';
5532        }
5533      }
5534      decide();
5535    }
5536
5537    // Texto da praça em transmissão ("Você está ouvindo X"), injetado pelo
5538    // seletor de praças (Modo Rede). No estado fallback ele passa a ser a linha
5539    // de apoio do bloco de texto — o elemento original é ocultado por CSS para
5540    // não duplicar a informação. Fora do Modo Rede o elemento não existe e o
5541    // fallback fica com duas linhas (selo + nome da emissora).
5542    function getCityLine() {
5543      var el = document.getElementById('agNowPlaying');
5544      if (!el || el.style.display === 'none') return '';
5545      return (el.textContent || '').trim();
5546    }
5547
5548    // Localiza o bloco capa+texto em qualquer um dos quatro temas.
5549    function findInfoEl(playerEl, titleEl) {
5550      var themed = playerEl.querySelector(
5551        '.neon-player__info, .wave-player__info, .pulse-player__info, .glow-player__info'
5552      );
5553      if (themed) return themed;
5554      return (titleEl.parentNode && titleEl.parentNode !== playerEl) ? titleEl.parentNode : null;
5555    }
5556
5557    function applyMetadataFilter() {
5558      if (_busy) return; // Evitar reentrada
5559
5560      var playerEl = document.getElementById('player') ||
5561                     document.querySelector('.neon-player, .radio-player');
5562      if (!playerEl) return;
5563
5564      var titleEl  = document.getElementById('playerTitle');
5565      var artistEl = document.getElementById('playerArtist');
5566      if (!titleEl || !artistEl) return;
5567
5568      var infoEl = findInfoEl(playerEl, titleEl);
5569      if (!infoEl) return;
5570
5571      var title  = (titleEl.textContent || '').trim();
5572      var artist = (artistEl.textContent || '').trim();
5573
5574      // Sem faixa exibível → ESTADO FALLBACK: a linha de título recebe o nome
5575      // da emissora e a de apoio recebe a praça em transmissão. A classe
5576      // .nmp-no-track no player liga o design próprio desse estado (bloco de
5577      // texto compacto + selo "AO VIVO"); o esqueleto continua o mesmo.
5578      var hasTrack   = !isPlaceholderTitle(title) && isMusicMetadata(title, artist);
5579      var showTitle  = hasTrack ? title  : FALLBACK_NAME;
5580      var showArtist = hasTrack ? artist : getCityLine();
5581
5582      // COM FAIXA → LINHA ÚNICA "MÚSICA • ARTISTA".
5583      // Duas linhas de ~150px espremiam os dois textos; em uma linha só o texto
5584      // tem o dobro da largura útil e o excedente rola em marquee. O slot do
5585      // artista continua no DOM, apenas vazio (.nmp-empty) — o esqueleto do
5586      // mini player não muda. Sem faixa, o fallback segue com as duas linhas
5587      // (nome da emissora + praça), cada uma com seu próprio marquee.
5588      var titleParts, artistParts;
5589      if (hasTrack) {
5590        titleParts = [{ text: showTitle, cls: 'nmp-track' }];
5591        if (showArtist) {
5592          titleParts.push({ text: ' • ', cls: 'nmp-sep' });
5593          titleParts.push({ text: showArtist, cls: 'nmp-artist' });
5594        }
5595        artistParts = [];
5596        showArtist  = ''; // o slot do artista fica vazio → sai do fluxo
5597      } else {
5598        titleParts  = [{ text: showTitle }
5598];
5599        artistParts = [{ text: showArtist }];
5600      }
5601
5602      _busy = true;
5603      try {
5604        // Classes de estado no #player — não são observadas pelo
5605        // MutationObserver (que só olha o texto de title/artist), então não há
5606        // risco de reentrância aqui.
5607        playerEl.classList.toggle('nmp-no-track', !hasTrack);
5608        playerEl.classList.toggle('nmp-no-name', !hasTrack && !showTitle);
5609        playerEl.classList.toggle('nmp-one-line', hasTrack);
5610
5611        // O bloco capa+texto NUNCA é ocultado — o esqueleto é sempre o mesmo.
5612        infoEl.style.display = '';
5613
5614        // Exibição dedicada para marquee (não toca nos originais observados)
5615        var displayTitle  = getOrCreateDisplayEl(titleEl, 'nmpDisplayTitle');
5616        var displayArtist = getOrCreateDisplayEl(artistEl, 'nmpDisplayArtist');
5617
5618        applyMarqueeOnDisplay(displayTitle, titleParts);
5619        applyMarqueeOnDisplay(displayArtist, artistParts);
5620
5621        // Linha vazia é retirada do fluxo no fallback e na linha única (regras
5622        // CSS #player.nmp-no-track .nmp-empty / #player.nmp-one-line .nmp-empty)
5623        // — evita o vão vertical em branco entre o selo e o texto.
5624        displayTitle.classList.toggle('nmp-empty', !showTitle);
5625        displayArtist.classList.toggle('nmp-empty', !showArtist);
5626
5627        // Usa classe CSS com !important para sobrescrever regras de tema (ex: wave-player__title)
5628        titleEl.classList.add('nmp-src-hidden');
5629        artistEl.classList.add('nmp-src-hidden');
5630        displayTitle.classList.remove('nmp-src-hidden');
5631        displayArtist.classList.remove('nmp-src-hidden');
5632        displayTitle.style.display = '';
5633        displayArtist.style.display = '';
5634      } finally {
5635        _busy = false;
5636      }
5637    }
5638
5639    // ----------------------------------------------------------------
5640    // Observer nos dois elementos originais.
5641    // CRITICAL: usar characterData:true + subtree:true para detectar
5642    // quando player.js faz `element.textContent = "..."` (muda text node)
5643    // O flag _busy já previne o loop de reintrância.
5644    // ----------------------------------------------------------------
5645    var titleEl  = document.getElementById('playerTitle');
5646    var artistEl = document.getElementById('playerArtist');
5647    var mo = new MutationObserver(function() {
5648      if (_busy) return;
5649      applyMetadataFilter();
5650    });
5651    var obsOpts = { childList: true, characterData: true, subtree: true };
5652    if (titleEl)  mo.observe(titleEl,  obsOpts);
5653    if (artistEl) mo.observe(artistEl, obsOpts);
5654
5655    // Também acionar quando o próprio radioPlayer dispara changestate
5656    setTimeout(applyMetadataFilter, 800);
5657    // Passada extra ao fim da carência: troca "Carregando..." pelo nome da
5658    // emissora caso o streaming não tenha mandado metadado nenhum.
5659    setTimeout(applyMetadataFilter, LOADING_GRACE_MS + 200);
5660    document.addEventListener('radioPlayerStateChange', function() {
5661      if (_busy) return;
5662      // Pequeno delay para o DOM ja ter sido atualizado
5663      setTimeout(applyMetadataFilter, 50);
5664    });
5665
5666    // Rotação de tela / mudança de largura muda a decisão do marquee.
5667    var _rzTimer;
5668    window.addEventListener('resize', function() {
5669      clearTimeout(_rzTimer);
5670      _rzTimer = setTimeout(applyMetadataFilter, 200);
5671    });
5672
5673    // Expor para reavaliação externa (ex.: troca de praça no Modo Rede)
5674    window.checkMiniPlayerOverflow = applyMetadataFilter;
5675  })();
5676
5677});
5678</script>
5678
5679
5680<!-- EXPANDED MOBILE PLAYER CARD -->
5681<div class="expanded-player-card" id="expandedPlayerCard">
5682    <div class="ep-bg-layer" id="epBgLayer1" style="opacity: 1;"></div>
5683    <div class="ep-bg-layer" id="epBgLayer2" style="opacity: 0;"></div>
5684    <div class="ep-bg-overlay"></div>
5685    <button class="ep-handle-btn" id="epHandle" aria-label="Minimize">
5686        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>
5687    </button>
5688    <div class="ep-content">
5689        <div class="ep-artwork has-image">
5690            <img src="" alt="Album Art" id="epArtworkImg">
5691        </div>
5692        <div class="ep-metadata">
5693            <h2 class="ep-title" id="epTitle">...</h2>
5694            <p class="ep-artist" id="epArtist">...</p>
5695            <canvas id="epWaveform" class="ep-waveform" width="120" height="30"></canvas>
5696        </div>
5697        <div class="ep-controls">
5698            <button class="ep-play-btn" id="epPlayBtn" aria-label="Play/Pause">
5699                <div class="ep-play-icon" id="epPlayIcon">
5700                    <!-- Ícone injetado dinamicamente -->
5701                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6 3.5a1.5 1.5 0 0 1 2.3-.8l11.5 8a1.5 1.5 0 0 1 0 2.6l-11.5 8A1.5 1.5 0 0 1 6 20.5v-17z" fill="currentColor"/></svg>
5702                </div>
5703            </button>
5704        </div>
5705    </div>
5706</div>
5707
5708<style>
5709/* Oculto em Desktop, exibido em Mobile */
5710.expanded-player-card {
5711    display: none;
5712}
5713
5714@media (max-width: 1024px), (pointer: coarse) and (max-width: 1366px) {
5715    .expanded-player-card {
5716        display: flex;
5717        flex-direction: column;
5718        position: fixed;
5719        bottom: calc(85px + env(safe-area-inset-bottom));
5720        left: 12px;
5721        width: calc(100% - 24px);
5722        height: 60px;
5723        z-index: 99999;
5724        background-color: var(--neon-bg-deep, var(--bg-color, #121212));
5725        color: var(--neon-text, var(--text-color, #ffffff));
5726        border-radius: 12px;
5727        opacity: 0;
5728        pointer-events: none;
5729        transition: all 0.42s cubic-bezier(0.32, 0.72, 0, 1);
5730        overflow: hidden;
5731        box-sizing: border-box;
5732    }
5733
5734    .expanded-player-card.active {
5735        bottom: 0;
5736        left: 0;
5737        width: 100%;
5738        height: 100vh;
5739        height: 100dvh;
5740        border-radius: 0;
5741        opacity: 1;
5742        pointer-events: auto;
5743    }
5744    
5745    .ep-bg-layer {
5746        position: absolute;
5747        top: 0; left: 0; right: 0; bottom: 0;
5748        z-index: 0;
5749        transition: opacity 1.5s ease;
5750        background-size: cover;
5751        background-position: center;
5752        background-image: linear-gradient(135deg, var(--neon-bg-deep, var(--bg-color, #121212)) 0%, rgba(0,0,0,0.9) 100%);
5753    }
5754    
5755    body.theme-light .ep-bg-layer {
5756        background-image: linear-gradient(135deg, var(--neon-bg-deep, var(--bg-color, #f0eef5)) 0%, rgba(255,255,255,0.9) 100%);
5757    }
5758    
5759    .ep-bg-overlay {
5760        position: absolute;
5761        top: 0; left: 0; right: 0; bottom: 0;
5762        z-index: 1;
5763        background: linear-gradient(to bottom, rgba(0,0,0,0.4) 0%, var(--neon-bg-deep, var(--bg-color, #121212)) 100%);
5764        pointer-events: none;
5765    }
5766    
5767    body.theme-light .ep-bg-overlay {
5768        background: linear-gradient(to bottom, rgba(255,255,255,0.2) 0%, var(--neon-bg-deep, var(--bg-color, #f0eef5)) 100%);
5769    }
5770    
5771    .ep-handle-btn {
5772        position: absolute;
5773        top: calc(16px + env(safe-area-inset-top));
5774        left: 16px;
5775        width: 44px;
5776        height: 44px;
5777        border-radius: 50%;
5778        background-color: var(--glass-border, rgba(255,255,255,0.1));
5779        border: none;
5780        display: flex;
5781        justify-content: center;
5782        align-items: center;
5783        cursor: pointer;
5784        color: var(--neon-text, var(--text-color, #fff));
5785        transition: transform 0.1s, background-color 0.2s;
5786        z-index: 99;
5787        padding: 0;
5788        pointer-events: auto;
5789    }
5790    
5791    .ep-handle-btn:active {
5792        transform: scale(0.9);
5793        background-color: var(--neon-surface-hover, rgba(255,255,255,0.2));
5794    }
5795    
5796    .ep-content {
5797        flex: 1;
5798        display: flex;
5799        flex-direction: column;
5800        align-items: center;
5801        justify-content: center;
5802        width: 100%;
5803        padding: 0 24px;
5804        box-sizing: border-box;
5805        opacity: 0;
5806        transition: opacity 0.2s ease;
5807        position: relative;
5808        z-index: 2;
5809    }
5810    .expanded-player-card.active .ep-content {
5811        opacity: 1;
5812        transition-delay: 0.15s;
5813    }
5814    
5815    .ep-artwork {
5816        width: 85%;
5817        aspect-ratio: 1 / 1;
5818        border-radius: 16px;
5819        background-color: var(--glass-border, rgba(255,255,255,0.1));
5820        box-shadow: var(--shadow-lg, 0 16px 40px rgba(0,0,0,0.5));
5821        margin-bottom: 6vh;
5822        overflow: hidden;
5823        display: flex;
5824        align-items: center;
5825        justify-content: center;
5826    }
5827    
5828    .ep-artwork img {
5829        width: 100%;
5830        height: 100%;
5831        object-fit: cover;
5832    }
5833    
5834    .ep-metadata {
5835        width: 100%;
5836        text-align: center;
5837        margin-bottom: 6vh;
5838    }
5839    
5840    .ep-title {
5841        font-family: var(--font-primary, sans-serif);
5842        font-size: 24px;
5843        font-weight: 700;
5844        margin: 0 0 8px 0;
5845        white-space: nowrap;
5846        overflow: hidden;
5847        text-overflow: ellipsis;
5848        color: var(--neon-text, var(--primary-color, var(--text-color, #fff)));
5849    }
5850    
5851    .ep-artist {
5852        font-family: var(--font-secondary, var(--font-primary, sans-serif));
5853        font-size: 16px;
5854        font-weight: 400;
5855        margin: 0;
5856        color: var(--neon-text-muted, var(--text-color, #ccc));
5857        opacity: 0.8;
5858        white-space: nowrap;
5859        overflow: hidden;
5860        text-overflow: ellipsis;
5861    }
5862    
5863    .ep-waveform {
5864        display: block;
5865        margin: 16px auto 0 auto;
5866        opacity: 0.8;
5867    }
5868    
5869    .ep-controls {
5870        width: 100%;
5871        display: flex;
5872        justify-content: center;
5873        align-items: center;
5874    }
5875    
5876    .ep-play-btn {
5877        width: 72px;
5878        height: 72px;
5879        border-radius: 50%;
5880        background-color: var(--primary-color, #1B1464);
5881        border: none;
5882        display: flex;
5883        justify-content: center;
5884        align-items: center;
5885        cursor: pointer;
5886        padding: 0;
5887        box-shadow: 0 8px 16px rgba(0,0,0,0.2);
5888        transition: transform 0.2s, background-color 0.2s;
5889        color: #ffffff !important; 
5890    }
5891    
5892    .ep-play-btn:active {
5893        transform: scale(0.95);
5894    }
5895    
5896    .ep-play-icon {
5897        width: 28px;
5898        height: 28px;
5899        display: flex;
5900        justify-content: center;
5901        align-items: center;
5902    }
5903    .ep-play-icon svg {
5904        width: 100%;
5905        height: 100%;
5906        color: #ffffff;
5907        fill: currentColor;
5908    }
5909}
5910</style>
5911    
5912    <!-- Barra de Status de Conexão Global (Apenas Mobile via CSS) -->
5913    
5914<div id="connectionStatusBar" role="alert" aria-live="assertive" aria-atomic="true">
5915    <span id="connectionStatusIcon"></span>
5916    <span id="connectionStatusMsg"></span>
5917</div>
5918
5919<style>
5920/* Oculto em desktop */
5921#connectionStatusBar {
5922    display: none;
5923}
5924
5925@media (max-width: 768px) {
5926    #connectionStatusBar {
5927        position: fixed;
5928        top: calc(env(safe-area-inset-top) + 12px);
5929        left: 16px;
5930        right: 16px;
5931        z-index: 100000;
5932        display: flex;
5933        align-items: center;
5934        gap: 10px;
5935        padding: 12px 20px;
5936        border-radius: 50px;
5937        color: #ffffff;
5938        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
5939        font-size: 14px;
5940        font-weight: 500;
5941        line-height: 1.3;
5942        box-sizing: border-box;
5943        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
5944        /* Estado padrão: acima da viewport com fade */
5945        transform: translateY(-80px);
5946        opacity: 0;
5947        pointer-events: none;
5948        transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1),
5949                    opacity 0.3s ease,
5950                    background-color 0.25s ease;
5951        will-change: transform, opacity;
5952    }
5953
5954    #connectionStatusBar.is-visible {
5955        transform: translateY(0);
5956        opacity: 1;
5957        pointer-events: auto;
5958    }
5959
5960    #connectionStatusBar.state-offline {
5961        background-color: #111111;
5962    }
5963
5964    #connectionStatusBar.state-online {
5965        background-color: #2e7d32;
5966    }
5967
5968    #connectionStatusIcon {
5969        flex-shrink: 0;
5970        width: 20px;
5971        height: 20px;
5972        display: flex;
5973        align-items: center;
5974        justify-content: center;
5975    }
5976
5977    #connectionStatusIcon svg {
5978        width: 20px;
5979        height: 20px;
5980        display: block;
5981    }
5982
5983    #connectionStatusMsg {
5984        flex: 1;
5985        min-width: 0;
5986        white-space: nowrap;
5987        overflow: hidden;
5988        text-overflow: ellipsis;
5989    }
5990}
5991</style>
5992
5993<script>
5994(function () {
5995    /* Ícone Wi-Fi com X — estilo Happn */
5996    var ICON_OFFLINE = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 6C4.27 3.47 8.46 2 12 2s7.73 1.47 11 4"/><path d="M5 10a10.16 10.16 0 0 1 7-2.82A10.16 10.16 0 0 1 19 10"/><path d="M8.53 14A5.14 5.14 0 0 1 12 12.85"/><line x1="15" y1="15" x2="21" y2="21"/><line x1="21" y1="15" x2="15" y2="21"/></svg>';
5997    var ICON_ONLINE  = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>';
5998
5999    var bar      = document.getElementById('connectionStatusBar');
6000    var iconEl   = document.getElementById('connectionStatusIcon');
6001    var msgEl    = document.getElementById('connectionStatusMsg');
6002    var dismissTimer = null;
6003
6004    function showBar(type) {
6005        if (!bar) return;
6006
6007        if (dismissTimer) {
6008            clearTimeout(dismissTimer);
6009            dismissTimer = null;
6010        }
6011
6012        // Remove estados anteriores e força reflow para reiniciar a transição
6013        bar.classList.remove('state-offline', 'state-online', 'is-visible');
6014        void bar.offsetWidth;
6015
6016        if (type === 'offline') {
6017            iconEl.innerHTML = ICON_OFFLINE;
6018            msgEl.textContent = 'Sem conexão à internet';
6019            bar.classList.add('state-offline', 'is-visible');
6020
6021            // Vibração háptica — iOS não suporta navigator.vibrate
6022            if (navigator.vibrate) {
6023                navigator.vibrate([200, 100, 200]);
6024            }
6025        } else {
6026            iconEl.innerHTML = ICON_ONLINE;
6027            msgEl.textContent = 'Conexão restabelecida';
6028            bar.classList.add('state-online', 'is-visible');
6029
6030            dismissTimer = setTimeout(function () {
6031                bar.classList.remove('is-visible');
6032                dismissTimer = null;
6033            }, 3000);
6034        }
6035    }
6036
6037    window.addEventListener('offline', function () { showBar('offline'); });
6038    window.addEventListener('online',  function () { showBar('online');  });
6039})();
6040</script>
6040
6041
6042    <!-- Audio Player Script — não carregado dentro do app Rádio 3.0: sem o markup
6043         do player ele quebraria no bindEvents, e lá o site não deve tocar áudio nem
6044         disputar a Media Session com o player nativo. Quem usa window.radioPlayer
6045         já confere se ele existe. -->
6046        
6046<script src="https://nativafmbauru.com.br/assets/js/player.js?v=1790900781"></script>
6046
6047        
6047<script src="https://nativafmbauru.com.br/assets/js/app.js?v=1790900781" defer></script>
6047
6048
6049    <!-- PWA Service Worker Registration -->
6050    
6050<script src="https://nativafmbauru.com.br/sw-init.js" defer></script>
6050
6051
6052    <!-- Analytics Tracker -->
6053    
6053<script src="https://nativafmbauru.com.br/assets/js/tracker.js" defer></script>
6053
6054
6055    <!-- Top Músicas: título/artista que não cabe no card desliza em vez de cortar -->
6056    
6056<script src="https://nativafmbauru.com.br/assets/js/chart-marquee.js?v=1790785599" defer></script>
6056
6057
6058    <!-- Banner Tracking (impressões e cliques) -->
6059    <!-- Não redeclarar: o head.php do tema já define `const SITE_URL`. Usar
6060         window.SITE_URL evita "Identifier 'SITE_URL' has already been declared"
6061         (que quebrava o tracking de banner e scripts seguintes). -->
6062    
6062<script>window.SITE_URL = window.SITE_URL || 'https://nativafmbauru.com.br';</script>
6062
6063        
6063<script>const ACTIVE_CITY_ID = null;</script>
6063
6064    
6064<script src="https://nativafmbauru.com.br/assets/js/banner-tracking.js?v=1784297539" defer></script>
6064
6065
6066    
6067    <!-- JSON-LD para SEO -->
6068    
6068<script type="application/ld+json">
6069    {
6070      "@context": "https://schema.org",
6071      "@type": "RadioStation",
6072      "name": "Nativa FM Bauru",
6073      "url": "https://nativafmbauru.com.br",
6074      "logo": "https://nativafmbauru.com.br/uploads/media/6a18a5b4f2efe_1780000180.webp",
6075      "description": "A Nativa é tudo e muito mais!"
6076    }
6077    </script>
6077
6078
6079    <!-- Código Personalizado — fim do <body> (raw, escopo do tenant) -->
6080        
6080<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"04e69c4ac2a5417fa45cc4543cb77976","r":1,"spa":2}' crossorigin="anonymous"></script>
6080
6081</body>
6082</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.