PageSourceSearch

https://www.farmaciasbrava.com.br/nossas-lojas

html farmaciasbrava.com.br collected 2026-09-24 10:42:29 UTC 151,009 bytes, 3,719 lines download raw bytes

1<!DOCTYPE html>
2<html lang="pt-br">
3
4
5
6
7<head>
8
9  <meta charset="UTF-8">
10  <meta name="viewport" content="width=device-width, initial-scale=1.0">
11  
12  <!-- SEO Meta Tags -->
13  <title>Encontre uma Farmácia Brava perto de você | Farmácias Brava </title>
14  <meta name="description" content="Encontre a Farmácia Brava mais próxima. Consulte endereços, horários de atendimento e telefones das nossas lojas.">
15  <meta name="keywords" content="ecommerce, compras online, ofertas, produtos">
16  <meta name="author" content="RetailOn">
17  <meta name="robots" content="index, follow">
18  <link rel="canonical" href="https://www.farmaciasbrava.com.br/nossas-lojas">
19  
20  <!-- Open Graph / Facebook -->
21  <meta property="og:type" content="website">
22  <meta property="og:url" content="https://www.farmaciasbrava.com.br/nossas-lojas">
23  <meta property="og:title" content="Encontre uma Farmácia Brava perto de você | Farmácias Brava ">
24  <meta property="og:description" content="Encontre a Farmácia Brava mais próxima. Consulte endereços, horários de atendimento e telefones das nossas lojas.">
25  <meta property="og:image" content="https://storage.googleapis.com/retailon-publico/brava/admin/icone-perfil.png">
26  <meta property="og:image:secure_url" content="https://storage.googleapis.com/retailon-publico/brava/admin/icone-perfil.png">
27  <meta property="og:image:width" content="1200">
28  <meta property="og:image:height" content="630">
29  <meta property="og:image:type" content="image/jpeg">
30
31  <!-- Twitter -->
32  <meta property="twitter:card" content="summary_large_image">
33  <meta property="twitter:url" content="https://www.farmaciasbrava.com.br/nossas-lojas">
34  <meta property="twitter:title" content="Farmácias Brava ">
35  <meta property="twitter:description" content="Aproveite nossas ofertas no site ou pelo app e receba em casa ou retire seus pedidos na loja.">
36  <meta property="twitter:image" content="https://storage.googleapis.com/retailon-publico/brava/admin/icone-perfil.png">
37  
38  <!-- Mobile Web App -->
39  <meta name="theme-color" content="#ffffff">
40  <meta name="mobile-web-app-capable" content="yes">
41  <meta name="apple-mobile-web-app-capable" content="yes">
42  <meta name="apple-mobile-web-app-status-bar-style" content="default">
43  <meta name="apple-mobile-web-app-title" content="Farmácias Brava ">
44  
45  
46  
47  <!-- Favicon -->
48  
49  <link rel="icon" type="image/x-icon" href="https://storage.googleapis.com/retailon-publico/brava/imagens/favicon.png">
50  <link rel="apple-touch-icon" sizes="180x180" href="https://storage.googleapis.com/retailon-publico/brava/imagens/favicon.png">
51  <link rel="icon" type="image/png" sizes="16x16" href="https://storage.googleapis.com/retailon-publico/brava/imagens/favicon.png">
52  <link rel="icon" type="image/png" sizes="32x32" href="https://storage.googleapis.com/retailon-publico/brava/imagens/favicon.png">
53  
54
55  
55<script type="ff2c2aaab21707ab2ba08cc2-text/javascript">
56    /*
57    * Tags do Django que serão utilizadas dentro dos scripts da aplicação
58    * Lógica feita através da inserção de uma função na API 'window' do navegador que retorna o valor desejado e que foi configurada como read-only, assim nao sendo possível alterar via console do navegador
59    * Toda a lógica é executada após o carregamento da página para nao impactar na performace inicial
60    * ATENÇÃO: DEVIDO A ISSO, TOME CUIDADO COM O USO DA VARIÁVEL, POIS SÓ SERÁ POSSÍVEL REALIZAR AÇÕES APÓS O CARREGAMENTO DA PÁGINA
61    */
62    const APP_CONTEXT_VALUE = Object.freeze({
63      auth: Object.freeze({
64        is_autenticado: false,
65        nm_primeiro: ``,
66      }),
67      ambiente: Object.freeze({
68        is_app: /true/.test(`${false}`),
69        is_pagina_produto: /true/.test(`${false}`),
70      }),
71      app: Object.freeze({
72        link_android: '',
73        link_ios: '',
74        play_store: '',
75        app_store: '',
76        deep_link: '',
77        deep_link_android: '',
78        deep_link_ios: '',
79      }),
80      seguranca: Object.freeze({
81        csrf_token: 'OVFTj6iZUaoYaiuN12wRuhMzbo7fwr0GG8qNrhXRXeVzuizy7rszjfRVVKazkHx7',
82        session_uuid: '',
83      }),
84      pagamento: Object.freeze({
85        integrador_antifraude: 'getnet',
86        adquirente: 'getnet',
87        public_token: '',
88        url_antifraude: 'https://api.globalgetnet.com/dpm/digital\u002Dplatform/antifraud/afdf.js',
89      }),
90      integracoes: Object.freeze({
91        recaptcha_site_key: '6LeTEYgsAAAAAAS\u002DrSySSWZyRiNHzHcfExsfIjqY',
92      }),
93      preco: Object.freeze({
94        estado: '',
95        estado_padrao: '',
96        filial_id: '',
97      }),
98    });
99
100    Object.defineProperty(window, "APP_CONTEXT", {
101      value: () => APP_CONTEXT_VALUE,
102      writable: false,
103      configurable: false,
104    });
105
106    // Aliases de compatibilidade para scripts legados.
107    Object.defineProperty(window, "IS_AUTENTICADO", {
108      value: () => window.APP_CONTEXT().auth.is_autenticado,
109      writable: false,
110      configurable: false,
111    });
112    Object.defineProperty(window, "NM_PRIMEIRO", {
113      value: () => window.APP_CONTEXT().auth.nm_primeiro,
114      writable: false,
115      configurable: false,
116    });
117
118    const IS_APP = /true/.test(`${false}`);
119    Object.defineProperty(window, "IS_APP", {
120      value: () => window.APP_CONTEXT().ambiente.is_app,
121      writable: false,
122      configurable: false,
123    });
124    Object.defineProperty(window, "CSRF_TOKEN", {
125      value: () => window.APP_CONTEXT().seguranca.csrf_token,
126      writable: false,
127      configurable: false,
128    });
129    Object.defineProperty(window, "INTEGRADOR_ANTIFRAUDE", {
130      value: () => window.APP_CONTEXT().pagamento.integrador_antifraude,
131      writable: false,
132      configurable: false,
133    });
134    Object.defineProperty(window, "ADQUIRENTE", {
135      value: () => window.APP_CONTEXT().pagamento.adquirente,
136      writable: false,
137      configurable: false,
138    });
139    Object.defineProperty(window, "PUBLIC_TOKEN", {
140      value: () => window.APP_CONTEXT().pagamento.public_token,
141      writable: false,
142      configurable: false,
143    });
144    Object.defineProperty(window, "__ANTIFRAUDE_AFDF_URL", {
145      value: () => window.APP_CONTEXT().pagamento.url_antifraude,
146      writable: false,
147      configurable: false,
148    });
149    Object.defineProperty(window, "SESSION_UUID", {
150      value: () => window.APP_CONTEXT().seguranca.session_uuid,
151      writable: false,
152      configurable: false,
153    });
154    Object.defineProperty(window, "recaptcha_site_key", {
155      value: () => window.APP_CONTEXT().integracoes.recaptcha_site_key,
156      writable: false,
157      configurable: false,
158    });
159  </script>
159
160
161  <!-- CRÍTICOS (preconnect) -->
162  <link rel="preconnect" href="https://www.googletagmanager.com" crossorigin>
163  <link rel="preconnect" href="https://static.hotjar.com" crossorigin>    
164  <link rel="preconnect" href="https://www.clarity.ms" crossorigin>
165  <link rel="preconnect" href="https://connect.facebook.net" crossorigin>
166  <link rel="preconnect" href="https://analytics.tiktok.com" crossorigin>
167  <link rel="preconnect" href="https://bat.bing.com" crossorigin>
168  <link rel="preconnect" href="https://tag.navdmp.com" crossorigin>
169
170  <!-- BAIXA PRIORIDADE (dns-prefetch) -->
171  <link rel="dns-prefetch" href="//www.google-analytics.com">
172  <link rel="dns-prefetch" href="//googleads.g.doubleclick.net">
173  <link rel="dns-prefetch" href="//ad.doubleclick.net">
174  
175  
175<script type="ff2c2aaab21707ab2ba08cc2-text/javascript">
176    window.__AN_CFG = {
177      gtm: "GTM-THG4PHZ",           // se tiver GTM, deixe GA4/Meta pelo GTM, exceto para o RetailON
178      ga4: "",           // use só se NÃO tiver GTM
179      ga4_retailon: "",      // chave secundária para o RetailON G-RQCDM9M3X2
180      tenant_name: "brava", // nome do tenant
181      tenant_id: "1", // id do tenant
182      tenant_segment: "None", // segmento do tenant
183      price_zone: "", // zona de preço do tenant
184
185      hotjar: { hjid: "6549243", hjsv: "6" },
186      fb_pixel: "780780368411618",
187      tiktok: "",
188      bing_uet: "", 
189      clarity: "",
190      navegg_acc: "",
191      streamshop_ads: "true", //
192      // flags de controle
193      metaAutoPageView: false,         // GTM já dispara? então false
194      gaAutoPageView: false,           // deixamos Analytics.page() cuidar
195      tiktokAutoPage: false            // chamamos ttq.page() via Analytics.page()
196    };
197  </script>
197
198
199  
200  
201  
201<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/sha256.min.js" async defer type="ff2c2aaab21707ab2ba08cc2-text/javascript"></script>
vendor: 73 bytes, lines 201-203
201
202  
203  <script src="https://www.google.com/recaptcha/enterprise.js?render=
2036LeTEYgsAAAAAAS-rSySSWZyRiNHzHcfExsfIjqY
vendor: 66 bytes, lines 203-206
203" type="ff2c2aaab21707ab2ba08cc2-text/javascript"></script>
204  
205
206  
206<script type="ff2c2aaab21707ab2ba08cc2-text/javascript" src="/staticfiles/js/analytics-loader.js" defer></script>
206
207  
208  <style>
209    
210      @font-face {
211  font-family: 'Gilroy';
212  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-Thin.woff2') format('woff2');
213  font-weight: 100;
214  font-style: normal;
215  font-display: swap;
216}
217
218@font-face {
219  font-family: 'Gilroy';
220  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-UltraLight.woff2') format('woff2');
221  font-weight: 200;
222  font-style: normal;
223  font-display: swap;
224}
225
226@font-face {
227  font-family: 'Gilroy';
228  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-Light.woff2') format('woff2');
229  font-weight: 300;
230  font-style: normal;
231  font-display: swap;
232}
233
234@font-face {
235  font-family: 'Gilroy';
236  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-Regular.woff2') format('woff2');
237  font-weight: 400;
238  font-style: normal;
239  font-display: swap;
240}
241
242@font-face {
243  font-family: 'Gilroy';
244  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-RegularItalic.woff2') format('woff2');
245  font-weight: 400;
246  font-style: italic;
247  font-display: swap;
248}
249
250@font-face {
251  font-family: 'Gilroy';
252  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-Medium.woff2') format('woff2');
253  font-weight: 500;
254  font-style: normal;
255  font-display: swap;
256}
257
258@font-face {
259  font-family: 'Gilroy';
260  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-MediumItalic.woff2') format('woff2');
261  font-weight: 500;
262  font-style: italic;
263  font-display: swap;
264}
265
266@font-face {
267  font-family: 'Gilroy';
268  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-SemiBold.woff2') format('woff2');
269  font-weight: 600;
270  font-style: normal;
271  font-display: swap;
272}
273
274@font-face {
275  font-family: 'Gilroy';
276  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-SemiBoldItalic.woff2') format('woff2');
277  font-weight: 600;
278  font-style: italic;
279  font-display: swap;
280}
281
282@font-face {
283  font-family: 'Gilroy';
284  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-Bold.woff2') format('woff2');
285  font-weight: 700;
286  font-style: normal;
287  font-display: swap;
288}
289
290@font-face {
291  font-family: 'Gilroy';
292  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-BoldItalic.woff2') format('woff2');
293  font-weight: 700;
294  font-style: italic;
295  font-display: swap;
296}
297
298@font-face {
299  font-family: 'Gilroy';
300  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-ExtraBold.woff2') format('woff2');
301  font-weight: 800;
302  font-style: normal;
303  font-display: swap;
304}
305
306@font-face {
307  font-family: 'Gilroy';
308  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-Black.woff2') format('woff2');
309  font-weight: 900;
310  font-style: normal;
311  font-display: swap;
312}
313
314@font-face {
315  font-family: 'Gilroy';
316  src: url('/staticfiles/css/fonts/fonte-gilroy/Gilroy-Heavy.woff2') format('woff2');
317  font-weight: 950;
318  font-style: normal;
319  font-display: swap;
320}
321    
322    :root {
323      
324        --f-base: 'Gilroy';
325      
326      
327        --c-header-btn-bg: var(--c-brand-primary);
328--c-header-btn-border: var(--c-brand-primary);
329--c-header-btn-bg-hover: #00235a;
330--c-header-btn-text: var(--c-brand-on);
331--c-header-btn-text-hover: var(--c-brand-on-hover);
332--c-footer-topbar-bg: #001ccd;
333--c-footer-topbar-text: #fff;
334--c-footer-topbar-link: #fff;
335--c-footer-mid-bg: #001ccd;
336--c-footer-mid-text: #fff;
337--c-footer-mid-link-bg: #fff;
338--c-footer-bottombar-bg: #001ccd;
339--c-footer-bottombar-text: var(--c-brand-on);
340--c-footer-btn-bg: rgba(170, 170, 238, 0);
341--c-footer-btn-text: #FFF;
342--c-footer-btn-bg-hover: #1b34d3;
343--c-footer-btn-text-hover: #FFF;
344--c-footer-btn-border: #FFF;
345--c-footer-menu-mobile-text: var(--c-brand-primary);
346--c-header-topbar-bg: var(--c-brand-secondary);
347--c-header-topbar-text: var(--c-brand-on);
348--c-header-topbar-link: var(--c-brand-on);
349--c-header-mid-bg: var(--c-brand-primary);
350--c-header-mid-text: var(--c-brand-on);
351--c-header-carrinho-bg: #5D90FF;
352--c-header-bottombar-bg: var(--c-white);
353--c-header-bottombar-text: #1b2985;
354--c-header-bottombar-categorias-bg: var(--c-brand-primary);
355--c-header-bottombar-categorias-text: var(--c-brand-on);
356--c-categorias-hover: #1b2985;
357--c-brand-primary: #002aff;
358--c-brand-secondary: #ff006c;
359--c-base-fundo: #fff;
360--c-base-texto: #444;
361--c-brand-accent: #ff006c;
362--c-brand-on: #fff;
363--c-brand-primary-hover: #003CFF;
364--c-brand-secondary-hover: #FF3384;
365--c-brand-accent-hover: #FF3384;
366--c-brand-on-hover: #FFF;
367--c-white: #fff;
368--loader-tenant: url("https://storage.googleapis.com/retailon-publico/brava/admin/loader-brava.gif");
369--c-text-primary: #444;
370--c-text-secondary: #616161;
371--c-text-muted: #8a9297;
372--c-text-subtle: #a3a3a3;
373--c-text-inverse: #000;
374--c-text-link: #002aff;
375--c-text-link-hover: #002aff;
376--c-text-brand-primary: #002aff;
377--c-text-brand-secondary: #ff006c;
378--c-cookiebanner-bg: var(--c-brand-secondary);
379--c-cookiebanner-border: var(--c-brand-primary);
380--c-cookiebanner-text: var(--c-brand-on);
381--c-cookiebanner-link: var(--c-brand-accent);
382--r-cookiebanner-radius: 12px;
383--c-cookiebanner-btn-bg: var(--c-brand-primary);
384--c-cookiebanner-btn-text: var(--c-brand-on);
385--c-cookiebanner-btn-border: var(--c-brand-primary);
386--c-cookiebanner-btn-bg-hover: color-mix(in srgb, var(--c-cookiebanner-btn-bg) 82%, black);
387--r-cookiebanner-btn-radius: 20px;
388--filter-icon-primary: brightness(0) saturate(100%) invert(12%) sepia(100%) saturate(4818%) hue-rotate(235deg) brightness(100%) contrast(127%);
389--filter-icon-secondary: brightness(0) saturate(100%) invert(14%) sepia(91%) saturate(6564%) hue-rotate(332deg) brightness(112%) contrast(109%);
390--filter-icon-wishlist: brightness(0) saturate(100%) invert(14%) sepia(66%) saturate(7307%) hue-rotate(329deg) brightness(102%) contrast(107%);
391--filter-icon-gray: brightness(0) saturate(100%) invert(75%) sepia(4%) saturate(0%) hue-rotate(172deg) brightness(92%) contrast(90%);
392--client-swiper-scrollbar-background: #002aff2b;
393--client-swiper-scrollbar-color: #002aff;
394--client-swiper-scrollbar-size: 7px;
395--client-swiper-pagination-bullet-border-radius: 50px;
396--client-swiper-pagination-bullet-size: 12px;
397--client-swiper-pagination-bullet-active-size: 12px;
398--client-swiper-pagination-bullets-space: 4px;
399--client-swiper-pagination-background: #002aff;
400--client-swiper-pagination-color: #002aff;
401--client-opacity-button-next-prev: 0;
402--client-opacity-mobile-next-prev: 1;
403--client-bg-button-next-prev: #FFF;
404--h-swipper-button: 30px;
405--w-swipper-button: 30px;
406--s-arrow-image: 20px;
407--c-border-default: #002aff;
408--c-border-muted: #E9F2F9;
409--c-border-strong: #E9F2F9;
410--r-rounded-default: 0.5rem;
411--c-divider-muted: #E9F2F9;
412--container-max-width: 1300px;
413--c-page-bg: #fff;
414--c-section-bg: #fff;
415--c-card-bg: #fff;
416--c-card-border: var(--c-border-muted);
417--c-divider: var(--c-border-muted);
418--c-surface-base: #E9F2F9;
419--c-surface-muted: #E9F2F9;
420--c-surface-soft: #E9F2F9;
421--c-surface-subtle: #E9F2F9;
422--c-surface-inverse: #001d4b;
423--c-surface-default: var(--c-white);
424--c-surface-brand: #EFF5FF;
425--c-surface-brand-hover: #d9e6fc;
426--c-pdp-h1-text: #242424;
427--f-pdp-h1-mobile: 18px;
428--f-pdp-h1-desktop: 25px;
429--c-pdp-avaliacoes-text: var(--c-brand-primary);
430--c-pdp-sem-avaliacoes-text: #808080;
431--c-pdp-controlado-border: #ffc9c9;
432--c-pdp-controlado-bg: #fef2f2;
433--c-pdp-controlado-titulo-text: #e7000b;
434--c-pdp-controlado-descricao-text: #4a5565;
435--c-pdp-termolabil-border: #c6c3fa;
436--c-pdp-termolabil-bg: #e8edfe;
437--c-pdp-termolabil-titulo-text: #0300b4;
438--c-pdp-termolabil-descricao-text: #4a5565;
439--c-pdp-galeria-border: #FFF;
440--r-pdp-galeria: 0px;
441--c-pdp-vendido-entregue-text: #8a9297;
442--slide-thumb-active: #002aff;
443--slide-thumb-not-active: #92969b;
444--c-pdp-breadcrumb-text: #8a9297;
445--c-pdp-breadcrumb-link-text: #444;
446--c-pdp-apresentacao-descricao-bullets-text: #8a9297;
447--c-pdp-apresentacao-descricao-text: #444;
448--r-pdp-apresentacoes: 50px;
449--c-pdp-apresentacoes-titulo-text: #444;
450--c-pdp-apresentacoes-ativa: var(--c-brand-secondary);
451--c-pdp-apresentacoes-ativa-text: var(--c-text-brand-secondary);
452--c-pdp-resumo-text: #8a9297;
453--c-pdp-resumo-aviso-border: #ffc9c9;
454--c-pdp-resumo-aviso-bg: #fef2f2;
455--c-pdp-resumo-aviso-text: #4a5565;
456--c-pdp-descricao-completa-text: var(--c-brand-primary);
457--c-pdp-btn-avaliacao-bg: var(--c-brand-secondary);
458--c-pdp-avaliacao-accent: var(--c-brand-primary);
459--c-pdp-avaliacoes-border: #ebe6e7;
460--r-pdp-avaliacoes: 20px;
461--c-pdp-pbm-accent: var(--c-brand-primary);
462--c-pdp-especificacoes-border: #d1d5dc;
463--r-pdp-especificacoes: 20px;
464--c-pdp-especificacoes-divisor: #f6f3f4;
465--c-pdp-especificacoes-link: var(--c-brand-primary);
466--c-pdp-divisor: #d1d5dc;
467--c-pdp-bg: #fff;
468--f-pdp-titulo: 700;
469--c-pdp-texto: #8a9297;
470--f-pdp-cta: 18px;
471--c-pdp-qtd-menos-icon: var(--c-brand-primary);
472--c-pdp-qtd-mais-icon: var(--c-brand-primary);
473--c-pdp-oferta-formas-pagamento-text: var(--c-brand-primary);
474--c-pdp-oferta-pbm-border: #ebe6e7;
475--c-pdp-oferta-pbm-bg: #F5FFF6;
476--r-pdp-oferta-pbm: 10px;
477--c-pdp-oferta-pbm-text: #00691D;
478--c-pdp-oferta-border: #d1d5dc;
479--r-pdp-oferta: 20px;
480--c-pdp-oferta-bg: #fff;
481--c-pdp-oferta-text: #444;
482--c-pdp-oferta-qtd-border: #ebe6e7;
483--r-pdp-oferta-qtd: 10px;
484--c-pdp-oferta-qtd-bg: #fff;
485--c-pdp-entrega-border: #d1d5dc;
486--r-pdp-entrega: 10px;
487--c-pdp-entrega-bg: #fff;
488--c-pdp-entrega-titulo: var(--c-brand-primary);
489--c-pdp-entrega-expandida-bg: #fff;
490--r-pdp-tab: 50px;
491--py-pdp-tab: 8px;
492--c-pdp-tab-inativa-text: #444;
493--c-pdp-tab-inativa-border: var(--c-brand-primary);
494--c-pdp-atalho-tab-bg: var(--c-brand-primary);
495--c-pdp-atalho-tab-text: #FFF;
496--r-cta-radius: 20px;
497--r-btn-comprar: 20px;
498--h-btn-comprar: 38px;
499--c-btn-padrao-comprar-bg: var(--c-brand-secondary);
500--c-btn-padrao-comprar-text: var(--c-brand-on);
501--c-btn-padrao-comprar-bg-hover: color-mix(in srgb, var(--c-btn-padrao-comprar-bg) 82%, black);
502--c-btn-padrao-comprar-text-hover: var(--c-brand-on);
503--c-btn-padrao-comprar-border: ;
504--c-btn-desconto-comprar-bg: var(--c-brand-primary);
505--c-btn-desconto-comprar-text: var(--c-brand-on);
506--c-btn-desconto-comprar-bg-hover: color-mix(in srgb, var(--c-btn-desconto-comprar-bg) 82%, black);
507--c-btn-desconto-comprar-text-hover: var(--c-brand-on);
508--c-btn-desconto-comprar-border: var(--c-brand-primary);
509--c-btn-pbm-comprar-bg: #00691d;
510--c-btn-pbm-comprar-text: var(--c-brand-on);
511--c-btn-pbm-comprar-bg-hover: color-mix(in srgb, var(--c-btn-pbm-comprar-bg) 82%, black);
512--c-btn-pbm-comprar-text-hover: var(--c-brand-on);
513--c-btn-pbm-comprar-border: ;
514--r-badge-tags: 20px;
515--c-badge-pbm-bg: #DEF5EB;
516--c-badge-pbm-text: #00AF66;
517--c-badge-desconto-bg: var(--c-brand-secondary);
518--c-badge-desconto-text: #FFF;
519--r-badge-percentual: 2px;
520--c-badge-percentual-bg: #00A66F;
521--c-badge-percentual-text: #FFF;
522--r-badge-secundaria: 2px;
523--c-badge-secundaria-bg: var(--c-brand-primary);
524--c-badge-secundaria-text: #FFF;
525--r-badge-receita: 0px;
526--c-badge-receita-bg: #e62d36;
527--c-badge-receita-text: #FFF;
528--c-emphasis: #1b2985;
529--c-bg-fundo-soft: #dbe2ff;
530--c-bg-pesquisa-soft: #fff;
531--c-bg-nossas-lojas: #fff;
532--c-btn-nossas-lojas: #fff;
533--c-checkbox-nossas-lojas: #fff;
534--c-carrinho: #fff;
535--c-comprar-produto-bg: #FFF;
536--c-breadcrumb-nav-text: #6b7280;
537--c-breadcrumb-link: var(--c-brand-primary);
538--c-breadcrumb-atual-text: #1f2937;
539--c-page-inst-h1-text: var(--c-brand-primary);
540--c-page-inst-subtitulo-text: var(--c-brand-secondary);
541--c-page-inst-hero-bg: #fff;
542--c-page-inst-texto-muted: #374151;
543--c-page-inst-secao-bg: var(--c-surface-muted);
544--c-page-inst-link: #007bff;
545--c-page-inst-link-hover: #3d85c6;
546--c-page-inst-accent-text: var(--c-brand-accent);
547--c-page-fc-titulo-text: var(--c-brand-primary);
548--c-page-fc-banner-bg: var(--c-brand-primary);
549--c-page-fc-form-bg: var(--c-surface-subtle);
550--c-page-fc-btn-bg: var(--c-brand-secondary);
551--c-page-fc-btn-text: #fff;
552--c-page-fc-input-bg: #fff;
553--c-page-lojas-titulo-text: var(--c-brand-primary);
554--c-page-lojas-subtitulo-text: #374151;
555--c-page-lojas-select-text: var(--c-brand-primary);
556--c-page-lojas-select-bg: #fff;
557--c-page-lojas-btn-outline-hover-bg: #f3f4f6;
558--c-checkout-aside-bg: #fff;
559--c-checkout-header-bg: #fff;
560--c-checkout-header-text: #444;
561--c-checkout-endereco-bg: #fff;
562--c-checkout-endereco-text: #444;
563--c-checkout-aside-footer-bg: #fff;
564--c-checkout-cupom-bg: var(--c-brand-primary);
565--c-checkout-radio-button-bg: var(--c-brand-primary);
566--c-checkout-button-bg: var(--c-brand-primary);
567--c-checkout-default-text: var(--c-text-primary);
568--c-checkout-primary-text: var(--c-brand-primary);
569--c-checkout-secondary-text: var(--c-brand-secondary);
570--c-checkout-accent-text: var(--c-brand-accent);
571--c-checkout-surface-muted: var(--c-surface-muted);
572--c-checkout-surface-selected: var(--c-surface-soft);
573--c-checkout-muted-border: #e4e7ea;
574--c-checkout-accent-border: var(--c-brand-secondary);
575--c-checkout-divider: var(--c-border-muted);
576--c-checkout-primary-border: var(--c-brand-primary);
577--c-checkout-icon: var(--c-brand-primary);
578--c-checkout-voltar-icon: var(--c-brand-primary);
579--c-checkout-cta-bg: var(--c-brand-secondary);
580--c-checkout-cta-text: var(--c-brand-on);
581--c-checkout-cta-border: var(--c-brand-secondary);
582--r-checkout-cta: 50px;
583--c-checkout-active-step-bg: var(--c-brand-primary);
584--c-checkout-active-step-icon: #fff;
585--c-checkout-inative-step-bg: #95A0AF;
586--c-checkout-inative-step-icon: #fff;
587--c-checkout-line-step-bg: #E0E4EA;
588--r-checkout-step: 50px;
589--c-popup-checkout-bg: #fff;
590--c-popup-checkout-border: var(--c-border-default);
591--c-popup-checkout-default-text: var(--c-text-primary);
592--c-popup-checkout-accent-text: var(--c-text-brand-primary);
593--r-popup-checkout-border-radius-top-right: 30px;
594--r-popup-checkout-border-radius-top-left: 30px;
595--c-checkout-input-cabecalho-bg: #FFF;
596--c-checkout-input-cabecalho-h: 35px;
597--c-checkout-input-cabecalho-radius: 2rem 0 0 2rem;
598--c-checkout-input-cabecalho-mr: 0;
599--c-checkout-input-cabecalho-btn-radius: 0 2rem 2rem 0;
600--c-checkout-endereco-icon: #444;
601--p-pesquisa-toggle: 0.5rem 0.875rem;
602--r-pesquisa-toggle-inicio: 9999px 0 0 9999px;
603--r-pesquisa-toggle-fim: 0 9999px 9999px 0;
604--gap-pesquisa-toggle: 0px;
605--w-pesquisa-toggle: 25px;
606--c-pesquisa-primary: var(--c-brand-primary);
607--c-pesquisa-primary-on: var(--c-brand-on);
608--c-pesquisa-secondary: var(--c-brand-secondary);
609--c-pesquisa-secondary-on: #fff;
610--c-pesquisa-bg-soft: var(--c-bg-pesquisa-soft);
611--c-pesquisa-surface-muted: var(--c-surface-muted);
612--c-pesquisa-toggle-inativo-bg: #eee;
613--c-pesquisa-toolbar-text: #000;
614--c-pesquisa-termo-text: #9ca3af;
615--c-pesquisa-texto: #444;
616--c-pesquisa-texto-ordenacao: #1C1B1B;
617--c-pesquisa-limpar-filtros: #E62D36;
618--c-pesquisa-filtro-chip-bg: color-mix(in srgb, var(--c-pesquisa-primary) 15%, transparent);
619--c-pesquisa-popup-bg: #fff;
620--c-overlay-soft: rgba(0, 0, 0, 0.3);
621--c-overlay-default: rgba(0, 0, 0, 0.5);
622--c-overlay-strong: rgba(0, 0, 0, 0.7);
623--c-success: #C6FF99;
624--c-warning: #FFF9B3;
625--c-danger: #E60005;
626--c-danger-soft: #ef4444;
627--c-info: #0000ff;
628--c-badge-bg: var(--c-surface-brand);
629--c-badge-text: var(--c-text-brand-primary);
630--c-badge-accent-bg: var(--c-brand-accent);
631--c-badge-accent-text: var(--c-brand-on);
632--c-pulse: rgba(0, 42, 255, 0.40);
633--c-btn-primary-bg: var(--c-brand-primary);
634--c-btn-primary-text: var(--c-brand-on);
635--c-btn-primary-border: var(--c-brand-primary);
636--c-btn-primary-hover-bg: var(--c-brand-primary-hover);
637--c-btn-primary-hover-text: var(--c-brand-on-hover);
638--c-btn-secondary-bg: var(--c-brand-secondary);
639--c-btn-secondary-text: var(--c-brand-on);
640--c-btn-secondary-border: var(--c-brand-secondary);
641--c-btn-secondary-hover-bg: var(--c-brand-secondary-hover);
642--c-btn-secondary-hover-text: var(--c-brand-on-hover);
643--c-btn-ghost-bg: rgba(255, 255, 255, 0);
644--c-btn-ghost-text: #1e2939;
645--c-btn-ghost-hover-bg: #fbf9fa;
646--c-btn-ghost-hover-text: #1e2939;
647--c-btn-ghost-border: #d1d5dc;
648--c-btn-muted-bg: #ebe6e7;
649--c-btn-muted-text: #1e2939;
650--c-btn-muted-hover-bg: rgba(255, 255, 255, 0);
651--c-btn-muted-hover-text: #1e2939;
652--c-btn-muted-border: rgba(255, 255, 255, 0);
653--c-btn-danger-bg: #ef4444;
654--c-btn-danger-text: #fff;
655--c-btn-danger-hover-bg: #e7000b;
656--c-btn-danger-hover-text: #fff;
657--c-btn-danger-border: rgba(255, 255, 255, 0);
658--c-menu-aside-bg: #fff;
659--c-menu-aside-coluna-esq-bg: #F5F5F5;
660--c-menu-aside-coluna-esq-border: #E5E5E5;
661--c-menu-aside-item-ativo-bg: #fff;
662--c-menu-aside-categoria-text: #333;
663--c-menu-aside-categoria-ativo-text: var(--c-brand-secondary);
664--c-menu-aside-barra-lateral-bg: var(--c-brand-secondary);
665--c-menu-aside-subtitulo-text: #111;
666--c-menu-aside-voltar-text: var(--c-brand-secondary);
667--c-menu-aside-pill-bg: var(--c-surface-subtle);
668--c-menu-aside-pill-text: #333;
669--c-menu-aside-vazio-text: #6b7280;
670--c-menu-cat-mobile-text: #fff;
671--c-menu-cat-mobile-barra-ativa-bg: #fff;
672--c-text-itens: #444;
673--c-text-itens-pilulas: 000;
674--c-background-itens-pilulas: #FFDE21;
675--c-background-destaque-pilulas: #FFDE21;
676--c-text-destaque-pilulas: #000;
677--f-title-carrossel-produtos-mobile: 12px;
678--f-title-carrossel-produtos-desktop: 16px;
679--c-title-carrossel-produtos: #444;
680--c-vermais-text-carrossel-produtos: #444;
681--c-border-vermais-carrossel-produtos: #E9E9E9;
682--c-bg-vermais-carrossel-produtos: #E9E9E9;
683--c-bg-hover-vermais-carrossel-produtos: #E9E9E9;
684--c-text-hover-vermais-carrossel-produtos: #444;
685--c-border-hover-vermais-carrossel-produtos: #E9E9E9;
686--c-border-card-carrossel-produtos: #E9E9E9;
687--c-bg-card-carrossel-produtos: #FFF;
688--c-text-nome-produto-carrossel-produtos: #444;
689--c-text-preco-carrossel-produtos: #444;
690--c-background-informacoes: #E9E9E9;
691--c-text-informacoes: #444;
692--c-background-item-informacoes: #E9E9E9;
693--c-border-item-informacoes: #E9E9E9;
694--c-border-imagens-redondas: #D9D9D9;
695--c-text-imagens-redondas: #444;
696      
697    }
698  </style>
699
700  
701
702  
703    <style>
704    
705</style>
706  
707
708  <link rel="stylesheet" href="/staticfiles/css/output.css">
709
710  
710<script type="ff2c2aaab21707ab2ba08cc2-text/javascript" src="/staticfiles/js/index.js"></script>
710
711
712  <!-- Structured Data - Schema.org -->
713  
713<script type="application/ld+json">
714  {
715    "@context": "https://schema.org",
716    "@type": "WebSite",
717    "name": "Farmácias Brava ",
718    "url": "https://www.farmaciasbrava.com.br",
719    "description": "Aproveite nossas ofertas no site ou pelo app e receba em casa ou retire seus pedidos na loja.",
720    "potentialAction": {
721      "@type": "SearchAction",
722      "target": {
723        "@type": "EntryPoint",
724        "urlTemplate": "https://www.farmaciasbrava.com.br/pesquisa/{search_term_string}"
725      },
726      "query-input": "required name=search_term_string"
727    }
728  }
729  </script>
729
730
731  
731<script type="application/ld+json">
732  {
733    "@context": "https://schema.org",
734    "@type": "Organization",
735    "name": "Farmácias Brava ",
736    "url": "https://www.farmaciasbrava.com.br",
737    "logo": "https://storage.googleapis.com/retailon-publico/brava/imagens/favicon.png",
738    "contactPoint": {
739      "@type": "ContactPoint",
740      "contactType": "Customer Service",
741      "availableLanguage": "Portuguese"
742    },
743    "sameAs": []
744  }
745  </script>
745
746
747
748  
749  
750  
751
752</head>
753
754<body class="min-h-screen flex flex-col">
vendor: 83 bytes, lines 754-760
754
755
756  
757
758  
759  <noscript>
760    <iframe src="https://www.googletagmanager.com/ns.html?id=
760GTM-THG4PHZ
vendor: 104 bytes, lines 760-767
760"
761      height="0" width="0" style="display:none;visibility:hidden"></iframe>
762  </noscript>
763  
764
765  
766  
767  
767<div id="app_aviso">
768    
769  </div>
770  
771
772
773  
774  
775  <div id="app_header">
776    
777      
778
779
780    <header class="w-full fixed z-50">
781      <div class="w-full bg-[var(--c-header-topbar-bg)] px-4 py-2 gap-y-2">
782        <p class="text-[var(--c-header-topbar-text)] font-semibold text-center">Frete grátis acima de R$ 100,00 | 6x sem juros</p>
783      </div>
784
785      <div class="w-full bg-[var(--c-header-mid-bg)] py-5 gap-y-2">
786        <div class="container mx-auto flex-1">
787          <div class="flex flex-row justify-between items-center gap-x-4 px-4">
788            <div class="flex items-center">
789              <!-- Menu -->
790              
791              <!-- Logo -->
792              <a href="/" class="flex items-center shrink-0">
793                <img loading="lazy" src="/staticfiles/img/client2/logo_branca.png" alt="Logo" width="180" height="auto" class="px-3">
794              </a>
795            </div>
796            <!-- Barra de pesquisa e localização -->
797            <div class="flex flex-col gap-y-3 flex-1 min-w-0">
798              <div class="bg-white rounded-full flex items-center px-3 relative">
799                <input id="header-search-input" autocomplete="off" type="text" placeholder="Buscar na Brava" class="flex-1 ml-2 outline-none text-sm">
800                <button type="button" class="flex items-center justify-center cursor-pointer rounded-full border-1 border-[var(--c-brand-primary)] w-6 h-6 hover:shadow-md transition" onclick="if (!window.__cfRLUnblockHandlers) return false; submitHeaderSearch()" data-cf-modified-ff2c2aaab21707ab2ba08cc2-="">
801                  <img loading="lazy" src="/staticfiles/img/client2/icon_search.png" alt="Pesquisa" class="w-3 h-3" />
802                </button>
803
804                <div id="header-search-dropdown" class="absolute top-full left-0 mt-2 w-full bg-white rounded-2xl shadow-[0_1px_8px_rgba(0,0,0,0.15)] border border-[#E6E6E6] z-50 hidden">
805                  <div id="header-search-dropdown-content" class="p-3"></div>
806                </div>
807
808                
809              </div>
810              
811            </div>
812
813            <div class="flex items-center gap-8 text-[var(--c-header-mid-text)] shrink-0">
814
815              <div class="flex items-center gap-2">
816                <!-- Bloco 1: Login -->
817                <img loading="lazy" src="/staticfiles/img/client2/user_perfil.png" alt="Ícone usuário" class="w-8 h-8" />
818                
819                <p class="text-sm leading-tight">
820                  Olá!<br/>
821                  
822                    <a href="/login">
823                      <span class="font-bold">Entre ou cadastre-se</span>
824                    </a>
825                  
826                </p>
827              </div>
828
829              <!-- Bloco 2: Localização -->
830              
831
832              <!-- Bloco: Ultimo pedido -->
833              <div class="relative inline-block">
834                <!-- BOTÃO DE ABERTURA -->
835                <div id="btn-dropdown"
836                    class="flex items-center gap-2 px-3 py-2 cursor-pointer justify-center rounded-xl hover:bg-[#003CFF] hover:shadow transition">
837                    <div class="relative" data-target="notification">
838                      <img loading="lazy" id="img-ultimo-pedido" src="/staticfiles/img/client2/box_white.png" alt="Ícone localização" class="w-10 h-10" />
839                    </div>
840                  <p class="text-sm leading-tight">
841                    Último<br />
842                    <span class="font-bold">pedido</span>
843                  </p>
844                </div>
845
846                <!-- DROPDOWN -->
847                <div id="dropdown-menu" class="py-[20px] px-[20px] absolute left-[-40px] z-50 bg-white border border-gray-200 rounded-xl shadow-lg w-100 hidden">
848
849                  <!-- TOGGLE DE ENTREGA -->
850                  <div class="w-full max-w-md mx-auto">
851                    
852
853                      <div class="grid grid-cols-1 gap-4">
854                        <div class="flex justify-center items-center">
855                          <img loading="lazy" src="/staticfiles/img/client2/cart-pedido.png" class="w-30 h-30 p-1" alt="Atendimento">
856                        </div>
857                        <p class="mb-2 text-[14px] font-semibold text-gray-600 text-center">Necessário estar logado para visualizar o último pedido</p>
858                        <a href="/login" class="text-center">
859                          <div class="flex justify-center items-center w-full h-10 bg-[var(--c-brand-secondary)] hover:opacity-90 text-white rounded-lg " id="verificar-cpf">
860                            Entre ou cadastre-se
861                          </div>
862                        </a>
863                      </div>
864
865                    
866                  </div>
867                </div>
868              </div>
869
870              <!-- Bloco 3: Cesta -->
871              <div class="flex items-center cursor-pointer qtd-checkout gap-2 px-3 py-2 bg-[var(--c-header-carrinho-bg)] rounded-xl" data-content="" onclick="if (!window.__cfRLUnblockHandlers) return false; toggleCarrinho('open')" data-cf-modified-ff2c2aaab21707ab2ba08cc2-="">
872                <div class="relative">
873                  <img loading="lazy" src="/staticfiles/img/client2/cesta.png" alt="Ícone cesta" class="w-8 h-8 " />
874                  <!-- Badge de quantidade -->
875                  <span data-target="badge-qtd-itens"
876                    class="absolute -bottom-1 -left-1 bg-[var(--c-brand-secondary)] text-white text-[xx-small] w-4 h-4 rounded-full flex items-center justify-center font-bold">
877                    0
878                  </span>
879                </div>
880                <div class="text-sm leading-tight text-nowrap">
881                  Minha cesta<br/>
882                  <span class="font-bold" data-target="badge-total-cesta">R$ 0,00</span>
883                </div>
884              </div>
885            </div>
886          </div>
887        </div>
888      </div>
889      <div class="w-full bg-[var(--c-header-bottombar-bg)] shadow-[9px_-2px_10px_rgb(0,0,0,0.38)] gap-y-2 ">
890        <div class="container mx-auto flex-1">
891          <div class="flex flex-row items-center gap-x-4 relative">
892            <div class="flex items-stretch w-full">
893              <ul class="grid grid-cols-5 flex-1 divide-x divide-white/40">
894                
895                <!-- Menu desktop -->
896                
897                <li class="list-none relative flex bg-[var(--c-brand-primary)] rounded-b-[20px] hover:bg-[#1b2985] hover:shadow-sm items-center justify-center px-10 transition" data-target="menu-principal" onmouseenter="if (!window.__cfRLUnblockHandlers) return false; toggleContainerMenuCategorias('open')" onmouseleave="if (!window.__cfRLUnblockHandlers) return false; closeMenuCategoriasSeNaoEstiverFocado()" data-cf-modified-ff2c2aaab21707ab2ba08cc2-="">
898                  <a href="/" class="flex items-center justify-center">
899                    <img loading="lazy" loading="lazy"src="/staticfiles/img/client2/menu-bar.png" alt="Menu" width="18" height="18" class="img-filter-fff">
900                    <span class="text-[#FFF] text-base font-semibold pl-2">Categorias</span>
901                  </a>
902                </li>
903
904                <!--<li>
905                  <a href="/categorias/saldao" class="group block text-center px-10 py-1.5 text-[var(--c-header-bottombar-text)] font-semibold text-[15px] hover:bg-white/15 whitespace-nowrap">
906                    <span class="relative inline-block">
907                      Saldão
908                      <span class="absolute bottom-0 left-0 h-[1.3px] bg-current w-0 group-hover:w-full transition-all duration-300 ease-out"></span>
909                    </span>
910                  </a>
911                </li>-->
912                <li>
913                  <a href="/nossas-lojas" class="group block text-center px-10 py-1.5 text-[var(--c-header-bottombar-text)] font-semibold text-[15px] hover:bg-white/15 whitespace-nowrap">
914                    <span class="relative inline-block">
915                      Nossas Lojas
916                      <span class="absolute bottom-0 left-0 h-[1.3px] bg-current w-0 group-hover:w-full transition-all duration-300 ease-out"></span>
917                    </span>
918                  </a>
919                </li>
920                <li>
921                  <a href="/trabalhe-conosco" class="group block text-center px-10 py-1.5 text-[var(--c-header-bottombar-text)] font-semibold text-[15px] hover:bg-white/15 whitespace-nowrap">
922                    <span class="relative inline-block">
923                      Trabalhe Conosco
924                      <span class="absolute bottom-0 left-0 h-[1.3px] bg-current w-0 group-hover:w-full transition-all duration-300 ease-out"></span>
925                    </span>
926                  </a>
927                </li>
928                <li class="bg-[var(--c-brand-secondary)]">
929                  <a href="/franquias" class="group block text-center px-10 py-1.5 text-white font-semibold text-[15px] hover:bg-white/15 whitespace-nowrap">
930                    <span class="relative inline-block">
931                      Seja um franqueado
932                      <span class="absolute bottom-0 left-0 h-[1.3px] bg-current w-0 group-hover:w-full transition-all duration-300 ease-out"></span>
933                    </span>
934                  </a>
935                </li>
936
937                <!-- Menu desktop -->
938                <div class="absolute left-0 top-full w-full z-40">
939                  <div class="container mx-auto flex-1">
940                    
941                    <div class="container mx-auto flex absolute h-[520px] border-1 border-[var(--c-brand-primary)] w-full bg-[#fff] rounded-[15p
941x] hidden" data-target="container-menu-principal" onmouseenter="if (!window.__cfRLUnblockHandlers) return false; toggleContainerMenuCategoriasEmFoco('open')" onmouseleave="if (!window.__cfRLUnblockHandlers) return false; toggleContainerMenuCategorias('close');" data-cf-modified-ff2c2aaab21707ab2ba08cc2-="">
942                      <div class="h-full w-[230px] bg-[#dee3ff] rounded-[15px] flex flex-col">
943                        
944                        <!-- LOGO -->
945                        <div class="flex items-center px-4 py-2 pt-[30px] pb-2">
946                          <img loading="lazy" src="/staticfiles/img/client2/logo_azul_rosa.png" alt="Logo" class="w-[120px]">
947                        </div>
948        
949                        <a href="/login" class="flex items-center px-4 py-2 cursor-pointer">
950                            <img loading="lazy" src="/staticfiles/img/client2/fav_icon.png" alt="Medicamentos" class="img-filter-002aff w-6 h-6">
951                            <span class="pl-3 text-[var(--c-brand-primary)] font-semibold text-[14px]">Lista de Desejos</span>
952                        </a>
953                        <a href="/login" class="flex items-center px-4 py-2 cursor-pointer">
954                            <img loading="lazy" src="/staticfiles/img/client2/box.png" alt="Medicamentos" class="img-filter-002aff  w-6 h-6">
955                            <span class="pl-3 text-[var(--c-brand-primary)] font-semibold text-[14px]">Minhas compras</span>
956                        </a>
957                        <div class="flex items-center px-4 py-3">
958                            <span class="pr-3 text-[var(--c-brand-primary)] font-semibold text-[18px]">Categorias</span>
959                        </div>
960
961                        <!-- LISTA DE CATEGORIAS -->
962                        <div class="" id="menu-categorias-esquerda"></div>
963
964                      </div>
965                      <div class="h-full w-full min-h-0 overflow-hidden px-6 py-4 flex flex-col" id="menu-categorias-direita"></div>
966
967                    </div>
968                      
969                  </div>
970                </div>
971                
972              </ul>
973
974              
975              
976              
977            </div>
978          </div>
979        </div>
980      </div>
981    </header>
982    
983    
984    
984<script type="ff2c2aaab21707ab2ba08cc2-text/javascript">
985
986      // Controle do dropdown de localização
987      const btnDropdown = document.getElementById('btn-dropdown');
988      const dropdownMenu = document.getElementById('dropdown-menu');
989
990      // Expor ID do usuário para chaves de storage
991      window.APP_USER_ID = null;
992      window.ULTIMO_PEDIDO_STATUS_KEY = null;
993      const STORAGE_SEEN_KEY = (userId) => `ultimoPedidoStatusSeen:${userId||'anon'}`;
994
995      btnDropdown.addEventListener('click', (e) => {
996        e.stopPropagation(); 
997        dropdownMenu.classList.toggle('hidden');
998        // Se abriu, marca como visualizado e remove badge
999        if (!dropdownMenu.classList.contains('hidden')) {
1000          marcarUltimoPedidoComoVisto();
1001          ensureNotificationBadge(false);
1002        }
1003      });
1004
1005      document.addEventListener('click', () => {
1006        dropdownMenu.classList.add('hidden');
1007      });
1008
1009      dropdownMenu.addEventListener('click', (e) => {
1010        e.stopPropagation();
1011      });
1012
1013      
1014      
1015      
1016
1017      
1018
1019      function ensureNotificationBadge(show){
1020        try {
1021          const target = document.querySelector('[data-target="notification"]');
1022          if(!target) return;
1023          let badge = target.querySelector('[data-notification-badge]');
1024          if (show) {
1025            if (!badge){
1026              badge = document.createElement('span');
1027              badge.setAttribute('data-notification-badge','1');
1028              badge.className = 'absolute bottom-0 -left-1 bg-[var(--c-brand-secondary)] text-white text-[xx-small] w-4 h-4 rounded-full flex items-center justify-center font-bold';
1029              badge.textContent = '!';
1030              target.appendChild(badge);
1031            }
1032          } else if (badge) {
1033            badge.remove();
1034          }
1035        } catch(err){ console.error(err); }
1036      }
1037
1038      function marcarUltimoPedidoComoVisto(){
1039        try {
1040          const userId = window.APP_USER_ID;
1041          if (!window.ULTIMO_PEDIDO_STATUS_KEY) return;
1042          localStorage.setItem(STORAGE_SEEN_KEY(userId), window.ULTIMO_PEDIDO_STATUS_KEY);
1043        } catch(err){ console.error(err); }
1044      }
1045
1046      function getPedidoFromResponse(payload){
1047        // Tenta localizar o objeto do pedido em diferentes chaves comuns
1048        const obj = payload?.pedido || payload?.data || payload?.result || payload;
1049        return obj || null;
1050      }
1051
1052      function renderUltimoPedidoStatusCard(p){
1053        // Campos defensivos
1054        const numero   = p?.id || '—';
1055        const status   = p?.nm_descritivo || '—';
1056        const tipo_entrega  = p?.entrega_descricao || '—';
1057        const endereco = `${p?.endereco_destino}, ${p?.numero_destino}, ${p?.bairro_destino} | ${p?.cidade_destino} - ${p?.estado_destino}`;
1058        const hash = p?.hash || '';
1059        const img = p?.entrega_imagem || '/staticfiles/img/client2/icon-delivery-white.png';
1060        const status_imagem = p?.status_imagem || '/staticfiles/img/client2/box_white.png';
1061
1062        (()=>{
1063          const el = document.getElementById('img-ultimo-pedido');
1064          if (el) {
1065            el.src = img;
1066            el.alt = 'Status do último pedido';
1067            el.onerror = function(){ this.onerror=null; this.src=status_imagem; };
1068          }
1069        })();
1070
1071        return `
1072          <a href="/cliente/pedido/${hash}" class="flex items-center w-full p-2 rounded-lg border border-gray-200 hover:bg-[#dee3ff] cursor-pointer transition">
1073            <div class="grid grid-cols-1 gap-1 flex-1 min-w-0">
1074              <div class="flex justify-between items-center">
1075                <div class="flex items-center">
1076                  <div class="img-filter-002aff pr-2 flex-shrink-0">
1077                    <img loading="lazy" src="${img}" class="w-7 h-7" alt="Ícone entrega" />
1078                  </div>
1079                  <p class="font-semibold text-sm text-gray-900">Pedido nº ${numero}</p>
1080                </div>
1081                <p class="text-xs text-gray-600 leading-snug break-words">${tipo_entrega}</p>
1082              </div>
1083              <p class="text-sm text-gray-600">
1084                Status do Pedido: <span class="text-gray-600 pl-2">${status}</span>
1085              </p>
1086              ${endereco ? `
1087              <div class="text-sm text-gray-400">
1088                <p class="text-sm text-gray-400 leading-snug break-words">${endereco}</p>
1089              </div>` : ''}
1090            </div>
1091          </a>
1092        `;
1093      }
1094
1095      async function atualizarUltimoPedido(){
1096        try {
1097          const container = document.getElementById('ultimo-pedido-status');
1098          if(!container) return;
1099          container.classList.remove('hidden');
1100
1101          const resp = await fetch('/cliente/buscar/componente/ultimo/pedido', {
1102            method: 'GET',
1103            headers: {
1104              'Content-Type': 'application/json',
1105              'X-CSRFToken': window.CSRF_TOKEN(),
1106            },
1107          });
1108
1109          const payload = await resp.json().catch(() => ({}));
1110          const ok = resp.ok && (payload?.status ?? true);
1111          if (ok) {
1112            const pedido = getPedidoFromResponse(payload);
1113            if (pedido) {
1114              container.innerHTML = renderUltimoPedidoStatusCard(pedido);
1115              // Determina chave de status atual
1116              const numero = pedido?.numero || pedido?.num || pedido?.id || pedido?.cd_pedido || '';
1117              const status = pedido?.status_atual_id || '';
1118              window.ULTIMO_PEDIDO_STATUS_KEY = `${numero}|${status}`;
1119
1120              // Badge de notificação: mostrar somente se status mudou desde o último visto
1121              const seenKey = localStorage.getItem(STORAGE_SEEN_KEY(window.APP_USER_ID));
1122              const precisaAlertar = !!window.ULTIMO_PEDIDO_STATUS_KEY && window.ULTIMO_PEDIDO_STATUS_KEY !== seenKey;
1123              ensureNotificationBadge(precisaAlertar);
1124            } else {
1125              container.innerHTML = 
1126                `<div class="w-full text-center bg-white">
1127                  <div class="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-[var(--c-brand-primary)]/10">
1128                    <svg class="h-7 w-7 text-[var(--c-brand-primary)]" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
1129                      <path d="M12.1 21.35a1 1 0 0 1-1.2 0C5.6 17.3 2 14.13 2 10.27A5.27 5.27 0 0 1 7.27 5a5.5 5.5 0 0 1 4.73 2.73A5.5 5.5 0 0 1 16.73 5 5.27 5.27 0 0 1 22 10.27c0 3.86-3.6 7.03-8.9 11.08Z"/>
1130                    </svg>
1131                  </div>
1132                  <p class="text-lg font-semibold text-gray-900" id="empty-title">Nada por aqui… ainda</p>
1133                  
1134                  <div class="mt-5 flex flex-col items-center gap-2 sm:flex-row sm:justify-center">
1135                    <a href="/login" class="rounded-lg border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
1136                      Entre ou cadastre-se
1137                    </a>
1138                  </div>
1139                  
1140                </div>`;
1141              ensureNotificationBadge(false);
1142            }
1143          } else {
1144            container.innerHTML = 
1145                `<div class="w-full text-center bg-white">
1146                  <div class="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-[var(--c-brand-primary)]/10">
1147                    <svg class="h-7 w-7 text-[var(--c-brand-primary)]" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
1148                      <path d="M12.1 21.35a1 1 0 0 1-1.2 0C5.6 17.3 2 14.13 2 10.27A5.27 5.27 0 0 1 7.27 5a5.5 5.5 0 0 1 4.73 2.73A5.5 5.5 0 0 1 16.73 5 5.27 5.27 0 0 1 22 10.27c0 3.86-3.6 7.03-8.9 11.08Z"/>
1149                    </svg>
1150                  </div>
1151                  <p class="text-lg font-semibold text-gray-900" id="empty-title">Nada por aqui… ainda</p>
1152                  
1153                  <div class="mt-5 flex flex-col items-center gap-2 sm:flex-row sm:justify-center">
1154                    <a href="/login" class="rounded-lg border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
1155                      Entre ou cadastre-se
1156                    </a>
1157                  </div>
1158                  
1159                </div>`;
1160            ensureNotificationBadge(false);
1161          }
1162        } catch (error) {
1163          console.error(error);
1164          const container = document.getElementById('ultimo-pedido-status');
1165          if (container) container.innerHTML = 'Não foi possível carregar o último pedido';
1166          ensureNotificationBadge(false);
1167        }
1168      }
1169
1170      document.addEventListener('DOMContentLoaded', atualizarUltimoPedido);
1171
1172    </script>
1172 
1173        
1174    
1174<script type="ff2c2aaab21707ab2ba08cc2-text/javascript">
1175    //navbar menu
1176
1177        containerMenuCategoriasAtivo = false
1178        function toggleContainerMenuCategoriasEmFoco(status){
1179          containerMenuCategoriasAtivo = status == 'open' ? true : false
1180        }
1181        function closeMenuCategoriasSeNaoEstiverFocado(){
1182          if(!document.querySelector('[data-target="container-menu-principal"]').classList.contains('hidden')){
1183            setTimeout(() => {
1184              if(!containerMenuCategoriasAtivo)
1185                toggleContainerMenuCategorias('close')
1186            });
1187          }
1188        }
1189
1190        function toggleContainerMenuCategorias(status){
1191          const containerMenuPrincipal = document.querySelector('[data-target="container-menu-principal"]')
1192          const menuPrincipal = document.querySelector('[data-target="menu-principal"]')
1193          if(containerMenuPrincipal){
1194            if(status === 'open'){
1195              containerMenuPrincipal.classList.remove('hidden')
1196                if (menuPrincipal) {
1197                  menuPrincipal.style.backgroundColor = '#1b2985';
1198                  //menuPrincipal.classList.add('bg-[var(--c-categorias-hover)]')
1199                }
1200              // Evento: abriu menu de categorias
1201              trackMenuCategoriaClick({
1202                event: 'open_menu_categorias',
1203                content_type: 'menu',
1204                content_id: 'menu_categorias_header',
1205              });
1206            } else {
1207              if (menuPrincipal) {
1208                menuPrincipal.style.backgroundColor = '';
1209                //menuPrincipal.classList.remove('bg-[var(--c-categorias-hover)]')
1210              }
1211              containerMenuPrincipal.classList.add('hidden')
1212              containerMenuCategoriasAtivo = false
1213
1214              // Evento: fechou menu de categorias
1215              trackMenuCategoriaClick({
1216                event: 'close_menu_categorias',
1217                content_type: 'menu',
1218                content_id: 'menu_categorias_header',
1219              });
1220            }
1221          }
1222        }
1223        function exibirMenuCategorias(el) {
1224          const categoriaHover = el?.getAttribute('data-categoria')
1225          if(!categoriaHover)
1226            return
1227          const menuCategorias = document.querySelector(`[data-sub-categoria="${categoriaHover}"]`)
1228          if(!menuCategorias || !menuCategorias?.classList?.contains('hidden'))
1229            return
1230          const todosMenusCategorias = document.querySelectorAll('[data-sub-categoria]')
1231          todosMenusCategorias.forEach(menu => {
1232            menu?.classList?.add('hidden')
1233          })
1234          menuCategorias?.classList?.remove('hidden')
1235        }
1236
1237    function trackMenuCategoriaClick(data) {
1238      try {
1239        if (typeof filtroParaDadosAnaliticos === 'function') {
1240          filtroParaDadosAnaliticos('MenuAndCallToAction', {
1241            section: 'menu_categorias',
1242            ...data,
1243          });
1244        }
1245      } catch (e) {
1246        console.error('Erro ao disparar evento de menu categorias:', e);
1247      }
1248    }
1249    
1250      function montarMenu(arvore) {
1251
1252        const toNode = (n) => {
1253          const children = Array.isArray(n?.filhos) ? n.filhos : [];
1254      
1255          return {
1256            id: n?.id,
1257            url: n?.url || '#',
1258            label: n?.nome || '',
1259            order: typeof n?.ordem === 'number' ? n.ordem : Number.MAX_SAFE_INTEGER,
1260      
1261            // mantém o que seu render já espera
1262            children: children.map(toNode),
1263      
1264            // opcionais (se quiser manter compatibilidade com banner)
1265            banner: n?.imagem || null,
1266            banner_url: n?.url || null,
1267          };
1268        };
1269        arvore = arvore.map(toNode);
1270
1271        const left = document.getElementById('menu-categorias-esquerda');
1272        const right = document.getElementById('menu-categorias-direita');
1273        if (!left || !right) return;
1274    
1275        left.innerHTML = '';
1276        right.innerHTML = '';
1277
1278        const ordenadas = [...(arvore || [])].sort((a, b) => {
1279          const ao = typeof a.order === 'number' ? a.order : Number.MAX_SAFE_INTEGER;
1280          const bo = typeof b.order === 'number' ? b.order : Number.MAX_SAFE_INTEGER;
1281          return ao - bo;
1282        });
1283
1284        // Helper
1285        const toSentenceCase = (str) => {
1286          const s = (str || '').toLowerCase();
1287          return s ? s.charAt(0).toUpperCase() + s.slice(1) : s;
1288        };
1289
1290        // Monta os itens do menu esquerdo e os painéis da direita
1291        ordenadas.forEach((cat, idx) => {
1292          // Item esquerda: <a> clicável com seta ao lado, data-categoria + onmouseenter para exibirMenuCategorias
1293          const item = document.createElement('a');
1294          item.href = cat.url;
1295          item.className = 'flex items-center px-4 py-2 w-full cursor-pointer group';
1296          item.setAttribute('data-target', 'item-categorias');
1297          item.setAttribute('data-categoria', String(cat.id));
1298          item.setAttribute('onmouseenter', 'exibirMenuCategorias(this)');
1299    
1300          item.innerHTML = `
1301            <span class="text-[#444] font-semibold group-hover:font-bold text-[15px] pr-3">${cat.label}</span>
1302            <img loading="lazy" src="/staticfiles/img/client2/arrow-right.svg" alt="Seta" width="21" height="21">
1303          `;
1304
1305          item.addEventListener('click', () => {
1306            trackMenuCategoriaClick({
1307              event: 'click_categoria_principal',
1308              content_type: 'categoria',
1309              content_id: cat.id,
1310              label: cat.label,
1311            });
1312          });
1313    
1314          left.appendChild(item);
1315
1316          // Painel direita: pré-renderizado com data-sub-categoria (estrutura SEO-friendly)
1317        const panel = document.createElement('div');
1318        panel.className = `flex-1 flex flex-col overflow-hidden${idx === 0 ? '' : ' hidden'}`;
1319        panel.setAttribute('data-sub-categoria', String(cat.id));
1320
1321        panel.innerHTML = `
1322          <div class="flex justify-between shrink-0">
1323            <p class="text-[16px] text-[var(--c-brand-primary)] font-bold uppercase">${cat.label}</p>
1324            <a href="${cat.url}" class="text-[#1b2985] font-medium text-[12px]">Ver todos</a>
1325          </div>
1326        `;
1327
1328        const categoriesWrap = document.createElement('div');
1329        categoriesWrap.className = 'flex-1 min-h-0 overflow-hidden pt-2';
1330
1331        const grid = document.createElement('div');
1332        grid.className = 'w-full h-full overflow-hidden';
1333        grid.style.cssText = 'columns: 6; column-fill: auto;';
1334
1335        (cat.children || []).forEach(sec => {
1336          const block = document.createElement('div');
1337          block.className = ' mb-3 flex flex-col gap-y-0.5';
1338
1339          const tituloSec = document.createElement('a');
1340          tituloSec.href = sec.url;
1341          tituloSec.className = 'pb-0.5 text-[16px] font-semibold text-[var(--c-brand-primary)] leading-tight';
1342          tituloSec.textContent = sec.label;
1343
1344          tituloSec.addEventListener('click', () => {
1345            trackMenuCategoriaClick({
1346              event: 'click_subcategoria',
1347              content_type: 'subcategoria',
1348              content_id: sec.id,
1349              label: sec.label,
1350              parent_id: cat.id,
1351              parent_label: cat.label,
1352            });
1353          });
1354
1355          block.appendChild(tituloSec);
1356
1357          if (Array.isArray(sec.children)) {
1358            sec.children.forEach(ter => {
1359              const linkTer = document.createElement('a');
1360              linkTer.href = ter.url;
1361              linkTer.className = 'text-[14px] text-[#444] hover:underline leading-snug';
1362              linkTer.textContent = toSentenceCase(ter.label);
1363
1364              linkTer.addEventListener('click', () => {
1365                trackMenuCategoriaClick({
1366                  event: 'click_subcategoria_nivel_2',
1367                  content_type: 'subcategoria_2',
1368                  content_id: ter.id,
1369                  label: ter.label,
1370                  parent_id: sec.id,
1371                  parent_label: sec.label,
1372                  root_id: cat.id,
1373                  root_label: cat.label,
1374                });
1375              });
1376
1377              block.appendChild(linkTer);
1378            });
1379          }
1380
1381          grid.appendChild(block);
1382        });
1383
1384        const banner = document.createElement('div');
1385        banner.className = 'flex items-center w-full shrink-0 pt-2';
1386        const bHref = cat.banner_url || cat.url || '#';
1387        const bImg = cat.banner ? `<img loading="lazy" src="${cat.banner}" alt="Banner ${cat.label}" class="w-full rounded-[15px] object-cover" style="height: 90px; object-position: center;">` : '<img loading="lazy" src="https://placehold.co/1000x90" alt="Banner ${cat.label}" class="w-full rounded-[15px] object-cover" style="height: 90px; object-position: center;">';
1388        banner.innerHTML = `<a href="${bHref}" class="cursor-pointer w-full block" target="_blank" rel="noopener noreferrer">${bImg}</a>`;
1389
1390        categoriesWrap.appendChild(grid);
1391        panel.appendChild(categoriesWrap);
1392        panel.appendChild(banner);
1393        right.appendChild(panel);
1394      });
1395    }
1396    
1397      // CARREGAMENTO DE PESQUISA
1398
1399      function inicializarHeaderSearch(){
1400        try {
1401          const input = document.getElementById('header-search-input');
1402          const dropdown = document.getElementById('header-search-dropdown');
1403          const content = document.getElementById('header-search-dropdown-content');
1404          if(!input || !dropdown || !content) return;
1405
1406          // Delegação: termos/histórico (bind uma vez)
1407          bindHeaderSearchDelegates();
1408
1409          const debounced = debounce(renderHeaderSearch, 200);
1410
1411          input.addEventListener('focus', () => {
1412            abrirDropdown();
1413            renderHeaderSearch(); // decide histórico x resultados
1414          });
1415
1416          input.addEventListener('input', () => {
1417            abrirDropdown();
1418            debounced();
1419          });
1420
1421          input.addEventListener('keydown', (e) => {
1422            if (e.key === 'Enter') submitHeaderSearch();
1423            if (e.key === 'Escape') fecharDropdown();
1424          });
1425
1426          // Fecha clicando fora
1427          document.addEventListener('mousedown', (e) => {
1428            const t = e.target;
1429            if (t === input || input.contains(t)) return;
1430            if (dropdown && (t === dropdown || dropdown.contains(t))) return;
1431            fecharDropdown();
1432          });
1433        } catch (error) {
1434          console.error(error);
1435        }
1436      }
1437
1438      function bindHeaderSearchDelegates(){
1439        const content = document.getElementById('header-search-dropdown-content');
1440        if (!content || content.dataset.bound) return;
1441
1442        content.addEventListener('click', (e) => {
1443          const termBtn = e.target.closest('[data-term]');
1444          if (termBtn) {
1445            const termo = decodeURIComponent(termBtn.getAttribute('data-term') || '');
1446            preencherBuscaCom(termo);
1447            submitHeaderSearch();
1448            return;
1449          }
1450          const rmBtn = e.target.closest('[data-hist-remove]');
1451          if (rmBtn) {
1452            const termo = decodeURIComponent(rmBtn.getAttribute('data-hist-remove') || '');
1453            HeaderSearchCore.removeHistoricoPesquisa(termo);
1454            atualizarDropdownComHistoricoESugestoes();
1455            return;
1456          }
1457          const clrBtn = e.target.closest('[data-hist-clear]');
1458          if (clrBtn) {
1459            HeaderSearchCore.clearHistoricoPesquisa();
1460            atualizarDropdownComHistoricoESugestoes();
1461            return;
1462          }
1463        });
1464
1465        content.dataset.bound = '1';
1466      }
1467
1468      function abrirDropdown(){
1469        const dd = document.getElementById('header-search-dropdown');
1470        if(dd) dd.classList.remove('hidden');
1471      }
1472      function fecharDropdown(){
1473        const dd = document.getElementById('header-search-dropdown');
1474        if(dd) dd.classList.add('hidden');
1475      }
1476
1477      async function renderHeaderSearch(){
1478        const input = document.getElementById('header-search-input');
1479        const content = document.getElementById('header-search-dropdown-content');
1480        if(!input || !content) return;
1481
1482        const termo = (input.value || '').trim();
1483        if(!termo){
1484          atualizarDropdownComHistoricoESugestoes();
1485          return;
1486        }
1487
1488        content.innerHTML = HeaderSearchCore.templateLoading();
1489
1490        const { termos, produtos } = await HeaderSearchCore.getSearchData(termo);
1491
1492        let html = '';
1493        if (Array.isArray(termos) && termos.length) {
1494          html += `<p class="text-[12px] text-[#777] px-1 mb-1">Termos sugeridos</p>`;
1495          html += termos.map(s => `
1496            <button type="button"
1497                    class="w-full text-left px-2 py-1.5 hover:bg-[#f6f7ff] rounded cursor-pointer"
1498                    data-term="${encodeURIComponent(s)}">
1499              ${HeaderSearchCore.escapeHtml(s)}
1500            </button>
1501          `).join('');
1502          if (produtos?.length) html += `<hr class="my-2 border-[#eee]">`;
1503        }
1504
1505        if (produtos?.length){
1506          html += `<p class="text-[12px] text-[#777] px-1 mb-2">Produtos sugeridos</p>`;
1507          html += renderDropdownProdutos2Cols(produtos); // mantém 2 colunas no desktop
1508          html += `
1509            <div class="mt-4 flex justify-center">
1510              <a class="block text-[var(--c-brand-primary)] font-semibold px-2 py-2 hover:underline"
1511                href="/pesquisa/${encodeURIComponent(termo)}">Ver todos os produtos</a>
1512            </div>`;
1513        } else {
1514          html += `
1515            <a class="block text-[var(--c-brand-primary)] font-semibold px-2 py-2 hover:underline"
1516              href="/pesquisa/${encodeURIComponent(termo)}">
1517              Ver resultados para "${HeaderSearchCore.escapeHtml(termo)}"
1518            </a>`;
1519        }
1520
1521        content.innerHTML = html;
1522      }
1523
1524      function atualizarDropdownComHistoricoESugestoes(){
1525        const content = document.getElementById('header-search-dropdown-content');
1526        const input = document.getElementById('header-search-input');
1527        if(!content || !input) return;
1528
1529        const historico = HeaderSearchCore.getHistoricoPesquisa();
1530        let html = '';
1531        if (historico.length){
1532          html += `
1533            <div class="flex items-center justify-between px-1 mb-1">
1534              <p class="text-[12px] text-[#777]">Histórico</p>
1535              <button type="button" class="text-[12px] text-[#888] hover:underline" data-hist-clear>
1536                Limpar
1537              </button>
1538            </div>
1539          `;
1540          html += historico.map(h => `
1541            <div class="flex items-center justify-between px-2 py-1.5 hover:bg-[#f6f7ff] rounded">
1542              <button type="button" class="text-left flex-1" data-term="${encodeURIComponent(h)}">
1543                ${HeaderSearchCore.escapeHtml(h)}
1544              </button>
1545              <button type="button" class="text-[#999] ml-2" aria-label="Remover"
1546                      data-hist-remove="${encodeURIComponent(h)}">✕</button>
1547            </div>
1548          `).join('');
1549        } else {
1550          html += `<p class="text-[12px] text-[#777] px-1">Sem histórico recente</p>`;
1551        }
1552
1553        content.innerHTML = html;
1554      }
1555
1556      function preencherBuscaCom(termo){
1557        const input = document.getElementById('header-search-input');
1558        if(!input) return;
1559        input.value = termo;
1560        abrirDropdown();
1561        renderHeaderSearch();
1562      }
1563
1564      function submitHeaderSearch(){
1565        const input = document.getElementById('header-search-input');
1566        if(!input) return;
1567        const termo = (input.value || '').trim();
1568        if(!termo){
1569          abrirDropdown();
1570          atualizarDropdownComHistoricoESugestoes();
1571          return;
1572        }
1573        HeaderSearchCore.addHistoricoPesquisa(termo);
1574        window.location.href = `/pesquisa/${encodeURIComponent(termo)}`;
1575      }
1576
1577      document.addEventListener('DOMContentLoaded', () => {
1578        inicializarHeaderSearch();
1579      });
1580
1581      function renderDropdownProdutos2Cols(listaProdutos = []) {
1582        const itens = listaProdutos.map(templateCardProdutoDropdown).join('');
1583        return `
1584          <div class="grid grid-cols-2 gap-2 p-2">
1585            ${itens}
1586          </div>
1587        `;
1588      }
1589
1590      function templateCardProdutoDropdown(produto){
1591        const produto_id = produto?.produto_id || '';
1592        const imagem   = produto?.imagem_produto || '';
1593        const nome     = produto?.nm_produto || '';
1594        const url      = `/${produto?.url_produto || ''}`;
1595        const perc = ''
1596        //const perc     = temDesc ? Math.round(((valorIni - valor) / valorIni) * 100) : 0;
1597
1598        return `
1599          <a class="block group" href="${url}" aria-label="${escapeHtml(nome)}" data-target="pesquisa-header" data-invisible="true" data-cd-produto="${produto_id}" data-notificar-disponibilidade="true">
1600            <div class="relative border border-gray-200 rounded-[16px] p-3 w-full h-full flex gap-x-3 hover:shadow-sm transition">
1601              
1602              ${perc ? `
1603              <div class="absolute p-0.5 top-2 left-2 z-[3] flex items-center justify-center rounded-lg bg-[#9FFCAC] text-[#0C670F] font-semibold">
1604                <div class="text-[8px]/[11px] font-bold flex flex-col items-center leading-none">
1605                  <span>-${perc}%</span><span>OFF</span>
1606                </div>
1607                <img loading="lazy" src="/staticfiles/img/client2/icon-arrow-down-desc2.svg" alt="Selo de Oferta"
1608                    class="w-[14px] h-[18px] ml-1">
1609              </div>` : ''}
1610
1611              <!-- Imagem -->
1612              <div class="flex-none">
1613                <img
1614                  loading="lazy"
1615                  class="w-[70px] h-[70px] object-contain"
1616                  src="${imagem}"
1617                  onerror="this.onerror=null;this.src='https://placehold.co/190x190';"
1618                  alt="${escapeHtml(nome)}">
1619              </div>
1620
1621              <!-- Conteúdo -->
1622              <div class="flex flex-col flex-1 min-w-0 relative">
1623                <span class="text-[12px] text-[#444] font-semibold line-clamp-2">
1624                  ${escapeHtml(nome)}
1625                </span>
1626
1627                <div class="text-[15px] text-[#444] font-black min-w-0 mt-1" data-target="preco-produto">
1628                  <div class="placeholder" style="height: 30px;"></div>
1629                </div>
1630
1631                <div class="absolute bottom-0 right-0 z-[3]" data-target="comprar-produto">
1632                  <div class="placeholder h-[24px]"></div>
1633                </div>
1634              </div>
1635            </div>
1636          </a>
1637        `;
1638      }
1639    </script>
1639
1640      
1641    
1642
1643  </div>
1644  
1645
1646
1647  
1648  
1649  <div id="app_menu">
1650    
1651  </div>
1652  
1653
1654
1655  <div id="checkout-desfoco" class="fixed top-0 right-0 bottom-0 left-0 bg-[#000] opacity-[.4] z-[12] closed" data-seletor="" data-popup-checkout="" onclick="if (!window.__cfRLUnblockHandlers) return false; toggleCarrinhoDesfoco(this)" data-cf-modified-ff2c2aaab21707ab2ba08cc2-=""></div>
1656
1657  <div id="pagina-header" class="flex flex-1 pb-8 md:pb-8 mt-35">
1658    <main class="container mx-auto flex-1" >
1659      
1660
1661<div class="flex flex-col gap-y-7.5 md:gap-y-10 px-0 lg:px-4">
1662    
1663    
1664      <h1 class="sr-only">Encontre uma Loja das Farmácias Brava</h1>
1665    
1666    
1667        
1668            <link
1669rel="stylesheet"
1670href="https://unpkg.com/[email protected]/dist/leaflet.css"
1671integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
1672crossorigin=""
1673/>
1674<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin="" defer type="ff2c2aaab21707ab2ba08cc2-text/javascript"></script>
1674
1675
1676<div aria-labelledby="nossas-lojas" class="container mx-auto px-2 md:px-4 py-3 md:py-6">
1677  <!-- Hero/banner -->
1678  <section class="w-full">
1679      <div class="container mx-auto grid grid-cols-12 gap-5 items-center">
1680        <div class="col-span-12 py-5">
1681          <div class="w-full rounded-lg">
1682            <img src="/staticfiles/img/client2/institucional/banner_nossas_lojas.png" alt="Banner" class="w-full h-full object-cover">
1683          </div>
1684        </div>
1685      </div>
1686    </section>
1687    
1688    <!-- Seção busca + mapa -->
1689    <section class="w-full bg-[var(--c-brand-secondary)] py-10 rounded-xl">
1690      <div class="container mx-auto grid grid-cols-12 gap-8 px-2 md:px-10">
1691        <!-- Coluna filtros -->
1692        <div class="col-span-12 md:col-span-6">
1693          <div class="max-w-xl">
1694            <h2 class="text-[#87f0fe] text-3xl font-bold">Encontre a<br> Brava mais próxima</h2>
1695            <p class="text-white text-xl mt-4">
1696              Há sempre uma Brava perto de você! Informe seu estado para
1697              encontrar a unidade mais próxima.
1698            </p>
1699            
1700            
1701    
1702            <!-- Filtro 24h -->
1703            <div class="mt-2 flex items-center gap-2">
1704              <input id="chk-24h" type="checkbox" class="form-checkbox cursor-pointer peer relative h-5 w-5 mr-2 shrink-0 appearance-none rounded-sm
1705              bg-white after:absolute after:left-0 after:top-0 after:h-full after:w-full after:bg-[url('/staticfiles/img/icon_check.svg')] 
1706              after:bg-[length:40px] after:bg-center after:bg-no-repeat after:content-[''] checked:bg-[var(--c-brand-primary)] 
1707              checked:border-[var(--c-brand-primary)] hover:ring hover:ring-gray-200 focus:outline-none">
1708              <label for="chk-24h" class="text-white cursor-pointer">Somente unidades 24h</label>
1709            </div>
1710    
1711    
1712            <div class="mt-6 flex flex-col gap-3">
1713              <button id="btn-geolocate" type="button" class="w-full inline-flex justify-center cursor-pointer items-center gap-2 rounded-lg bg-[#eae0ff] px-4 py-3 font-semibold shadow">
1714                <img src="/staticfiles/img/client2/institucional/gps.webp" alt="Localização" class="w-5 h-5">
1715                Usar minha localização
1716              </button>
1717    
1718              <div class="relative">
1719                <select id="select-estado" aria-label="Estado"
1720                        class="appearance-none justify-between w-full rounded-lg px-4 py-3 pr-10 border-0 shadow bg-white text-gray-400 font-semibold
1721                              focus:outline-none focus:ring-2 focus:ring-[var(--c-brand-secondary)]">
1722                  <option selected>Estado</option>
1723                </select>
1724                <!-- seta -->
1725                <img src="/staticfiles/img/client2/icon-arrow-down-pink.svg" alt="Seta" class="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4">
1726              </div>
1727              <div class="relative">
1728                <select id="select-filiais" aria-label="Filiais"
1729                        class="appearance-none justify-between w-full rounded-lg px-4 py-3 pr-10 border-0 shadow bg-white text-gray-400 font-semibold
1730                              focus:outline-none focus:ring-2 focus:ring-[var(--c-brand-secondary)]">
1731                  <option selected disabled>Filiais</option>
1732                </select>
1733                <!-- seta -->
1734                <img src="/staticfiles/img/client2/icon-arrow-down-pink.svg" alt="Seta" class="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4">
1735              </div>
1736              
1737            </div>
1738          </div>
1739        </div>
1740    
1741        <!-- Coluna mapa -->
1742        <div class="col-span-12 md:col-span-6">
1743          <div class="rounded-xl overflow-hidden bg-white shadow-xl">
1744            <div id="lojas-map" class="w-full h-[380px] lg:h-[360px] z-0"></div>
1745          </div>
1746        </div>
1747    
1748        <!-- Card loja selecionada -->
1749        <div class="col-span-12">
1750          <div class="bg-white/95 rounded-xl shadow-xl p-5">
1751            <p id="loja-endereco" class="font-semibold text-center uppercase text-lg text-gray-800" aria-l
1751ive="polite">
1752              Selecione uma unidade no mapa para ver o endereço.
1753            </p>
1754            <div class="mt-5 grid grid-cols-12 gap-3">
1755    
1756              <a id="btn-whats"
1757                class="col-span-12 md:col-span-4 button bg-[#eae0ff] text-[#000] opacity-60 pointer-events-none"
1758                target="_blank" rel="noopener" aria-disabled="true">
1759                <div class="flex items-center justify-center gap-3 py-1.5">
1760                  <img src="/staticfiles/img/client2/institucional/whats.svg" alt="Whatsapp" class="w-5 h-5">
1761                  Whatsapp
1762                </div>
1763              </a>
1764    
1765              <a id="btn-conheca"
1766                class="col-span-12 md:col-span-4 button bg-[#eae0ff] text-[#000] opacity-60 pointer-events-none"
1767                target="_blank" rel="noopener" aria-disabled="true">
1768                <div class="flex items-center justify-center gap-3 py-1.5">
1769                  <img src="/staticfiles/img/client2/institucional/loja.webp" alt="Conheça a loja" class="w-5 h-5">
1770                  Conheça a loja
1771                </div>
1772              </a>
1773    
1774              <a id="btn-rota"
1775                class="col-span-12 md:col-span-4 button bg-[#eae0ff] text-[#000] opacity-60 pointer-events-none"
1776                target="_blank" rel="noopener" aria-disabled="true">
1777                <div class="flex items-center justify-center gap-3 py-1.5">
1778                  <img src="/staticfiles/img/client2/institucional/mapa.webp" alt="Traçar rota" class="w-5 h-5">
1779                  Traçar rota
1780                </div>
1781              </a>
1782            </div>
1783          </div>
1784        </div>
1785      </div>
1786    </section>
1787  </div>
1788  
1789  
1789<script defer type="ff2c2aaab21707ab2ba08cc2-text/javascript">
1790    document.addEventListener('DOMContentLoaded', () => {
1791      // ----------------- MAPA -----------------
1792      const defaultCoords = [-26.229, -52.671];
1793    
1794      const map = L.map('lojas-map', { scrollWheelZoom: false }).setView(defaultCoords, 12);
1795    
1796      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
1797        maxZoom: 19,
1798        attribution: '&copy; OpenStreetMap'
1799      }).addTo(map);
1800
1801      async function getLojas() {
1802        load('on', document.body);
1803          try {
1804            const resp = await fetch("/dados/filiais", {
1805              method: "POST",
1806              headers: { "Content-Type": "application/json", "X-CSRFToken": window.CSRF_TOKEN() },
1807              body: JSON.stringify({})
1808            });
1809            const data = await resp.json();
1810    
1811            if (resp.ok && data.status) {
1812              const lista = Array.isArray(data.lista_filiais) ? data.lista_filiais : [];
1813              lojas = lista.map((f) => {
1814                const lat = parseFloat(f.latitude);
1815                const lng = parseFloat(f.longitude);
1816                const hasCoords = Number.isFinite(lat) && Number.isFinite(lng);
1817                const filiais = f?.nm_completo || '';
1818                const enderecoFmt = [
1819                  [f?.endereco, f?.numero].filter(Boolean).join(', '),
1820                  f?.bairro,
1821                  [filiais, f?.nm_abrev].filter(Boolean).join(' - '),
1822                  f?.cep_id ? `CEP ${f.cep_id}` : ''
1823                ].filter(Boolean).join(' | ');
1824                const telefoneDigits = (f?.telefone ? String(f.telefone) : '').replace(/\D/g, '');
1825                const whatsapp = telefoneDigits ? `https://wa.me/55${telefoneDigits}` : null;
1826                const nomeLoja = (f?.nm_completo || f?.nm_descritivo || `Filial ${f?.codigo || ''}`).trim();
1827                const coords = hasCoords ? [lat, lng] : null;
1828                return {
1829                  id: String(f?.id ?? f?.codigo ?? cryptoRandomId()),
1830                  uf: f?.nm_abrev || '',
1831                  filiais,
1832                  nome: nomeLoja,
1833                  coords,
1834                  endereco: enderecoFmt,
1835                  whatsapp,
1836                  url: buildGooglePlaceUrl(nomeLoja, enderecoFmt, coords),
1837                  aberto24h: !!f?.is_24hr
1838                };
1839              });
1840
1841              // Reconstroi índice por id
1842              lojaById.clear();
1843              lojas.forEach(l => lojaById.set(l.id, l));
1844
1845              // Popular selects dinâmicos
1846              populateEstadoSelect();
1847
1848              // Renderiza mapa com as lojas
1849              renderMarkers();
1850
1851            } else {
1852              toastr?.error(data.descricao || 'Não foi possível encontrar as lojas.');
1853            }
1854          } finally {
1855            load('off', document.body);
1856          }
1857      }
1858
1859      getLojas();
1860
1861
1862      let lojas = [];
1863      const lojaById = new Map();
1864    
1865      // ----------------- ELEMENTOS UI -----------------
1866      const enderecoEl   = document.getElementById('loja-endereco');
1867      const btnRota      = document.getElementById('btn-rota');
1868      const btnWhats     = document.getElementById('btn-whats');
1869      const btnConheca   = document.getElementById('btn-conheca');
1870    
1871      const btnGeo       = document.getElementById('btn-geolocate');
1872      const inputEnd     = document.getElementById('endereco-input');
1873      const btnBuscarEnd = document.getElementById('btn-buscar-endereco');
1874      const statusEnd    = document.getElementById('endereco-status');
1875      const chk24h       = document.getElementById('chk-24h');
1876    
1877      const selectEstado   = document.getElementById('select-estado');
1878      const selectfiliais   = document.getElementById('select-filiais');
1879      const selectFranquia = document.getElementById('select-franquia') || null;
1880    
1881      // ----------------- HELPERS -----------------
1882      function norm(s){
1883        return String(s || '')
1884          .toLowerCase()
1885          .normalize('NFD')
1886          .replace(/[\u0300-\u036f]/g, '');
1887      }
1888      function cryptoRandomId(){
1889        return Math.random().toString(36).slice(2) + Date.now().toString(36);
1890      }
1891    
1892      function setLinkDisabled(a, disabled) {
1893        if (!a) return;
1894        if (disabled) {
1895          a.setAttribute('aria-disabled', 'true');
1896          a.classList.add('opacity-60', 'pointer-events-none');
1897          a.removeAttribute('href');
1898        } else {
1899          a.setAttribute('aria-disabled', 'false');
1900          a.classList.remove('opacity-60', 'pointer-events-none');
1901        }
1902      }
1903    
1904      function buildMapsDirUrl(coords){
1905        const [lat, lng] = coords;
1906        const destination = encodeURIComponent(`${lat},${lng}`);
1907        return `https://www.google.com/maps/dir/?api=1&destination=${destination}`;
1908      }
1909
1910      function buildGooglePlaceUrl(nome, endereco, coords){
1911        if (Array.isArray(coords) && coords.length === 2 && coords.every(Number.isFinite)) {
1912          return `https://www.google.com/maps?q=${coords[0]},${coords[1]}`;
1913        }
1914        const query = [nome, endereco].filter(Boolean).join(' ').trim();
1915        if (!query) return '';
1916        return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(query)}`;
1917      }
1918    
1919      function selectLoja(loja){
1920        if (!loja) return;
1921    
1922        enderecoEl && (enderecoEl.textContent = loja.endereco);
1923    
1924        setLinkDisabled(btnWhats, !loja.whatsapp);
1925        if (btnWhats && loja.whatsapp) btnWhats.href = loja.whatsapp;
1926    
1927        setLinkDisabled(btnConheca, !loja.url || loja.url === '#');
1928        if (btnConheca && loja.url) btnConheca.href = loja.url;
1929    
1930        const hasCoords = Array.isArray(loja.coords) && loja.coords.length === 2 && loja.coords.every(Number.isFinite);
1931        setLinkDisabled(btnRota, !hasCoords);
1932        if (btnRota && hasCoords) btnRota.href = buildMapsDirUrl(loja.coords);
1933      }
1934    
1935      // Estado inicial
1936      setLinkDisabled(btnWhats, true);
1937      setLinkDisabled(btnConheca, true);
1938      setLinkDisabled(btnRota, true);
1939        
1940      const FranquiasAPI = {
1941        list({ uf, filiais, only24h = false }) {
1942          return new Promise((resolve) => {
1943            setTimeout(() => {
1944              const data = lojas
1945                .filter(l =>
1946                  (!uf || l.uf === uf) &&
1947                  (!filiais || l.filiais === filiais) &&
1948                  (!only24h || l.aberto24h)
1949                )
1950                .map(l => ({
1951                  id: l.id,
1952                  nome: l.nome,
1953                  filiais: l.filiais,
1954                  uf: l.uf,
1955                  aberto24h: l.aberto24h
1956                }));
1957              resolve(data);
1958            }, 300); // simula latência
1959          });
1960        }
1961      };
1962    
1963      function resetFranquiaSelect(texto = 'Franquia') {
1964        if (!selectFranquia) return;
1965        selectFranquia.innerHTML = `<option selected disabled>${texto}</option>`;
1966        selectFranquia.disabled = true;
1967      }
1968    
1969      async function loadFranquias() {
1970        if (!selectEstado || !selectfiliais || !selectFranquia) return;
1971    
1972        const uf = selectEstado.value;
1973        const filiais = selectfiliais.value;
1974    
1975        resetFranquiaSelect('Carregando…');
1976    
1977        const lista = await FranquiasAPI.list({
1978          uf,
1979          filiais,
1980          only24h: !!(chk24h && chk24h.checked)
1981        });
1982    
1983        resetFranquiaSelect('Franquia');
1984        if (!lista.length) {
1985          const opt = new Option('Sem franquias nessa região', '');
1986          opt.disabled = true;
1987          selectFranquia.add(opt);
1988          return;
1989        }
1990    
1991        lista.forEach(f => selectFranquia.add(new Option(f.nome, f.id)));
1992        selectFranquia.disabled = false;
1993      }
1994    
1995      // ----------------- MARCADORES -----------------
1996      const markerLayer = L.layerGroup().addTo(map);
1997      let markersMap = new Map(); // loja -> marker
1998    
1999      function getFiltrosSelecionados() {
2000        const uf = selectEstado && selectEstado.value !== 'Estado' ? selectEstado.value : '';
2001        const filiaisVal = selectfiliais && !selectfiliais.disabled && selectfiliais.value !== 'Filiais'
2002          ? selectfiliais.value
2003          : '';
2004        const somente24h = !!(chk24h && chk24h.checked);
2005        return { uf, filiais: filiaisVal, somente24h };
2006      }
2007
2008      function getLojasFiltradas() {
2009        const { uf, filiais, somente24h } = getFiltrosSelecionados();
2010        return lojas.filter((l) => {
2011          if (somente24h && !l.aberto24h) return false;
2012          if (uf && l.uf !== uf) return false;
2013          if (filiais && norm(l.filiais) !== norm(filiais)) return false;
2014          return Array.isArray(l.coords) && l.coords.length === 2;
2015        });
2016      }
2017
2018      function trackStoreSearch(trigger) {
2019        try {
2020          if (typeof filtroParaDadosAnaliticos !== 'function') return;
2021
2022          const { uf, filiais, somente24h } = getFiltrosSelecionados();
2023          const searchPieces = [uf, filiais].filter(Boolean);
2024          const searchTerm = searchPieces.join(' | ') || (trigger === 'geolocation' ? 'geolocalizacao' : 'todos');
2025
2026          filtroParaDadosAnaliticos('Search', {
2027            search_term: searchTerm,
2028            search_type: 'store',
2029            results_count: getLojasFiltradas().length,
2030            state: uf || undefined,
2031            is_24h: somente24h,
2032            trigger
2033          });
2034        } catch (_) {}
2035      }
2036
2037      function renderMarkers() {
2038        markerLayer.clearLayers();
2039        markersMap = new Map();
2040    
2041        const filtradas = getLojasFiltradas();
2042    
2043        const created = [];
2044    
2045        filtradas.forEach((loja) => {
2046          const marker = L.marker(loja.coords).addTo(markerLayer);
2047          const tag24h = loja.aberto24h ? ' <span style="color:#16a34a;font-weight:600;">(24h)</span>' : '';
2048          marker.bindPopup(`<strong>${loja.nome}</strong>${tag24h}`);
2049          marker.on('click', () => selectLoja(loja));
2050          markersMap.set(loja, marker);
2051          created.push(marker);
2052        });
2053    
2054        if (created.length) {
2055          const group = L.featureGroup(created);
2056          map.fitBounds(group.getBounds().pad(0.2));
2057        } else {
2058          map.setView(defaultCoords, 12);
2059          if (enderecoEl) enderecoEl.textContent = 'Nenhuma unidade encontrada com o filtro aplicado.';
2060          setLinkDisabled(btnRota, true);
2061          setLinkDisabled(btnWhats, true);
2062          setLinkDisabled(btnConheca, true);
2063        }
2064      }
2065    
2066      // renderMarkers() será chamado após o carregamento da API
2067    
2068      // ----------------- GEOLOCALIZAÇÃO -----------------
2069      btnGeo && btnGeo.addEventListener('click', async () => {
2070        trackStoreSearch('geolocation');
2071        if (!('geolocation' in navigator)) {
2072          toastr.error('Seu navegador não suporta geolocalização.', 'Erro');
2073          return;
2074        }
2075        if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
2076          toastr.error('Ative HTTPS para usar geolocalização.', 'Erro');
2077          return;
2078        }
2079    
2080        navigator.geolocation.getCurrentPosition(
2081          ({ coords }) => {
2082            const { latitude, longitude, accuracy } = coords;
2083            map.setView([latitude, longitude], 13);
2084            const userPane = map.createPane('userPane');
2085            userPane.style.zIndex = 650; // acima de markers (600)
2086            L.circle([latitude, longitude], {
2087              pane: 'userPane',
2088              radius: Math.max(150, accuracy || 200),
2089              color: '#2563eb',
2090              fillColor: '#2563eb',
2091              fillOpacity: 0.2
2092            }).addTo(map);
2093          },
2094          (err) => {
2095            if (err.code === 1) toastr.error('Permissão negada. Libere a localização e recarregue.', 'Erro');
2096            else if (err.code === 2) toastr.error('Posição indisponível. Tente novamente.', 'Erro');
2097            else if (err.code === 3) toastr.error('Tempo esgotado. Tente de novo.', 'Erro');
2098          },
2099          { enableHighAccuracy: true, timeout: 10000, maximumAge: 30000 }
2100        );
2101      });
2102    
2103      // ----------------- GEOCODING / BUSCA -----------------
2104      let userSearchMarker = null;
2105    
2106      async function geocodeAddress(q) {
2107        if (statusEnd) statusEnd.textContent = 'Buscando endereço…';
2108        try {
2109          const url = `https://nominatim.openstreetmap.org/search?format=json&limit=1&countrycodes=br&q=${encodeURIComponent(q)}`;
2110          const res = await fetch(url);
2111          if (!res.ok) throw new Error('Falha no geocoding');
2112          const data = await res.json();
2113          if (!data.length) {
2114            if (statusEnd) statusEnd.textContent = 'Endereço não encontrado.';
2115            return;
2116          }
2117          const { lat, lon, display_name } = data[0];
2118          if (statusEnd) statusEnd.textContent = display_name;
2119    
2120          const latNum = parseFloat(lat), lonNum = parseFloat(lon);
2121          map.setView([latNum, lonNum], 14);
2122    
2123          if (userSearchMarker) map.removeLayer(userSearchMarker);
2124          userSearchMarker = L.marker([latNum, lonNum]).addTo(map).bindPopup('Endereço buscado').openPopup();
2125        } catch (e) {
2126          if (statusEnd) statusEnd.textContent = 'Erro ao buscar endereço.';
2127          console.error(e);
2128        }
2129      }
2130    
2131      async function buscarEnderecoOuLoja(){
2132        const q = (inputEnd && inputEnd.value || '').trim();
2133        if(!q) return;
2134    
2135        // 1) Tenta por nome/endereço nas lojas (respeitando o 24h)
2136        const qn = norm(q);
2137        const somente24h = !!(chk24h && chk24h.checked);
2138    
2139        const matches = lojas.filter(l =>
2140          (!somente24h || l.aberto24h) &&
2141          (norm(l.nome).includes(qn) || norm(l.endereco).includes(qn))
2142        );
2143    
2144        if (matches.length > 0) {
2145          if (statusEnd) statusEnd.textContent = matches.length === 1
2146            ? `Loja encontrada: ${matches[0].nome}`
2147            : `${matches.length} lojas encontradas`;
2148    
2149          // atualiza markers conforme filtro atual
2150          renderMarkers();
2151    
2152          // pega os markers das lojas encontradas
2153          const ms = matches.map(l => markersMap.get(l)).filter(Boolean);
2154    
2155          if (ms.length === 1) {
2156            const m = ms[0];
2157            const { lat, lng } = m.getLatLng();
2158            map.setView([lat, lng], 15);
2159            m.openPopup();
2160            selectLoja(matches[0]);
2161          } else if (ms.length > 1) {
2162            const group = L.featureGroup(ms);
2163            map.fitBounds(group.getBounds().pad(0.2));
2164            ms[0].openPopup();
2165            selectLoja(matches[0]);
2166          }
2167          return; // já resolveu localmente
2168        }
2169    
2170        // 2) Fallback: geocoding (endereço)
2171        await geocodeAddress(q);
2172      }
2173    
2174      btnBuscarEnd && btnBuscarEnd.addEventListener('click', buscarEnderecoOuLoja);
2175      inputEnd && inputEnd.addEventListener('keydown', (e) => {
2176        if (e.key === 'Enter') { e.preventDefault(); buscarEnderecoOuLoja(); }
2177      });
2178    
2179      // ----------------- ESTADOS / filiaisS (dinâmico da API) -----------------
2180      function buildIndexPorUffiliais() {
2181        const mapUf = new Map();
2182        lojas.forEach(l => {
2183          if (!l.uf) return;
2184          if (!mapUf.has(l.uf)) mapUf.set(l.uf, new Set());
2185          if (l.filiais) mapUf.get(l.uf).add(l.filiais);
2186        });
2187        return mapUf;
2188      }
2189
2190      function populateEstadoSelect() {
2191        if (!selectEstado) return;
2192        // limpa mantendo placeholder
2193        selectEstado.innerHTML = '<option selected>Estado</option>';
2194        const mapUf = buildIndexPorUffiliais();
2195        const ufs = Array.from(mapUf.keys()).sort((a,b) => a.localeCompare(b));
2196        ufs.forEach(uf => selectEstado.add(new Option(uf, uf)));
2197        selectEstado.disabled = ufs.length === 0;
2198        // ao popular estados, reseta filiais/franquia
2199        if (selectfiliais) {
2200          selectfiliais.innerHTML = '<option selected disabled>Filiais</option>';
2201          selectfiliais.disabled = true;
2202        }
2203        resetFranquiaSelect();
2204      }
2205
2206      function populatefiliaisSelect(uf) {
2207        if (!selectfiliais) return;
2208        selectfiliais.innerHTML = '<option selected disabled>Filiais</option>';
2209        const mapUf = buildIndexPorUffiliais();
2210        const filiaissSet = mapUf.get(uf);
2211        if (!filiaissSet) { selectfiliais.disabled = true; resetFranquiaSelect(); return; }
2212        const filiaiss = Array.from(filiaissSet).sort((a,b) => a.localeCompare(b));
2213        filiaiss.forEach(c => selectfiliais.add(new Option(c, c)));
2214        selectfiliais.disabled = filiaiss.length === 0;
2215        resetFranquiaSelect();
2216      }
2217
2218      if (selectEstado) {
2219        selectEstado.addEventListener('change', () => {
2220          populatefiliaisSelect(selectEstado.value);
2221          renderMarkers();
2222          trackStoreSearch('state_select');
2223        });
2224        selectfiliais && selectfiliais.addEventListener('change', () => {
2225          loadFranquias();
2226          renderMarkers();
2227          trackStoreSearch('secondary_select');
2228
2229          const { uf, filiais, somente24h } = getFiltrosSelecionados();
2230          const lojaSelecionada = lojas.find((l) => {
2231            if (somente24h && !l.aberto24h) return false;
2232            if (uf && l.uf !== uf) return false;
2233            if (filiais && norm(l.filiais) !== norm(filiais)) return false;
2234            return Array.isArray(l.coords) && l.coords.length === 2 && l.coords.every(Number.isFinite);
2235          });
2236
2237          if (!lojaSelecionada) return;
2238
2239          const marker = markersMap.get(lojaSelecionada);
2240          if (!marker) return;
2241
2242          const { lat, lng } = marker.getLatLng();
2243          map.setView([lat, lng], 15);
2244          marker.openPopup();
2245          selectLoja(lojaSelecionada);
2246        });
2247      }
2248    
2249      // ----------------- FILTRO 24h -----------------
2250      chk24h && chk24h.addEventListener('change', () => {
2251        renderMarkers();
2252        // se já tiver UF+filiais selecionados, recarrega a lista
2253        if (selectEstado?.value && selectfiliais?.value) loadFranquias();
2254      });
2255    
2256      // ----------------- SELEÇÃO DE FRANQUIA -----------------
2257      selectFranquia && selectFranquia.addEventListener('change', () => {
2258        const id = selectFranquia.value;
2259        const loja = lojaById.get(id);
2260        if (!loja) return;
2261    
2262        // garante markers atualizados conforme filtro atual
2263        renderMarkers();
2264    
2265        // tenta achar o marker dessa loja
2266        let marker = markersMap.get(loja);
2267        const hasCoords = Array.isArray(loja.coords) && loja.coords.length === 2 && loja.coords.every(Number.isFinite);
2268        if (!hasCoords){
2269          // sem coordenadas: não cria marker, apenas atualiza o card e desabilita rota
2270          setLinkDisabled(btnRota, true);
2271          selectLoja(loja);
2272          return;
2273        }
2274        if (!marker) {
2275          // se o filtro 24h ocultou, adiciona um marker avulso para focalizar
2276          marker = L.marker(loja.coords).addTo(markerLayer).bindPopup(`<strong>${loja.nome}</strong>`);
2277        }
2278    
2279        const { lat, lng } = marker.getLatLng();
2280        map.setView([lat, lng], 15);
2281        marker.openPopup();
2282        selectLoja(loja);
2283      });
2284    
2285    });
2286  </script>
2286
2287        
2288    
2289</div>
2290 
2291    </main>
2292
2293    
2294    <aside id="checkout-asidebar" class="fixed top-0 right-0 w-screen lg:w-[35vw] h-screen duration-[0.3s] z-11 md:z-[12] hidden">
2295      <div id="checkout-template"></div>
2296    </aside>
2297    
2298
2299  </div>
2300
2301  
2302  
2303  <div id="app_footer">
2304    
2305      
2306    <footer class="mt-4 flex flex-col ">
2307      <div class="w-full bg-[var(--c-footer-topbar-bg)] text-[var(--c-footer-mid-text)]">
2308        <div class="container mx-auto p-4">
2309          <!-- Newsletter -->
2310          <div class="grid grid-cols-3 py-6 flex items-center w-full justify-between">
2311            <div class="col-span-1 flex justify-between">
2312              <p class="text-xl font-medium flex items-center justify-center gap-2 text-nowrap">
2313                <img src="/staticfiles/img/client2/icon_ofertas.webp" alt="Enviar" class="w-8 h-8" />
2314                Receba as melhores ofertas!
2315              </p>
2316            </div>
2317            <form id="form-newsletter" action="" novalidate class="col-span-2 flex items-center w-full border-[1px] border-white rounded-full pl-[30px]">
2318              
2319              <input type="email" name="email" id="email-newsletter" placeholder="Digite o seu e-mail" autocomplete="off" maxlength="200"
2320                  class="text-xs text-white bg-transparent flex-1 min-w-0 outline-none placeholder-white" />
2321              <button type="submit" class="bg-white text-[#0044ff] rounded-full px-[6px] py-[6px] m-[8px] cursor-pointer transition duration-200 ease-in-out hover:scale-110">
2322                <img src="/staticfiles/img/client2/arrow-right.svg" alt="Enviar" class="w-5 h-5" />
2323              </button>
2324            </form>
2325          </div>
2326        </div>
2327      </div>
2328
2329
2330      <div class="w-full bg-[var(--c-footer-bottombar-bg)] text-[var(--c-footer-mid-text)]">
2331        <div class="container mx-auto md:flex-row justify-between items-center p-4">
2332          <!-- Contato e Links -->
2333          <div class="flex py-5 grid-cols-2 gap-8 justify-between text-left">
2334            <!-- Contato -->
2335            <div class="space-y-6">
2336              <p class="text-lg font-semibold">Não encontrou o que precisava? Fale com a gente!</p>
2337              <div class="flex flex-col md:flex-row gap-4 justify-center md:justify-start">
2338                <a href="/fale-conosco" class="border border-white hover:bg-[#1b34d3] px-5 py-3 rounded-lg flex items-center justify-center gap-2">
2339                  <img src="/staticfiles/img/client2/icon_operador.webp" alt="Enviar" class="w-5 h-5"/>
2340                  Fale Conosco
2341                </a>
2342                <a href="/nossas-lojas" class="border border-white hover:bg-[#1b34d3] px-5 py-3 rounded-lg flex items-center justify-center gap-2">
2343                  <img src="/staticfiles/img/client2/icon_loja.png" alt="Enviar" class="w-5 h-5"/>
2344                  Nossas lojas
2345                </a>
2346                <a href="/aplicativos" class="border border-white hover:bg-[#1b34d3] px-5 py-3 rounded-lg flex items-center justify-center gap-2">
2347                  <img src="https://storage.googleapis.com/retailon-publico/brava/admin/icon-phone_17055.svg" alt="Enviar" class="w-auto h-6 img-filter-fff"/>
2348                  Intranet
2349                </a>
2350              </div>
2351              <div class="text-sm mt-4 space-y-2">
2352                <div class="flex items-center gap-5">
2353                  <div class="flex items-center gap-1 hover:underline">
2354                    <a href="/pagina/quem-somos" class="">Nossa história</a>
2355                    <img src="/staticfiles/img/client2/icon_seta_diagonal_white.png" alt="Seta" class="inline w-2 h-2"/>
2356                  </div>
2357                  <div class="flex items-center gap-1 hover:underline">
2358                    <a href="/trabalhe-conosco" class="">Trabalhe conosco</a>
2359                    <img src="/staticfiles/img/client2/icon_seta_diagonal_white.png" alt="Seta" class="inline w-2 h-2"/>
2360                  </div>
2361                  
2362                  <div class="flex items-center gap-1 hover:underline">
2363                    <a href="/pagina/notinha-amiga" class="">Brava Vantagens e Notinha Amiga</a>
2364                    <img src="/staticfiles/img/client2/icon_seta_diagonal_white.png" alt="Seta" class="inline w-2 h-2"/>
2365                  </div>
2366                </div>
2367                <div class="flex items-center gap-5">
2368                  
2369                  
2370                  <div class="flex items-center gap-1 hover:underline">
2371                    <a href="/pagina/pedido-patrocinio" class="">Pedidos de patrocínios e projetos</a>
2372                    <img src="/staticfiles/img/client2/icon_seta_diagonal_white.png" alt="Seta" class="inline w-2 h-2"/>
2373                  </div>
2374                </div>
2375                
2376              </div>
2377            </div>
2378
2379            <!-- Franquia e QR Code -->
2380            <div class="flex justify-between">
2381              <div class="gap-4">
2382                <div class="flex items-center gap-8 p-2">
2383                  <div class="flex flex-col items-center gap-4">
2384                    <a href="/franquias" class="border border-white hover:bg-[#1b34d3] px-4 py-2 rounded-lg">Seja um franqueado</a>
2385                  </div>
2386                  
2387                </div>
2388                <div class="flex gap-2 p-2">
2389                  <div class="bg-white rounded-md p-1">
2390                    <a href="https://www.facebook.com/farmaciasbrava1?locale=pt_BR" target="_blank" rel="noopener noreferrer">
2391                      <img src="/staticfiles/img/client2/icon_facebook.png" class="w-7 h-7 transition duration-200 ease-in-out hover:scale-105" alt="Facebook" />
2392                    </a>
2393                  </div>
2394                  <div class="bg-white rounded-md p-1">
2395                    <a href="https://www.instagram.com/farmaciasbrava/" target="_blank" rel="noopener noreferrer">
2396                      <img src="/staticfiles/img/client2/icon_instagram.png" class="w-7 h-7 transition duration-200 ease-in-out hover:scale-105" alt="Instagram" />
2397                    </a>
2398                  </div>
2399                  <div class="bg-white rounded-md p-1">
2400                    <a href="https://www.linkedin.com/company/farmaciasbrava/" target="_blank" rel="noopener noreferrer">
2401                      <img src="/staticfiles/img/client2/icon_linkedin.png" class="w-7 h-7 transition duration-200 ease-in-out hover:scale-105" alt="LinkedIn" />
2402                    </a>
2403                  </div>
2404                  <div class="bg-white rounded-md p-1">
2405                    <a href="https://www.youtube.com/@redefarmaciasbrava" target="_blank" rel="noopener noreferrer">
2406                      <img src="/staticfiles/img/client2/icon_youtube.png" class="w-7 h-7 transition duration-200 ease-in-out hover:scale-105" alt="YouTube" />
2407                    </a>
2408                  </div>
2409                </div>
2410
2411              </div>
2412              
2413            </div>
2414
2415          </div>
2416          <!-- Encartes -->
2417          <div class="flex justify-center py-4">
2418            <div class="flex w-full gap-5">
2419              <a href="https://storage.googleapis.com/retailon-publico/brava/admin/flyer-setembro-pr-ajustado_5fc18.pdf" class="flex items-center justify-center border hover:bg-[#1b34d3] border-white px-4 py-3 w-full rounded-lg text-center" target="_blank">
2420                <img src="/staticfiles/img/client2/icon_revista.png" alt="Encarte" class="w-5 h-5 mr-2" />
2421                Encarte Paraná
2422              </a>
2423              <a href="https://storage.googleapis.com/retailon-publico/brava/admin/flyer-setembro-pr-ajustado.pdf" class="flex items-center justify-center border hover:bg-[#1b34d3] border-white px-4 py-3 w-full rounded-lg text-center" target="_blank">
2424                <img src="/staticfiles/img/client2/icon_revista.png" alt="Encarte" class="w-5 h-5 mr-2" />
2425                Encarte Santa Catarina
2426              </a>
2427            </div>
2428          </div>
2429
2430          <!-- Políticas -->
2431          <div class="text-xs text-center pt-4 pb-6 space-x-2">
2432            <a href="/pagina/politica-guia-seguranca" class="hover:underline">Guia de segurança</a> 
2433            <span>|</span>
2434            <a href="/pagina/politica-privacidade" class="hover:underline">Política de privacidade</a>          
2435            <span>|</span>
2436            <a href="/pagina/politica-dados-pessoais" class="hover:underline">Solicitação sobre dados pessoais</a>
2437            <span>|</span>
2438            <a href="/pagina/politica-entrega" class="hover:underline">Política de entrega</a>
2439            <span>|</span>
2440            <a href="/pagina/politica-troca-devolucao" class="hover:underline">Troca e devolução</a>
2441          </div>
2442          
2443        </div>
2444      </div>
2445
2446      <div class="w-full flex justify-center items-center py-1 bg-[#eeeeee] shadow-[0_-2px_5px_rgba(0,0,0,0.06)]">
2447        <div class="flex flex-col items-center justify-around my-3">
2448          <span class="text-[#333] text-sm">Desenvolvido por:</span>
2449          <a href="https://retailon.com.br/?utm_source=brava&utm_medium=rodape&utm_id=inteliger" target="_blank">
2450            <img loading="lazy" src="https://storage.googleapis.com/retailon-publico/inteliger/logos/logo-pequena.webp" alt="Logo RetailON"
2451              class="mx-auto w-[130px]">
2452          </a>
2453        </div>
2454      </div>
2455    </footer>
2456
2457    
2457<script type="ff2c2aaab21707ab2ba08cc2-text/javascript">
2458      async function cadastrarEmailNewsletter() {
2459        const email = document.getElementById('email-newsletter').value;
2460        if (!email) {
2461          toastr.error('Por favor, preencha o e-mail!');
2462          return;
2463        }
2464        try {
2465          const response = await fetch('cliente/promocao/criar', {
2466            method: 'POST',
2467            headers: {
2468              'Content-Type': 'application/json',
2469              'X-CSRFToken': window.CSRF_TOKEN(),
2470            },
2471            body: JSON.stringify({ email }),
2472          });
2473
2474          if (response.ok) {
2475            toastr.success('E-mail cadastrado com sucesso!');
2476          } else {
2477              toastr.error('Erro ao cadastrar e-mail!');
2478          }
2479        } catch (error) {
2480          toastr.error('Erro ao cadastrar e-mail!');
2481        }
2482      }
2483
2484      document.getElementById('form-newsletter').addEventListener('submit', (e) => {
2485        e.preventDefault();
2486        e.stopPropagation();
2487        cadastrarEmailNewsletter();
2488      });
2489    </script>
2489
2490    
2491  </div>
2492  
2493
2494
2495  
2495<script type="ff2c2aaab21707ab2ba08cc2-text/javascript" src="/staticfiles/js/defer.js" defer></script>
2495
2496  
2496<script type="ff2c2aaab21707ab2ba08cc2-text/javascript" src="/staticfiles/js/carrosseis.js" defer></script>
2496
2497  
2497<script type="ff2c2aaab21707ab2ba08cc2-text/javascript" src="/staticfiles/js/pbm.js" defer></script>
2497
2498  
2499
2500  
2501    
2501<script defer type="ff2c2aaab21707ab2ba08cc2-text/javascript">
2502
2503
2504document.addEventListener('DOMContentLoaded', async () => {
2505  buscarProdutosAvaliados()
2506  buscarProdutosFavoritos()
2507})
2508
2509async function buscarProdutosAvaliados(produtos_id = []) {
2510  let produtoId = produtos_id?.length ? produtos_id : [];
2511
2512  if (!produtoId?.length) {
2513    const produtosComAvaliacao = document.querySelectorAll('[data-target="avaliacao-produto"]');
2514    if (!produtosComAvaliacao?.length) return;
2515    produtosComAvaliacao.forEach(produto => {
2516      const cdProduto = produto?.closest('[data-cd-produto]')?.getAttribute('data-cd-produto');
2517      if (cdProduto) produtoId.push(cdProduto);
2518    });
2519    if (produtoId?.length) {
2520      produtoId = Array.from(new Set(produtoId));
2521    } else {
2522      return;
2523    }
2524  } else {
2525    produtoId = Array.from(new Set(produtoId));
2526  }
2527
2528    const request = await fetch(`/produto/buscar/avaliacoes`, {
2529      method: "POST",
2530      headers: {
2531        "X-CSRFToken": window.CSRF_TOKEN(),
2532        "Content-Type": "application/json",
2533      },
2534      body: JSON.stringify({
2535        produtos_id: produtoId
2536      })
2537    })
2538
2539    for (const cdProduto of produtoId) {
2540      const htmlDefault = `
2541        <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2542        <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2543        <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2544        <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2545        <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2546        <span class="text-[10px] font-semibold text-[#444] ml-1">(0)</span>
2547      `
2548      const produtoElementos = document.querySelectorAll(`[data-cd-produto="${cdProduto}"]`)
2549      if (produtoElementos?.length) {
2550        produtoElementos.forEach(produtoElemento => {
2551          if(produtoElemento.querySelector('[data-target="avaliacao-produto"]'))
2552            produtoElemento.querySelector('[data-target="avaliacao-produto"]').innerHTML = htmlDefault
2553        })
2554      }
2555    }
2556
2557    const response = await request.json()
2558
2559    if (!request.ok || !response?.status || !Object.keys(response?.avaliacoes_produtos)?.length)
2560      return
2561
2562    const avaliacoes = response?.avaliacoes_produtos
2563
2564    Object.keys(avaliacoes).forEach((produto_id) => {
2565
2566      const listaAvaliacoes = avaliacoes[produto_id]
2567      const produtoElementosComAvaliacoes = document.querySelectorAll(`[data-cd-produto="${produto_id}"]`)
2568
2569      if (produtoElementosComAvaliacoes?.length && listaAvaliacoes?.length) {
2570
2571        const mediaAvaliacoes = listaAvaliacoes?.reduce((acc, avaliacao) => acc + avaliacao?.nota_avaliacao, 0) / listaAvaliacoes?.length
2572        
2573        let htmlContainerAvaliacoes = ``
2574
2575        if(mediaAvaliacoes >= 1) {
2576          htmlContainerAvaliacoes += `
2577            <img src="/staticfiles/img/client2/icon-avaliacao-fill.svg" alt="Estrela" width="15" height="15"> 
2578          `
2579        } else {
2580          htmlContainerAvaliacoes += `
2581            <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2582          `
2583        }
2584        if(mediaAvaliacoes >= 2) {
2585          htmlContainerAvaliacoes += `
2586            <img src="/staticfiles/img/client2/icon-avaliacao-fill.svg" alt="Estrela" width="15" height="15"> 
2587          `
2588        } else {
2589          htmlContainerAvaliacoes += `
2590            <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2591          `
2592        }
2593        if(mediaAvaliacoes >= 3) {
2594          htmlContainerAvaliacoes += `
2595            <img src="/staticfiles/img/client2/icon-avaliacao-fill.svg" alt="Estrela" width="15" height="15"> 
2596          `
2597        } else {
2598          htmlContainerAvaliacoes += `
2599            <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2600          `
2601        }
2602        if(mediaAvaliacoes >= 4) {
2603          htmlContainerAvaliacoes += `
2604            <img src="/staticfiles/img/client2/icon-avaliacao-fill.svg" alt="Estrela" width="15" height="15"> 
2605          `
2606        } else {
2607          htmlContainerAvaliacoes += `
2608            <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2609          `
2610        }
2611        if(mediaAvaliacoes >= 5) {
2612          htmlContainerAvaliacoes += `
2613            <img src="/staticfiles/img/client2/icon-avaliacao-fill.svg" alt="Estrela" width="15" height="15"> 
2614          `
2615        } else {
2616          htmlContainerAvaliacoes += `
2617            <img src="/staticfiles/img/client2/icon-avaliacao.svg" alt="Estrela" width="15" height="15"> 
2618          `
2619        }
2620
2621        htmlContainerAvaliacoes += `
2622          <span class="text-[10px] font-semibold text-[#444] ml-1">(${listaAvaliacoes?.length})</span>
2623        `
2624
2625        produtoElementosComAvaliacoes.forEach(produtoElementoComAvaliacoes => {
2626          if(produtoElementoComAvaliacoes.querySelector('[data-target="avaliacao-produto"]'))
2627            produtoElementoComAvaliacoes.querySelector('[data-target="avaliacao-produto"]').innerHTML = htmlContainerAvaliacoes
2628        })
2629      }
2630    })
2631  
2632}
2633
2634async function buscarProdutosFavoritos() {
2635
2636  if(!document.querySelectorAll('[data-favoritar]')?.length)
2637    return
2638
2639  const request = await fetch(`/produto/buscar/favoritos`, {
2640    method: "GET",
2641    headers: {
2642      "X-CSRFToken": window.CSRF_TOKEN(),
2643    }
2644  })
2645  
2646  const response = await request.json()
2647
2648  if(!request.ok || !response?.status || !response?.produtos?.length)
2649    return
2650
2651  const favoritos = response?.produtos
2652  for(const favorito of favoritos){
2653    const els = document.querySelectorAll(`[data-favoritar="${favorito?.id}"]`)
2654    els.forEach(el => {
2655      el.setAttribute('data-is-favoritado', 'true')
2656      el.innerHTML = `
2657        <img src="/staticfiles/img/client2/icon_wishlist_fill.svg" class="cursor-pointer" alt="Remover dos favoritos" width="35" height="35">
2658      `
2659    })
2660  }
2661}
2662
2663async function favoritarProduto(el, produtoId) {
2664
2665  if(!produtoId)
2666    return
2667
2668  const isFavoritado = el?.getAttribute('data-is-favoritado') === 'true'
2669
2670  const elPaginaProduto = el?.closest('[data-target="pagina-produto"]')
2671  const elLoader = elPaginaProduto
2672    ? document.body
2673    : (el?.closest('[data-target="carrossel-produto"]') || el)
2674
2675  load('on', [elLoader])
2676
2677  const request = await fetch(`/produto/atualizar/favorito`, {
2678    method: "POST",
2679    headers: {
2680      "Content-Type": "application/json",
2681      "X-CSRFToken": window.CSRF_TOKEN(),
2682    },
2683    body: JSON.stringify({
2684      produto_id: produtoId
2685    })
2686  })
2687  
2688  const response = await request.json()
2689
2690  if(!request.ok || !response?.status){
2691    toastr.error(response?.descricao || 'Não foi possível executar a ação. Tente novamente.')
2692    if(el){
2693      el.setAttribute('data-is-favoritado', 'false')
2694      el.innerHTML = `
2695        <img src="/staticfiles/img/client2/icon_wishlist.svg"
2696          class="cursor-pointer"
2697          width="35" height="35"
2698          alt="Adicionar aos favoritos"
2699        >
2700      `;
2701    }
2702    load('off', [elLoader])
2703    return
2704  }    
2705  
2706  if(el){
2707    el.setAttribute('data-is-favoritado', !isFavoritado)
2708    el.innerHTML = `
2709      <img src="/staticfiles/img/client2/icon_${!isFavoritado ? 'wishlist_fill' : 'wishlist'}.svg"
2710        class="cursor-pointer"
2711        width="35" height="35"
2712        alt="${!isFavoritado ? 'Adicionar aos favoritos' : 'Remover dos favoritos'}"
2713      >
2714    `;
2715  }
2716  load('off', [elLoader])
2717}
2718
2719function visualizarMenuCategorias() {
2720    const menuCategoriaContainer = document.getElementById("menu-categorias-mobile");
2721    menuCategoriaContainer?.classList?.toggle("hidden");
2722}
2723_logicaMenuCategoriasCarregada = true;
2724
2725/*
2726* Pesquisa mobile
2727*/
2728// function sidebarPesquisa(toggle) {
2729//   if (toggle === "open") {
2730//     document.getElementById("pesquisa-sidebar")?.classList?.remove("hidden");
2731//     setTimeout(() => {
2732//       document.getElementById("pesquisa-sidebar-input")?.focus();
2733//     }, 150);
2734//     const debouncedPesquisa = debounce(buscarProdutosSidebarPesquisa, 750);
2735//     const input = document.getElementById("pesquisa-sidebar-input");
2736//     input.addEventListener("input", debouncedPesquisa);
2737//     return;
2738//   }
2739//   if (toggle === "close") {
2740//     document.getElementById("pesquisa-sidebar")?.classList?.add("hidden");
2741//     if (document.getElementById("template-produtos-sidebar-pesquisa"))
2742//       document.getElementById("template-produtos-sidebar-pesquisa").innerHTML =
2743//         "";
2744//     return;
2745//   }
2746//   if (!toggle)
2747//     document.getElementById("pesquisa-sidebar")?.classList?.toggle("hidden");
2748// }
2749
2750function sidebarPesquisa(state){
2751  const aside = document.getElementById('pesquisa-sidebar');
2752  if(!aside) return;
2753
2754  const input = document.getElementById('pesquisa-sidebar-input');
2755
2756  if(state === 'open'){
2757    document.body.classList.add('overflow-hidden');
2758    aside.classList.remove('hidden');
2759    inicializarSidebarPesquisa()
2760    input.focus();
2761  } else {
2762    document.body.classList.remove('overflow-hidden');
2763    aside.classList.add('hidden');
2764  }
2765}
2766
2767_sidebarPesquisaCarregada = true;
2768
2769function clearSidebarPesquisa() {
2770  if (document.getElementById("pesquisa-sidebar-input"))
2771    document.getElementById("pesquisa-sidebar-input").value = "";
2772  document.getElementById("pesquisa-sidebar-input")?.focus();
2773}
2774
2775// function buscarProdutosSidebarPesquisa() {
2776//   const termo = document.getElementById("pesquisa-sidebar-input")?.value;
2777//   if (!termo) {
2778//     if (document.getElementById("template-produtos-sidebar-pesquisa"))
2779//       document.getElementById("template-produtos-sidebar-pesquisa").innerHTML =
2780//         "";
2781//     return;
2782//   }
2783
2784//   load("on", document.getElementById("pesquisa-sidebar"));
2785
2786//   const produtos = [
2787//     {
2788//       imagem_produto: "produtos/1001815_200x200.webp",
2789//       cd_produto: "1001815",
2790//       categoria: "ZERO AÇÚCAR",
2791//       parceiro: "",
2792//       avaliacao: null,
2793//       tags_nomes:
2794//         ";pinati swet mini cocadinha queimada sem acucar 14g;queimada;cocadinha;qooeimada;keimada;zem;sweet;açúxar;açúcar;doce pinati swet mini cocadinha queimada sem acucar;doce;doce pinati sweet mini cocadinha queimada sem acucar 14g;doce pinati swet mini cocadinha queimada acucar 14g;doce pinati swet mini cocadinha sem acucar 14g;zweet;doce pinati swet mini cocadinha queimada sem acucar 14g;doce swet mini cocadinha queimada sem acucar 14g;xoxadina;sem;doce pinati mini cocadinha queimada sem acucar 14g;pinati;xoxadinha;doxe;cocadina;doce pinati swet mini queimada sem acucar 14g;mini;14g;doce pinati swet mini cocadinha queimada sem 14g;doce pinati swet cocadinha queimada sem acucar 14g;",
2795//       marca: "PINATI",
2796//       nm_produto: "Doce Pinati Sweet Mini Cocadinha Queimada Sem Açúcar 14g",
2797//       tags_agrupamentos:
2798//         ";ate-10-reais;td-consumidor-50;desc-semana-consumidor;",
2799//       is_servico: false,
2800//       fabricante: "SUPER SAUDE NUTRICIONAL",
2801//       filtros: {
2802//         selo: "",
2803//         marca: "PINATI",
2804//         tipo: "",
2805//         categoria: "ZERO AÇÚCAR",
2806//         fabricante: "SUPER SAUDE NUTRICIONAL",
2807//         avaliacao: null,
2808//         palavras: {},
2809//       },
2810//       url_produto: "doce-pinati-sweet-mini-cocadinha-queimada-sem-acucar-14g",
2811//       is_disponivel: true,
2812//     },
2813//     {
2814//       imagem_produto: "produtos/1002811_200x200.webp",
2815//       cd_produto: "1002811",
2816//       categoria: "REFRIGERANTE",
2817//       parceiro: "",
2818//       avaliacao: null,
2819//       tags_nomes:
2820//         ";refrigerante lata;coca-cola lata 310ml;lata;xoxa-xola;310ml;refrigerante lata 310ml;refrigerante coca-cola lata;refrijerante;refrigerante;coca-cola;refrigerante coca-cola lata 310ml;coca-cola lata;refrigerante 310ml;coca-cola 310ml;refrigerante coca-cola;refrigerante coca-cola 310ml;",
2821//       marca: "COCA COLA",
2822//       nm_produto: "Refrigerante Coca-Cola Lata 310ml",
2823//       tags_agrupamentos: ";mosaico-refrigerante;mosaico-bebidas;",
2824//       is_servico: false,
2825//       fabricante: "COCA COLA",
2826//       filtros: {
2827//         selo: "",
2828//         marca: "COCA COLA",
2829//         tipo: "",
2830//         categoria: "REFRIGERANTE",
2831//         fabricante: "COCA COLA",
2832//         avaliacao: null,
2833//         palavras: {},
2834//       },
2835//       url_produto: "refrigerante-coca-cola-lata-310ml",
2836//       is_disponivel: true,
2837//     },
2838//     {
2839//       imagem_produto: "produtos/69625_5tL4aHL.jpg",
2840//       cd_produto: "69625",
2841//       categoria: "REFRIGERANTE",
2842//       parceiro: "",
2843//       avaliacao: null,
2844//       tags_nomes:
2845//         ";coca-cola lata 350ml;refrigerante coca-cola lata 350ml;refrigerante lata;lata;xoxa-xola;refrigerante lata 350ml;refrigerante coca-cola 350ml;refrigerante coca-cola lata;refrijerante;refrigerante;coca-cola;refrigerante 350ml;coca-cola lata;350ml;refrigerante coca-cola;coca-cola 350ml;",
2846//       marca: "COCA COLA",
2847//       nm_produto: "Refrigerante Coca-Cola Lata 350ml",
2848//       tags_agrupamentos:
2849//         ";mercearia-leve-mais;dinheiro-de-volta-marco;lamina-coca-cola;coca-cola;conveniencia-almanaque;alm-jan25-mercearia;complete-sua-cesta;mosaico-halloween;mosaico-halloween;mosaico-halloween;mosaico-halloween;mosaico-halloween;mosaico-halloween;mosaico-refrigerante;mosaico-refrigerante;mosaico-refrigerante;mosaico-refrigerante;mosaico-refrigerante;mosaico-refrigerante;mosaico-refrigerante;mosaico-bebidas;mosaico-bebidas;mosaico-bebidas;mosaico-bebidas;mosaico-bebidas;mosaico-bebidas;mosaico-bebidas;ate-10-reais;",
2850//       is_servico: false,
2851//       fabricante: "COCA COLA",
2852//       filtros: {
2853//         selo: "produtos/selos/GA - SELO 5_modelo 1.png",
2854//         marca: "COCA COLA",
2855//         tipo: "",
2856//         categoria: "REFRIGERANTE",
2857//         fabricante: "COCA COLA",
2858//         avaliacao: null,
2859//         palavras: {},
2860//       },
2861//       url_produto: "refrigerante-coca-cola-lata-350ml",
2862//       is_disponivel: true,
2863//     },
2864//   ];
2865
2866//   setTimeout(() => {
2867//     construirTemplateProdutosSidebarPesquisa(produtos);
2868//     load("off", document.getElementById("pesquisa-sidebar"));
2869//     // ViewItemList + SelectItem base para resultados simulados
2870//     try {
2871//       if (typeof filtroParaDadosAnaliticos === 'function') {
2872//         const items = (produtos || []).map((p, i) => ({
2873//           id: String(p?.cd_produto || ''),
2874//           item_name: p?.nm_produto || '',
2875//           price: +p?.valor || 0,
2876//           quantidade: 1,
2877//           index: i + 1,
2878//           item_list_name: 'Sidebar Pesquisa',
2879//           item_list_id: 'sidebar_pesquisa'
2880//         })).filter(x => x.id);
2881//         if (items.length) filtroParaDadosAnaliticos('ViewItemList', { items });
2882//       }
2883//     } catch(_){}
2884//   }, 1500);
2885// }
2886
2887// function construirTemplateProdutosSidebarPesquisa(produtos) {
2888//   if (!produtos?.length) return;
2889//   let html = `
2890//     <p class="text-sm font-bold text-[#444]">Resultados</p> 
2891//   `;
2892//   for (const produto of produtos) {
2893//     html += `
2894//       <a class="flex justify-between items-center gap-x-4" onclick="(function(){ try { if (typeof filtroParaDadosAnaliticos === 'function') filtroParaDadosAnaliticos('SelectItem', { event:'click_card', item_list_name:'Sidebar Pesquisa', item_list_id:'sidebar_pesquisa' }); } catch(_){} })()" href="/${
2895//         produto?.url_produto
2896//       }">
2897//         <div class="flex items-center gap-x-4">
2898//           <img src="/media/${
2899//             produto?.imagem_produto
2900//           }"
2901//             class="p-1 border-1 rounded-lg border-[#E6E6E6]" loading="lazy" alt="${
2902//               produto?.cd_produto
2903//             }" width="50" height="50">
2904//           <p class="text-xs text-[#444] line-clamp-2">${produto?.nm_produto}</p>
2905//         </div>
2906//         <p class="text-xs text-[#3F84C7] font-bold flex">${formatFloat(
2907//           produto?.preco || 0,
2908//           { currency: true }
2909//         )}</p>
2910//       </a>
2911//     `;
2912//   }
2913//   if (document.getElementById("template-produtos-sidebar-pesquisa"))
2914//     document.getElementById("template-produtos-sidebar-pesquisa").innerHTML =
2915//       html;
2916// }
2917
2918// --- pesquisa ---
2919
2920const HEADER_SEARCH_CATALOGO = [
2921  // {
2922  //   produto__nm_ecommerce: "Algodão Multiuso 50g - Marca Alfa",
2923  //   produto__nm_url_ecommerce: "algodao-multiuso-50g-marca-alfa",
2924  //   produto__imagem: "produtos/55520_200x200.jpg",
2925  //   valor_ini: 9.99,
2926  //   valor: 7.99,
2927  // },
2928  // {
2929  //   produto__nm_ecommerce: "Algodão Multiuso 50g - Marca Alfa",
2930  //   produto__nm_url_ecommerce: "algodao-multiuso-50g-marca-alfa",
2931  //   produto__imagem: "produtos/55520_200x200.jpg",
2932  //   valor_ini: 9.99,
2933  //   valor: 7.99,
2934  // },
2935  // {
2936  //   produto__nm_ecommerce: "Algodão Multiuso 50g - Marca Alfa",
2937  //   produto__nm_url_ecommerce: "algodao-multiuso-50g-marca-alfa",
2938  //   produto__imagem: "produtos/55520_200x200.jpg",
2939  //   valor_ini: 9.99,
2940  //   valor: 7.99,
2941  // },
2942  // {
2943  //   produto__nm_ecommerce: "Algodão Multiuso 50g - Marca Alfa",
2944  //   produto__nm_url_ecommerce: "algodao-multiuso-50g-marca-alfa",
2945  //   produto__imagem: "produtos/55520_200x200.jpg",
2946  //   valor_ini: 9.99,
2947  //   valor: 7.99,
2948  // },
2949  // {
2950  //   produto__nm_ecommerce: "Algodão Multiuso 50g - Marca Alfa",
2951  //   produto__nm_url_ecommerce: "algodao-multiuso-50g-marca-alfa",
2952  //   produto__imagem: "produtos/55520_200x200.jpg",
2953  //   valor_ini: 9.99,
2954  //   valor: 7.99,
2955  // },
2956  // {
2957  //   produto__nm_ecommerce: "Algodão Multiuso 50g - Marca Alfa",
2958  //   produto__nm_url_ecommerce: "algodao-multiuso-50g-marca-alfa",
2959  //   produto__imagem: "produtos/55520_200x200.jpg",
2960  //   valor_ini: 9.99,
2961  //   valor: 7.99,
2962  // },
2963  // {
2964  //   produto__nm_ecommerce: "Algodão Multiuso 50g - Marca Alfa",
2965  //   produto__nm_url_ecommerce: "algodao-multiuso-50g-marca-alfa",
2966  //   produto__imagem: "produtos/55520_200x200.jpg",
2967  //   valor_ini: 9.99,
2968  //   valor: 7.99,
2969  // },
2970  // {
2971  //   produto__nm_ecommerce: "Algodão Bola 50 Unidades - Marca Beta",
2972  //   produto__nm_url_ecommerce: "algodao-bola-50-un-beta",
2973  //   produto__imagem: "produtos/55520_200x200.jpg",
2974  //   valor_ini: 12.9,
2975  //   valor: 9.9,
2976  // },
2977  // {
2978  //   produto__nm_ecommerce: "Discos de Algodão 70 Unidades - Marca Gama",
2979  //   produto__nm_url_ecommerce: "discos-algodao-70un-gama",
2980  //   produto__imagem: "produtos/55520_200x200.jpg",
2981  //   valor_ini: 14.9,
2982  //   valor: 14.9,
2983  // },
2984  // {
2985  //   produto__nm_ecommerce: "Hidratante Corporal 400ml",
2986  //   produto__nm_url_ecommerce: "hidratante-corporal-400ml",
2987  //   produto__imagem: "produtos/55520_200x200.jpg",
2988  //   valor_ini: 29.9,
2989  //   valor: 19.9,
2990  // },
2991  // {
2992  //   produto__nm_ecommerce: "Shampoo Nutritivo 300ml",
2993  //   produto__nm_url_ecommerce: "shampoo-nutritivo-300ml",
2994  //   produto__imagem: "produtos/55520_200x200.jpg",
2995  //   valor_ini: 24.9,
2996  //   valor: 22.9,
2997  // },
2998];
2999
3000window.HeaderSearchCore = {
3001  buscarSugestoes,
3002  buscarProdutosPorTermo,
3003  getSearchData,
3004  getHistoricoPesquisa,
3005  setHistoricoPesquisa,
3006  addHistoricoPesquisa,
3007  removeHistoricoPesquisa,
3008  clearHistoricoPesquisa,
3009  escapeHtml,
3010  normalizeText,
3011  uniqueArray,
3012  templateLoading,
3013};
3014
3015async function buscarSugestoes(termo) {
3016  termo = (termo || "").trim();
3017  if (!termo) return [];
3018
3019  const termoNorm = normalizeText(termo);
3020  const lenSemEspaco = termoNorm.replace(/\s+/g, "").length;
3021
3022  //const base = ['shampoo', 'condicionador', 'cerave', 'vitamina c', 'fralda', 'hidratante', 'algodão'];
3023  const base = [];
3024  const baseFiltrada =
3025    lenSemEspaco >= 3
3026      ? base.filter((t) => normalizeText(t).includes(termoNorm))
3027      : [];
3028
3029  const tokensProdutos = [];
3030  try {
3031    for (const p of HEADER_SEARCH_CATALOGO || []) {
3032      const nome = p?.nm_produto || "";
3033      const partes = String(nome)
3034        .split(/[^A-Za-zÀ-ÖØ-öø-ÿ0-9]+/)
3035        .filter(Boolean);
3036      for (const tk of partes) {
3037        const tkNorm = normalizeText(tk);
3038        if (tkNorm.length >= 3 && tkNorm.includes(termoNorm)) {
3039          tokensProdutos.push(tk.toLowerCase());
3040        }
3041      }
3042    }
3043  } catch {}
3044
3045  const combinadas = uniqueArray([...baseFiltrada, ...tokensProdutos]);
3046  return combinadas.slice(0, 5);
3047}
3048
3049const _cachePesquisa = new Map();
3050let _abortPesquisaCtrl = null;
3051
3052/**
3053  * Busca sugestões de produtos no backend, reaproveitando o POST da pesquisa.
3054  * Retorna até 6 itens ou [].
3055  */
3056async function buscarProdutosPorTermo(termo) {
3057  termo = (termo || "").trim();
3058  if (!termo) return [];
3059
3060  const termoNorm = normalizeText(termo);
3061  if (termoNorm.length < 3) return [];
3062
3063  if (_cachePesquisa.has(termo)) {
3064    return _cachePesquisa.get(termo);
3065  }
3066
3067  // Cancela a requisição anterior
3068  if (_abortPesquisaCtrl) {
3069    _abortPesquisaCtrl.abort();
3070  }
3071  _abortPesquisaCtrl = new AbortController();
3072
3073  const body = new URLSearchParams();
3074  body.set("pesquisa", termo);
3075  const csrf = window.CSRF_TOKEN();
3076  if (csrf) {
3077    body.set("csrfmiddlewaretoken", csrf);
3078  }
3079
3080  try {
3081    const resp = await fetch("/sugestoes", {
3082      method: "POST",
3083      headers: {
3084        "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
3085        "X-CSRFToken": csrf || "",
3086      },
3087      body,
3088      credentials: "same-origin",
3089      signal: _abortPesquisaCtrl.signal,
3090    });
3091
3092    if (!resp.ok) {
3093      return [];
3094    }
3095
3096    const data = await resp.json();
3097    const items = Array.isArray(data?.dados.produtos)
3098      ? data.dados.produtos
3099      : [];
3100
3101    const resultados = items.slice(0, 6);
3102
3103    _cachePesquisa.set(termo, resultados);
3104
3105    return resultados;
3106  } catch (err) {
3107    if (err?.name === "AbortError") return [];
3108    console.error("Erro ao buscar sugestões:", err);
3109    return [];
3110  }
3111}
3112
3113let precosTimer = null;
3114
3115// Pega dados de busca em paralelo (reúso no desk e mobile)
3116async function getSearchData(termo) {
3117  termo = (termo || "").trim();
3118  if (!termo || termo.length < 3) return { termos: [], produtos: [] };
3119  const [termos, produtos] = await Promise.all([
3120    buscarSugestoes(termo),
3121    buscarProdutosPorTermo(termo),
3122  ]);
3123  // dispara 1 vez, substituindo o anterior
3124    clearTimeout(precosTimer);
3125    precosTimer = setTimeout(() => {
3126    try { carregarPrecos(); } catch(_){}
3127  }, 300);
3128
3129    // Search analytics
3130    try { if (typeof filtroParaDadosAnaliticos === 'function') filtroParaDadosAnaliticos('Search', { search_term: termo }); } catch(_){}
3131
3132    return { termos, produtos };
3133}
3134
3135function getHistoricoPesquisa() {
3136  try {
3137    const raw = localStorage.getItem("header_search_history");
3138    const lista = raw ? JSON.parse(raw) : [];
3139    return Array.isArray(lista) ? lista : [];
3140  } catch {
3141    return [];
3142  }
3143}
3144function setHistoricoPesquisa(lista) {
3145  try {
3146    localStorage.setItem(
3147      "header_search_history",
3148      JSON.stringify(lista.slice(0, 8))
3149    );
3150  } catch {}
3151}
3152function addHistoricoPesquisa(termo) {
3153  termo = (termo || "").trim();
3154  if (!termo) return;
3155  const lista = getHistoricoPesquisa().filter(
3156    (t) => t.toLowerCase() !== termo.toLowerCase()
3157  );
3158  lista.unshift(termo);
3159  setHistoricoPesquisa(lista);
3160}
3161function removeHistoricoPesquisa(termo) {
3162  const lista = getHistoricoPesquisa().filter(
3163    (t) => t.toLowerCase() !== (termo || "").toLowerCase()
3164  );
3165  setHistoricoPesquisa(lista);
3166  atualizarDropdownComHistoricoESugestoes();
3167}
3168function clearHistoricoPesquisa() {
3169  setHistoricoPesquisa([]);
3170  atualizarDropdownComHistoricoESugestoes();
3171}
3172
3173function escapeHtml(str) {
3174  return String(str)
3175    .replace(/&/g, "&amp;")
3176    .replace(/</g, "&lt;")
3177    .replace(/>/g, "&gt;")
3178    .replace(/"/g, "&quot;")
3179    .replace(/'/g, "&#39;");
3180}
3181
3182function normalizeText(str) {
3183  return String(str || "")
3184    .toLowerCase()
3185    .normalize("NFD")
3186    .replace(/[\u0300-\u036f]/g, "");
3187}
3188
3189function uniqueArray(arr) {
3190  const set = new Set();
3191  const out = [];
3192  for (const v of arr) {
3193    const key = normalizeText(v);
3194    if (!set.has(key)) {
3195      set.add(key);
3196      out.push(v);
3197    }
3198  }
3199  return out;
3200}
3201
3202function templateLoading() {
3203  return `<div class="p-3 text-[12px] text-[#666]">Carregando...</div>`;
3204}
3205
3206// --- fim pesquisa ---
3207
3208
3209
3210
3211
3212// --- Avise-me ---
3213(function () {
3214  const ICONE_SINO = '<path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6v-5c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6z"/>';
3215
3216  let timer_avise_me = null;
3217  let avise_me_pos_login_agendado = false;
3218
3219  const dict_cores_mensagem = {
3220    success: 'bg-[#0C670F] border-[#9FFCAC] text-white',
3221    error: 'bg-[#B42318] border-[#FECDCA] text-white',
3222    warning: 'bg-[#B54708] border-[#FEDF89] text-white',
3223  };
3224
3225  function removerMensagensInlineAviseMe(btn) {
3226    const bloco = btn?.closest('[data-target="comprar-produto"]')
3227      || btn?.closest('[data-notificar-disponibilidade="true"]');
3228    bloco?.querySelectorAll('[data-target="mensagem-avise-me"]').forEach((el) => el.remove());
3229  }
3230
3231  function exibirMensagemAviseMe(tipo, msg) {
3232    if (window.toastr?.[tipo]) {
3233      window.toastr[tipo](msg);
3234    } else {
3235      exibirToastAviseMe(tipo, msg);
3236    }
3237  }
3238
3239  function garantirEstilosAviseMe() {
3240    let style = document.getElementById('avise-me-estilos');
3241    if (!style) {
3242      style = document.createElement('style');
3243      style.id = 'avise-me-estilos';
3244      document.head.appendChild(style);
3245    }
3246
3247    style.textContent = `
3248      [data-target="btn-notificar-disponibilidade"] {
3249        background-color: var(--dark-gray, #838383) !important;
3250        border-color: var(--dark-gray, #838383) !important;
3251        color: #fff !important;
3252        transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, opacity 0.2s ease;
3253        opacity: 0.6;
3254      }
3255      [data-target="btn-notificar-disponibilidade"] span,
3256      [data-target="btn-notificar-disponibilidade"] svg {
3257        color: inherit !important;
3258      }
3259      [data-target="btn-notificar-disponibilidade"]:not(.is-avise-me-solicitado):hover,
3260      [data-target="pesquisa-header"]:hover [data-target="btn-notificar-disponibilidade"]:not(.is-avise-me-solicitado),
3261      [data-target="pesquisa-header-mobile"]:hover [data-target="btn-notificar-disponibilidade"]:not(.is-avise-me-solicitado),
3262      [data-target="pesquisa-produto-linear"]:hover [data-target="btn-notificar-disponibilidade"]:not(.is-avise-me-solicitado),
3263      [data-target="pesquisa-produto-colunar"]:hover [data-target="btn-notificar-disponibilidade"]:not(.is-avise-me-solicitado),
3264      [data-target="carrossel-produto"]:hover [data-target="btn-notificar-disponibilidade"]:not(.is-avise-me-solicitado) {
3265        background-color: var(--c-btn-padrao-comprar-bg-hover, var(--c-btn-padrao-comprar-bg)) !important;
3266        border-color: var(--c-btn-padrao-comprar-border) !important;
3267        color: var(--c-btn-padrao-comprar-text-hover, var(--c-btn-padrao-comprar-text, #fff)) !important;
3268        opacity: 1;
3269      }
3270      [data-target="pesquisa-header"] [data-target="comprar-produto"],
3271      [data-target="pesquisa-header-mobile"] [data-target="comprar-produto"],
3272      [data-target="pesquisa-header"] > div,
3273      [data-target="pesquisa-header-mobile"] > div {
3274        overflow: visible;
3275      }
3276      [data-target="pesquisa-header"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto,
3277      [data-target="pesquisa-header-mobile"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto {
3278        width: 2.5rem !important;
3279        max-width: 2.5rem !important;
3280        overflow: hidden;
3281      }
3282      [data-target="pesquisa-header"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto .avise-me-texto,
3283      [data-target="pesquisa-header-mobile"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto .avise-me-texto {
3284        display: none;
3285      }
3286      [data-target="pesquisa-header"]:hover [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado),
3287      [data-target="pesquisa-header-mobile"]:hover [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado),
3288      [data-target="pesquisa-header"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado):hover,
3289      [data-target="pesquisa-header-mobile"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado):hover {
3290        width: auto !important;
3291        max-width: none !important;
3292        padding-inline: 0.5rem !important;
3293      }
3294      [data-target="pesquisa-header"]:hover [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado) .avise-me-texto,
3295      [data-target="pesquisa-header-mobile"]:hover [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado) .avise-me-texto,
3296      [data-target="pesquisa-header"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado):hover .avise-me-texto,
3297      [data-target="pesquisa-header-mobile"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado):hover .avise-me-texto {
3298        display: inline;
3299      }
3300      [data-target="pesquisa-header"]:hover [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado) svg,
3301      [data-target="pesquisa-header-mobile"]:hover [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado) svg,
3302      [data-target="pesquisa-header"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado):hover svg,
3303      [data-target="pesquisa-header-mobile"] [data-target="btn-notificar-disponibilidade"].is-avise-me-compacto:not(.is-avise-me-solicitado):hover svg {
3304        display: none;
3305      }
3306      [data-target="btn-notificar-disponibilidade"].is-avise-me-solicitado,
3307      [data-target="btn-notificar-disponibilidade"].is-avise-me-solicitado span,
3308      [data-target="btn-notificar-disponibilidade"].is-avise-me-solicitado svg {
3309        cursor: default !important;
3310      }
3311      [data-target="btn-notificar-disponibilidade"].is-avise-me-solicitado {
3312        background-color: var(--dark-gray, #838383) !important;
3313        border-color: var(--dark-gray, #838383) !important;
3314        opacity: 0.6;
3315      }
3316      [data-target="comprar-produto"].is-avise-me-solicitado-bloco,
3317      [data-target="comprar-produto"].is-avise-me-solicitado-bloco * {
3318        cursor: default !important;
3319      }
3320    `;
3321  }
3322
3323  function aplicarGrayscaleIndisponivelAviseMe(produto_el) {
3324    if (!produto_el) return;
3325
3326    const target = produto_el.dataset?.target || '';
3327    if (target === 'pagina-produto') return;
3328
3329    produto_el.style.filter = '';
3330    produto_el.querySelectorAll('img').forEach(function (img) {
3331      img.style.filter = 'grayscale(1)';
3332    });
3333  }
3334
3335  function garantirContainerMensagemAviseMe() {
3336    let container = document.getElementById('avise-me-mensagem-container');
3337    if (container) return container;
3338
3339    container = document.createElement('div');
3340    container.id = 'avise-me-mensagem-container';
3341    container.className = 'fixed top-4 right-4 z-[9999] flex flex-col gap-2 w-[min(100%,22rem)] pointer-events-none px-4';
3342    container.setAttribute('aria-live', 'polite');
3343    container.setAttribute('aria-atomic', 'true');
3344    document.body.appendChild(container);
3345    return container;
3346  }
3347
3348  function exibirToastAviseMe(tipo, msg) {
3349    const container = garantirContainerMensagemAviseMe();
3350    const toast = document.createElement('div');
3351    const classe_cor = dict_cores_mensagem[tipo] || dict_cores_mensagem.success;
3352
3353    toast.className = `pointer-events-auto px-4 py-3 rounded-[12px] border text-[13px] leading-snug font-semibold shadow-lg transition-opacity duration-300 opacity-100 ${classe_cor}`;
3354    toast.setAttribute('role', 'status');
3355    toast.textContent = msg;
3356    container.appendChild(toast);
3357
3358    window.setTimeout(function () {
3359      toast.classList.replace('opacity-100', 'opacity-0');
3360      window.setTimeout(function () {
3361        toast.remove();
3362        if (!container.childElementCount) container.remove();
3363      }, 300);
3364    }, 4500);
3365  }
3366
3367  function isContextoCompactoAviseMe(btn) {
3368    const produto_el = btn?.closest?.('[data-notificar-disponibilidade="true"]');
3369    const target = produto_el?.dataset?.target || '';
3370    return target === 'pesquisa-header' || target === 'pesquisa-header-mobile';
3371  }
3372
3373  function compactarLayoutAviseMe(comprar_el, produto_el) {
3374    const target = produto_el?.dataset?.target || '';
3375    if (target === 'pesquisa-header' || target === 'pesquisa-header-mobile') return;
3376  }
3377
3378  function desabilitarBotaoAviseMeSolicitado(btn) {
3379    if (!btn) return;
3380
3381    btn.removeAttribute('disabled');
3382    btn.setAttribute('aria-disabled', 'true');
3383    btn.tabIndex = -1;
3384    btn.classList.remove('cursor-pointer');
3385    btn.classList.add('is-avise-me-solicitado', 'cursor-default');
3386
3387    const comprar_el = btn.closest('[data-target="comprar-produto"]');
3388    if (comprar_el) comprar_el.classList.add('is-avise-me-solicitado-bloco');
3389  }
3390
3391  const CHAVE_AVISE_ME_PENDENTE = 'avise_me_pendente';
3392
3393  function obterUrlRetornoAviseMe() {
3394    return window.location.pathname + window.location.search + window.location.hash;
3395  }
3396
3397  function montarUrlRetornoAviseMe(produto_id) {
3398    const url = new URL(window.location.href);
3399    url.searchParams.delete('avise_me_produto');
3400    url.searchParams.set('avise_me_produto', String(produto_id));
3401    return url.pathname + url.search + url.hash;
3402  }
3403
3404  function salvarPendenciaAviseMe(produto_id) {
3405    try {
3406      sessionStorage.setItem(CHAVE_AVISE_ME_PENDENTE, JSON.stringify({
3407        produto_id: String(produto_id),
3408        url: obterUrlRetornoAviseMe(),
3409      }));
3410    } catch (_) {}
3411  }
3412
3413  function limparPendenciaAviseMe() {
3414    try {
3415      sessionStorage.removeItem(CHAVE_AVISE_ME_PENDENTE);
3416    } catch (_) {}
3417
3418    try {
3419      const url = new URL(window.location.href);
3420      if (!url.searchParams.has('avise_me_produto')) return;
3421      url.searchParams.delete('avise_me_produto');
3422      window.history.replaceState(null, '', url.pathname + url.search + url.hash);
3423    } catch (_) {}
3424  }
3425
3426  function obterProdutoIdAviseMePendente() {
3427    try {
3428      const da_url = new URLSearchParams(window.location.search).get('avise_me_produto');
3429      if (da_url) return da_url;
3430    } catch (_) {}
3431
3432    try {
3433      const pendente = sessionStorage.getItem(CHAVE_AVISE_ME_PENDENTE);
3434      if (pendente) return JSON.parse(pendente).produto_id || null;
3435    } catch (_) {}
3436
3437    return null;
3438  }
3439
3440  function isUsuarioAutenticadoAviseMe() {
3441    if (typeof window.IS_AUTENTICADO === 'function') {
3442      return window.IS_AUTENTICADO();
3443    }
3444    if (typeof window.APP_CONTEXT === 'function') {
3445      return !!window.APP_CONTEXT()?.auth?.is_autenticado;
3446    }
3447    return false;
3448  }
3449
3450  function redirecionarLoginAviseMe(produto_id) {
3451    if (produto_id) {
3452      salvarPendenciaAviseMe(produto_id);
3453    }
3454    exibirMensagemAviseMe('error', 'Faça login para ser avisado quando o produto estiver disponível.');
3455    window.setTimeout(function () {
3456      const url_retorno = produto_id
3457        ? montarUrlRetornoAviseMe(produto_id)
3458        : obterUrlRetornoAviseMe();
3459      window.location.href = '/login?next=' + encodeURIComponent(url_retorno);
3460    }, 1200);
3461  }
3462
3463  function redirecionarSeAviseMePendentePosLogin() {
3464    if (!isUsuarioAutenticadoAviseMe()) return false;
3465    if (obterProdutoIdAviseMePendente()) return false;
3466
3467    let pendente = null;
3468    try {
3469      const raw = sessionStorage.getItem(CHAVE_AVISE_ME_PENDENTE);
3470      if (raw) pendente = JSON.parse(raw);
3471    } catch (_) {}
3472
3473    if (!pendente?.produto_id) return false;
3474
3475    const url_alvo = new URL(pendente.url || '/', window.location.origin);
3476    url_alvo.searchParams.set('avise_me_produto', String(pendente.produto_id));
3477    const destino = url_alvo.pathname + url_alvo.search + url_alvo.hash;
3478    const atual = obterUrlRetornoAviseMe();
3479
3480    if (destino !== atual) {
3481      window.location.href = destino;
3482      return true;
3483    }
3484
3485    return false;
3486  }
3487
3488  function encontrarBotaoAviseMeProduto(produto_id) {
3489    return document.querySelector(
3490      `[data-notificar-disponibilidade="true"][data-cd-produto="${produto_id}"] [data-target="btn-notificar-disponibilidade"]`
3491    );
3492  }
3493
3494  function marcarBotaoAviseMeSolicitado(btn, produto_id) {
3495    const btn_alvo = btn || encontrarBotaoAviseMeProduto(produto_id);
3496    if (!btn_alvo) return;
3497
3498    removerMensagensInlineAviseMe(btn_alvo);
3499
3500    const comprar_el = btn_alvo.closest('[data-target="comprar-produto"]');
3501    if (comprar_el) comprar_el.dataset.aviseMeSolicitado = 'true';
3502
3503    const is_compacto = isContextoCompactoAviseMe(btn_alvo);
3504
3505    btn_alvo.innerHTML = `
3506      <svg xmlns="http://www.w3.org/2000/svg" width="17.5" height="17.5" viewBox="0 0 24 24" fill="currentColor" class="text-white shrink-0" aria-hidden="true">
3507        ${ICONE_SINO}
3508      </svg>
3509      ${is_compacto
3510        ? '<span class="avise-me-texto font-bold text-[13px] text-white whitespace-nowrap">Avise-me solicitado</span>'
3511        : '<span class="font-bold text-[13px] text-white">Avise-me solicitado</span>'}
3512    `;
3513    if (is_compacto) btn_alvo.classList.add('is-avise-me-compacto');
3514    desabilitarBotaoAviseMeSolicitado(btn_alvo);
3515  }
3516
3517  function agendarProcessarAviseMePosLogin() {
3518    const produto_id = obterProdutoIdAviseMePendente();
3519    if (!produto_id || !isUsuarioAutenticadoAviseMe()) return;
3520    if (avise_me_pos_login_agendado) return;
3521    avise_me_pos_login_agendado = true;
3522
3523    let tentativas = 0;
3524    const max_tentativas = 30;
3525
3526    const tentar = function () {
3527      tentativas += 1;
3528      const btn = encontrarBotaoAviseMeProduto(produto_id);
3529      if (btn && btn.getAttribute('aria-disabled') !== 'true') {
3530        notificarDisponibilidadeProduto(produto_id, btn, true);
3531        return;
3532      }
3533      if (tentativas < max_tentativas) {
3534        window.setTimeout(tentar, 200);
3535        return;
3536      }
3537      notificarDisponibilidadeProduto(produto_id, null, true);
3538    };
3539
3540    window.setTimeout(tentar, 400);
3541  }
3542
3543  async function notificarDisponibilidadeProduto(produto_id, btn, is_pos_login) {
3544    if (!produto_id) return;
3545
3546    if (btn?.getAttribute('aria-disabled') === 'true') return;
3547
3548    if (!isUsuarioAutenticadoAviseMe()) {
3549      redirecionarLoginAviseMe(produto_id);
3550      return;
3551    }
3552
3553    try {
3554      const request = await fetch('/produto/notificar-disponibilidade', {
3555        method: 'POST',
3556        headers: {
3557          'Content-Type': 'application/json',
3558          'X-CSRFToken': window.CSRF_TOKEN?.() || '',
3559        },
3560        body: JSON.stringify({ produto_id: produto_id }),
3561      });
3562
3563      const response = await request.json();
3564
3565      if (!request.ok || !response?.status) {
3566        const descricao_erro = response?.descricao || '';
3567        if (
3568          request.status === 401
3569          || request.status === 403
3570          || /identificado|login|autentic/i.test(descricao_erro)
3571        ) {
3572          redirecionarLoginAviseMe(produto_id);
3573          return;
3574        }
3575        exibirMensagemAviseMe('error', descricao_erro || 'Não foi possível cadastrar a notificação. Tente novamente.');
3576        return;
3577      }
3578
3579      const msg_toast = response?.descricao || 'Notificação cadastrada com sucesso';
3580
3581      marcarBotaoAviseMeSolicitado(btn, produto_id);
3582
3583      if (is_pos_login || obterProdutoIdAviseMePendente()) {
3584        limparPendenciaAviseMe();
3585      }
3586
3587      exibirMensagemAviseMe('success', msg_toast);
3588    } catch (e) {
3589      exibirMensagemAviseMe('error', 'Não foi possível cadastrar a notificação. Tente novamente.');
3590    }
3591  }
3592
3593  function montarIconeSinoAviseMe(tamanho) {
3594    return `<svg xmlns="http://www.w3.org/2000/svg" width="${tamanho}" height="${tamanho}" viewBox="0 0 24 24" fill="currentColor" class="text-white shrink-0" aria-hidden="true">${ICONE_SINO}</svg>`;
3595  }
3596
3597  function montarHtmlBotaoAviseMe(produto_id, produto_el) {
3598    const target = produto_el?.dataset?.target || '';
3599    const is_compacto = target === 'pesquisa-header' || target === 'pesquisa-header-mobile';
3600    const is_pagina_produto = target === 'pagina-produto';
3601    const classe_botao = is_pagina_produto ? 'rounded-[var(--r-btn-comprar)]' : 'rounded-[var(--r-cta-radius)]';
3602    const tamanho_icone = 17.5;
3603    const texto_avise_me = is_compacto
3604      ? '<span class="avise-me-texto font-bold text-[13px] text-white whitespace-nowrap"> Indisponível, Avise-me </span>'
3605      : '<span class="font-bold text-[13px] text-white">Avise-me</span>';
3606    const classe_tamanho = is_compacto
3607      ? 'relative w-10 is-avise-me-compacto h-[var(--h-btn-comprar)] p-1 shrink-0 gap-x-1.5'
3608      : 'w-full h-[var(--h-btn-comprar)] p-0.5';
3609
3610    const html_botao = `
3611      <button type="button"
3612        class="flex flex-row justify-center items-center cursor-pointer border-1
3613          ${classe_tamanho} ${classe_botao}"
3614        data-target="btn-notificar-disponibilidade"
3615        data-cd-produto="${produto_id}"
3616        ${is_compacto ? 'aria-label=" Indisponível, Avise-me "' : ''}
3617        onclick="event.preventDefault(); event.stopPropagation(); window.notificarDisponibilidadeProduto('${produto_id}', this); return false;">
3618        ${is_compacto ? texto_avise_me : ''}
3619        ${montarIconeSinoAviseMe(tamanho_icone)}
3620        ${is_compacto ? '' : texto_avise_me}
3621      </button>
3622    `;
3623
3624    if (is_pagina_produto) {
3625      return `
3626        <div class="flex flex-col gap-2 w-full" data-target="bloco-avise-me">
3627          <span class="font-bold text-red-600 bg-white whitespace-nowrap text-md text-center p-0.5">Produto indisponível</span>
3628          ${html_botao}
3629        </div>
3630      `;
3631    }
3632
3633    return html_botao;
3634  }
3635
3636  function isConteudoIndisponivelAviseMe(comprar_el) {
3637    if (!comprar_el || comprar_el.dataset.aviseMeSolicitado === 'true') {
3638      return false;
3639    }
3640    if (comprar_el.querySelector('[data-target="btn-notificar-disponibilidade"]')) {
3641      return false;
3642    }
3643    return /indispon/i.test(comprar_el.textContent || '');
3644  }
3645
3646  function aplicarBotoesAviseMe() {
3647    document.querySelectorAll('[data-notificar-disponibilidade="true"]').forEach((produto_el) => {
3648      const produto_id = produto_el.getAttribute('data-cd-produto');
3649      if (!produto_id) return;
3650
3651      produto_el.querySelectorAll('[data-target="comprar-produto"]').forEach((comprar_el) => {
3652        if (comprar_el.dataset.aviseMeSolicitado === 'true') return;
3653        if (!isConteudoIndisponivelAviseMe(comprar_el)) return;
3654        compactarLayoutAviseMe(comprar_el, produto_el);
3655        comprar_el.innerHTML = montarHtmlBotaoAviseMe(produto_id, produto_el);
3656        aplicarGrayscaleIndisponivelAviseMe(produto_el);
3657      });
3658    });
3659  }
3660
3661  function observarComprarProdutoAviseMe(comprar_el) {
3662    if (!comprar_el || comprar_el.dataset.aviseMeObservado === 'true') return;
3663    comprar_el.dataset.aviseMeObservado = 'true';
3664    new MutationObserver(agendarAplicarBotoesAviseMe).observe(comprar_el, {
3665      childList: true,
3666      subtree: true,
3667      characterData: true,
3668    });
3669  }
3670
3671  function iniciarObservadoresAviseMe() {
3672    document.querySelectorAll('[data-notificar-disponibilidade="true"] [data-target="comprar-produto"]').forEach(observarComprarProdutoAviseMe);
3673  }
3674
3675  function agendarAplicarBotoesAviseMe() {
3676    clearTimeout(timer_avise_me);
3677    timer_avise_me = setTimeout(function () {
3678      aplicarBotoesAviseMe();
3679      iniciarObservadoresAviseMe();
3680    }, 80);
3681  }
3682
3683  function iniciarAviseMe() {
3684    garantirEstilosAviseMe();
3685    aplicarBotoesAviseMe();
3686    iniciarObservadoresAviseMe();
3687  }
3688
3689  window.notificarDisponibilidadeProduto = notificarDisponibilidadeProduto;
3690  window.iniciarAviseMe = iniciarAviseMe;
3691
3692  window.addEventListener('load', function () {
3693    if (redirecionarSeAviseMePendentePosLogin()) return;
3694
3695    iniciarAviseMe();
3696    new MutationObserver(agendarAplicarBotoesAviseMe).observe(document.body, {
3697      childList: true,
3698      subtree: true,
3699    });
3700    agendarProcessarAviseMePosLogin();
3701  });
3702})();
3703// fim avise-me 
3704
3705
3706
3707</script>
vendor: 159 bytes, lines 3707-3716
3707
3708  
3709
3710  
3711
3712  
3713
3714  
3715
3716<script src="/cdn-cgi/scripts/7d0fa10a/cloudflare-static/rocket-loader.min.js" data-cf-settings="ff2c2aaab21707ab2ba08cc2-|49" defer></script>
3716<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":"76d8126d89a14c5d9414af4de517c5fc","spa":2}' crossorigin="anonymous"></script>
3716
3717</body>
3718
3719</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.