var/cache/dev/twig/7e/7e1eaabe8cf91543b9a61edc82fd2f29.php line 2543

Open in your IDE?
  1. <?php
  2. use Twig\Environment;
  3. use Twig\Error\LoaderError;
  4. use Twig\Error\RuntimeError;
  5. use Twig\Extension\CoreExtension;
  6. use Twig\Extension\SandboxExtension;
  7. use Twig\Markup;
  8. use Twig\Sandbox\SecurityError;
  9. use Twig\Sandbox\SecurityNotAllowedTagError;
  10. use Twig\Sandbox\SecurityNotAllowedFilterError;
  11. use Twig\Sandbox\SecurityNotAllowedFunctionError;
  12. use Twig\Source;
  13. use Twig\Template;
  14. use Twig\TemplateWrapper;
  15. /* base_home.html.twig */
  16. class __TwigTemplate_c86efc76357b73ced93910d382926e56 extends Template
  17. {
  18.     private Source $source;
  19.     /**
  20.      * @var array<string, Template>
  21.      */
  22.     private array $macros = [];
  23.     public function __construct(Environment $env)
  24.     {
  25.         parent::__construct($env);
  26.         $this->source $this->getSourceContext();
  27.         $this->parent false;
  28.         $this->blocks = [
  29.             'title' => [$this'block_title'],
  30.             'stylesheets' => [$this'block_stylesheets'],
  31.             'body' => [$this'block_body'],
  32.             'javascripts' => [$this'block_javascripts'],
  33.         ];
  34.     }
  35.     protected function doDisplay(array $context, array $blocks = []): iterable
  36.     {
  37.         $macros $this->macros;
  38.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  39.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template""base_home.html.twig"));
  40.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  41.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template""base_home.html.twig"));
  42.         // line 1
  43.         yield "<!DOCTYPE html>
  44. <html lang=\"fr\" class=\"no-js\">
  45. \t<head>
  46. \t\t<!-- Mobile Specific Meta -->
  47. \t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no\">
  48. \t\t<meta name=\"mobile-web-app-capable\" content=\"yes\">
  49. \t\t<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">
  50. \t\t<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\">
  51. \t\t<meta name=\"apple-mobile-web-app-title\" content=\"MaketOu\">
  52. \t\t<meta name=\"theme-color\" content=\"#ffa200\">
  53. \t\t<meta name=\"msapplication-TileColor\" content=\"#ffa200\">
  54. \t\t<meta
  55. \t\tname=\"msapplication-config\" content=\"";
  56.         // line 14
  57.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/browserconfig.xml"), "html"nulltrue);
  58.         yield "\">
  59. \t\t<!-- Favicon-->
  60. \t\t<link rel=\"shortcut icon\" href=\"";
  61.         // line 17
  62.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-16x16.png"), "html"nulltrue);
  63.         yield "\">
  64. \t\t<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"";
  65.         // line 18
  66.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/apple-touch-icon.png"), "html"nulltrue);
  67.         yield "\">
  68. \t\t<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"";
  69.         // line 19
  70.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-32x32.png"), "html"nulltrue);
  71.         yield "\">
  72. \t\t<link
  73. \t\trel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"";
  74.         // line 21
  75.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-16x16.png"), "html"nulltrue);
  76.         yield "\">
  77. \t\t<!-- PWA Manifest -->
  78. \t\t<link
  79. \t\trel=\"manifest\" href=\"";
  80.         // line 25
  81.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("manifest.json"), "html"nulltrue);
  82.         yield "\">
  83. \t\t<!-- Author Meta -->
  84. \t\t<meta
  85. \t\tname=\"author\" content=\"Foulgor Tech\">
  86. \t\t<!-- Meta Description -->
  87. \t\t<meta
  88. \t\tname=\"description\" content=\"\">
  89. \t\t<!-- Meta Keyword -->
  90. \t\t<meta
  91. \t\tname=\"keywords\" content=\"\">
  92. \t\t<!-- meta character set -->
  93. \t\t<meta
  94. \t\tcharset=\"UTF-8\">
  95. \t\t<!-- Site Title -->
  96. \t\t<title>
  97. \t\t\t";
  98.         // line 40
  99.         yield from $this->unwrap()->yieldBlock('title'$context$blocks);
  100.         // line 42
  101.         yield "\t\t</title>
  102. \t\t<!--
  103. \t\t\t\t\t\t        CSS
  104. \t\t\t\t\t\t        ============================================= -->
  105. \t\t<link rel=\"stylesheet\" href=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.css\"/>
  106. \t\t<link rel=\"stylesheet\" href=\"";
  107.         // line 47
  108.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/linearicons.css"), "html"nulltrue);
  109.         yield "\">
  110. \t\t<link rel=\"stylesheet\" href=\"";
  111.         // line 48
  112.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/font-awesome.min.css"), "html"nulltrue);
  113.         yield "\">
  114. \t\t<link rel=\"stylesheet\" href=\"";
  115.         // line 49
  116.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/themify-icons.css"), "html"nulltrue);
  117.         yield "\">
  118. \t\t<link rel=\"stylesheet\" href=\"";
  119.         // line 50
  120.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/bootstrap.css"), "html"nulltrue);
  121.         yield "\">
  122. \t\t<link rel=\"stylesheet\" href=\"";
  123.         // line 51
  124.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/owl.carousel.css"), "html"nulltrue);
  125.         yield "\">
  126. \t\t<link rel=\"stylesheet\" href=\"";
  127.         // line 52
  128.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/nice-select.css"), "html"nulltrue);
  129.         yield "\">
  130. \t\t<link rel=\"stylesheet\" href=\"";
  131.         // line 53
  132.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/nouislider.min.css"), "html"nulltrue);
  133.         yield "\">
  134. \t\t<link rel=\"stylesheet\" href=\"";
  135.         // line 54
  136.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/ion.rangeSlider.css"), "html"nulltrue);
  137.         yield "\"/>
  138. \t\t<link rel=\"stylesheet\" href=\"";
  139.         // line 55
  140.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/ion.rangeSlider.skinFlat.css"), "html"nulltrue);
  141.         yield "\"/>
  142. \t\t<link rel=\"stylesheet\" href=\"";
  143.         // line 56
  144.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/magnific-popup.css"), "html"nulltrue);
  145.         yield "\">
  146. \t\t<link rel=\"stylesheet\" href=\"";
  147.         // line 57
  148.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/main.css"), "html"nulltrue);
  149.         yield "\">
  150. \t\t<link rel=\"stylesheet\" href=\"";
  151.         // line 58
  152.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/cart-modal.css"), "html"nulltrue);
  153.         yield "\">
  154. \t\t<link rel=\"stylesheet\" href=\"";
  155.         // line 59
  156.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/buttons-unified.css"), "html"nulltrue);
  157.         yield "\">
  158. \t\t<link rel=\"stylesheet\" href=\"";
  159.         // line 60
  160.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/design-system.css"), "html"nulltrue);
  161.         yield "\">
  162. \t\t<link rel=\"stylesheet\" href=\"";
  163.         // line 61
  164.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/dark-mode-forced.css"), "html"nulltrue);
  165.         yield "\">
  166. \t\t<link rel=\"stylesheet\" href=\"";
  167.         // line 62
  168.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/dark-mode-complete.css"), "html"nulltrue);
  169.         yield "\">
  170. \t\t<link rel=\"stylesheet\" href=\"";
  171.         // line 63
  172.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/navbar-icons-enhanced.css"), "html"nulltrue);
  173.         yield "\">
  174. \t\t<link rel=\"stylesheet\" href=\"";
  175.         // line 64
  176.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/dark-mode-pages-specific.css"), "html"nulltrue);
  177.         yield "\">
  178. \t\t<meta
  179. \t\tcharset=\"UTF-8\">
  180. \t\t";
  181.         // line 68
  182.         yield "
  183. \t\t<style>
  184. \t\t\t/* Styles pour l'icône de notification */
  185. \t\t\t.notification-icon {
  186. \t\t\t\tposition: relative;
  187. \t\t\t\tdisplay: inline-block;
  188. \t\t\t\tcolor: #333;
  189. \t\t\t\ttext-decoration: none;
  190. \t\t\t\ttransition: color 0.3s ease;
  191. \t\t\t}
  192. \t\t\t.notification-icon:hover {
  193. \t\t\t\tcolor: #007bff;
  194. \t\t\t}
  195. \t\t\t.notification-badge {
  196. \t\t\t\tposition: absolute;
  197. \t\t\t\ttop: -4px;
  198. \t\t\t\tright: -2px;
  199. \t\t\t\tbackground: #dc3545 !important;
  200. \t\t\t\tcolor: white !important;
  201. \t\t\t\tborder-radius: 50%;
  202. \t\t\t\twidth: 18px;
  203. \t\t\t\theight: 18px;
  204. \t\t\t\tfont-size: 8px !important;
  205. \t\t\t\tdisplay: flex !important;
  206. \t\t\t\talign-items: center !important;
  207. \t\t\t\tjustify-content: center !important;
  208. \t\t\t\tfont-weight: bold !important;
  209. \t\t\t\tanimation: pulse 2s infinite;
  210. \t\t\t\tz-index: 10;
  211. \t\t\t\tline-height: 1 !important;
  212. \t\t\t}
  213. \t\t\t/* Forcer le texte en blanc pour tous les éléments du badge - avec spécificité maximale */
  214. \t\t\t.notification-badge,
  215. \t\t\t.notification-badge.text-white,
  216. \t\t\t.notification-badge *,
  217. \t\t\t#notificationBadge,
  218. \t\t\t#notificationBadge.text-white,
  219. \t\t\t#notificationBadge *,
  220. \t\t\tspan.notification-badge,
  221. \t\t\tspan.notification-badge.text-white,
  222. \t\t\tspan#notificationBadge,
  223. \t\t\tspan#notificationBadge.text-white {
  224. \t\t\t\tcolor: white !important;
  225. \t\t\t\ttext-color: white !important;
  226. \t\t\t\t-webkit-text-fill-color: white !important;
  227. \t\t\t}
  228. \t\t\t/* S'assurer que le contenu texte est bien en blanc */
  229. \t\t\t.notification-badge::before,
  230. \t\t\t.notification-badge::after {
  231. \t\t\t\tcolor: white !important;
  232. \t\t\t}
  233. \t\t\t/* Forcer la couleur pour tous les sélecteurs possibles avec spécificité maximale */
  234. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge,
  235. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge.text-white,
  236. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span.notification-badge,
  237. \t\t\t.notification-icon .notification-badge,
  238. \t\t\t.notification-icon .notification-badge.text-white,
  239. \t\t\t.notification-icon span.notification-badge,
  240. \t\t\ta.notification-icon .notification-badge,
  241. \t\t\ta.notification-icon span.notification-badge {
  242. \t\t\t\tcolor: white !important;
  243. \t\t\t\ttext-color: white !important;
  244. \t\t\t\t-webkit-text-fill-color: white !important;
  245. \t\t\t}
  246. \t\t\t/* Forcer la couleur pour tous les enfants directs */
  247. \t\t\t.notification-icon > .notification-badge,
  248. \t\t\t.notification-icon > span.notification-badge {
  249. \t\t\t\tcolor: white !important;
  250. \t\t\t}
  251. \t\t\t@keyframes pulse {
  252. \t\t\t\t0% {
  253. \t\t\t\t\ttransform: scale(1);
  254. \t\t\t\t}
  255. \t\t\t\t50% {
  256. \t\t\t\t\ttransform: scale(1.1);
  257. \t\t\t\t}
  258. \t\t\t\t100% {
  259. \t\t\t\t\ttransform: scale(1);
  260. \t\t\t\t}
  261. \t\t\t}
  262. \t\t\t.notification-icon:hover .notification-badge {
  263. \t\t\t\tanimation: none;
  264. \t\t\t}
  265. \t\t\t/* Container pour les icônes - toujours alignées horizontalement */
  266. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
  267. \t\t\t\tdisplay: flex !important;
  268. \t\t\t\tflex-direction: row !important;
  269. \t\t\t\talign-items: center !important;
  270. \t\t\t\tjustify-content: center !important;
  271. \t\t\t\tgap: 15px !important;
  272. \t\t\t\tlist-style: none !important;
  273. \t\t\t\tmargin: 0 !important;
  274. \t\t\t\tpadding: 0 !important;
  275. \t\t\t\twidth: auto !important;
  276. \t\t\t}
  277. \t\t\t/* Surcharger les styles existants pour les li contenant le wrapper */
  278. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right li:has(.navbar-icons-wrapper) {
  279. \t\t\t\tmargin-left: 0 !important;
  280. \t\t\t\tmargin-right: 0 !important;
  281. \t\t\t\tdisplay: flex !important;
  282. \t\t\t\talign-items: center !important;
  283. \t\t\t\tjustify-content: center !important;
  284. \t\t\t}
  285. \t\t\t/* Styles pour les icônes */
  286. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart,
  287. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon,
  288. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon,
  289. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .dark-mode-toggle,
  290. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
  291. \t\t\t\tdisplay: flex !important;
  292. \t\t\t\talign-items: center !important;
  293. \t\t\t\tjustify-content: center !important;
  294. \t\t\t\twidth: 40px !important;
  295. \t\t\t\theight: 40px !important;
  296. \t\t\t\tmin-width: 40px !important;
  297. \t\t\t\tmin-height: 40px !important;
  298. \t\t\t\tcolor: #333 !important;
  299. \t\t\t\ttext-decoration: none !important;
  300. \t\t\t\ttransition: all 0.3s ease !important;
  301. \t\t\t\tborder-radius: 50% !important;
  302. \t\t\t\tposition: relative !important;
  303. \t\t\t\tmargin: 0 !important;
  304. \t\t\t\tpadding: 0 !important;
  305. \t\t\t}
  306. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart:hover,
  307. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon:hover,
  308. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon:hover,
  309. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .dark-mode-toggle:hover,
  310. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search:hover {
  311. \t\t\t\tbackground-color: #f0f0f0 !important;
  312. \t\t\t\tcolor: #ffa200 !important;
  313. \t\t\t\ttransform: scale(1.1) !important;
  314. \t\t\t}
  315. \t\t\t/* Surcharger le line-height de main.css */
  316. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart span,
  317. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span,
  318. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search span {
  319. \t\t\t\tfont-size: 18px !important;
  320. \t\t\t\tline-height: 1 !important;
  321. \t\t\t\tdisplay: flex !important;
  322. \t\t\t\talign-items: center !important;
  323. \t\t\t\tjustify-content: center !important;
  324. \t\t\t\tcolor: inherit !important;
  325. \t\t\t\tfont-weight: normal !important;
  326. \t\t\t}
  327. \t\t\t/* Icône de comparaison en noir comme le panier */
  328. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon {
  329. \t\t\t\tcolor: #333 !important;
  330. \t\t\t}
  331. \t\t\t/* L'icône elle-même (lnr-sync) doit être noire, mais pas le badge */
  332. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon > span.lnr-sync,
  333. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon span:not(.comparison-badge) {
  334. \t\t\t\tcolor: #333 !important;
  335. \t\t\t\tfont-size: 18px !important;
  336. \t\t\t\tline-height: 1 !important;
  337. \t\t\t\tdisplay: flex !important;
  338. \t\t\t\talign-items: center !important;
  339. \t\t\t\tjustify-content: center !important;
  340. \t\t\t\tfont-weight: normal !important;
  341. \t\t\t}
  342. \t\t\t/* Le badge doit rester blanc */
  343. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon .comparison-badge {
  344. \t\t\t\tcolor: white !important;
  345. \t\t\t}
  346. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
  347. \t\t\t\tbackground: transparent !important;
  348. \t\t\t\tborder: 0 !important;
  349. \t\t\t\tcursor: pointer !important;
  350. \t\t\t\tpadding: 0 !important;
  351. \t\t\t}
  352. \t\t\t/* Alignement des icônes navbar sur mobile */
  353. \t\t\t@media(max-width: 991.98px) {
  354. \t\t\t\t/* Container navbar-right en colonne sur mobile */
  355. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right {
  356. \t\t\t\t\tdisplay: flex !important;
  357. \t\t\t\t\tflex-direction: column !important;
  358. \t\t\t\t\talign-items: center !important;
  359. \t\t\t\t\tjustify-content: center !important;
  360. \t\t\t\t\twidth: 100% !important;
  361. \t\t\t\t\tgap: 0 !important;
  362. \t\t\t\t\tmargin: 0 !important;
  363. \t\t\t\t\tpadding: 10px 0 !important;
  364. \t\t\t\t}
  365. \t\t\t\t/* Le container d'icônes reste horizontal */
  366. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
  367. \t\t\t\t\twidth: 100% !important;
  368. \t\t\t\t\tjustify-content: center !important;
  369. \t\t\t\t\tdisplay: flex !important;
  370. \t\t\t\t\tflex-direction: row !important;
  371. \t\t\t\t}
  372. \t\t\t\t/* Le bouton compte en bas - pleine largeur */
  373. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right li:last-child {
  374. \t\t\t\t\twidth: 100% !important;
  375. \t\t\t\t\tdisplay: flex !important;
  376. \t\t\t\t\tjustify-content: center !important;
  377. \t\t\t\t\tmargin-top: 12px !important;
  378. \t\t\t\t\tpadding-top: 12px !important;
  379. \t\t\t\t\tborder-top: 1px solid #e0e0e0 !important;
  380. \t\t\t\t}
  381. \t\t\t\t/* Bouton compte responsive */
  382. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .btn-account {
  383. \t\t\t\t\twidth: 100%;
  384. \t\t\t\t\tmax-width: 200px;
  385. \t\t\t\t\tpadding: 10px 20px;
  386. \t\t\t\t\tfont-size: 14px;
  387. \t\t\t\t}
  388. \t\t\t}
  389. \t\t\t/* Styles pour les messages flash - Design moderne */
  390. \t\t\t.flash-message {
  391. \t\t\t\tanimation: slideInDownFlash 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  392. \t\t\t\tposition: relative;
  393. \t\t\t\toverflow: visible !important;
  394. \t\t\t\tborder: none !important;
  395. \t\t\t\tpadding: 16px 20px !important;
  396. \t\t\t\tborder-radius: 12px !important;
  397. \t\t\t\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
  398. \t\t\t\tdisplay: flex !important;
  399. \t\t\t\talign-items: center;
  400. \t\t\t\tgap: 12px;
  401. \t\t\t\tmargin-bottom: 15px;
  402. \t\t\t\tbackdrop-filter: blur(10px);
  403. \t\t\t\ttransition: all 0.3s ease;
  404. \t\t\t}
  405. \t\t\t/* S'assurer que les icônes Font Awesome sont visibles */
  406. \t\t\t.flash-message i.fa {
  407. \t\t\t\tdisplay: inline-block !important;
  408. \t\t\t\tvisibility: visible !important;
  409. \t\t\t\topacity: 1 !important;
  410. \t\t\t\twidth: auto !important;
  411. \t\t\t\theight: auto !important;
  412. \t\t\t\tfont-family: \"FontAwesome\" !important;
  413. \t\t\t\tfont-style: normal !important;
  414. \t\t\t\tfont-weight: normal !important;
  415. \t\t\t\ttext-rendering: auto !important;
  416. \t\t\t\t-webkit-font-smoothing: antialiased !important;
  417. \t\t\t\t-moz-osx-font-smoothing: grayscale !important;
  418. \t\t\t\tline-height: 1 !important;
  419. \t\t\t\tflex-shrink: 0 !important;
  420. \t\t\t}
  421. \t\t\t/* Forcer l'affichage des pseudo-éléments Font Awesome */
  422. \t\t\t.flash-message i.fa::before {
  423. \t\t\t\tdisplay: inline-block !important;
  424. \t\t\t\tvisibility: visible !important;
  425. \t\t\t\topacity: 1 !important;
  426. \t\t\t\tcontent: attr(data-icon) !important;
  427. \t\t\t}
  428. \t\t\t/* Styles spécifiques pour chaque icône */
  429. \t\t\t.flash-message i.fa-check-circle::before {
  430. \t\t\t\tcontent: \"\\f058\" !important;
  431. \t\t\t}
  432. \t\t\t.flash-message i.fa-exclamation-circle::before {
  433. \t\t\t\tcontent: \"\\f06a\" !important;
  434. \t\t\t}
  435. \t\t\t.flash-message i.fa-exclamation-triangle::before {
  436. \t\t\t\tcontent: \"\\f071\" !important;
  437. \t\t\t}
  438. \t\t\t.flash-message i.fa-info-circle::before {
  439. \t\t\t\tcontent: \"\\f05a\" !important;
  440. \t\t\t}
  441. \t\t\t.flash-message:hover {
  442. \t\t\t\tbox-shadow: 0 6px 20px rgba(0, 0, 0, 0.2) !important;
  443. \t\t\t\ttransform: translateY(-2px);
  444. \t\t\t}
  445. \t\t\t.flash-message::before {
  446. \t\t\t\tcontent: '';
  447. \t\t\t\tposition: absolute;
  448. \t\t\t\tleft: 0;
  449. \t\t\t\ttop: 0;
  450. \t\t\t\tbottom: 0;
  451. \t\t\t\twidth: 5px;
  452. \t\t\t\tbackground: linear-gradient(180deg, currentColor 0%, rgba(255,255,255,0.3) 100%);
  453. \t\t\t\tborder-radius: 12px 0 0 12px;
  454. \t\t\t}
  455. \t\t\t.flash-message.alert-success {
  456. \t\t\t\tbackground: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%) !important;
  457. \t\t\t\tcolor: #155724 !important;
  458. \t\t\t\tborder-left: 5px solid #28a745 !important;
  459. \t\t\t}
  460. \t\t\t.flash-message.alert-success i.fa {
  461. \t\t\t\tcolor: #28a745 !important;
  462. \t\t\t\tfont-size: 1.3rem !important;
  463. \t\t\t\tdisplay: inline-block !important;
  464. \t\t\t\tmargin-right: 8px;
  465. \t\t\t\tvertical-align: middle;
  466. \t\t\t}
  467. \t\t\t.flash-message.alert-danger {
  468. \t\t\t\tbackground: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%) !important;
  469. \t\t\t\tcolor: #721c24 !important;
  470. \t\t\t\tborder-left: 5px solid #dc3545 !important;
  471. \t\t\t}
  472. \t\t\t.flash-message.alert-danger i.fa {
  473. \t\t\t\tcolor: #dc3545 !important;
  474. \t\t\t\tfont-size: 1.3rem !important;
  475. \t\t\t\tdisplay: inline-block !important;
  476. \t\t\t\tmargin-right: 8px;
  477. \t\t\t\tvertical-align: middle;
  478. \t\t\t}
  479. \t\t\t.flash-message.alert-warning {
  480. \t\t\t\tbackground: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%) !important;
  481. \t\t\t\tcolor: #856404 !important;
  482. \t\t\t\tborder-left: 5px solid #ffc107 !important;
  483. \t\t\t}
  484. \t\t\t.flash-message.alert-warning i.fa {
  485. \t\t\t\tcolor: #ffa200 !important;
  486. \t\t\t\tfont-size: 1.3rem !important;
  487. \t\t\t\tdisplay: inline-block !important;
  488. \t\t\t\tmargin-right: 8px;
  489. \t\t\t\tvertical-align: middle;
  490. \t\t\t}
  491. \t\t\t.flash-message.alert-info {
  492. \t\t\t\tbackground: linear-gradient(135deg, #d1ecf1 0%, #bee5eb 100%) !important;
  493. \t\t\t\tcolor: #0c5460 !important;
  494. \t\t\t\tborder-left: 5px solid #17a2b8 !important;
  495. \t\t\t}
  496. \t\t\t.flash-message.alert-info i.fa {
  497. \t\t\t\tcolor: #17a2b8 !important;
  498. \t\t\t\tfont-size: 1.3rem !important;
  499. \t\t\t\tdisplay: inline-block !important;
  500. \t\t\t\tmargin-right: 8px;
  501. \t\t\t\tvertical-align: middle;
  502. \t\t\t}
  503. \t\t\t.flash-message strong {
  504. \t\t\t\tflex: 1;
  505. \t\t\t\tfont-weight: 600;
  506. \t\t\t\tfont-size: 0.95rem;
  507. \t\t\t\tline-height: 1.5;
  508. \t\t\t}
  509. \t\t\t.flash-message .btn-close {
  510. \t\t\t\topacity: 0.7;
  511. \t\t\t\tpadding: 8px !important;
  512. \t\t\t\tmargin: -8px -8px -8px auto !important;
  513. \t\t\t\ttransition: all 0.2s ease;
  514. \t\t\t\tborder-radius: 50% !important;
  515. \t\t\t\tbackground: rgba(0, 0, 0, 0.05) !important;
  516. \t\t\t\twidth: 32px !important;
  517. \t\t\t\theight: 32px !important;
  518. \t\t\t\tdisplay: flex !important;
  519. \t\t\t\talign-items: center !important;
  520. \t\t\t\tjustify-content: center !important;
  521. \t\t\t\tborder: none !important;
  522. \t\t\t\tcursor: pointer !important;
  523. \t\t\t\tposition: relative !important;
  524. \t\t\t}
  525. \t\t\t/* Ajouter une icône X visible dans le bouton */
  526. \t\t\t.flash-message .btn-close::before {
  527. \t\t\t\tcontent: '×' !important;
  528. \t\t\t\tfont-size: 24px !important;
  529. \t\t\t\tline-height: 1 !important;
  530. \t\t\t\tcolor: currentColor !important;
  531. \t\t\t\tfont-weight: bold !important;
  532. \t\t\t\tdisplay: block !important;
  533. \t\t\t\tposition: absolute !important;
  534. \t\t\t\ttop: 50% !important;
  535. \t\t\t\tleft: 50% !important;
  536. \t\t\t\ttransform: translate(-50%, -50%) !important;
  537. \t\t\t}
  538. \t\t\t.flash-message .btn-close:hover {
  539. \t\t\t\topacity: 1 !important;
  540. \t\t\t\tbackground: rgba(0, 0, 0, 0.15) !important;
  541. \t\t\t\ttransform: rotate(90deg) !important;
  542. \t\t\t}
  543. \t\t\t.flash-message .btn-close:hover::before {
  544. \t\t\t\ttransform: translate(-50%, -50%) rotate(-90deg) !important;
  545. \t\t\t}
  546. \t\t\t@keyframes slideInDownFlash {
  547. \t\t\t\tfrom {
  548. \t\t\t\t\topacity: 0;
  549. \t\t\t\t\ttransform: translateY(-30px) scale(0.95);
  550. \t\t\t\t}
  551. \t\t\t\tto {
  552. \t\t\t\t\topacity: 1;
  553. \t\t\t\t\ttransform: translateY(0) scale(1);
  554. \t\t\t\t}
  555. \t\t\t}
  556. \t\t\t#flash-messages-container {
  557. \t\t\t\tmargin-top: 20px;
  558. \t\t\t\tmargin-bottom: 0;
  559. \t\t\t}
  560. \t\t\t@media(max-width: 768px) {
  561. \t\t\t\t.flash-message {
  562. \t\t\t\t\tpadding: 14px 16px !important;
  563. \t\t\t\t\tfont-size: 0.9rem;
  564. \t\t\t\t}
  565. \t\t\t\t.flash-message i {
  566. \t\t\t\t\tfont-size: 1.2rem !important;
  567. \t\t\t\t}
  568. \t\t\t}
  569. \t\t\t/* Styles pour l'icône de comparaison */
  570. \t\t\t.comparison-icon {
  571. \t\t\t\tposition: relative;
  572. \t\t\t\tdisplay: inline-block;
  573. \t\t\t\tcolor: #333;
  574. \t\t\t\ttext-decoration: none;
  575. \t\t\t\ttransition: all 0.3s ease;
  576. \t\t\t}
  577. \t\t\t.comparison-icon:hover {
  578. \t\t\t\tcolor: #ffa200;
  579. \t\t\t}
  580. \t\t\t.comparison-badge {
  581. \t\t\t\tposition: absolute;
  582. \t\t\t\ttop: -4px;
  583. \t\t\t\tright: -2px;
  584. \t\t\t\tbackground: #095ad3 !important;
  585. \t\t\t\tcolor: white !important;
  586. \t\t\t\tborder-radius: 50%;
  587. \t\t\t\twidth: 18px;
  588. \t\t\t\theight: 18px;
  589. \t\t\t\tfont-size: 8px !important;
  590. \t\t\t\tdisplay: flex !important;
  591. \t\t\t\talign-items: center !important;
  592. \t\t\t\tjustify-content: center !important;
  593. \t\t\t\tfont-weight: bold !important;
  594. \t\t\t\tanimation: pulse 2s infinite;
  595. \t\t\t\tz-index: 10;
  596. \t\t\t\tline-height: 1 !important;
  597. \t\t\t}
  598. \t\t\t/* Correction de l'alignement des boutons actifs dans prd-bottom */
  599. \t\t\t/* Ne s'applique qu'aux boutons actifs pour éviter de casser le comportement hover */
  600. \t\t\t.single-product .product-details .prd-bottom .social-info.active {
  601. \t\t\t\tvertical-align: middle !important;
  602. \t\t\t\tposition: relative !important;
  603. \t\t\t\ttop: 0 !important;
  604. \t\t\t\ttransform: none !important;
  605. \t\t\t\tmargin: 0 !important;
  606. \t\t\t\tpadding: 0 !important;
  607. \t\t\t\tline-height: normal !important;
  608. \t\t\t\twidth: 35px !important;
  609. \t\t\t\theight: auto !important;
  610. \t\t\t\tmin-height: auto !important;
  611. \t\t\t\tmax-height: none !important;
  612. \t\t\t}
  613. \t\t\t.single-product .product-details .prd-bottom .social-info.wishlist-btn.active,
  614. \t\t\t.single-product .product-details .prd-bottom .social-info.comparison-btn.active {
  615. \t\t\t\tvertical-align: middle !important;
  616. \t\t\t\tposition: relative !important;
  617. \t\t\t\ttop: 0 !important;
  618. \t\t\t\ttransform: none !important;
  619. \t\t\t\tmargin: 0 !important;
  620. \t\t\t\tpadding: 0 !important;
  621. \t\t\t\tline-height: normal !important;
  622. \t\t\t\twidth: 35px !important;
  623. \t\t\t\theight: auto !important;
  624. \t\t\t\tmin-height: auto !important;
  625. \t\t\t\tmax-height: none !important;
  626. \t\t\t}
  627. \t\t\t.single-product .product-details .prd-bottom .social-info.active .hover-text {
  628. \t\t\t\tmargin: 0 !important;
  629. \t\t\t\tpadding: 0 !important;
  630. \t\t\t\tline-height: normal !important;
  631. \t\t\t\tposition: absolute !important;
  632. \t\t\t\ttop: 0 !important;
  633. \t\t\t\tbackground: #ffa200 !important;
  634. \t\t\t\tleft: -40px !important;
  635. \t\t\t}
  636. \t\t\t/* S'assurer qu'aucune marge supplémentaire n'est ajoutée quand un bouton est actif */
  637. \t\t\t.single-product .product-details .prd-bottom .social-info.active span,
  638. \t\t\t.single-product .product-details .prd-bottom .social-info.active p {
  639. \t\t\t\tmargin: 0 !important;
  640. \t\t\t\tpadding: 0 !important;
  641. \t\t\t}
  642. \t\t\t/* Empêcher le hover de changer la largeur quand le bouton est actif */
  643. \t\t\t.single-product .product-details .prd-bottom .social-info.active:hover {
  644. \t\t\t\twidth: 35px !important;
  645. \t\t\t}
  646. \t\t\t.comparison-icon:hover .comparison-badge {
  647. \t\t\t\tanimation: none;
  648. \t\t\t}
  649. \t\t\t/* Styles pour les mega-menus - style comme la barre de recherche */
  650. \t\t\t.mega-menu {
  651. \t\t\t\twidth: 100%;
  652. \t\t\t\tmax-width: 1200px;
  653. \t\t\t\tleft: 50%;
  654. \t\t\t\ttransform: translateX(-50%);
  655. \t\t\t\tpadding: 25px;
  656. \t\t\t\tborder-radius: 12px;
  657. \t\t\t\tbox-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
  658. \t\t\t\tborder: none;
  659. \t\t\t\tbackground: white;
  660. \t\t\t\tdisplay: none;
  661. \t\t\t\tposition: absolute;
  662. \t\t\t\ttop: 100%;
  663. \t\t\t\tz-index: 9999 !important;
  664. \t\t\t\tmargin-top: 10px;
  665. \t\t\t\topacity: 0;
  666. \t\t\t\tvisibility: hidden;
  667. \t\t\t\ttransition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
  668. \t\t\t}
  669. \t\t\t.mega-menu.active {
  670. \t\t\t\tdisplay: block;
  671. \t\t\t\topacity: 1;
  672. \t\t\t\tvisibility: visible;
  673. \t\t\t\ttransform: translateX(-50%) translateY(0);
  674. \t\t\t}
  675. \t\t\t.nav-item.dropdown {
  676. \t\t\t\tposition: relative !important;
  677. \t\t\t}
  678. \t\t\t@media(min-width: 768px) {
  679. \t\t\t\t.nav-item.dropdown {
  680. \t\t\t\t\tposition: relative !important;
  681. \t\t\t\t}
  682. \t\t\t\t.mega-menu {
  683. \t\t\t\t\tposition: absolute !important;
  684. \t\t\t\t\tleft: 50% !important;
  685. \t\t\t\t\ttransform: translateX(-50%) !important;
  686. \t\t\t\t\twidth: auto !important;
  687. \t\t\t\t\tmin-width: 600px !important;
  688. \t\t\t\t}
  689. \t\t\t}
  690. \t\t\t/* Correction supplémentaire pour l'affichage sur la page d'accueil */
  691. \t\t\tbody.home .nav-item.dropdown,
  692. \t\t\t.nav-item.dropdown {
  693. \t\t\t\tposition: relative !important;
  694. \t\t\t}
  695. \t\t\tbody.home .mega-menu,
  696. \t\t\t.mega-menu {
  697. \t\t\t\tposition: absolute !important;
  698. \t\t\t\tleft: 50% !important;
  699. \t\t\t\ttransform: translateX(-50%) translateY(0) !important;
  700. \t\t\t\twidth: auto !important;
  701. \t\t\t\tmin-width: 600px !important;
  702. \t\t\t\tmax-width: 90% !important;
  703. \t\t\t\ttop: 100% !important;
  704. \t\t\t\tmargin-top: 10px !important;
  705. \t\t\t}
  706. \t\t\t/* Assurer que les mega-menus sont toujours visibles au survol */
  707. \t\t\t.nav-item.dropdown:hover .mega-menu {
  708. \t\t\t\topacity: 1 !important;
  709. \t\t\t\tvisibility: visible !important;
  710. \t\t\t\tdisplay: block !important;
  711. \t\t\t\ttransform: translateX(-50%) translateY(0) !important;
  712. \t\t\t}
  713. \t\t\t.mega-menu .dropdown-item {
  714. \t\t\t\tpadding: 0;
  715. \t\t\t\tborder: none;
  716. \t\t\t}
  717. \t\t\t.mega-menu .dropdown-header {
  718. \t\t\t\tfont-weight: 700;
  719. \t\t\t\tcolor: #2c3e50;
  720. \t\t\t\tmargin-bottom: 18px;
  721. \t\t\t\tpadding-bottom: 10px;
  722. \t\t\t\tborder-bottom: 3px solid #3498db;
  723. \t\t\t\tfont-size: 16px;
  724. \t\t\t\ttext-transform: uppercase;
  725. \t\t\t\tletter-spacing: 0.5px;
  726. \t\t\t}
  727. \t\t\t.mega-menu .dropdown-item a {
  728. \t\t\t\tdisplay: block;
  729. \t\t\t\tpadding: 10px 15px;
  730. \t\t\t\tcolor: #555;
  731. \t\t\t\ttext-decoration: none;
  732. \t\t\t\tborder-radius: 6px;
  733. \t\t\t\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  734. \t\t\t\tposition: relative;
  735. \t\t\t\toverflow: hidden;
  736. \t\t\t}
  737. \t\t\t.mega-menu .dropdown-item a::before {
  738. \t\t\t\tcontent: '';
  739. \t\t\t\tposition: absolute;
  740. \t\t\t\ttop: 0;
  741. \t\t\t\tleft: -100%;
  742. \t\t\t\twidth: 100%;
  743. \t\t\t\theight: 100%;
  744. \t\t\t\tbackground: linear-gradient(90deg, transparent, rgba(52, 152, 219, 0.1), transparent);
  745. \t\t\t\ttransition: left 0.5s;
  746. \t\t\t}
  747. \t\t\t.mega-menu .dropdown-item a:hover::before {
  748. \t\t\t\tleft: 100%;
  749. \t\t\t}
  750. \t\t\t.mega-menu .dropdown-item a:hover {
  751. \t\t\t\tbackground: linear-gradient(135deg, #f8f9fa, #e3f2fd);
  752. \t\t\t\tcolor: #2980b9;
  753. \t\t\t\ttransform: translateX(8px);
  754. \t\t\t\tbox-shadow: 0 2px 8px rgba(52, 152, 219, 0.2);
  755. \t\t\t}
  756. \t\t\t.mega-menu .dropdown-item a i {
  757. \t\t\t\twidth: 22px;
  758. \t\t\t\ttext-align: center;
  759. \t\t\t\tmargin-right: 8px;
  760. \t\t\t\tcolor: #3498db;
  761. \t\t\t\ttransition: color 0.3s ease;
  762. \t\t\t}
  763. \t\t\t.mega-menu .dropdown-item a:hover i {
  764. \t\t\t\tcolor: #2980b9;
  765. \t\t\t}
  766. \t\t\t/* Animation d'apparition améliorée */
  767. \t\t\t@keyframes slideInDown {
  768. \t\t\t\tfrom {
  769. \t\t\t\t\topacity: 0;
  770. \t\t\t\t\ttransform: translateY(-20px);
  771. \t\t\t\t}
  772. \t\t\t\tto {
  773. \t\t\t\t\topacity: 1;
  774. \t\t\t\t\ttransform: translateY(0);
  775. \t\t\t\t}
  776. \t\t\t}
  777. \t\t\t.mega-menu {
  778. \t\t\t\tanimation: slideInDown 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  779. \t\t\t}
  780. \t\t\t/* Effet de survol sur le lien principal */
  781. \t\t\t.nav-item.dropdown .nav-link {
  782. \t\t\t\tposition: relative;
  783. \t\t\t\ttransition: all 0.3s ease;
  784. \t\t\t}
  785. \t\t\t.nav-item.dropdown .nav-link::after {
  786. \t\t\t\tcontent: '';
  787. \t\t\t\tposition: absolute;
  788. \t\t\t\tbottom: -2px;
  789. \t\t\t\tleft: 50%;
  790. \t\t\t\twidth: 0;
  791. \t\t\t\theight: 2px;
  792. \t\t\t\tbackground: linear-gradient(90deg, #3498db, #2980b9);
  793. \t\t\t\ttransition: all 0.3s ease;
  794. \t\t\t\ttransform: translateX(-50%);
  795. \t\t\t}
  796. \t\t\t.nav-item.dropdown:hover .nav-link::after {
  797. \t\t\t\twidth: 100%;
  798. \t\t\t}
  799. \t\t\t.nav-item.dropdown:hover .nav-link {
  800. \t\t\t\tcolor: #2980b9;
  801. \t\t\t}
  802. \t\t\t@keyframes fadeInDown {
  803. \t\t\t\tfrom {
  804. \t\t\t\t\topacity: 0;
  805. \t\t\t\t\ttransform: translateY(-10px);
  806. \t\t\t\t}
  807. \t\t\t\tto {
  808. \t\t\t\t\topacity: 1;
  809. \t\t\t\t\ttransform: translateY(0);
  810. \t\t\t\t}
  811. \t\t\t}
  812. \t\t\t/* Responsive */
  813. \t\t\t@media(max-width: 768px) {
  814. \t\t\t\t.mega-menu {
  815. \t\t\t\t\twidth: 100%;
  816. \t\t\t\t\tleft: 0;
  817. \t\t\t\t\tpadding: 15px;
  818. \t\t\t\t}
  819. \t\t\t\t.mega-menu .row {
  820. \t\t\t\t\tmargin: 0;
  821. \t\t\t\t}
  822. \t\t\t\t.mega-menu .col-md-3 {
  823. \t\t\t\t\tmargin-bottom: 20px;
  824. \t\t\t\t}
  825. \t\t\t}
  826. \t\t\t/* ============================================
  827. \t\t\t.footer-area {
  828. \t\t\t\tbackground: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
  829. \t\t\t\tposition: relative;
  830. \t\t\t\toverflow: hidden;
  831. \t\t\t\tpadding: 50px 0 20px;
  832. \t\t\t}
  833. \t\t\t.footer-pattern {
  834. \t\t\t\tposition: absolute;
  835. \t\t\t\ttop: 0;
  836. \t\t\t\tleft: 0;
  837. \t\t\t\tright: 0;
  838. \t\t\t\tbottom: 0;
  839. \t\t\t\tbackground-image: radial-gradient(circle at 20% 50%, rgba(255, 162, 0, 0.1) 0%, transparent 50%), radial-gradient(circle at 80% 80%, rgba(255, 162, 0, 0.08) 0%, transparent 50%);
  840. \t\t\t\tpointer-events: none;
  841. \t\t\t}
  842. \t\t\t.footer-area .container {
  843. \t\t\t\tposition: relative;
  844. \t\t\t\tz-index: 1;
  845. \t\t\t}
  846. \t\t\t/* Widgets */
  847. \t\t\t.single-footer-widget {
  848. \t\t\t\tcolor: rgba(255, 255, 255, 0.9);
  849. \t\t\t}
  850. \t\t\t.footer-brand {
  851. \t\t\t\tfont-size: 1.6rem;
  852. \t\t\t\tfont-weight: 700;
  853. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  854. \t\t\t\t-webkit-background-clip: text;
  855. \t\t\t\t-webkit-text-fill-color: transparent;
  856. \t\t\t\tbackground-clip: text;
  857. \t\t\t\tmargin-bottom: 12px;
  858. \t\t\t\tdisplay: inline-block;
  859. \t\t\t}
  860. \t\t\t.footer-widget-title {
  861. \t\t\t\tcolor: #fff;
  862. \t\t\t\tfont-size: 1rem;
  863. \t\t\t\tfont-weight: 600;
  864. \t\t\t\tmargin-bottom: 18px;
  865. \t\t\t\tposition: relative;
  866. \t\t\t\tpadding-bottom: 8px;
  867. \t\t\t}
  868. \t\t\t.footer-widget-title::after {
  869. \t\t\t\tcontent: '';
  870. \t\t\t\tposition: absolute;
  871. \t\t\t\tbottom: 0;
  872. \t\t\t\tleft: 0;
  873. \t\t\t\twidth: 40px;
  874. \t\t\t\theight: 3px;
  875. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  876. \t\t\t\tborder-radius: 2px;
  877. \t\t\t}
  878. \t\t\t.footer-description {
  879. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  880. \t\t\t\tline-height: 1.6;
  881. \t\t\t\tfont-size: 0.9rem;
  882. \t\t\t\tmargin-bottom: 0;
  883. \t\t\t}
  884. \t\t\t/* Liste de liens */
  885. \t\t\t.footer-list {
  886. \t\t\t\tlist-style: none;
  887. \t\t\t\tpadding: 0;
  888. \t\t\t\tmargin: 0;
  889. \t\t\t}
  890. \t\t\t.footer-list li {
  891. \t\t\t\tmargin-bottom: 10px;
  892. \t\t\t}
  893. \t\t\t.footer-list li a {
  894. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  895. \t\t\t\ttext-decoration: none;
  896. \t\t\t\ttransition: all 0.3s ease;
  897. \t\t\t\tfont-size: 0.9rem;
  898. \t\t\t\tdisplay: inline-flex;
  899. \t\t\t\talign-items: center;
  900. \t\t\t}
  901. \t\t\t.footer-list li a i {
  902. \t\t\t\tfont-size: 0.8rem;
  903. \t\t\t\topacity: 0.6;
  904. \t\t\t\ttransition: all 0.3s ease;
  905. \t\t\t}
  906. \t\t\t.footer-list li a:hover {
  907. \t\t\t\tcolor: #ffa200;
  908. \t\t\t\ttransform: translateX(5px);
  909. \t\t\t}
  910. \t\t\t.footer-list li a:hover i {
  911. \t\t\t\topacity: 1;
  912. \t\t\t\tcolor: #ffa200;
  913. \t\t\t}
  914. \t\t\t/* Newsletter */
  915. \t\t\t.footer-newsletter-text {
  916. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  917. \t\t\t\tfont-size: 0.85rem;
  918. \t\t\t\tmargin-bottom: 15px;
  919. \t\t\t\tline-height: 1.5;
  920. \t\t\t}
  921. \t\t\t.footer-newsletter-wrapper {
  922. \t\t\t\tmargin-bottom: 15px;
  923. \t\t\t}
  924. \t\t\t.newsletter-input-group {
  925. \t\t\t\tdisplay: flex;
  926. \t\t\t\talign-items: center;
  927. \t\t\t\tbackground: rgba(255, 255, 255, 0.08);
  928. \t\t\t\tborder-radius: 30px;
  929. \t\t\t\tpadding: 4px 4px 4px 15px;
  930. \t\t\t\tbackdrop-filter: blur(10px);
  931. \t\t\t\tborder: 1px solid rgba(255, 255, 255, 0.15);
  932. \t\t\t\ttransition: all 0.3s ease;
  933. \t\t\t\tgap: 8px;
  934. \t\t\t}
  935. \t\t\t.newsletter-input-group:focus-within {
  936. \t\t\t\tbackground: rgba(255, 255, 255, 0.12);
  937. \t\t\t\tborder-color: rgba(255, 162, 0, 0.6);
  938. \t\t\t\tbox-shadow: 0 0 0 2px rgba(255, 162, 0, 0.15);
  939. \t\t\t}
  940. \t\t\t.newsletter-icon {
  941. \t\t\t\tcolor: rgba(255, 255, 255, 0.5);
  942. \t\t\t\tfont-size: 0.9rem;
  943. \t\t\t\tflex-shrink: 0;
  944. \t\t\t}
  945. \t\t\t.newsletter-input-group:focus-within .newsletter-icon {
  946. \t\t\t\tcolor: #ffa200;
  947. \t\t\t}
  948. \t\t\t.newsletter-input {
  949. \t\t\t\tflex: 1;
  950. \t\t\t\tbackground: transparent;
  951. \t\t\t\tborder: none;
  952. \t\t\t\tcolor: #fff;
  953. \t\t\t\tpadding: 10px 8px;
  954. \t\t\t\tfont-size: 0.9rem;
  955. \t\t\t\tmin-width: 0;
  956. \t\t\t}
  957. \t\t\t.newsletter-input::placeholder {
  958. \t\t\t\tcolor: rgba(255, 255, 255, 0.4);
  959. \t\t\t\tfont-size: 0.85rem;
  960. \t\t\t}
  961. \t\t\t.newsletter-input:focus {
  962. \t\t\t\toutline: none;
  963. \t\t\t\tbox-shadow: none;
  964. \t\t\t}
  965. \t\t\t.newsletter-btn {
  966. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  967. \t\t\t\tborder: none;
  968. \t\t\t\tcolor: white;
  969. \t\t\t\twidth: 42px;
  970. \t\t\t\theight: 42px;
  971. \t\t\t\tmin-width: 42px;
  972. \t\t\t\tmin-height: 42px;
  973. \t\t\t\tborder-radius: 50%;
  974. \t\t\t\tdisplay: flex;
  975. \t\t\t\talign-items: center;
  976. \t\t\t\tjustify-content: center;
  977. \t\t\t\tcursor: pointer;
  978. \t\t\t\ttransition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  979. \t\t\t\tflex-shrink: 0;
  980. \t\t\t\tbox-shadow: 0 4px 15px rgba(255, 162, 0, 0.4), 0 0 0 0 rgba(255, 162, 0, 0.4);
  981. \t\t\t\tfont-size: 0.9rem;
  982. \t\t\t\tposition: relative;
  983. \t\t\t\toverflow: hidden;
  984. \t\t\t}
  985. \t\t\t.newsletter-btn::before {
  986. \t\t\t\tcontent: '';
  987. \t\t\t\tposition: absolute;
  988. \t\t\t\ttop: 50%;
  989. \t\t\t\tleft: 50%;
  990. \t\t\t\twidth: 0;
  991. \t\t\t\theight: 0;
  992. \t\t\t\tborder-radius: 50%;
  993. \t\t\t\tbackground: rgba(255, 255, 255, 0.3);
  994. \t\t\t\ttransform: translate(-50%, -50%);
  995. \t\t\t\ttransition: width 0.6s ease, height 0.6s ease;
  996. \t\t\t}
  997. \t\t\t.newsletter-btn:hover::before {
  998. \t\t\t\twidth: 100%;
  999. \t\t\t\theight: 100%;
  1000. \t\t\t}
  1001. \t\t\t.newsletter-btn:hover {
  1002. \t\t\t\ttransform: translateX(3px) scale(1.05);
  1003. \t\t\t\tbox-shadow: 0 6px 20px rgba(255, 162, 0, 0.5), 0 0 0 8px rgba(255, 162, 0, 0.1);
  1004. \t\t\t\tbackground: linear-gradient(135deg, #e8910a 0%, #ffa200 100%);
  1005. \t\t\t}
  1006. \t\t\t.newsletter-btn:active {
  1007. \t\t\t\ttransform: translateX(3px) scale(0.98);
  1008. \t\t\t\tbox-shadow: 0 3px 10px rgba(255, 162, 0, 0.4);
  1009. \t\t\t}
  1010. \t\t\t.newsletter-btn:focus {
  1011. \t\t\t\toutline: none;
  1012. \t\t\t\tbox-shadow: 0 4px 15px rgba(255, 162, 0, 0.4), 0 0 0 3px rgba(255, 162, 0, 0.3);
  1013. \t\t\t}
  1014. \t\t\t.newsletter-btn-icon,
  1015. \t\t\t.newsletter-btn-loader {
  1016. \t\t\t\tposition: relative;
  1017. \t\t\t\tz-index: 2;
  1018. \t\t\t\tdisplay: flex;
  1019. \t\t\t\talign-items: center;
  1020. \t\t\t\tjustify-content: center;
  1021. \t\t\t\ttransition: all 0.3s ease;
  1022. \t\t\t}
  1023. \t\t\t.newsletter-btn:hover .newsletter-btn-icon {
  1024. \t\t\t\ttransform: translateX(2px) rotate(-10deg);
  1025. \t\t\t}
  1026. \t\t\t.newsletter-btn.loading .newsletter-btn-icon {
  1027. \t\t\t\topacity: 0;
  1028. \t\t\t\ttransform: scale(0);
  1029. \t\t\t}
  1030. \t\t\t.newsletter-btn.loading .newsletter-btn-loader {
  1031. \t\t\t\tdisplay: flex !important;
  1032. \t\t\t}
  1033. \t\t\t.newsletter-btn.success {
  1034. \t\t\t\tbackground: linear-gradient(135deg, #28a745 0%, #20c997 100%);
  1035. \t\t\t\tbox-shadow: 0 4px 15px rgba(40, 167, 69, 0.4);
  1036. \t\t\t}
  1037. \t\t\t.newsletter-btn.success .newsletter-btn-icon i::before {
  1038. \t\t\t\tcontent: \"\\f00c\";
  1039. \t\t\t}
  1040. \t\t\t/* Trust badges */
  1041. \t\t\t.footer-trust-badges {
  1042. \t\t\t\tdisplay: flex;
  1043. \t\t\t\tflex-direction: row;
  1044. \t\t\t\tgap: 15px;
  1045. \t\t\t\tflex-wrap: wrap;
  1046. \t\t\t}
  1047. \t\t\t.trust-item {
  1048. \t\t\t\tdisplay: flex;
  1049. \t\t\t\talign-items: center;
  1050. \t\t\t\tgap: 6px;
  1051. \t\t\t\tcolor: rgba(255, 255, 255, 0.6);
  1052. \t\t\t\tfont-size: 0.8rem;
  1053. \t\t\t}
  1054. \t\t\t.trust-item i {
  1055. \t\t\t\tcolor: #ffa200;
  1056. \t\t\t\tfont-size: 0.9rem;
  1057. \t\t\t}
  1058. \t\t\t/* Social icons */
  1059. \t\t\t.footer-social {
  1060. \t\t\t\tmargin-top: 0 !important;
  1061. \t\t\t\tposition: relative !important;
  1062. \t\t\t\twidth: 100% !important;
  1063. \t\t\t\tclear: both !important;
  1064. \t\t\t\tfloat: none !important;
  1065. \t\t\t}
  1066. \t\t\t.footer-social h6 {
  1067. \t\t\t\tcolor: #fff;
  1068. \t\t\t\tfont-size: 0.95rem;
  1069. \t\t\t\tfont-weight: 600;
  1070. \t\t\t\tmargin-bottom: 12px !important;
  1071. \t\t\t\tdisplay: block !important;
  1072. \t\t\t\twidth: 100% !important;
  1073. \t\t\t\tposition: relative !important;
  1074. \t\t\t\tclear: both !important;
  1075. \t\t\t\tfloat: none !important;
  1076. \t\t\t}
  1077. \t\t\t.footer-social-icons {
  1078. \t\t\t\tdisplay: flex !important;
  1079. \t\t\t\tgap: 12px !important;
  1080. \t\t\t\tflex-wrap: wrap !important;
  1081. \t\t\t\talign-items: center !important;
  1082. \t\t\t\tjustify-content: flex-start !important;
  1083. \t\t\t\twidth: 100% !important;
  1084. \t\t\t\tposition: relative !important;
  1085. \t\t\t\tclear: both !important;
  1086. \t\t\t\tfloat: none !important;
  1087. \t\t\t\tmargin: 0 !important;
  1088. \t\t\t\tpadding: 0 !important;
  1089. \t\t\t}
  1090. \t\t\t.social-icon {
  1091. \t\t\t\twidth: 38px !important;
  1092. \t\t\t\theight: 38px !important;
  1093. \t\t\t\tmin-width: 38px !important;
  1094. \t\t\t\tmin-height: 38px !important;
  1095. \t\t\t\tdisplay: inline-flex !important;
  1096. \t\t\t\talign-items: center !important;
  1097. \t\t\t\tjustify-content: center !important;
  1098. \t\t\t\tbackground: rgba(255, 255, 255, 0.1) !important;
  1099. \t\t\t\tborder-radius: 50% !important;
  1100. \t\t\t\tcolor: rgba(255, 255, 255, 0.8) !important;
  1101. \t\t\t\ttext-decoration: none !important;
  1102. \t\t\t\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
  1103. \t\t\t\tfont-size: 16px !important;
  1104. \t\t\t\tline-height: 1 !important;
  1105. \t\t\t\tbackdrop-filter: blur(10px) !important;
  1106. \t\t\t\tborder: 1px solid rgba(255, 255, 255, 0.1) !important;
  1107. \t\t\t\tflex-shrink: 0 !important;
  1108. \t\t\t\tposition: relative !important;
  1109. \t\t\t\tfloat: none !important;
  1110. \t\t\t\tmargin: 0 !important;
  1111. \t\t\t\tpadding: 0 !important;
  1112. \t\t\t\tvertical-align: middle !important;
  1113. \t\t\t}
  1114. \t\t\t.social-icon i {
  1115. \t\t\t\tfont-size: 16px !important;
  1116. \t\t\t\tline-height: 1 !important;
  1117. \t\t\t\tdisplay: inline-block !important;
  1118. \t\t\t\ttransition: transform 0.3s ease !important;
  1119. \t\t\t\tposition: relative !important;
  1120. \t\t\t\tz-index: 1 !important;
  1121. \t\t\t\tmargin: 0 !important;
  1122. \t\t\t\tpadding: 0 !important;
  1123. \t\t\t}
  1124. \t\t\t.social-icon:hover {
  1125. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%) !important;
  1126. \t\t\t\ttransform: translateY(-5px) scale(1.1) !important;
  1127. \t\t\t\tcolor: white !important;
  1128. \t\t\t\tborder-color: transparent !important;
  1129. \t\t\t\tbox-shadow: 0 8px 20px rgba(255, 162, 0, 0.4) !important;
  1130. \t\t\t}
  1131. \t\t\t.social-icon:hover i {
  1132. \t\t\t\ttransform: scale(1.1) !important;
  1133. \t\t\t}
  1134. \t\t\t/* Footer divider */
  1135. \t\t\t.footer-divider {
  1136. \t\t\t\theight: 1px;
  1137. \t\t\t\tbackground: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  1138. \t\t\t\tmargin: 30px 0 20px;
  1139. \t\t\t}
  1140. \t\t\t/* Footer bottom */
  1141. \t\t\t.footer-bottom {
  1142. \t\t\t\tpadding-top: 15px;
  1143. \t\t\t}
  1144. \t\t\t.footer-text {
  1145. \t\t\t\tcolor: rgba(255, 255, 255, 0.6);
  1146. \t\t\t\tfont-size: 0.9rem;
  1147. \t\t\t\tmargin: 0;
  1148. \t\t\t\ttext-align: center;
  1149. \t\t\t}
  1150. \t\t\t/* Responsive */
  1151. \t\t\t@media(max-width: 991.98px) {
  1152. \t\t\t\t.footer-area {
  1153. \t\t\t\t\tpadding: 40px 0 20px;
  1154. \t\t\t\t}
  1155. \t\t\t\t.single-footer-widget {
  1156. \t\t\t\t\tmargin-bottom: 30px;
  1157. \t\t\t\t}
  1158. \t\t\t\t.footer-social {
  1159. \t\t\t\t\tmargin-top: 15px;
  1160. \t\t\t\t}
  1161. \t\t\t}
  1162. \t\t\t@media(max-width: 767.98px) {
  1163. \t\t\t\t.footer-area {
  1164. \t\t\t\t\tpadding: 35px 0 18px;
  1165. \t\t\t\t}
  1166. \t\t\t\t.footer-brand {
  1167. \t\t\t\t\tfont-size: 1.4rem;
  1168. \t\t\t\t}
  1169. \t\t\t\t.footer-widget-title {
  1170. \t\t\t\t\tfont-size: 0.95rem;
  1171. \t\t\t\t}
  1172. \t\t\t\t.newsletter-input-group {
  1173. \t\t\t\t\tpadding: 3px 3px 3px 12px;
  1174. \t\t\t\t}
  1175. \t\t\t\t.newsletter-input {
  1176. \t\t\t\t\tpadding: 8px 6px;
  1177. \t\t\t\t\tfont-size: 0.85rem;
  1178. \t\t\t\t}
  1179. \t\t\t\t.newsletter-btn {
  1180. \t\t\t\t\twidth: 38px;
  1181. \t\t\t\t\theight: 38px;
  1182. \t\t\t\t\tmin-width: 38px;
  1183. \t\t\t\t\tmin-height: 38px;
  1184. \t\t\t\t\tfont-size: 0.85rem;
  1185. \t\t\t\t}
  1186. \t\t\t\t.footer-trust-badges {
  1187. \t\t\t\t\tflex-direction: row;
  1188. \t\t\t\t\tflex-wrap: wrap;
  1189. \t\t\t\t\tjustify-content: flex-start;
  1190. \t\t\t\t\tgap: 12px;
  1191. \t\t\t\t}
  1192. \t\t\t}
  1193. \t\t\t@media(max-width: 575.98px) {
  1194. \t\t\t\t.footer-area {
  1195. \t\t\t\t\tpadding: 40px 0 20px;
  1196. \t\t\t\t}
  1197. \t\t\t\t.footer-brand {
  1198. \t\t\t\t\tfont-size: 1.3rem;
  1199. \t\t\t\t}
  1200. \t\t\t\t.social-icon {
  1201. \t\t\t\t\twidth: 38px;
  1202. \t\t\t\t\theight: 38px;
  1203. \t\t\t\t\tfont-size: 16px;
  1204. \t\t\t\t}
  1205. \t\t\t\t.social-icon i {
  1206. \t\t\t\t\tfont-size: 16px;
  1207. \t\t\t\t}
  1208. \t\t\t}
  1209. \t\t</style>
  1210. \t\t";
  1211.         // line 1243
  1212.         yield from $this->unwrap()->yieldBlock('stylesheets'$context$blocks);
  1213.         // line 1246
  1214.         yield "
  1215. \t\t<!-- Script pour forcer l'application des styles CSS après chargement -->
  1216. \t\t<script>
  1217. \t\t\tdocument.addEventListener('DOMContentLoaded', function () { // Forcer le masquage du toggle sur grands écrans
  1218. if (window.innerWidth >= 992) {
  1219. const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
  1220. togglers.forEach(function (toggler) {
  1221. if (toggler) {
  1222. toggler.style.display = 'none';
  1223. toggler.style.visibility = 'hidden';
  1224. toggler.style.opacity = '0';
  1225. toggler.style.width = '0';
  1226. toggler.style.height = '0';
  1227. toggler.style.padding = '0';
  1228. toggler.style.margin = '0';
  1229. toggler.style.border = 'none';
  1230. toggler.style.position = 'absolute';
  1231. toggler.style.left = '-9999px';
  1232. }
  1233. });
  1234. const iconBars = document.querySelectorAll('.navbar-toggler .icon-bar, .header_area .navbar .navbar-toggler .icon-bar, .navbar-toggler-icon');
  1235. iconBars.forEach(function (bar) {
  1236. if (bar) {
  1237. bar.style.display = 'none';
  1238. bar.style.visibility = 'hidden';
  1239. }
  1240. });
  1241. }
  1242. // Alignement des icônes navbar sur mobile
  1243. const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
  1244. navbarRight.forEach(function (nav) {
  1245. if (nav && window.innerWidth<= 991.98) {
  1246.                     // Mobile: colonne avec icônes alignées horizontalement
  1247.                     nav.style.display = 'flex';
  1248.                     nav.style.flexDirection = 'column';
  1249.                     nav.style.alignItems = 'center';
  1250.                     nav.style.textAlign = 'center';
  1251.                     
  1252.                     // Le container d'icônes reste horizontal
  1253.                     const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
  1254.                     if (iconsContainer) {
  1255.                         iconsContainer.style.display = 'flex';
  1256.                         iconsContainer.style.flexDirection = 'row';
  1257.                         iconsContainer.style.justifyContent = 'center';
  1258.                     }
  1259.                     
  1260.                     // Le bouton compte en bas
  1261.                     const accountBtn = nav.querySelector('li:last-child');
  1262.                     if (accountBtn) {
  1263.                         accountBtn.style.width = '100%';
  1264.                         accountBtn.style.display = 'flex';
  1265.                         accountBtn.style.justifyContent = 'center';
  1266.                         accountBtn.style.marginTop = '12px';
  1267.                         accountBtn.style.paddingTop = '12px';
  1268.                         accountBtn.style.borderTop = '1px solid #e0e0e0';
  1269.                     }
  1270.                 } else if (nav && window.innerWidth> 991.98) { // Desktop: alignement horizontal normal
  1271. nav.style.display = 'flex';
  1272. nav.style.flexDirection = 'row';
  1273. nav.style.alignItems = 'center';
  1274. nav.style.justifyContent = 'flex-end';
  1275. }
  1276. });
  1277. });
  1278. // Réappliquer lors du redimensionnement
  1279. window.addEventListener('resize', function () {
  1280. if (window.innerWidth >= 992) {
  1281. const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
  1282. togglers.forEach(function (toggler) {
  1283. if (toggler) {
  1284. toggler.style.display = 'none';
  1285. toggler.style.visibility = 'hidden';
  1286. }
  1287. });
  1288. }
  1289. // Réappliquer l'alignement des icônes navbar
  1290. const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
  1291. navbarRight.forEach(function (nav) {
  1292. if (nav && window.innerWidth<= 991.98) {
  1293.                     // Mobile: colonne avec icônes alignées horizontalement
  1294.                     nav.style.display = 'flex';
  1295.                     nav.style.flexDirection = 'column';
  1296.                     nav.style.alignItems = 'center';
  1297.                     nav.style.textAlign = 'center';
  1298.                     
  1299.                     // Le container d'icônes reste horizontal
  1300.                     const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
  1301.                     if (iconsContainer) {
  1302.                         iconsContainer.style.display = 'flex';
  1303.                         iconsContainer.style.flexDirection = 'row';
  1304.                         iconsContainer.style.justifyContent = 'center';
  1305.                     }
  1306.                     
  1307.                     const accountBtn = nav.querySelector('li:last-child');
  1308.                     if (accountBtn) {
  1309.                         accountBtn.style.width = '100%';
  1310.                         accountBtn.style.display = 'flex';
  1311.                         accountBtn.style.justifyContent = 'center';
  1312.                         accountBtn.style.marginTop = '12px';
  1313.                         accountBtn.style.paddingTop = '12px';
  1314.                         accountBtn.style.borderTop = '1px solid #e0e0e0';
  1315.                     }
  1316.                 } else if (nav && window.innerWidth> 991.98) { // Desktop: alignement horizontal normal
  1317. nav.style.display = 'flex';
  1318. nav.style.flexDirection = 'row';
  1319. nav.style.alignItems = 'center';
  1320. nav.style.justifyContent = 'flex-end';
  1321. }
  1322. });
  1323. });
  1324. \t\t</script>
  1325. \t</head>
  1326. \t<body
  1327. \t\t";
  1328.         // line 1364
  1329.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == "listing"))) {
  1330.             yield " id=\"category\" ";
  1331.         }
  1332.         // line 1365
  1333.         yield "\t\tstyle=\"transition: background-color 0.3s ease, color 0.3s ease;\"
  1334. \t\tclass=\"theme-transition\">
  1335. \t\t<!-- Start Header Area -->
  1336. \t\t<header class=\"header_area sticky-header\">
  1337. \t\t\t<div class=\"main_menu\">
  1338. \t\t\t\t<nav class=\"navbar navbar-expand-lg navbar-light main_box\">
  1339. \t\t\t\t\t<div
  1340. \t\t\t\t\t\tclass=\"container\">
  1341. \t\t\t\t\t\t<!-- Brand and toggle get grouped for better mobile display -->
  1342. \t\t\t\t\t\t<a class=\"navbar-brand logo_h\" href=\"";
  1343.         // line 1375
  1344.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
  1345.         yield "\"><img style=\"width: auto;height: 60px\" src=\"";
  1346.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("logo.png"), "html"nulltrue);
  1347.         yield "\" alt=\"\"></a>
  1348. \t\t\t\t\t\t<button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarSupportedContent\" aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">
  1349. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  1350. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  1351. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  1352. \t\t\t\t\t\t</button>
  1353. \t\t\t\t\t\t<!-- Collect the nav links, forms, and other content for toggling -->
  1354. \t\t\t\t\t\t<div class=\"collapse navbar-collapse offset\" id=\"navbarSupportedContent\">
  1355. \t\t\t\t\t\t\t<ul class=\"nav navbar-nav menu_nav ml-auto\">
  1356. \t\t\t\t\t\t\t\t<li class=\"nav-item ";
  1357.         // line 1384
  1358.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " home"))) {
  1359.             yield "active";
  1360.         }
  1361.         yield "\">
  1362. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"";
  1363.         // line 1385
  1364.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
  1365.         yield "\">Accueil</a>
  1366. \t\t\t\t\t\t\t\t</li>
  1367. \t\t\t\t\t\t\t\t<li class=\"nav-item ";
  1368.         // line 1387
  1369.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " shops"))) {
  1370.             yield "active";
  1371.         }
  1372.         yield "\">
  1373. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"";
  1374.         // line 1388
  1375.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_shops_list");
  1376.         yield "\">Boutiques</a>
  1377. \t\t\t\t\t\t\t\t</li>
  1378. \t\t\t\t\t\t\t\t<li class=\"nav-item ";
  1379.         // line 1390
  1380.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " listing"))) {
  1381.             yield "active";
  1382.         }
  1383.         yield "\">
  1384. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"";
  1385.         // line 1391
  1386.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1387.         yield "\">Produits</a>
  1388. \t\t\t\t\t\t\t\t</li>
  1389. \t\t\t\t\t\t\t\t<li class=\"nav-item ";
  1390.         // line 1393
  1391.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " contact"))) {
  1392.             yield "active";
  1393.         }
  1394.         yield "\">
  1395. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"";
  1396.         // line 1394
  1397.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_contact");
  1398.         yield "\">Contact</a>
  1399. \t\t\t\t\t\t\t\t</li>
  1400. \t\t\t\t\t\t\t</ul>
  1401. \t\t\t\t\t\t\t<ul class=\"nav navbar-nav navbar-right\">
  1402. \t\t\t\t\t\t\t\t<li class=\"nav-item\">
  1403. \t\t\t\t\t\t\t\t\t<div class=\"navbar-icons-wrapper\">
  1404. \t\t\t\t\t\t\t\t\t\t<a href=\"";
  1405.         // line 1400
  1406.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_cart");
  1407.         yield "\" class=\"cart ";
  1408.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " cart"))) {
  1409.             yield "active";
  1410.         }
  1411.         yield "\" aria-label=\"Panier\">
  1412. \t\t\t\t\t\t\t\t\t\t\t<span class=\"ti-bag\"></span>
  1413. \t\t\t\t\t\t\t\t\t\t</a>
  1414. \t\t\t\t\t\t\t\t\t\t";
  1415.         // line 1403
  1416.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse1403)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  1417.             // line 1404
  1418.             yield "\t\t\t\t\t\t\t\t\t\t\t<a href=\"";
  1419.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("notifications_list");
  1420.             yield "\" class=\"notification-icon\" title=\"Notifications\" aria-label=\"Notifications\">
  1421. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"ti-bell\"></span>
  1422. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"notification-badge text-white\" id=\"notificationBadge\" style=\"display: none;color: white;\">0</span>
  1423. \t\t\t\t\t\t\t\t\t\t\t</a>
  1424. \t\t\t\t\t\t\t\t\t\t\t<a href=\"";
  1425.             // line 1408
  1426.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_product_comparison");
  1427.             yield "\" class=\"comparison-icon\" title=\"Comparaison\" aria-label=\"Comparaison\">
  1428. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"lnr lnr-sync\"></span>
  1429. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"comparison-badge text-white\" id=\"comparisonBadge\" style=\"display: none;color: white;\">0</span>
  1430. \t\t\t\t\t\t\t\t\t\t\t</a>
  1431. \t\t\t\t\t\t\t\t\t\t";
  1432.         }
  1433.         // line 1413
  1434.         yield "\t\t\t\t\t\t\t\t\t\t";
  1435.         yield Twig\Extension\CoreExtension::include($this->env$context"components/_dark_mode_toggle.html.twig");
  1436.         yield "
  1437. \t\t\t\t\t\t\t\t\t\t<button class=\"search\" type=\"button\" aria-label=\"Recherche\">
  1438. \t\t\t\t\t\t\t\t\t\t\t<span class=\"lnr lnr-magnifier\" id=\"search\"></span>
  1439. \t\t\t\t\t\t\t\t\t\t</button>
  1440. \t\t\t\t\t\t\t\t\t</div>
  1441. \t\t\t\t\t\t\t\t</li>
  1442. \t\t\t\t\t\t\t\t<li class=\"nav-item\">
  1443. \t\t\t\t\t\t\t\t\t";
  1444.         // line 1420
  1445.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse1420)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  1446.             // line 1421
  1447.             yield "\t\t\t\t\t\t\t\t\t\t<a class=\"nav-link btn btn-primary btn-account text-white\" href=\"";
  1448.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_account_index");
  1449.             yield "\">
  1450. \t\t\t\t\t\t\t\t\t\t\t<i class=\"ti-user\"></i>
  1451. \t\t\t\t\t\t\t\t\t\t\tMon compte
  1452. \t\t\t\t\t\t\t\t\t\t</a>
  1453. \t\t\t\t\t\t\t\t\t";
  1454.         } else {
  1455.             // line 1426
  1456.             yield "\t\t\t\t\t\t\t\t\t\t<a class=\"nav-link btn btn-primary btn-account text-white\" href=\"";
  1457.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
  1458.             yield "\">
  1459. \t\t\t\t\t\t\t\t\t\t\t<i class=\"ti-lock\"></i>
  1460. \t\t\t\t\t\t\t\t\t\t\tSe connecter
  1461. \t\t\t\t\t\t\t\t\t\t</a>
  1462. \t\t\t\t\t\t\t\t\t";
  1463.         }
  1464.         // line 1431
  1465.         yield "\t\t\t\t\t\t\t\t</li>
  1466. \t\t\t\t\t\t\t</ul>
  1467. \t\t\t\t\t\t</div>
  1468. \t\t\t\t\t</div>
  1469. \t\t\t\t</nav>
  1470. \t\t\t</div>
  1471. \t\t\t<div class=\"search_input\" id=\"search_input_box\">
  1472. \t\t\t\t<div class=\"container\">
  1473. \t\t\t\t\t<form class=\"d-flex justify-content-between\" id=\"search_form\" action=\"";
  1474.         // line 1439
  1475.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1476.         yield "\" method=\"get\">
  1477. \t\t\t\t\t\t<input type=\"text\" class=\"form-control\" id=\"search_input\" name=\"q\" placeholder=\"Rechercher un produit, une boutique, une catégorie...\" autocomplete=\"off\" value=\"";
  1478.         // line 1440
  1479.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->sourceCoreExtension::getAttribute($this->env$this->sourceCoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "request", [], "any"falsefalsefalse1440), "query", [], "any"falsefalsefalse1440), "get", ["q"""], "method"falsefalsefalse1440), "html"nulltrue);
  1480.         yield "\">
  1481. \t\t\t\t\t\t<button type=\"button\" class=\"btn\" id=\"search_submit_btn\">
  1482. \t\t\t\t\t\t\t<i class=\"lnr lnr-magnifier\"></i>
  1483. \t\t\t\t\t\t</button>
  1484. \t\t\t\t\t\t";
  1485.         // line 1444
  1486.         if ((($tmp CoreExtension::getAttribute($this->env$this->sourceCoreExtension::getAttribute($this->env$this->sourceCoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "request", [], "any"falsefalsefalse1444), "query", [], "any"falsefalsefalse1444), "get", ["q"], "method"falsefalsefalse1444)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  1487.             // line 1445
  1488.             yield "\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-clear-search\" id=\"clear_search_btn\" title=\"Effacer la recherche\">
  1489. \t\t\t\t\t\t\t\t<i class=\"lnr lnr-cross\"></i>
  1490. \t\t\t\t\t\t\t</button>
  1491. \t\t\t\t\t\t";
  1492.         }
  1493.         // line 1449
  1494.         yield "\t\t\t\t\t\t<span class=\"lnr lnr-cross\" id=\"close_search\" title=\"Fermer la recherche\"></span>
  1495. \t\t\t\t\t</form>
  1496. \t\t\t\t\t<div id=\"search_results\" class=\"search-results-container\"></div>
  1497. \t\t\t\t</div>
  1498. \t\t\t</div>
  1499. \t\t\t<script>
  1500. \t\t\t\twindow.searchSuggestUrl = \"";
  1501.         // line 1455
  1502.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_search_suggest");
  1503.         yield "\";
  1504. \t\t\t\twindow.listingUrl = \"";
  1505.         // line 1456
  1506.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1507.         yield "\";
  1508. \t\t\t</script>
  1509. \t\t</header>
  1510. \t\t<!-- End Header Area -->
  1511. \t\t<!-- Flash Messages -->
  1512. \t\t<div class=\"container mt-3\" id=\"flash-messages-container\" style=\"position: relative; z-index: 1050;\">
  1513. \t\t\t<div class=\"row\">
  1514. \t\t\t\t<div class=\"col-12\">
  1515. \t\t\t\t\t";
  1516.         // line 1465
  1517.         $context['_parent'] = $context;
  1518.         $context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "flashes", ["success"], "method"falsefalsefalse1465));
  1519.         foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
  1520.             // line 1466
  1521.             yield "\t\t\t\t\t\t<div class=\"alert alert-success alert-dismissible fade show flash-message\" role=\"alert\">
  1522. \t\t\t\t\t\t\t<i class=\"fa fa-check-circle\"></i>
  1523. \t\t\t\t\t\t\t<strong>";
  1524.             // line 1468
  1525.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html"nulltrue);
  1526.             yield "</strong>
  1527. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  1528. \t\t\t\t\t\t</div>
  1529. \t\t\t\t\t";
  1530.         }
  1531.         $_parent $context['_parent'];
  1532.         unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
  1533.         $context array_intersect_key($context$_parent) + $_parent;
  1534.         // line 1472
  1535.         yield "
  1536. \t\t\t\t\t";
  1537.         // line 1473
  1538.         $context['_parent'] = $context;
  1539.         $context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "flashes", ["error"], "method"falsefalsefalse1473));
  1540.         foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
  1541.             // line 1474
  1542.             yield "\t\t\t\t\t\t<div class=\"alert alert-danger alert-dismissible fade show flash-message\" role=\"alert\">
  1543. \t\t\t\t\t\t\t<i class=\"fa fa-exclamation-circle\"></i>
  1544. \t\t\t\t\t\t\t<strong>";
  1545.             // line 1476
  1546.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html"nulltrue);
  1547.             yield "</strong>
  1548. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  1549. \t\t\t\t\t\t</div>
  1550. \t\t\t\t\t";
  1551.         }
  1552.         $_parent $context['_parent'];
  1553.         unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
  1554.         $context array_intersect_key($context$_parent) + $_parent;
  1555.         // line 1480
  1556.         yield "
  1557. \t\t\t\t\t";
  1558.         // line 1481
  1559.         $context['_parent'] = $context;
  1560.         $context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "flashes", ["warning"], "method"falsefalsefalse1481));
  1561.         foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
  1562.             // line 1482
  1563.             yield "\t\t\t\t\t\t<div class=\"alert alert-warning alert-dismissible fade show flash-message\" role=\"alert\">
  1564. \t\t\t\t\t\t\t<i class=\"fa fa-exclamation-triangle\"></i>
  1565. \t\t\t\t\t\t\t<strong>";
  1566.             // line 1484
  1567.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html"nulltrue);
  1568.             yield "</strong>
  1569. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  1570. \t\t\t\t\t\t</div>
  1571. \t\t\t\t\t";
  1572.         }
  1573.         $_parent $context['_parent'];
  1574.         unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
  1575.         $context array_intersect_key($context$_parent) + $_parent;
  1576.         // line 1488
  1577.         yield "
  1578. \t\t\t\t\t";
  1579.         // line 1489
  1580.         $context['_parent'] = $context;
  1581.         $context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "flashes", ["info"], "method"falsefalsefalse1489));
  1582.         foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
  1583.             // line 1490
  1584.             yield "\t\t\t\t\t\t<div class=\"alert alert-info alert-dismissible fade show flash-message\" role=\"alert\">
  1585. \t\t\t\t\t\t\t<i class=\"fa fa-info-circle\"></i>
  1586. \t\t\t\t\t\t\t<strong>";
  1587.             // line 1492
  1588.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html"nulltrue);
  1589.             yield "</strong>
  1590. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  1591. \t\t\t\t\t\t</div>
  1592. \t\t\t\t\t";
  1593.         }
  1594.         $_parent $context['_parent'];
  1595.         unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
  1596.         $context array_intersect_key($context$_parent) + $_parent;
  1597.         // line 1496
  1598.         yield "\t\t\t\t</div>
  1599. \t\t\t</div>
  1600. \t\t</div>
  1601. \t\t";
  1602.         // line 1500
  1603.         yield from $this->unwrap()->yieldBlock('body'$context$blocks);
  1604.         // line 1501
  1605.         yield "
  1606. \t\t<!-- start footer Area -->
  1607. \t\t<footer class=\"footer-area section_gap\">
  1608. \t\t\t<div class=\"footer-pattern\"></div>
  1609. \t\t\t<div class=\"container\">
  1610. \t\t\t\t<div class=\"row\">
  1611. \t\t\t\t\t<div class=\"col-lg-3 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  1612. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1613. \t\t\t\t\t\t\t<div class=\"footer-logo mb-3\">
  1614. \t\t\t\t\t\t\t\t<h4 class=\"footer-brand\">MaketOu</h4>
  1615. \t\t\t\t\t\t\t</div>
  1616. \t\t\t\t\t\t\t<p class=\"footer-description\">
  1617. \t\t\t\t\t\t\t\tMaketOu est la première marketplace haïtienne qui connecte les acheteurs et les vendeurs. 
  1618. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t                        Nous offrons une plateforme sécurisée et moderne pour le commerce en ligne en Haïti.
  1619. \t\t\t\t\t\t\t</p>
  1620. \t\t\t\t\t\t\t<div class=\"footer-social mt-3\">
  1621. \t\t\t\t\t\t\t\t<h6 class=\"mb-2\">Suivez-nous</h6>
  1622. \t\t\t\t\t\t\t\t<div class=\"footer-social-icons\">
  1623. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Facebook\" title=\"Facebook\">
  1624. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-facebook\"></i>
  1625. \t\t\t\t\t\t\t\t\t</a>
  1626. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Twitter\" title=\"Twitter\">
  1627. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-twitter\"></i>
  1628. \t\t\t\t\t\t\t\t\t</a>
  1629. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Instagram\" title=\"Instagram\">
  1630. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-instagram\"></i>
  1631. \t\t\t\t\t\t\t\t\t</a>
  1632. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"LinkedIn\" title=\"LinkedIn\">
  1633. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linkedin\"></i>
  1634. \t\t\t\t\t\t\t\t\t</a>
  1635. \t\t\t\t\t\t\t\t</div>
  1636. \t\t\t\t\t\t\t</div>
  1637. \t\t\t\t\t\t</div>
  1638. \t\t\t\t\t</div>
  1639. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  1640. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1641. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Liens rapides</h6>
  1642. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  1643. \t\t\t\t\t\t\t\t<li>
  1644. \t\t\t\t\t\t\t\t\t<a href=\"";
  1645.         // line 1540
  1646.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
  1647.         yield "\">
  1648. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Accueil</a>
  1649. \t\t\t\t\t\t\t\t</li>
  1650. \t\t\t\t\t\t\t\t<li>
  1651. \t\t\t\t\t\t\t\t\t<a href=\"";
  1652.         // line 1544
  1653.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1654.         yield "\">
  1655. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Produits</a>
  1656. \t\t\t\t\t\t\t\t</li>
  1657. \t\t\t\t\t\t\t\t<li>
  1658. \t\t\t\t\t\t\t\t\t<a href=\"";
  1659.         // line 1548
  1660.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_shops_list");
  1661.         yield "\">
  1662. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Boutiques</a>
  1663. \t\t\t\t\t\t\t\t</li>
  1664. \t\t\t\t\t\t\t\t";
  1665.         // line 1551
  1666.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse1551)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  1667.             // line 1552
  1668.             yield "\t\t\t\t\t\t\t\t\t<li>
  1669. \t\t\t\t\t\t\t\t\t\t<a href=\"";
  1670.             // line 1553
  1671.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_account_index");
  1672.             yield "\">
  1673. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Mon compte</a>
  1674. \t\t\t\t\t\t\t\t\t</li>
  1675. \t\t\t\t\t\t\t\t";
  1676.         } else {
  1677.             // line 1557
  1678.             yield "\t\t\t\t\t\t\t\t\t<li>
  1679. \t\t\t\t\t\t\t\t\t\t<a href=\"";
  1680.             // line 1558
  1681.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
  1682.             yield "\">
  1683. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Se connecter</a>
  1684. \t\t\t\t\t\t\t\t\t</li>
  1685. \t\t\t\t\t\t\t\t\t<li>
  1686. \t\t\t\t\t\t\t\t\t\t<a href=\"";
  1687.             // line 1562
  1688.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_register");
  1689.             yield "\">
  1690. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;S'inscrire</a>
  1691. \t\t\t\t\t\t\t\t\t</li>
  1692. \t\t\t\t\t\t\t\t";
  1693.         }
  1694.         // line 1566
  1695.         yield "\t\t\t\t\t\t\t</ul>
  1696. \t\t\t\t\t\t</div>
  1697. \t\t\t\t\t</div>
  1698. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  1699. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1700. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Pour les vendeurs</h6>
  1701. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  1702. \t\t\t\t\t\t\t\t<li>
  1703. \t\t\t\t\t\t\t\t\t<a href=\"";
  1704.         // line 1574
  1705.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_index");
  1706.         yield "\">
  1707. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Ouvrir une boutique</a>
  1708. \t\t\t\t\t\t\t\t</li>
  1709. \t\t\t\t\t\t\t\t<li>
  1710. \t\t\t\t\t\t\t\t\t<a href=\"";
  1711.         // line 1578
  1712.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_how_to_sell");
  1713.         yield "\">
  1714. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Comment vendre</a>
  1715. \t\t\t\t\t\t\t\t</li>
  1716. \t\t\t\t\t\t\t\t<li>
  1717. \t\t\t\t\t\t\t\t\t<a href=\"";
  1718.         // line 1582
  1719.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_pricing");
  1720.         yield "\">
  1721. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Tarifs</a>
  1722. \t\t\t\t\t\t\t\t</li>
  1723. \t\t\t\t\t\t\t\t<li>
  1724. \t\t\t\t\t\t\t\t\t<a href=\"";
  1725.         // line 1586
  1726.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_support");
  1727.         yield "\">
  1728. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Support vendeur</a>
  1729. \t\t\t\t\t\t\t\t</li>
  1730. \t\t\t\t\t\t\t</ul>
  1731. \t\t\t\t\t\t</div>
  1732. \t\t\t\t\t</div>
  1733. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  1734. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1735. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Support</h6>
  1736. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  1737. \t\t\t\t\t\t\t\t<li>
  1738. \t\t\t\t\t\t\t\t\t<a href=\"";
  1739.         // line 1597
  1740.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_help");
  1741.         yield "\">
  1742. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Centre d'Aide</a>
  1743. \t\t\t\t\t\t\t\t</li>
  1744. \t\t\t\t\t\t\t\t<li>
  1745. \t\t\t\t\t\t\t\t\t<a href=\"";
  1746.         // line 1601
  1747.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_contact");
  1748.         yield "\">
  1749. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Contactez-nous</a>
  1750. \t\t\t\t\t\t\t\t</li>
  1751. \t\t\t\t\t\t\t\t<li>
  1752. \t\t\t\t\t\t\t\t\t<a href=\"";
  1753.         // line 1605
  1754.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_faq");
  1755.         yield "\">
  1756. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;FAQ</a>
  1757. \t\t\t\t\t\t\t\t</li>
  1758. \t\t\t\t\t\t\t\t<li>
  1759. \t\t\t\t\t\t\t\t\t<a href=\"";
  1760.         // line 1609
  1761.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_privacy");
  1762.         yield "\">
  1763. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Politique de Confidentialité</a>
  1764. \t\t\t\t\t\t\t\t</li>
  1765. \t\t\t\t\t\t\t\t<li>
  1766. \t\t\t\t\t\t\t\t\t<a href=\"";
  1767.         // line 1613
  1768.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_terms");
  1769.         yield "\">
  1770. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Conditions d'Utilisation</a>
  1771. \t\t\t\t\t\t\t\t</li>
  1772. \t\t\t\t\t\t\t</ul>
  1773. \t\t\t\t\t\t</div>
  1774. \t\t\t\t\t</div>
  1775. \t\t\t\t\t<div class=\"col-lg-3 col-md-6 col-sm-6\">
  1776. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1777. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Newsletter</h6>
  1778. \t\t\t\t\t\t\t<p class=\"footer-newsletter-text\">Restez informé des dernières nouveautés</p>
  1779. \t\t\t\t\t\t\t<div class=\"footer-newsletter-wrapper\" id=\"mc_embed_signup\">
  1780. \t\t\t\t\t\t\t\t<form action=\"";
  1781.         // line 1624
  1782.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_newsletter_subscribe");
  1783.         yield "\" method=\"post\" class=\"footer-newsletter-form\">
  1784. \t\t\t\t\t\t\t\t\t<div class=\"newsletter-input-group\">
  1785. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope newsletter-icon\"></i>
  1786. \t\t\t\t\t\t\t\t\t\t<input class=\"form-control newsletter-input\" name=\"email\" placeholder=\"Votre email\" required type=\"email\">
  1787. \t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"newsletter-btn\" aria-label=\"S'abonner\">
  1788. \t\t\t\t\t\t\t\t\t\t\t<span class=\"newsletter-btn-icon\">
  1789. \t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paper-plane\" aria-hidden=\"true\"></i>
  1790. \t\t\t\t\t\t\t\t\t\t\t</span>
  1791. \t\t\t\t\t\t\t\t\t\t\t<span class=\"newsletter-btn-loader\" style=\"display: none;\">
  1792. \t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spinner fa-spin\" aria-hidden=\"true\"></i>
  1793. \t\t\t\t\t\t\t\t\t\t\t</span>
  1794. \t\t\t\t\t\t\t\t\t\t</button>
  1795. \t\t\t\t\t\t\t\t\t</div>
  1796. \t\t\t\t\t\t\t\t</form>
  1797. \t\t\t\t\t\t\t</div>
  1798. \t\t\t\t\t\t\t<div class=\"footer-trust-badges mt-3\">
  1799. \t\t\t\t\t\t\t\t<div class=\"trust-item\">
  1800. \t\t\t\t\t\t\t\t\t<i class=\"fa fa-shield\"></i>
  1801. \t\t\t\t\t\t\t\t\t<span>Paiement sécurisé</span>
  1802. \t\t\t\t\t\t\t\t</div>
  1803. \t\t\t\t\t\t\t\t<div class=\"trust-item\">
  1804. \t\t\t\t\t\t\t\t\t<i class=\"fa fa-truck\"></i>
  1805. \t\t\t\t\t\t\t\t\t<span>Livraison rapide</span>
  1806. \t\t\t\t\t\t\t\t</div>
  1807. \t\t\t\t\t\t\t</div>
  1808. \t\t\t\t\t\t</div>
  1809. \t\t\t\t\t</div>
  1810. \t\t\t\t</div>
  1811. \t\t\t\t<div class=\"footer-divider\"></div>
  1812. \t\t\t\t<div class=\"footer-bottom d-flex justify-content-center align-items-center flex-wrap\">
  1813. \t\t\t\t\t<p class=\"footer-text m-0\">
  1814. \t\t\t\t\t\tCopyright &copy;<script>
  1815. \t\t\t\t\t\t\tdocument.write(new Date().getFullYear());
  1816. \t\t\t\t\t\t</script>
  1817. \t\t\t\t\t\tTous droits réservés | Ce site a été fait avec
  1818. \t\t\t\t\t\t<i class=\"fa fa-heart-o\" aria-hidden=\"true\" style=\"color: #dc3545;\"></i>
  1819. \t\t\t\t\t\tpar
  1820. \t\t\t\t\t\t<a href=\"https://tech.foulgor.com\" target=\"_blank\" style=\"color: #ffa200;\">Foulgor Tech</a>
  1821. \t\t\t\t\t</p>
  1822. \t\t\t\t</div>
  1823. \t\t\t</div>
  1824. \t\t</footer>
  1825. \t\t<style>
  1826. \t\t\t.search-results-container {
  1827. \t\t\t\tposition: absolute;
  1828. \t\t\t\ttop: 100%;
  1829. \t\t\t\tleft: 15px;
  1830. \t\t\t\tright: 15px;
  1831. \t\t\t\tbackground: #fff;
  1832. \t\t\t\tborder: 1px solid #ddd;
  1833. \t\t\t\tborder-top: none;
  1834. \t\t\t\tz-index: 9999;
  1835. \t\t\t\tbox-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  1836. \t\t\t\tmax-height: 400px;
  1837. \t\t\t\toverflow-y: auto;
  1838. \t\t\t\tdisplay: none;
  1839. \t\t\t\tborder-radius: 0 0 4px 4px;
  1840. \t\t\t}
  1841. \t\t\t.search-results-container .list-group-item {
  1842. \t\t\t\tborder-left: none;
  1843. \t\t\t\tborder-right: none;
  1844. \t\t\t\tborder-radius: 0;
  1845. \t\t\t\tcursor: pointer;
  1846. \t\t\t\tpadding: 12px 15px;
  1847. \t\t\t\ttransition: background-color 0.2s ease;
  1848. \t\t\t}
  1849. \t\t\t.search-results-container .list-group-item:hover {
  1850. \t\t\t\tbackground-color: #f8f9fa;
  1851. \t\t\t}
  1852. \t\t\t.search-results-container .list-group-item i {
  1853. \t\t\t\tcolor: #777;
  1854. \t\t\t\tfont-size: 1.2rem;
  1855. \t\t\t}
  1856. \t\t\t/* Ensure container is relative for absolute positioning of results */
  1857. \t\t\t#search_input_box .container {
  1858. \t\t\t\tposition: relative;
  1859. \t\t\t}
  1860. \t\t\t#search_input_box .form-control {
  1861. \t\t\t\tflex: 1;
  1862. \t\t\t\tpadding-right: 10px;
  1863. \t\t\t}
  1864. \t\t\t#search_input_box #search_submit_btn {
  1865. \t\t\t\tbackground: transparent;
  1866. \t\t\t\tborder: 0;
  1867. \t\t\t\tcolor: #fff;
  1868. \t\t\t\tpadding: 0 15px;
  1869. \t\t\t\tcursor: pointer;
  1870. \t\t\t\ttransition: opacity 0.3s ease;
  1871. \t\t\t}
  1872. \t\t\t#search_input_box #search_submit_btn:hover {
  1873. \t\t\t\topacity: 0.8;
  1874. \t\t\t}
  1875. \t\t\t#search_input_box .btn-clear-search {
  1876. \t\t\t\tbackground: transparent;
  1877. \t\t\t\tborder: 0;
  1878. \t\t\t\tcolor: #fff;
  1879. \t\t\t\tpadding: 0 10px;
  1880. \t\t\t\tcursor: pointer;
  1881. \t\t\t\ttransition: opacity 0.3s ease;
  1882. \t\t\t\tdisplay: none;
  1883. \t\t\t}
  1884. \t\t\t#search_input_box .btn-clear-search:hover {
  1885. \t\t\t\topacity: 0.8;
  1886. \t\t\t}
  1887. \t\t\t#search_input_box .btn-clear-search i {
  1888. \t\t\t\tfont-size: 1.1rem;
  1889. \t\t\t}
  1890. \t\t\t#search_input_box form {
  1891. \t\t\t\tposition: relative;
  1892. \t\t\t\talign-items: center;
  1893. \t\t\t}
  1894. \t\t</style>
  1895. \t\t<script>
  1896. \t\t\t// Debounced autocomplete for header search
  1897. (function () {
  1898. const input = document.getElementById('search_input');
  1899. const box = document.getElementById('search_results');
  1900. const searchForm = document.getElementById('search_form');
  1901. const clearSearchBtn = document.getElementById('clear_search_btn');
  1902. const closeSearchBtn = document.getElementById('close_search');
  1903. if (! input || ! box) 
  1904. return;
  1905. // Fonction pour effacer la recherche
  1906. function clearSearch() {
  1907. input.value = '';
  1908. box.style.display = 'none';
  1909. box.innerHTML = '';
  1910. if (clearSearchBtn) {
  1911. clearSearchBtn.style.display = 'none';
  1912. }
  1913. // Si on est sur la page listing, utiliser AJAX pour mettre à jour
  1914. if (typeof currentFilters !== 'undefined') {
  1915. currentFilters.q = '';
  1916. currentFilters.page = 1;
  1917. if (typeof applyFilters === 'function') {
  1918. applyFilters();
  1919. }
  1920. if (typeof updateActiveFilters === 'function') {
  1921. updateActiveFilters();
  1922. }
  1923. } else { // Sinon, rediriger vers la page listing sans recherche
  1924. window.location.href = '";
  1925.         // line 1769
  1926.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1927.         yield "';
  1928. }
  1929. }
  1930. // Bouton pour effacer la recherche
  1931. if (clearSearchBtn) {
  1932. clearSearchBtn.addEventListener('click', function (e) {
  1933. e.preventDefault();
  1934. e.stopPropagation();
  1935. clearSearch();
  1936. });
  1937. }
  1938. // Bouton de soumission de recherche
  1939. var searchSubmitBtn = document.getElementById('search_submit_btn');
  1940. if (searchSubmitBtn) {
  1941. searchSubmitBtn.addEventListener('click', function (e) {
  1942. e.preventDefault();
  1943. e.stopPropagation();
  1944. const q = input.value.trim();
  1945. if (q.length === 0) {
  1946. clearSearch();
  1947. return false;
  1948. }
  1949. // Si on est sur la page listing, utiliser AJAX
  1950. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  1951. currentFilters.q = q;
  1952. currentFilters.page = 1;
  1953. applyFilters();
  1954. if (typeof updateActiveFilters === 'function') {
  1955. updateActiveFilters();
  1956. }
  1957. // Fermer la boîte de recherche
  1958. if (closeSearchBtn) {
  1959. closeSearchBtn.click();
  1960. }
  1961. } else { // Sinon, rediriger vers la page listing avec la recherche
  1962. const listingUrl = '";
  1963.         // line 1807
  1964.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1965.         yield "' + '?q=' + encodeURIComponent(q);
  1966. window.location.href = listingUrl;
  1967. }
  1968. return false;
  1969. });
  1970. }
  1971. // Gestion du formulaire de recherche
  1972. if (searchForm) {
  1973. searchForm.addEventListener('submit', function (e) {
  1974. e.preventDefault();
  1975. e.stopPropagation();
  1976. const q = input.value.trim();
  1977. if (q.length === 0) {
  1978. clearSearch();
  1979. return;
  1980. }
  1981. // Si on est sur la page listing, utiliser AJAX
  1982. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  1983. currentFilters.q = q;
  1984. currentFilters.page = 1;
  1985. applyFilters();
  1986. if (typeof updateActiveFilters === 'function') {
  1987. updateActiveFilters();
  1988. }
  1989. // Fermer la boîte de recherche
  1990. if (closeSearchBtn) {
  1991. closeSearchBtn.click();
  1992. }
  1993. } else { // Sinon, rediriger vers la page listing avec la recherche
  1994. const listingUrl = '";
  1995.         // line 1838
  1996.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1997.         yield "' + '?q=' + encodeURIComponent(q);
  1998. window.location.href = listingUrl;
  1999. }
  2000. return false;
  2001. });
  2002. }
  2003. let t = null;
  2004. input.addEventListener('input', function () {
  2005. const q = input.value.trim();
  2006. clearTimeout(t);
  2007. if (q.length === 0) {
  2008. box.style.display = 'none';
  2009. box.innerHTML = '';
  2010. // Afficher/masquer le bouton clear
  2011. if (clearSearchBtn) {
  2012. clearSearchBtn.style.display = 'none';
  2013. }
  2014. return;
  2015. }
  2016. // Afficher le bouton clear
  2017. if (clearSearchBtn) {
  2018. clearSearchBtn.style.display = 'block';
  2019. }
  2020. t = setTimeout(() => fetchSuggestions(q), 300);
  2021. });
  2022. function fetchSuggestions(q) {
  2023. const url = '";
  2024.         // line 1866
  2025.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_search_suggest");
  2026.         yield "' + '?q=' + encodeURIComponent(q);
  2027. fetch(url).then(r => r.json()).then(data => {
  2028. if (!data.success) {
  2029. box.style.display = 'none';
  2030. return;
  2031. }
  2032. renderSuggestions(data.results || []);
  2033. }).catch(() => {
  2034. box.style.display = 'none';
  2035. });
  2036. }
  2037. function renderSuggestions(items) {
  2038. if (! items.length) {
  2039. box.style.display = 'none';
  2040. box.innerHTML = '';
  2041. return;
  2042. }
  2043. box.innerHTML = items.map(it => suggestionItem(it)).join('');
  2044. box.style.display = 'block';
  2045. }
  2046. function suggestionItem(it) {
  2047. const icon = it.type === 'product' ? 'ti-package' : (it.type === 'shop' ? 'ti-briefcase' : (it.type === 'category' ? 'ti-layers' : 'ti-tag'));
  2048. const typeLabel = it.type === 'product' ? 'Produit' : (it.type === 'shop' ? 'Boutique' : (it.type === 'category' ? 'Catégorie' : 'Tag'));
  2049. return '<a href=\"' + it.url + '\" class=\"list-group-item list-group-item-action d-flex align-items-center\">' + '<i class=\"' + icon + ' me-3\"></i>' + '<span class=\"flex-grow-1\">' + escapeHtml(it.label) + '</span>' + '<span class=\"badge bg-light text-dark ms-2\">' + typeLabel + '</span>' + '</a>';
  2050. }
  2051. function escapeHtml(s) {
  2052. return s.replace(/[&<>\"]+/g, c => ({'&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;'}[c]));
  2053. }
  2054. document.addEventListener('click', function (e) {
  2055. if (! box.contains(e.target) && e.target !== input) {
  2056. box.style.display = 'none';
  2057. }
  2058. });
  2059. window.handleSearchSubmit = function (e) {
  2060. if (e) 
  2061. e.preventDefault();
  2062. const first = box.querySelector('a');
  2063. if (first) {
  2064. window.location.href = first.getAttribute('href');
  2065. return false;
  2066. }
  2067. // fallback to listing page search by name
  2068. const q = input.value.trim();
  2069. if (q.length) { // Si on est sur la page listing, utiliser AJAX
  2070. if (typeof currentFilters !== 'undefined') {
  2071. currentFilters.q = q;
  2072. currentFilters.page = 1;
  2073. if (typeof applyFilters === 'function') {
  2074. applyFilters();
  2075. }
  2076. if (typeof updateActiveFilters === 'function') {
  2077. updateActiveFilters();
  2078. }
  2079. } else {
  2080. window.location.href = '";
  2081.         // line 1927
  2082.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  2083.         yield "' + '?q=' + encodeURIComponent(q);
  2084. }
  2085. }
  2086. return false;
  2087. }
  2088. // Gestion de la touche Enter dans le champ de recherche
  2089. if (input) {
  2090. input.addEventListener('keydown', function (e) {
  2091. if (e.key === 'Enter' || e.keyCode === 13) {
  2092. e.preventDefault();
  2093. e.stopPropagation();
  2094. const q = input.value.trim();
  2095. if (q.length === 0) {
  2096. clearSearch();
  2097. return false;
  2098. }
  2099. // Si on est sur la page listing, utiliser AJAX
  2100. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  2101. currentFilters.q = q;
  2102. currentFilters.page = 1;
  2103. applyFilters();
  2104. if (typeof updateActiveFilters === 'function') {
  2105. updateActiveFilters();
  2106. }
  2107. // Fermer la boîte de recherche
  2108. if (closeSearchBtn) {
  2109. closeSearchBtn.click();
  2110. }
  2111. } else { // Sinon, rediriger vers la page listing avec la recherche
  2112. const listingUrl = '";
  2113.         // line 1958
  2114.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  2115.         yield "' + '?q=' + encodeURIComponent(q);
  2116. window.location.href = listingUrl;
  2117. }
  2118. return false;
  2119. }
  2120. });
  2121. }
  2122. // Ajouter un event listener au bouton de soumission (réutiliser la variable si elle existe déjà)
  2123. if (!searchSubmitBtn) {
  2124.     searchSubmitBtn = document.getElementById('search_submit_btn');
  2125. }
  2126. if (searchSubmitBtn) {
  2127. searchSubmitBtn.addEventListener('click', function (e) {
  2128. e.preventDefault();
  2129. e.stopPropagation();
  2130. const q = input.value.trim();
  2131. if (q.length === 0) {
  2132. clearSearch();
  2133. return false;
  2134. }
  2135. // Si on est sur la page listing, utiliser AJAX
  2136. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  2137. currentFilters.q = q;
  2138. currentFilters.page = 1;
  2139. applyFilters();
  2140. if (typeof updateActiveFilters === 'function') {
  2141. updateActiveFilters();
  2142. }
  2143. // Fermer la boîte de recherche
  2144. if (closeSearchBtn) {
  2145. closeSearchBtn.click();
  2146. }
  2147. } else { // Sinon, rediriger vers la page listing avec la recherche
  2148. const listingUrl = '";
  2149.         // line 1993
  2150.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  2151.         yield "' + '?q=' + encodeURIComponent(q);
  2152. window.location.href = listingUrl;
  2153. }
  2154. return false;
  2155. });
  2156. }
  2157. // Afficher le bouton clear au chargement si une recherche est active
  2158. document.addEventListener('DOMContentLoaded', function () {
  2159. const q = input.value.trim();
  2160. if (q.length > 0 && clearSearchBtn) {
  2161. clearSearchBtn.style.display = 'block';
  2162. }
  2163. });
  2164. })();
  2165. // Gestion des mega-menus avec clic (comme la barre de recherche)
  2166. document.addEventListener('DOMContentLoaded', function () {
  2167. const dropdownItems = document.querySelectorAll('.nav-item.dropdown');
  2168. dropdownItems.forEach(function (item) {
  2169. const dropdownToggle = item.querySelector('.dropdown-toggle');
  2170. const dropdownMenu = item.querySelector('.mega-menu');
  2171. if (! dropdownToggle || ! dropdownMenu) 
  2172. return;
  2173. // Fermer les autres menus quand on ouvre un nouveau
  2174. function closeAllMenus() {
  2175. dropdownItems.forEach(function (otherItem) {
  2176. const otherMenu = otherItem.querySelector('.mega-menu');
  2177. if (otherMenu && otherMenu !== dropdownMenu) {
  2178. \$(otherMenu).slideUp(300);
  2179. otherMenu.classList.remove('active');
  2180. }
  2181. });
  2182. }
  2183. // Toggle au clic (comme la barre de recherche)
  2184. dropdownToggle.addEventListener('click', function (e) {
  2185. e.preventDefault();
  2186. e.stopPropagation();
  2187. closeAllMenus();
  2188. if (dropdownMenu.classList.contains('active')) { // Fermer le menu
  2189. dropdownMenu.style.opacity = '0';
  2190. dropdownMenu.style.visibility = 'hidden';
  2191. dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
  2192. setTimeout(() => {
  2193. dropdownMenu.classList.remove('active');
  2194. dropdownMenu.style.display = 'none';
  2195. }, 300);
  2196. } else { // Ouvrir le menu
  2197. dropdownMenu.style.display = 'block';
  2198. setTimeout(() => {
  2199. dropdownMenu.classList.add('active');
  2200. dropdownMenu.style.opacity = '1';
  2201. dropdownMenu.style.visibility = 'visible';
  2202. dropdownMenu.style.transform = 'translateX(-50%) translateY(0)';
  2203. }, 10);
  2204. }
  2205. });
  2206. // Fermer au clic en dehors
  2207. document.addEventListener('click', function (e) {
  2208. if (! item.contains(e.target) && dropdownMenu.classList.contains('active')) {
  2209. dropdownMenu.style.opacity = '0';
  2210. dropdownMenu.style.visibility = 'hidden';
  2211. dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
  2212. setTimeout(() => {
  2213. dropdownMenu.classList.remove('active');
  2214. dropdownMenu.style.display = 'none';
  2215. }, 300);
  2216. }
  2217. });
  2218. // Animation des éléments du menu
  2219. const menuItems = dropdownMenu.querySelectorAll('.dropdown-item a');
  2220. menuItems.forEach(function (menuItem, index) {
  2221. menuItem.style.animationDelay = (index * 0.05) + 's';
  2222. });
  2223. });
  2224. // Gestion des clics sur mobile
  2225. if (window.innerWidth <= 768) {
  2226. dropdownItems.forEach(function (item) {
  2227. const dropdownToggle = item.querySelector('.dropdown-toggle');
  2228. const dropdownMenu = item.querySelector('.mega-menu');
  2229. dropdownToggle.addEventListener('click', function (e) {
  2230. e.preventDefault();
  2231. // Fermer tous les autres menus
  2232. dropdownItems.forEach(function (otherItem) {
  2233. if (otherItem !== item) {
  2234. const otherMenu = otherItem.querySelector('.mega-menu');
  2235. otherMenu.style.opacity = '0';
  2236. otherMenu.style.visibility = 'hidden';
  2237. otherMenu.style.transform = 'translateY(-10px)';
  2238. }
  2239. });
  2240. // Toggle le menu actuel
  2241. if (dropdownMenu.style.opacity === '1') {
  2242. dropdownMenu.style.opacity = '0';
  2243. dropdownMenu.style.visibility = 'hidden';
  2244. dropdownMenu.style.transform = 'translateY(-10px)';
  2245. } else {
  2246. dropdownMenu.style.opacity = '1';
  2247. dropdownMenu.style.visibility = 'visible';
  2248. dropdownMenu.style.transform = 'translateY(0)';
  2249. }
  2250. });
  2251. });
  2252. }
  2253. // Fermer les menus quand on clique ailleurs
  2254. document.addEventListener('click', function (e) {
  2255. if (! e.target.closest('.nav-item.dropdown')) {
  2256. dropdownItems.forEach(function (item) {
  2257. const dropdownMenu = item.querySelector('.mega-menu');
  2258. dropdownMenu.style.opacity = '0';
  2259. dropdownMenu.style.visibility = 'hidden';
  2260. dropdownMenu.style.transform = 'translateY(-10px)';
  2261. });
  2262. }
  2263. });
  2264. });
  2265. \t\t</script>
  2266. \t\t<!-- End footer Area -->
  2267. \t\t<script src=\"";
  2268.         // line 2127
  2269.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/vendor/jquery-2.2.4.min.js"), "html"nulltrue);
  2270.         yield "\"></script>
  2271. \t\t<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js\"></script>
  2272. \t\t<script>
  2273. \t\t\t// Initialiser le collapse Bootstrap 5 pour le menu hamburger après chargement de Bootstrap
  2274. document.addEventListener('DOMContentLoaded', function () { // Attendre que Bootstrap soit complètement chargé
  2275. if (typeof bootstrap !== 'undefined') {
  2276. const navbarToggler = document.querySelector('.navbar-toggler');
  2277. const navbarCollapse = document.getElementById('navbarSupportedContent');
  2278. if (navbarToggler && navbarCollapse) {
  2279. // Bootstrap 5 devrait gérer automatiquement avec data-bs-toggle
  2280. // Mais on s'assure que ça fonctionne en écoutant les événements
  2281. navbarCollapse.addEventListener('show.bs.collapse', function () {
  2282. navbarToggler.setAttribute('aria-expanded', 'true');
  2283. navbarToggler.classList.add('active');
  2284. });
  2285. navbarCollapse.addEventListener('hide.bs.collapse', function () {
  2286. navbarToggler.setAttribute('aria-expanded', 'false');
  2287. navbarToggler.classList.remove('active');
  2288. });
  2289. }
  2290. }
  2291. });
  2292. \t\t</script>
  2293. \t\t<script src=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.js\"></script>
  2294. \t\t<script src=\"";
  2295.         // line 2153
  2296.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.ajaxchimp.min.js"), "html"nulltrue);
  2297.         yield "\"></script>
  2298. \t\t<script src=\"";
  2299.         // line 2154
  2300.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.nice-select.min.js"), "html"nulltrue);
  2301.         yield "\"></script>
  2302. \t\t<script src=\"";
  2303.         // line 2155
  2304.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.sticky.js"), "html"nulltrue);
  2305.         yield "\"></script>
  2306. \t\t<script src=\"";
  2307.         // line 2156
  2308.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/nouislider.min.js"), "html"nulltrue);
  2309.         yield "\"></script>
  2310. \t\t<script src=\"";
  2311.         // line 2157
  2312.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/countdown.js"), "html"nulltrue);
  2313.         yield "\"></script>
  2314. \t\t<script src=\"";
  2315.         // line 2158
  2316.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.magnific-popup.min.js"), "html"nulltrue);
  2317.         yield "\"></script>
  2318. \t\t<script src=\"";
  2319.         // line 2159
  2320.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/owl.carousel.min.js"), "html"nulltrue);
  2321.         yield "\"></script>
  2322. \t\t<script src=\"https://maps.googleapis.com/maps/api/js?key=AIzaSyCjCGmQ0Uq4exrzdcL6rvxywDDOvfAu6eE\"></script>
  2323. \t\t<script src=\"";
  2324.         // line 2161
  2325.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/gmaps.min.js"), "html"nulltrue);
  2326.         yield "\"></script>
  2327. \t\t<script src=\"";
  2328.         // line 2162
  2329.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/main.js"), "html"nulltrue);
  2330.         yield "\"></script>
  2331. \t\t";
  2332.         // line 2164
  2333.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getFunction('encore_entry_script_tags')->getCallable()("app"), "html"nulltrue);
  2334.         yield "
  2335. \t\t<!-- PWA Service Worker Registration -->
  2336. \t\t<script>
  2337. \t\t\t// Enregistrement du Service Worker
  2338. if ('serviceWorker' in navigator) {
  2339. window.addEventListener('load', () => {
  2340. navigator.serviceWorker.register('";
  2341.         // line 2171
  2342.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("sw.js"), "html"nulltrue);
  2343.         yield "').then((registration) => {
  2344. console.log('Service Worker enregistré avec succès:', registration.scope);
  2345. // Vérifie les mises à jour du service worker
  2346. registration.addEventListener('updatefound', () => {
  2347. const newWorker = registration.installing;
  2348. newWorker.addEventListener('statechange', () => {
  2349. if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { // Nouveau service worker disponible
  2350. if (confirm('Une nouvelle version de MaketOu est disponible. Voulez-vous l\\'installer maintenant ?')) {
  2351. newWorker.postMessage({type: 'SKIP_WAITING'});
  2352. window.location.reload();
  2353. }
  2354. }
  2355. });
  2356. });
  2357. }).catch((error) => {
  2358. console.log('Échec de l\\'enregistrement du Service Worker:', error);
  2359. });
  2360. // Écoute les messages du service worker
  2361. navigator.serviceWorker.addEventListener('message', (event) => {
  2362. console.log('Message du Service Worker:', event.data);
  2363. });
  2364. });
  2365. }
  2366. \t\t</script>
  2367. \t\t<!-- PWA Install Script -->
  2368. \t\t<script src=\"";
  2369.         // line 2199
  2370.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("js/pwa-install.js"), "html"nulltrue);
  2371.         yield "\"></script>
  2372. \t\t<script>
  2373. \t\t\t// Charger les compteurs au chargement de la page
  2374. document.addEventListener('DOMContentLoaded', function () {
  2375. ";
  2376.         // line 2204
  2377.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2204)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2378.             // line 2205
  2379.             yield "loadNotificationCount();
  2380. // Délai pour s'assurer que la session est bien établie après connexion
  2381. setTimeout(function () {
  2382. loadComparisonCount();
  2383. }, 500);";
  2384.         }
  2385.         // line 2210
  2386.         yield "
  2387. // Gérer le bouton de recherche mobile
  2388. const searchMobileBtn = document.getElementById('searchMobileBtn');
  2389. if (searchMobileBtn) {
  2390. searchMobileBtn.addEventListener('click', function (e) {
  2391. e.preventDefault();
  2392. // Utiliser le même comportement que le bouton desktop
  2393. const searchBox = document.getElementById('search_input_box');
  2394. if (searchBox) {
  2395. searchBox.style.display = 'block';
  2396. const searchInput = document.getElementById('search_input');
  2397. if (searchInput) {
  2398. setTimeout(() => searchInput.focus(), 100);
  2399. }
  2400. }
  2401. });
  2402. }
  2403. });
  2404. function loadNotificationCount() {
  2405. ";
  2406.         // line 2230
  2407.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2230)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2408.             // line 2231
  2409.             yield "fetch('";
  2410.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("api_notifications_count");
  2411.             yield "').then(response => {
  2412. if (!response.ok) {
  2413. throw new Error('Erreur HTTP: ' + response.status);
  2414. }
  2415. return response.json();
  2416. }).then(data => {
  2417. const count = data.count || 0;
  2418. // Mettre à jour tous les badges de notification
  2419. const badges = [document.getElementById('notificationBadge'), document.getElementById('notificationBadgeMobile'), document.querySelector('.notification-badge')].filter(badge => badge !== null);
  2420. badges.forEach(badge => {
  2421. if (count > 0) {
  2422. badge.textContent = count;
  2423. badge.style.display = 'flex';
  2424. badge.style.color = 'white';
  2425. badge.style.backgroundColor = '#dc3545';
  2426. } else {
  2427. badge.style.display = 'none';
  2428. }
  2429. });
  2430. // Si on est sur la page des notifications, mettre à jour aussi le contenu de la page
  2431. if (typeof updateNotificationPageContent === 'function') {
  2432. updateNotificationPageContent(count);
  2433. }
  2434. }).catch(error => {
  2435. console.error('Erreur lors du chargement du compteur de notifications:', error);
  2436. });";
  2437.         }
  2438.         // line 2260
  2439.         yield "}
  2440. // Exposer la fonction globalement pour qu'elle puisse être appelée depuis d'autres pages
  2441. window.loadNotificationCount = loadNotificationCount;
  2442. // Recharger le compteur toutes les 30 secondes pour garder les données à jour
  2443. ";
  2444.         // line 2266
  2445.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2266)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2446.             // line 2267
  2447.             yield "setInterval(function () {
  2448. loadNotificationCount();
  2449. }, 30000);";
  2450.         }
  2451.         // line 2269
  2452.         yield "function loadComparisonCount() {
  2453. ";
  2454.         // line 2270
  2455.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2270)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2456.             // line 2271
  2457.             yield "// Ne pas appeler l'API si on est sur une page d'erreur ou de redirection
  2458. if (window.location.pathname.includes('/api/') || window.location.pathname.includes('/login')) {
  2459. return;
  2460. }
  2461. // Utiliser un try-catch pour éviter toute redirection
  2462. try {
  2463. fetch('";
  2464.             // line 2278
  2465.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_comparison_count");
  2466.             yield "', {
  2467. method: 'GET',
  2468. headers: {
  2469. 'X-Requested-With': 'XMLHttpRequest',
  2470. 'Accept': 'application/json'
  2471. },
  2472. credentials: 'same-origin',
  2473. redirect: 'error' // Empêcher les redirections automatiques
  2474. }).then(response => { // Vérifier si la réponse est OK
  2475. if (!response.ok) { // Si c'est une redirection (301, 302, etc.) ou une erreur d'authentification, ignorer silencieusement
  2476. if (response.status >= 300 && response.status < 400) {
  2477. console.warn('Redirection détectée, arrêt de la requête');
  2478. return null;
  2479. }
  2480. if (response.status === 401 || response.status === 403) {
  2481. console.warn('Utilisateur non authentifié pour la comparaison');
  2482. return null;
  2483. }
  2484. // Pour les autres erreurs, throw pour être capturé par catch
  2485. throw new Error('Erreur HTTP: ' + response.status);
  2486. }
  2487. // Vérifier que c'est bien du JSON
  2488. const contentType = response.headers.get('content-type');
  2489. if (! contentType || ! contentType.includes('application/json')) { // Si ce n'est pas du JSON, c'est probablement une redirection HTML
  2490. console.warn('La réponse n\\'est pas du JSON, probable redirection');
  2491. return null;
  2492. }
  2493. return response.json();
  2494. }).then(data => { // Si data est null (redirection ou erreur), ne rien faire
  2495. if (!data || typeof data.count === 'undefined') {
  2496. return;
  2497. }
  2498. // Mettre à jour les badges desktop et mobile
  2499. const badges = [document.getElementById('comparisonBadge'), document.getElementById('comparisonBadgeMobile')];
  2500. badges.forEach(badge => {
  2501. if (badge) {
  2502. if (data.count > 0) {
  2503. badge.textContent = data.count;
  2504. badge.style.display = 'flex';
  2505. } else {
  2506. badge.style.display = 'none';
  2507. }
  2508. }
  2509. });
  2510. }).catch(error => { // Ne pas afficher d'erreur si c'est juste une absence d'authentification ou une redirection
  2511. if (error.message && !error.message.includes('401') && !error.message.includes('403') && !error.message.includes('redirect')) {
  2512. console.error('Erreur lors du chargement du compteur de comparaison:', error);
  2513. }
  2514. // Empêcher toute redirection vers l'URL de l'API
  2515. return false;
  2516. });
  2517. } catch (e) { // Capturer toute erreur qui pourrait causer une redirection
  2518. console.warn('Erreur lors de l\\'appel à l\\'API de comparaison:', e);
  2519. }
  2520. ";
  2521.         }
  2522.         // line 2336
  2523.         yield "}
  2524. // Fonction globale pour gérer la comparaison
  2525. function toggleComparison(productId, element) {
  2526. if (! element) {
  2527. element = document.querySelector(`.comparison-btn[data-product-id=\"\${productId}\"]`);
  2528. }
  2529. if (! element) {
  2530. console.error('Bouton de comparaison non trouvé pour le produit', productId);
  2531. return;
  2532. }
  2533. const originalHtml = element.innerHTML;
  2534. // Désactiver le bouton/lien
  2535. if (element.tagName === 'BUTTON') {
  2536. element.disabled = true;
  2537. } else {
  2538. element.style.pointerEvents = 'none';
  2539. element.style.opacity = '0.6';
  2540. } element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
  2541. // Vérifier d'abord si le produit est déjà en comparaison
  2542. let isInComparison = false;
  2543. fetch(`/api/comparison/status/\${productId}`).then(response => response.json()).then(data => {
  2544. isInComparison = data.inComparison;
  2545. const url = isInComparison ? `/api/comparison/remove/\${productId}` : `/api/comparison/add/\${productId}`;
  2546. return fetch(url, {
  2547. method: 'POST',
  2548. headers: {
  2549. 'Content-Type': 'application/json',
  2550. 'X-Requested-With': 'XMLHttpRequest'
  2551. }
  2552. });
  2553. }).then(response => response.json()).then(data => {
  2554. if (data.success) { // Mettre à jour le compteur
  2555. loadComparisonCount();
  2556. // Mettre à jour l'apparence du bouton
  2557. if (element) { // Inverser l'état (car on vient de le changer)
  2558. const newState = ! isInComparison;
  2559. // Restaurer le HTML original puis mettre à jour
  2560. element.innerHTML = originalHtml;
  2561. if (newState) {
  2562. element.classList.add('active');
  2563. // Mettre à jour le texte pour les deux types de boutons
  2564. const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  2565. if (textEl) 
  2566. textEl.textContent = 'En comparaison';
  2567. // Mettre à jour l'icône si nécessaire (chercher dans span ou i)
  2568. const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
  2569. if (iconEl) {
  2570. iconEl.style.color = '#28a745';
  2571. iconEl.classList.add('active');
  2572. }
  2573. } else {
  2574. element.classList.remove('active');
  2575. const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  2576. if (textEl) 
  2577. textEl.textContent = 'Comparer';
  2578. // Restaurer la couleur de l'icône
  2579. const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
  2580. if (iconEl) {
  2581. iconEl.style.color = '';
  2582. iconEl.classList.remove('active');
  2583. }
  2584. }
  2585. }
  2586. // Afficher une notification
  2587. showNotification(data.message, 'success');
  2588. } else {
  2589. showNotification(data.message, 'error');
  2590. if (element) {
  2591. element.innerHTML = originalHtml;
  2592. }
  2593. }
  2594. }).catch(error => {
  2595. console.error('Erreur:', error);
  2596. showNotification('Une erreur est survenue', 'error');
  2597. if (element) {
  2598. element.innerHTML = originalHtml;
  2599. }
  2600. }). finally(() => {
  2601. if (element) {
  2602. if (element.tagName === 'BUTTON') {
  2603. element.disabled = false;
  2604. } else {
  2605. element.style.pointerEvents = '';
  2606. element.style.opacity = '';
  2607. }
  2608. }
  2609. });
  2610. }
  2611. // Fonction globale pour gérer les favoris
  2612. function toggleWishlist(productId, element) {
  2613. if (! element) {
  2614. element = document.querySelector(`.wishlist-btn[data-product-id=\"\${productId}\"]`);
  2615. }
  2616. if (! element) {
  2617. console.error('Bouton de wishlist non trouvé pour le produit', productId);
  2618. return;
  2619. }
  2620. const originalHtml = element.innerHTML;
  2621. // Désactiver le bouton/lien
  2622. if (element.tagName === 'BUTTON') {
  2623. element.disabled = true;
  2624. } else {
  2625. element.style.pointerEvents = 'none';
  2626. element.style.opacity = '0.6';
  2627. } element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
  2628. // Vérifier d'abord si le produit est déjà en favoris
  2629. let isInWishlist = false;
  2630. fetch(`/api/wishlist/status/\${productId}`).then(response => response.json()).then(data => {
  2631. isInWishlist = data.inWishlist;
  2632. const url = isInWishlist ? `/api/wishlist/remove/\${productId}` : `/api/wishlist/add/\${productId}`;
  2633. return fetch(url, {
  2634. method: 'POST',
  2635. headers: {
  2636. 'Content-Type': 'application/json',
  2637. 'X-Requested-With': 'XMLHttpRequest'
  2638. }
  2639. });
  2640. }).then(response => response.json()).then(data => {
  2641. if (data.success) { // Mettre à jour l'apparence du bouton
  2642. if (element) { // Inverser l'état (car on vient de le changer)
  2643. const newState = ! isInWishlist;
  2644. // Restaurer le HTML original puis mettre à jour
  2645. element.innerHTML = originalHtml;
  2646. // Chercher l'icône dans span ou i
  2647. const icon = element.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
  2648. const text = element.querySelector('.wishlist-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  2649. if (newState) {
  2650. if (icon) { // Pour les icônes linr, on change la classe
  2651. if (icon.classList.contains('lnr-heart')) {
  2652. icon.classList.remove('lnr-heart');
  2653. }
  2654. if (! icon.classList.contains('lnr-heart-filled')) {
  2655. icon.classList.add('lnr-heart-filled');
  2656. }
  2657. icon.style.color = '#dc3545';
  2658. }
  2659. element.classList.add('active');
  2660. if (text) 
  2661. text.textContent = 'Dans favoris';
  2662. } else {
  2663. if (icon) { // Restaurer l'icône originale
  2664. if (icon.classList.contains('lnr-heart-filled')) {
  2665. icon.classList.remove('lnr-heart-filled');
  2666. }
  2667. if (! icon.classList.contains('lnr-heart')) {
  2668. icon.classList.add('lnr-heart');
  2669. }
  2670. icon.style.color = '';
  2671. }
  2672. element.classList.remove('active');
  2673. if (text) 
  2674. text.textContent = 'Favoris';
  2675. }
  2676. }
  2677. // Afficher une notification
  2678. showNotification(data.message, 'success');
  2679. // Si on est sur la page wishlist, recharger la page
  2680. if (window.location.pathname.includes('/account/wishlist')) {
  2681. setTimeout(() => location.reload(), 1000);
  2682. }
  2683. } else {
  2684. showNotification(data.message, 'error');
  2685. if (element) {
  2686. element.innerHTML = originalHtml;
  2687. }
  2688. }
  2689. }).catch(error => {
  2690. console.error('Erreur:', error);
  2691. showNotification('Une erreur est survenue', 'error');
  2692. if (element) {
  2693. element.innerHTML = originalHtml;
  2694. }
  2695. }). finally(() => {
  2696. if (element) {
  2697. if (element.tagName === 'BUTTON') {
  2698. element.disabled = false;
  2699. } else {
  2700. element.style.pointerEvents = '';
  2701. element.style.opacity = '';
  2702. }
  2703. }
  2704. });
  2705. }
  2706. // Fonction pour afficher des notifications
  2707. function showNotification(message, type = 'success') { // Créer l'élément de notification
  2708. const notification = document.createElement('div');
  2709. notification.className = `alert alert-\${
  2710. type === 'success' ? 'success' : 'danger'
  2711. } alert-dismissible fade show position-fixed`;
  2712. notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);';
  2713. notification.innerHTML = `
  2714.             \${message}
  2715.             <button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\"></button>
  2716.         `;
  2717. document.body.appendChild(notification);
  2718. // Supprimer automatiquement après 3 secondes
  2719. setTimeout(() => {
  2720. notification.remove();
  2721. }, 3000);
  2722. }
  2723. // Initialiser les alertes Bootstrap 5 pour la fermeture
  2724. document.addEventListener('DOMContentLoaded', function () { // S'assurer que les alertes peuvent être fermées
  2725. const alertCloseButtons = document.querySelectorAll('.flash-message .btn-close');
  2726. alertCloseButtons.forEach(function (button) {
  2727. button.addEventListener('click', function () {
  2728. const alert = this.closest('.alert');
  2729. if (alert) {
  2730. alert.classList.remove('show');
  2731. setTimeout(function () {
  2732. alert.remove();
  2733. }, 150);
  2734. }
  2735. });
  2736. });
  2737. // Charger les statuts initiaux des produits
  2738. ";
  2739.         // line 2587
  2740.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2587)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2741.             // line 2588
  2742.             yield "// Charger les statuts de comparaison pour tous les produits visibles
  2743. document.querySelectorAll('.comparison-btn[data-product-id]').forEach(btn => {
  2744. const productId = btn.dataset.productId;
  2745. fetch(`/api/comparison/status/\${productId}`).then(response => response.json()).then(data => {
  2746. if (data.inComparison) {
  2747. btn.classList.add('active');
  2748. // Mettre à jour le texte pour les deux types de boutons
  2749. const textEl = btn.querySelector('.comparison-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
  2750. if (textEl) 
  2751. textEl.textContent = 'En comparaison';
  2752. // Mettre à jour l'icône si nécessaire
  2753. const iconEl = btn.querySelector('.lnr-sync, [class*=\"sync\"]');
  2754. if (iconEl) 
  2755. iconEl.style.color = '#28a745';
  2756. }
  2757. }).catch(() => {});
  2758. });
  2759. // Charger les statuts de wishlist pour tous les produits visibles
  2760. document.querySelectorAll('.wishlist-btn[data-product-id]').forEach(btn => {
  2761. const productId = btn.dataset.productId;
  2762. fetch(`/api/wishlist/status/\${productId}`).then(response => response.json()).then(data => {
  2763. if (data.inWishlist) {
  2764. // Chercher l'icône dans span ou i
  2765. const icon = btn.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
  2766. if (icon) {
  2767. icon.classList.remove('lnr-heart');
  2768. icon.classList.add('lnr-heart');
  2769. icon.style.color = '#ffa200';
  2770. }
  2771. // Mettre à jour le texte pour les deux types de boutons
  2772. const textEl = btn.querySelector('.wishlist-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
  2773. if (textEl) 
  2774. textEl.textContent = 'favoris';
  2775. }
  2776. }).catch(() => {});
  2777. });
  2778. // Charger le compteur de comparaison
  2779. loadComparisonCount();";
  2780.         }
  2781.         // line 2637
  2782.         yield "});
  2783. \t\t</script>
  2784. \t\t<script>
  2785. \t\t\t// Loader global pour tous les boutons de formulaire
  2786. document.addEventListener('DOMContentLoaded', function () { // Intercepter tous les formulaires
  2787. const forms = document.querySelectorAll('form');
  2788. forms.forEach(function (form) {
  2789. form.addEventListener('submit', function (e) {
  2790. const submitButtons = form.querySelectorAll('button[type=\"submit\"], input[type=\"submit\"], button:not([type])');
  2791. submitButtons.forEach(function (button) { // Vérifier si le bouton n'est pas déjà désactivé
  2792. if (! button.disabled && ! button.classList.contains('loading')) {
  2793. button.classList.add('loading');
  2794. button.disabled = true;
  2795. // Sauvegarder le texte original
  2796. const originalText = button.innerHTML;
  2797. button.setAttribute('data-original-text', originalText);
  2798. // Ajouter le loader
  2799. button.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Envoi...';
  2800. // Si le formulaire n'est pas valide, réactiver le bouton après 1 seconde
  2801. setTimeout(function () {
  2802. if (! form.checkValidity()) {
  2803. button.classList.remove('loading');
  2804. button.disabled = false;
  2805. button.innerHTML = originalText;
  2806. }
  2807. }, 1000);
  2808. }
  2809. });
  2810. });
  2811. });
  2812. // Pour les boutons qui déclenchent des actions AJAX
  2813. const ajaxButtons = document.querySelectorAll('[data-ajax], .ajax-submit, button[data-submit]');
  2814. ajaxButtons.forEach(function (button) {
  2815. button.addEventListener('click', function (e) {
  2816. if (this.disabled || this.classList.contains('loading')) {
  2817. e.preventDefault();
  2818. return false;
  2819. }
  2820. this.classList.add('loading');
  2821. this.disabled = true;
  2822. const originalText = this.innerHTML;
  2823. this.setAttribute('data-original-text', originalText);
  2824. this.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Chargement...';
  2825. });
  2826. });
  2827. // Gestionnaire spécifique pour le formulaire de newsletter
  2828. const newsletterForm = document.querySelector('.footer-newsletter-form');
  2829. if (newsletterForm) {
  2830. newsletterForm.addEventListener('submit', function (e) {
  2831. const submitBtn = this.querySelector('.newsletter-btn');
  2832. if (submitBtn && ! submitBtn.disabled) {
  2833. submitBtn.classList.add('loading');
  2834. submitBtn.disabled = true;
  2835. // Afficher le loader et masquer l'icône
  2836. const icon = submitBtn.querySelector('.newsletter-btn-icon');
  2837. const loader = submitBtn.querySelector('.newsletter-btn-loader');
  2838. if (icon) 
  2839. icon.style.display = 'none';
  2840. if (loader) 
  2841. loader.style.display = 'flex';
  2842. // Réactiver le bouton après 5 secondes au cas où la requête échoue silencieusement
  2843. setTimeout(function () {
  2844. if (submitBtn.classList.contains('loading')) {
  2845. submitBtn.classList.remove('loading');
  2846. submitBtn.disabled = false;
  2847. if (icon) 
  2848. icon.style.display = 'flex';
  2849. if (loader) 
  2850. loader.style.display = 'none';
  2851. }
  2852. }, 5000);
  2853. }
  2854. });
  2855. // Gérer la réponse du formulaire (si AJAX)
  2856. newsletterForm.addEventListener('submit', function (e) {
  2857. // Si le formulaire est soumis normalement (non-AJAX), le navigateur gère la réponse
  2858. // Sinon, on peut intercepter pour gérer la réponse AJAX ici
  2859. });
  2860. }
  2861. });
  2862. // CSS pour le spinner
  2863. const style = document.createElement('style');
  2864. style.textContent = `
  2865.     .spinner-border-sm {
  2866.         width: 1rem;
  2867.         height: 1rem;
  2868.         border-width: 0.15em;
  2869.     }
  2870.     .spinner-border {
  2871.         display: inline-block;
  2872.         width: 1rem;
  2873.         height: 1rem;
  2874.         vertical-align: text-bottom;
  2875.         border: 0.15em solid currentColor;
  2876.         border-right-color: transparent;
  2877.         border-radius: 50%;
  2878.         animation: spinner-border 0.75s linear infinite;
  2879.     }
  2880.     @keyframes spinner-border {
  2881.         to { transform: rotate(360deg); }
  2882.     }
  2883.     button.loading {
  2884.         opacity: 0.7;
  2885.         cursor: not-allowed !important;
  2886.     }
  2887. `;
  2888. document.head.appendChild(style);
  2889. \t\t</script>
  2890. \t\t<!-- Cart Modal -->
  2891. \t\t<div id=\"ebay-cart-modal\" class=\"ebay-cart-modal-overlay\" style=\"display: none;\" data-url=\"\">
  2892. \t\t\t<div class=\"ebay-cart-modal\">
  2893. \t\t\t\t<div class=\"ebay-modal-header\">
  2894. \t\t\t\t\t<h3>
  2895. \t\t\t\t\t\t<i class=\"lnr lnr-checkmark-circle\"></i>
  2896. \t\t\t\t\t\tAjouté au panier !</h3>
  2897. \t\t\t\t\t<button class=\"ebay-modal-close\" onclick=\"closeEbayCartModal()\">&times;</button>
  2898. \t\t\t\t</div>
  2899. \t\t\t\t<div class=\"ebay-modal-content\">
  2900. \t\t\t\t\t<div class=\"ebay-product-info\">
  2901. \t\t\t\t\t\t<div class=\"ebay-product-image\">
  2902. \t\t\t\t\t\t\t<img id=\"ebay-modal-product-image\" src=\"\" alt=\"Produit\"/>
  2903. \t\t\t\t\t\t</div>
  2904. \t\t\t\t\t\t<div class=\"ebay-product-details\">
  2905. \t\t\t\t\t\t\t<h4 id=\"ebay-modal-product-name\">Nom du produit</h4>
  2906. \t\t\t\t\t\t\t<div class=\"ebay-product-price\" id=\"ebay-modal-product-price\">Prix</div>
  2907. \t\t\t\t\t\t\t<div class=\"ebay-product-quantity\">
  2908. \t\t\t\t\t\t\t\t<span>Quantité:
  2909. \t\t\t\t\t\t\t\t</span>
  2910. \t\t\t\t\t\t\t\t<span id=\"ebay-modal-product-quantity\">1</span>
  2911. \t\t\t\t\t\t\t</div>
  2912. \t\t\t\t\t\t</div>
  2913. \t\t\t\t\t</div>
  2914. \t\t\t\t\t<!-- Recommendations Section -->
  2915. \t\t\t\t\t<div class=\"ebay-recommendations\" style=\"display: none;\">
  2916. \t\t\t\t\t\t<h4>Les clients ont aussi acheté :</h4>
  2917. \t\t\t\t\t\t<div
  2918. \t\t\t\t\t\t\tclass=\"ebay-recommendations-grid\" id=\"ebay-modal-recommendations\"><!-- Recommendations will be injected here -->
  2919. \t\t\t\t\t\t</div>
  2920. \t\t\t\t\t</div>
  2921. \t\t\t\t\t<div class=\"ebay-modal-actions\">
  2922. \t\t\t\t\t\t<button class=\"ebay-btn-continue\" onclick=\"closeEbayCartModal()\">
  2923. \t\t\t\t\t\t\tContinuer mes achats
  2924. \t\t\t\t\t\t</button>
  2925. \t\t\t\t\t\t<a href=\"";
  2926.         // line 2811
  2927.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_cart");
  2928.         yield "\" class=\"ebay-btn-view-cart\">
  2929. \t\t\t\t\t\t\tVoir mon panier
  2930. \t\t\t\t\t\t</a>
  2931. \t\t\t\t\t</div>
  2932. \t\t\t\t</div>
  2933. \t\t\t</div>
  2934. \t\t</div>
  2935. \t\t<script src=\"";
  2936.         // line 2819
  2937.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/cart-modal.js"), "html"nulltrue);
  2938.         yield "\"></script>
  2939. \t\t<script src=\"";
  2940.         // line 2820
  2941.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/notification-badge.js"), "html"nulltrue);
  2942.         yield "\"></script>
  2943. \t\t<script src=\"";
  2944.         // line 2821
  2945.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("js/dark-mode.js"), "html"nulltrue);
  2946.         yield "\"></script>
  2947. \t\t";
  2948.         // line 2823
  2949.         yield from $this->unwrap()->yieldBlock('javascripts'$context$blocks);
  2950.         // line 2824
  2951.         yield "\t</body>
  2952. </html>
  2953. ";
  2954.         
  2955.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  2956.         
  2957.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  2958.         yield from [];
  2959.     }
  2960.     // line 40
  2961.     /**
  2962.      * @return iterable<null|scalar|\Stringable>
  2963.      */
  2964.     public function block_title(array $context, array $blocks = []): iterable
  2965.     {
  2966.         $macros $this->macros;
  2967.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  2968.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""title"));
  2969.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  2970.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""title"));
  2971.         yield "MaketOu
  2972. \t\t\t";
  2973.         
  2974.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  2975.         
  2976.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  2977.         yield from [];
  2978.     }
  2979.     // line 1243
  2980.     /**
  2981.      * @return iterable<null|scalar|\Stringable>
  2982.      */
  2983.     public function block_stylesheets(array $context, array $blocks = []): iterable
  2984.     {
  2985.         $macros $this->macros;
  2986.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  2987.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""stylesheets"));
  2988.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  2989.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""stylesheets"));
  2990.         // line 1244
  2991.         yield "\t\t\t";
  2992.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getFunction('encore_entry_link_tags')->getCallable()("app"), "html"nulltrue);
  2993.         yield "
  2994. \t\t";
  2995.         
  2996.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  2997.         
  2998.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  2999.         yield from [];
  3000.     }
  3001.     // line 1500
  3002.     /**
  3003.      * @return iterable<null|scalar|\Stringable>
  3004.      */
  3005.     public function block_body(array $context, array $blocks = []): iterable
  3006.     {
  3007.         $macros $this->macros;
  3008.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  3009.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""body"));
  3010.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  3011.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""body"));
  3012.         
  3013.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  3014.         
  3015.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  3016.         yield from [];
  3017.     }
  3018.     // line 2823
  3019.     /**
  3020.      * @return iterable<null|scalar|\Stringable>
  3021.      */
  3022.     public function block_javascripts(array $context, array $blocks = []): iterable
  3023.     {
  3024.         $macros $this->macros;
  3025.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  3026.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""javascripts"));
  3027.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  3028.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""javascripts"));
  3029.         
  3030.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  3031.         
  3032.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  3033.         yield from [];
  3034.     }
  3035.     /**
  3036.      * @codeCoverageIgnore
  3037.      */
  3038.     public function getTemplateName(): string
  3039.     {
  3040.         return "base_home.html.twig";
  3041.     }
  3042.     /**
  3043.      * @codeCoverageIgnore
  3044.      */
  3045.     public function isTraitable(): bool
  3046.     {
  3047.         return false;
  3048.     }
  3049.     /**
  3050.      * @codeCoverageIgnore
  3051.      */
  3052.     public function getDebugInfo(): array
  3053.     {
  3054.         return array (  3342 => 2823,  3320 => 1500,  3306 => 1244,  3293 => 1243,  3269 => 40,  3256 => 2824,  3254 => 2823,  3249 => 2821,  3245 => 2820,  3241 => 2819,  3230 => 2811,  3054 => 2637,  3003 => 2588,  3001 => 2587,  2748 => 2336,  2687 => 2278,  2678 => 2271,  2676 => 2270,  2673 => 2269,  2668 => 2267,  2666 => 2266,  2658 => 2260,  2625 => 2231,  2623 => 2230,  2601 => 2210,  2594 => 2205,  2592 => 2204,  2584 => 2199,  2553 => 2171,  2543 => 2164,  2538 => 2162,  2534 => 2161,  2529 => 2159,  2525 => 2158,  2521 => 2157,  2517 => 2156,  2513 => 2155,  2509 => 2154,  2505 => 2153,  2476 => 2127,  2339 => 1993,  2301 => 1958,  2267 => 1927,  2203 => 1866,  2172 => 1838,  2138 => 1807,  2097 => 1769,  1949 => 1624,  1935 => 1613,  1928 => 1609,  1921 => 1605,  1914 => 1601,  1907 => 1597,  1893 => 1586,  1886 => 1582,  1879 => 1578,  1872 => 1574,  1862 => 1566,  1855 => 1562,  1848 => 1558,  1845 => 1557,  1838 => 1553,  1835 => 1552,  1833 => 1551,  1827 => 1548,  1820 => 1544,  1813 => 1540,  1772 => 1501,  1770 => 1500,  1764 => 1496,  1754 => 1492,  1750 => 1490,  1746 => 1489,  1743 => 1488,  1733 => 1484,  1729 => 1482,  1725 => 1481,  1722 => 1480,  1712 => 1476,  1708 => 1474,  1704 => 1473,  1701 => 1472,  1691 => 1468,  1687 => 1466,  1683 => 1465,  1671 => 1456,  1667 => 1455,  1659 => 1449,  1653 => 1445,  1651 => 1444,  1644 => 1440,  1640 => 1439,  1630 => 1431,  1621 => 1426,  1612 => 1421,  1610 => 1420,  1599 => 1413,  1591 => 1408,  1583 => 1404,  1581 => 1403,  1571 => 1400,  1562 => 1394,  1556 => 1393,  1551 => 1391,  1545 => 1390,  1540 => 1388,  1534 => 1387,  1529 => 1385,  1523 => 1384,  1509 => 1375,  1497 => 1365,  1493 => 1364,  1373 => 1246,  1371 => 1243,  194 => 68,  188 => 64,  184 => 63,  180 => 62,  176 => 61,  172 => 60,  168 => 59,  164 => 58,  160 => 57,  156 => 56,  152 => 55,  148 => 54,  144 => 53,  140 => 52,  136 => 51,  132 => 50,  128 => 49,  124 => 48,  120 => 47,  113 => 42,  111 => 40,  93 => 25,  86 => 21,  81 => 19,  77 => 18,  73 => 17,  67 => 14,  52 => 1,);
  3055.     }
  3056.     public function getSourceContext(): Source
  3057.     {
  3058.         return new Source("<!DOCTYPE html>
  3059. <html lang=\"fr\" class=\"no-js\">
  3060. \t<head>
  3061. \t\t<!-- Mobile Specific Meta -->
  3062. \t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no\">
  3063. \t\t<meta name=\"mobile-web-app-capable\" content=\"yes\">
  3064. \t\t<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">
  3065. \t\t<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\">
  3066. \t\t<meta name=\"apple-mobile-web-app-title\" content=\"MaketOu\">
  3067. \t\t<meta name=\"theme-color\" content=\"#ffa200\">
  3068. \t\t<meta name=\"msapplication-TileColor\" content=\"#ffa200\">
  3069. \t\t<meta
  3070. \t\tname=\"msapplication-config\" content=\"{{ asset('favicon/browserconfig.xml') }}\">
  3071. \t\t<!-- Favicon-->
  3072. \t\t<link rel=\"shortcut icon\" href=\"{{ asset('favicon/favicon-16x16.png') }}\">
  3073. \t\t<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"{{ asset('favicon/apple-touch-icon.png') }}\">
  3074. \t\t<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"{{ asset('favicon/favicon-32x32.png') }}\">
  3075. \t\t<link
  3076. \t\trel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"{{ asset('favicon/favicon-16x16.png') }}\">
  3077. \t\t<!-- PWA Manifest -->
  3078. \t\t<link
  3079. \t\trel=\"manifest\" href=\"{{ asset('manifest.json') }}\">
  3080. \t\t<!-- Author Meta -->
  3081. \t\t<meta
  3082. \t\tname=\"author\" content=\"Foulgor Tech\">
  3083. \t\t<!-- Meta Description -->
  3084. \t\t<meta
  3085. \t\tname=\"description\" content=\"\">
  3086. \t\t<!-- Meta Keyword -->
  3087. \t\t<meta
  3088. \t\tname=\"keywords\" content=\"\">
  3089. \t\t<!-- meta character set -->
  3090. \t\t<meta
  3091. \t\tcharset=\"UTF-8\">
  3092. \t\t<!-- Site Title -->
  3093. \t\t<title>
  3094. \t\t\t{% block title %}MaketOu
  3095. \t\t\t{% endblock %}
  3096. \t\t</title>
  3097. \t\t<!--
  3098. \t\t\t\t\t\t        CSS
  3099. \t\t\t\t\t\t        ============================================= -->
  3100. \t\t<link rel=\"stylesheet\" href=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.css\"/>
  3101. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/linearicons.css') }}\">
  3102. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/font-awesome.min.css') }}\">
  3103. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/themify-icons.css') }}\">
  3104. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/bootstrap.css') }}\">
  3105. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/owl.carousel.css') }}\">
  3106. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/nice-select.css') }}\">
  3107. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/nouislider.min.css') }}\">
  3108. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/ion.rangeSlider.css') }}\"/>
  3109. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/ion.rangeSlider.skinFlat.css') }}\"/>
  3110. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/magnific-popup.css') }}\">
  3111. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/main.css') }}\">
  3112. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/cart-modal.css') }}\">
  3113. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/buttons-unified.css') }}\">
  3114. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/design-system.css') }}\">
  3115. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/dark-mode-forced.css') }}\">
  3116. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/dark-mode-complete.css') }}\">
  3117. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/navbar-icons-enhanced.css') }}\">
  3118. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/dark-mode-pages-specific.css') }}\">
  3119. \t\t<meta
  3120. \t\tcharset=\"UTF-8\">
  3121. \t\t{# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
  3122. \t\t<style>
  3123. \t\t\t/* Styles pour l'icône de notification */
  3124. \t\t\t.notification-icon {
  3125. \t\t\t\tposition: relative;
  3126. \t\t\t\tdisplay: inline-block;
  3127. \t\t\t\tcolor: #333;
  3128. \t\t\t\ttext-decoration: none;
  3129. \t\t\t\ttransition: color 0.3s ease;
  3130. \t\t\t}
  3131. \t\t\t.notification-icon:hover {
  3132. \t\t\t\tcolor: #007bff;
  3133. \t\t\t}
  3134. \t\t\t.notification-badge {
  3135. \t\t\t\tposition: absolute;
  3136. \t\t\t\ttop: -4px;
  3137. \t\t\t\tright: -2px;
  3138. \t\t\t\tbackground: #dc3545 !important;
  3139. \t\t\t\tcolor: white !important;
  3140. \t\t\t\tborder-radius: 50%;
  3141. \t\t\t\twidth: 18px;
  3142. \t\t\t\theight: 18px;
  3143. \t\t\t\tfont-size: 8px !important;
  3144. \t\t\t\tdisplay: flex !important;
  3145. \t\t\t\talign-items: center !important;
  3146. \t\t\t\tjustify-content: center !important;
  3147. \t\t\t\tfont-weight: bold !important;
  3148. \t\t\t\tanimation: pulse 2s infinite;
  3149. \t\t\t\tz-index: 10;
  3150. \t\t\t\tline-height: 1 !important;
  3151. \t\t\t}
  3152. \t\t\t/* Forcer le texte en blanc pour tous les éléments du badge - avec spécificité maximale */
  3153. \t\t\t.notification-badge,
  3154. \t\t\t.notification-badge.text-white,
  3155. \t\t\t.notification-badge *,
  3156. \t\t\t#notificationBadge,
  3157. \t\t\t#notificationBadge.text-white,
  3158. \t\t\t#notificationBadge *,
  3159. \t\t\tspan.notification-badge,
  3160. \t\t\tspan.notification-badge.text-white,
  3161. \t\t\tspan#notificationBadge,
  3162. \t\t\tspan#notificationBadge.text-white {
  3163. \t\t\t\tcolor: white !important;
  3164. \t\t\t\ttext-color: white !important;
  3165. \t\t\t\t-webkit-text-fill-color: white !important;
  3166. \t\t\t}
  3167. \t\t\t/* S'assurer que le contenu texte est bien en blanc */
  3168. \t\t\t.notification-badge::before,
  3169. \t\t\t.notification-badge::after {
  3170. \t\t\t\tcolor: white !important;
  3171. \t\t\t}
  3172. \t\t\t/* Forcer la couleur pour tous les sélecteurs possibles avec spécificité maximale */
  3173. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge,
  3174. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge.text-white,
  3175. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span.notification-badge,
  3176. \t\t\t.notification-icon .notification-badge,
  3177. \t\t\t.notification-icon .notification-badge.text-white,
  3178. \t\t\t.notification-icon span.notification-badge,
  3179. \t\t\ta.notification-icon .notification-badge,
  3180. \t\t\ta.notification-icon span.notification-badge {
  3181. \t\t\t\tcolor: white !important;
  3182. \t\t\t\ttext-color: white !important;
  3183. \t\t\t\t-webkit-text-fill-color: white !important;
  3184. \t\t\t}
  3185. \t\t\t/* Forcer la couleur pour tous les enfants directs */
  3186. \t\t\t.notification-icon > .notification-badge,
  3187. \t\t\t.notification-icon > span.notification-badge {
  3188. \t\t\t\tcolor: white !important;
  3189. \t\t\t}
  3190. \t\t\t@keyframes pulse {
  3191. \t\t\t\t0% {
  3192. \t\t\t\t\ttransform: scale(1);
  3193. \t\t\t\t}
  3194. \t\t\t\t50% {
  3195. \t\t\t\t\ttransform: scale(1.1);
  3196. \t\t\t\t}
  3197. \t\t\t\t100% {
  3198. \t\t\t\t\ttransform: scale(1);
  3199. \t\t\t\t}
  3200. \t\t\t}
  3201. \t\t\t.notification-icon:hover .notification-badge {
  3202. \t\t\t\tanimation: none;
  3203. \t\t\t}
  3204. \t\t\t/* Container pour les icônes - toujours alignées horizontalement */
  3205. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
  3206. \t\t\t\tdisplay: flex !important;
  3207. \t\t\t\tflex-direction: row !important;
  3208. \t\t\t\talign-items: center !important;
  3209. \t\t\t\tjustify-content: center !important;
  3210. \t\t\t\tgap: 15px !important;
  3211. \t\t\t\tlist-style: none !important;
  3212. \t\t\t\tmargin: 0 !important;
  3213. \t\t\t\tpadding: 0 !important;
  3214. \t\t\t\twidth: auto !important;
  3215. \t\t\t}
  3216. \t\t\t/* Surcharger les styles existants pour les li contenant le wrapper */
  3217. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right li:has(.navbar-icons-wrapper) {
  3218. \t\t\t\tmargin-left: 0 !important;
  3219. \t\t\t\tmargin-right: 0 !important;
  3220. \t\t\t\tdisplay: flex !important;
  3221. \t\t\t\talign-items: center !important;
  3222. \t\t\t\tjustify-content: center !important;
  3223. \t\t\t}
  3224. \t\t\t/* Styles pour les icônes */
  3225. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart,
  3226. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon,
  3227. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon,
  3228. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .dark-mode-toggle,
  3229. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
  3230. \t\t\t\tdisplay: flex !important;
  3231. \t\t\t\talign-items: center !important;
  3232. \t\t\t\tjustify-content: center !important;
  3233. \t\t\t\twidth: 40px !important;
  3234. \t\t\t\theight: 40px !important;
  3235. \t\t\t\tmin-width: 40px !important;
  3236. \t\t\t\tmin-height: 40px !important;
  3237. \t\t\t\tcolor: #333 !important;
  3238. \t\t\t\ttext-decoration: none !important;
  3239. \t\t\t\ttransition: all 0.3s ease !important;
  3240. \t\t\t\tborder-radius: 50% !important;
  3241. \t\t\t\tposition: relative !important;
  3242. \t\t\t\tmargin: 0 !important;
  3243. \t\t\t\tpadding: 0 !important;
  3244. \t\t\t}
  3245. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart:hover,
  3246. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon:hover,
  3247. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon:hover,
  3248. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .dark-mode-toggle:hover,
  3249. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search:hover {
  3250. \t\t\t\tbackground-color: #f0f0f0 !important;
  3251. \t\t\t\tcolor: #ffa200 !important;
  3252. \t\t\t\ttransform: scale(1.1) !important;
  3253. \t\t\t}
  3254. \t\t\t/* Surcharger le line-height de main.css */
  3255. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart span,
  3256. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span,
  3257. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search span {
  3258. \t\t\t\tfont-size: 18px !important;
  3259. \t\t\t\tline-height: 1 !important;
  3260. \t\t\t\tdisplay: flex !important;
  3261. \t\t\t\talign-items: center !important;
  3262. \t\t\t\tjustify-content: center !important;
  3263. \t\t\t\tcolor: inherit !important;
  3264. \t\t\t\tfont-weight: normal !important;
  3265. \t\t\t}
  3266. \t\t\t/* Icône de comparaison en noir comme le panier */
  3267. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon {
  3268. \t\t\t\tcolor: #333 !important;
  3269. \t\t\t}
  3270. \t\t\t/* L'icône elle-même (lnr-sync) doit être noire, mais pas le badge */
  3271. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon > span.lnr-sync,
  3272. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon span:not(.comparison-badge) {
  3273. \t\t\t\tcolor: #333 !important;
  3274. \t\t\t\tfont-size: 18px !important;
  3275. \t\t\t\tline-height: 1 !important;
  3276. \t\t\t\tdisplay: flex !important;
  3277. \t\t\t\talign-items: center !important;
  3278. \t\t\t\tjustify-content: center !important;
  3279. \t\t\t\tfont-weight: normal !important;
  3280. \t\t\t}
  3281. \t\t\t/* Le badge doit rester blanc */
  3282. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon .comparison-badge {
  3283. \t\t\t\tcolor: white !important;
  3284. \t\t\t}
  3285. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
  3286. \t\t\t\tbackground: transparent !important;
  3287. \t\t\t\tborder: 0 !important;
  3288. \t\t\t\tcursor: pointer !important;
  3289. \t\t\t\tpadding: 0 !important;
  3290. \t\t\t}
  3291. \t\t\t/* Alignement des icônes navbar sur mobile */
  3292. \t\t\t@media(max-width: 991.98px) {
  3293. \t\t\t\t/* Container navbar-right en colonne sur mobile */
  3294. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right {
  3295. \t\t\t\t\tdisplay: flex !important;
  3296. \t\t\t\t\tflex-direction: column !important;
  3297. \t\t\t\t\talign-items: center !important;
  3298. \t\t\t\t\tjustify-content: center !important;
  3299. \t\t\t\t\twidth: 100% !important;
  3300. \t\t\t\t\tgap: 0 !important;
  3301. \t\t\t\t\tmargin: 0 !important;
  3302. \t\t\t\t\tpadding: 10px 0 !important;
  3303. \t\t\t\t}
  3304. \t\t\t\t/* Le container d'icônes reste horizontal */
  3305. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
  3306. \t\t\t\t\twidth: 100% !important;
  3307. \t\t\t\t\tjustify-content: center !important;
  3308. \t\t\t\t\tdisplay: flex !important;
  3309. \t\t\t\t\tflex-direction: row !important;
  3310. \t\t\t\t}
  3311. \t\t\t\t/* Le bouton compte en bas - pleine largeur */
  3312. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right li:last-child {
  3313. \t\t\t\t\twidth: 100% !important;
  3314. \t\t\t\t\tdisplay: flex !important;
  3315. \t\t\t\t\tjustify-content: center !important;
  3316. \t\t\t\t\tmargin-top: 12px !important;
  3317. \t\t\t\t\tpadding-top: 12px !important;
  3318. \t\t\t\t\tborder-top: 1px solid #e0e0e0 !important;
  3319. \t\t\t\t}
  3320. \t\t\t\t/* Bouton compte responsive */
  3321. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .btn-account {
  3322. \t\t\t\t\twidth: 100%;
  3323. \t\t\t\t\tmax-width: 200px;
  3324. \t\t\t\t\tpadding: 10px 20px;
  3325. \t\t\t\t\tfont-size: 14px;
  3326. \t\t\t\t}
  3327. \t\t\t}
  3328. \t\t\t/* Styles pour les messages flash - Design moderne */
  3329. \t\t\t.flash-message {
  3330. \t\t\t\tanimation: slideInDownFlash 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  3331. \t\t\t\tposition: relative;
  3332. \t\t\t\toverflow: visible !important;
  3333. \t\t\t\tborder: none !important;
  3334. \t\t\t\tpadding: 16px 20px !important;
  3335. \t\t\t\tborder-radius: 12px !important;
  3336. \t\t\t\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
  3337. \t\t\t\tdisplay: flex !important;
  3338. \t\t\t\talign-items: center;
  3339. \t\t\t\tgap: 12px;
  3340. \t\t\t\tmargin-bottom: 15px;
  3341. \t\t\t\tbackdrop-filter: blur(10px);
  3342. \t\t\t\ttransition: all 0.3s ease;
  3343. \t\t\t}
  3344. \t\t\t/* S'assurer que les icônes Font Awesome sont visibles */
  3345. \t\t\t.flash-message i.fa {
  3346. \t\t\t\tdisplay: inline-block !important;
  3347. \t\t\t\tvisibility: visible !important;
  3348. \t\t\t\topacity: 1 !important;
  3349. \t\t\t\twidth: auto !important;
  3350. \t\t\t\theight: auto !important;
  3351. \t\t\t\tfont-family: \"FontAwesome\" !important;
  3352. \t\t\t\tfont-style: normal !important;
  3353. \t\t\t\tfont-weight: normal !important;
  3354. \t\t\t\ttext-rendering: auto !important;
  3355. \t\t\t\t-webkit-font-smoothing: antialiased !important;
  3356. \t\t\t\t-moz-osx-font-smoothing: grayscale !important;
  3357. \t\t\t\tline-height: 1 !important;
  3358. \t\t\t\tflex-shrink: 0 !important;
  3359. \t\t\t}
  3360. \t\t\t/* Forcer l'affichage des pseudo-éléments Font Awesome */
  3361. \t\t\t.flash-message i.fa::before {
  3362. \t\t\t\tdisplay: inline-block !important;
  3363. \t\t\t\tvisibility: visible !important;
  3364. \t\t\t\topacity: 1 !important;
  3365. \t\t\t\tcontent: attr(data-icon) !important;
  3366. \t\t\t}
  3367. \t\t\t/* Styles spécifiques pour chaque icône */
  3368. \t\t\t.flash-message i.fa-check-circle::before {
  3369. \t\t\t\tcontent: \"\\f058\" !important;
  3370. \t\t\t}
  3371. \t\t\t.flash-message i.fa-exclamation-circle::before {
  3372. \t\t\t\tcontent: \"\\f06a\" !important;
  3373. \t\t\t}
  3374. \t\t\t.flash-message i.fa-exclamation-triangle::before {
  3375. \t\t\t\tcontent: \"\\f071\" !important;
  3376. \t\t\t}
  3377. \t\t\t.flash-message i.fa-info-circle::before {
  3378. \t\t\t\tcontent: \"\\f05a\" !important;
  3379. \t\t\t}
  3380. \t\t\t.flash-message:hover {
  3381. \t\t\t\tbox-shadow: 0 6px 20px rgba(0, 0, 0, 0.2) !important;
  3382. \t\t\t\ttransform: translateY(-2px);
  3383. \t\t\t}
  3384. \t\t\t.flash-message::before {
  3385. \t\t\t\tcontent: '';
  3386. \t\t\t\tposition: absolute;
  3387. \t\t\t\tleft: 0;
  3388. \t\t\t\ttop: 0;
  3389. \t\t\t\tbottom: 0;
  3390. \t\t\t\twidth: 5px;
  3391. \t\t\t\tbackground: linear-gradient(180deg, currentColor 0%, rgba(255,255,255,0.3) 100%);
  3392. \t\t\t\tborder-radius: 12px 0 0 12px;
  3393. \t\t\t}
  3394. \t\t\t.flash-message.alert-success {
  3395. \t\t\t\tbackground: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%) !important;
  3396. \t\t\t\tcolor: #155724 !important;
  3397. \t\t\t\tborder-left: 5px solid #28a745 !important;
  3398. \t\t\t}
  3399. \t\t\t.flash-message.alert-success i.fa {
  3400. \t\t\t\tcolor: #28a745 !important;
  3401. \t\t\t\tfont-size: 1.3rem !important;
  3402. \t\t\t\tdisplay: inline-block !important;
  3403. \t\t\t\tmargin-right: 8px;
  3404. \t\t\t\tvertical-align: middle;
  3405. \t\t\t}
  3406. \t\t\t.flash-message.alert-danger {
  3407. \t\t\t\tbackground: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%) !important;
  3408. \t\t\t\tcolor: #721c24 !important;
  3409. \t\t\t\tborder-left: 5px solid #dc3545 !important;
  3410. \t\t\t}
  3411. \t\t\t.flash-message.alert-danger i.fa {
  3412. \t\t\t\tcolor: #dc3545 !important;
  3413. \t\t\t\tfont-size: 1.3rem !important;
  3414. \t\t\t\tdisplay: inline-block !important;
  3415. \t\t\t\tmargin-right: 8px;
  3416. \t\t\t\tvertical-align: middle;
  3417. \t\t\t}
  3418. \t\t\t.flash-message.alert-warning {
  3419. \t\t\t\tbackground: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%) !important;
  3420. \t\t\t\tcolor: #856404 !important;
  3421. \t\t\t\tborder-left: 5px solid #ffc107 !important;
  3422. \t\t\t}
  3423. \t\t\t.flash-message.alert-warning i.fa {
  3424. \t\t\t\tcolor: #ffa200 !important;
  3425. \t\t\t\tfont-size: 1.3rem !important;
  3426. \t\t\t\tdisplay: inline-block !important;
  3427. \t\t\t\tmargin-right: 8px;
  3428. \t\t\t\tvertical-align: middle;
  3429. \t\t\t}
  3430. \t\t\t.flash-message.alert-info {
  3431. \t\t\t\tbackground: linear-gradient(135deg, #d1ecf1 0%, #bee5eb 100%) !important;
  3432. \t\t\t\tcolor: #0c5460 !important;
  3433. \t\t\t\tborder-left: 5px solid #17a2b8 !important;
  3434. \t\t\t}
  3435. \t\t\t.flash-message.alert-info i.fa {
  3436. \t\t\t\tcolor: #17a2b8 !important;
  3437. \t\t\t\tfont-size: 1.3rem !important;
  3438. \t\t\t\tdisplay: inline-block !important;
  3439. \t\t\t\tmargin-right: 8px;
  3440. \t\t\t\tvertical-align: middle;
  3441. \t\t\t}
  3442. \t\t\t.flash-message strong {
  3443. \t\t\t\tflex: 1;
  3444. \t\t\t\tfont-weight: 600;
  3445. \t\t\t\tfont-size: 0.95rem;
  3446. \t\t\t\tline-height: 1.5;
  3447. \t\t\t}
  3448. \t\t\t.flash-message .btn-close {
  3449. \t\t\t\topacity: 0.7;
  3450. \t\t\t\tpadding: 8px !important;
  3451. \t\t\t\tmargin: -8px -8px -8px auto !important;
  3452. \t\t\t\ttransition: all 0.2s ease;
  3453. \t\t\t\tborder-radius: 50% !important;
  3454. \t\t\t\tbackground: rgba(0, 0, 0, 0.05) !important;
  3455. \t\t\t\twidth: 32px !important;
  3456. \t\t\t\theight: 32px !important;
  3457. \t\t\t\tdisplay: flex !important;
  3458. \t\t\t\talign-items: center !important;
  3459. \t\t\t\tjustify-content: center !important;
  3460. \t\t\t\tborder: none !important;
  3461. \t\t\t\tcursor: pointer !important;
  3462. \t\t\t\tposition: relative !important;
  3463. \t\t\t}
  3464. \t\t\t/* Ajouter une icône X visible dans le bouton */
  3465. \t\t\t.flash-message .btn-close::before {
  3466. \t\t\t\tcontent: '×' !important;
  3467. \t\t\t\tfont-size: 24px !important;
  3468. \t\t\t\tline-height: 1 !important;
  3469. \t\t\t\tcolor: currentColor !important;
  3470. \t\t\t\tfont-weight: bold !important;
  3471. \t\t\t\tdisplay: block !important;
  3472. \t\t\t\tposition: absolute !important;
  3473. \t\t\t\ttop: 50% !important;
  3474. \t\t\t\tleft: 50% !important;
  3475. \t\t\t\ttransform: translate(-50%, -50%) !important;
  3476. \t\t\t}
  3477. \t\t\t.flash-message .btn-close:hover {
  3478. \t\t\t\topacity: 1 !important;
  3479. \t\t\t\tbackground: rgba(0, 0, 0, 0.15) !important;
  3480. \t\t\t\ttransform: rotate(90deg) !important;
  3481. \t\t\t}
  3482. \t\t\t.flash-message .btn-close:hover::before {
  3483. \t\t\t\ttransform: translate(-50%, -50%) rotate(-90deg) !important;
  3484. \t\t\t}
  3485. \t\t\t@keyframes slideInDownFlash {
  3486. \t\t\t\tfrom {
  3487. \t\t\t\t\topacity: 0;
  3488. \t\t\t\t\ttransform: translateY(-30px) scale(0.95);
  3489. \t\t\t\t}
  3490. \t\t\t\tto {
  3491. \t\t\t\t\topacity: 1;
  3492. \t\t\t\t\ttransform: translateY(0) scale(1);
  3493. \t\t\t\t}
  3494. \t\t\t}
  3495. \t\t\t#flash-messages-container {
  3496. \t\t\t\tmargin-top: 20px;
  3497. \t\t\t\tmargin-bottom: 0;
  3498. \t\t\t}
  3499. \t\t\t@media(max-width: 768px) {
  3500. \t\t\t\t.flash-message {
  3501. \t\t\t\t\tpadding: 14px 16px !important;
  3502. \t\t\t\t\tfont-size: 0.9rem;
  3503. \t\t\t\t}
  3504. \t\t\t\t.flash-message i {
  3505. \t\t\t\t\tfont-size: 1.2rem !important;
  3506. \t\t\t\t}
  3507. \t\t\t}
  3508. \t\t\t/* Styles pour l'icône de comparaison */
  3509. \t\t\t.comparison-icon {
  3510. \t\t\t\tposition: relative;
  3511. \t\t\t\tdisplay: inline-block;
  3512. \t\t\t\tcolor: #333;
  3513. \t\t\t\ttext-decoration: none;
  3514. \t\t\t\ttransition: all 0.3s ease;
  3515. \t\t\t}
  3516. \t\t\t.comparison-icon:hover {
  3517. \t\t\t\tcolor: #ffa200;
  3518. \t\t\t}
  3519. \t\t\t.comparison-badge {
  3520. \t\t\t\tposition: absolute;
  3521. \t\t\t\ttop: -4px;
  3522. \t\t\t\tright: -2px;
  3523. \t\t\t\tbackground: #095ad3 !important;
  3524. \t\t\t\tcolor: white !important;
  3525. \t\t\t\tborder-radius: 50%;
  3526. \t\t\t\twidth: 18px;
  3527. \t\t\t\theight: 18px;
  3528. \t\t\t\tfont-size: 8px !important;
  3529. \t\t\t\tdisplay: flex !important;
  3530. \t\t\t\talign-items: center !important;
  3531. \t\t\t\tjustify-content: center !important;
  3532. \t\t\t\tfont-weight: bold !important;
  3533. \t\t\t\tanimation: pulse 2s infinite;
  3534. \t\t\t\tz-index: 10;
  3535. \t\t\t\tline-height: 1 !important;
  3536. \t\t\t}
  3537. \t\t\t/* Correction de l'alignement des boutons actifs dans prd-bottom */
  3538. \t\t\t/* Ne s'applique qu'aux boutons actifs pour éviter de casser le comportement hover */
  3539. \t\t\t.single-product .product-details .prd-bottom .social-info.active {
  3540. \t\t\t\tvertical-align: middle !important;
  3541. \t\t\t\tposition: relative !important;
  3542. \t\t\t\ttop: 0 !important;
  3543. \t\t\t\ttransform: none !important;
  3544. \t\t\t\tmargin: 0 !important;
  3545. \t\t\t\tpadding: 0 !important;
  3546. \t\t\t\tline-height: normal !important;
  3547. \t\t\t\twidth: 35px !important;
  3548. \t\t\t\theight: auto !important;
  3549. \t\t\t\tmin-height: auto !important;
  3550. \t\t\t\tmax-height: none !important;
  3551. \t\t\t}
  3552. \t\t\t.single-product .product-details .prd-bottom .social-info.wishlist-btn.active,
  3553. \t\t\t.single-product .product-details .prd-bottom .social-info.comparison-btn.active {
  3554. \t\t\t\tvertical-align: middle !important;
  3555. \t\t\t\tposition: relative !important;
  3556. \t\t\t\ttop: 0 !important;
  3557. \t\t\t\ttransform: none !important;
  3558. \t\t\t\tmargin: 0 !important;
  3559. \t\t\t\tpadding: 0 !important;
  3560. \t\t\t\tline-height: normal !important;
  3561. \t\t\t\twidth: 35px !important;
  3562. \t\t\t\theight: auto !important;
  3563. \t\t\t\tmin-height: auto !important;
  3564. \t\t\t\tmax-height: none !important;
  3565. \t\t\t}
  3566. \t\t\t.single-product .product-details .prd-bottom .social-info.active .hover-text {
  3567. \t\t\t\tmargin: 0 !important;
  3568. \t\t\t\tpadding: 0 !important;
  3569. \t\t\t\tline-height: normal !important;
  3570. \t\t\t\tposition: absolute !important;
  3571. \t\t\t\ttop: 0 !important;
  3572. \t\t\t\tbackground: #ffa200 !important;
  3573. \t\t\t\tleft: -40px !important;
  3574. \t\t\t}
  3575. \t\t\t/* S'assurer qu'aucune marge supplémentaire n'est ajoutée quand un bouton est actif */
  3576. \t\t\t.single-product .product-details .prd-bottom .social-info.active span,
  3577. \t\t\t.single-product .product-details .prd-bottom .social-info.active p {
  3578. \t\t\t\tmargin: 0 !important;
  3579. \t\t\t\tpadding: 0 !important;
  3580. \t\t\t}
  3581. \t\t\t/* Empêcher le hover de changer la largeur quand le bouton est actif */
  3582. \t\t\t.single-product .product-details .prd-bottom .social-info.active:hover {
  3583. \t\t\t\twidth: 35px !important;
  3584. \t\t\t}
  3585. \t\t\t.comparison-icon:hover .comparison-badge {
  3586. \t\t\t\tanimation: none;
  3587. \t\t\t}
  3588. \t\t\t/* Styles pour les mega-menus - style comme la barre de recherche */
  3589. \t\t\t.mega-menu {
  3590. \t\t\t\twidth: 100%;
  3591. \t\t\t\tmax-width: 1200px;
  3592. \t\t\t\tleft: 50%;
  3593. \t\t\t\ttransform: translateX(-50%);
  3594. \t\t\t\tpadding: 25px;
  3595. \t\t\t\tborder-radius: 12px;
  3596. \t\t\t\tbox-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
  3597. \t\t\t\tborder: none;
  3598. \t\t\t\tbackground: white;
  3599. \t\t\t\tdisplay: none;
  3600. \t\t\t\tposition: absolute;
  3601. \t\t\t\ttop: 100%;
  3602. \t\t\t\tz-index: 9999 !important;
  3603. \t\t\t\tmargin-top: 10px;
  3604. \t\t\t\topacity: 0;
  3605. \t\t\t\tvisibility: hidden;
  3606. \t\t\t\ttransition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
  3607. \t\t\t}
  3608. \t\t\t.mega-menu.active {
  3609. \t\t\t\tdisplay: block;
  3610. \t\t\t\topacity: 1;
  3611. \t\t\t\tvisibility: visible;
  3612. \t\t\t\ttransform: translateX(-50%) translateY(0);
  3613. \t\t\t}
  3614. \t\t\t.nav-item.dropdown {
  3615. \t\t\t\tposition: relative !important;
  3616. \t\t\t}
  3617. \t\t\t@media(min-width: 768px) {
  3618. \t\t\t\t.nav-item.dropdown {
  3619. \t\t\t\t\tposition: relative !important;
  3620. \t\t\t\t}
  3621. \t\t\t\t.mega-menu {
  3622. \t\t\t\t\tposition: absolute !important;
  3623. \t\t\t\t\tleft: 50% !important;
  3624. \t\t\t\t\ttransform: translateX(-50%) !important;
  3625. \t\t\t\t\twidth: auto !important;
  3626. \t\t\t\t\tmin-width: 600px !important;
  3627. \t\t\t\t}
  3628. \t\t\t}
  3629. \t\t\t/* Correction supplémentaire pour l'affichage sur la page d'accueil */
  3630. \t\t\tbody.home .nav-item.dropdown,
  3631. \t\t\t.nav-item.dropdown {
  3632. \t\t\t\tposition: relative !important;
  3633. \t\t\t}
  3634. \t\t\tbody.home .mega-menu,
  3635. \t\t\t.mega-menu {
  3636. \t\t\t\tposition: absolute !important;
  3637. \t\t\t\tleft: 50% !important;
  3638. \t\t\t\ttransform: translateX(-50%) translateY(0) !important;
  3639. \t\t\t\twidth: auto !important;
  3640. \t\t\t\tmin-width: 600px !important;
  3641. \t\t\t\tmax-width: 90% !important;
  3642. \t\t\t\ttop: 100% !important;
  3643. \t\t\t\tmargin-top: 10px !important;
  3644. \t\t\t}
  3645. \t\t\t/* Assurer que les mega-menus sont toujours visibles au survol */
  3646. \t\t\t.nav-item.dropdown:hover .mega-menu {
  3647. \t\t\t\topacity: 1 !important;
  3648. \t\t\t\tvisibility: visible !important;
  3649. \t\t\t\tdisplay: block !important;
  3650. \t\t\t\ttransform: translateX(-50%) translateY(0) !important;
  3651. \t\t\t}
  3652. \t\t\t.mega-menu .dropdown-item {
  3653. \t\t\t\tpadding: 0;
  3654. \t\t\t\tborder: none;
  3655. \t\t\t}
  3656. \t\t\t.mega-menu .dropdown-header {
  3657. \t\t\t\tfont-weight: 700;
  3658. \t\t\t\tcolor: #2c3e50;
  3659. \t\t\t\tmargin-bottom: 18px;
  3660. \t\t\t\tpadding-bottom: 10px;
  3661. \t\t\t\tborder-bottom: 3px solid #3498db;
  3662. \t\t\t\tfont-size: 16px;
  3663. \t\t\t\ttext-transform: uppercase;
  3664. \t\t\t\tletter-spacing: 0.5px;
  3665. \t\t\t}
  3666. \t\t\t.mega-menu .dropdown-item a {
  3667. \t\t\t\tdisplay: block;
  3668. \t\t\t\tpadding: 10px 15px;
  3669. \t\t\t\tcolor: #555;
  3670. \t\t\t\ttext-decoration: none;
  3671. \t\t\t\tborder-radius: 6px;
  3672. \t\t\t\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  3673. \t\t\t\tposition: relative;
  3674. \t\t\t\toverflow: hidden;
  3675. \t\t\t}
  3676. \t\t\t.mega-menu .dropdown-item a::before {
  3677. \t\t\t\tcontent: '';
  3678. \t\t\t\tposition: absolute;
  3679. \t\t\t\ttop: 0;
  3680. \t\t\t\tleft: -100%;
  3681. \t\t\t\twidth: 100%;
  3682. \t\t\t\theight: 100%;
  3683. \t\t\t\tbackground: linear-gradient(90deg, transparent, rgba(52, 152, 219, 0.1), transparent);
  3684. \t\t\t\ttransition: left 0.5s;
  3685. \t\t\t}
  3686. \t\t\t.mega-menu .dropdown-item a:hover::before {
  3687. \t\t\t\tleft: 100%;
  3688. \t\t\t}
  3689. \t\t\t.mega-menu .dropdown-item a:hover {
  3690. \t\t\t\tbackground: linear-gradient(135deg, #f8f9fa, #e3f2fd);
  3691. \t\t\t\tcolor: #2980b9;
  3692. \t\t\t\ttransform: translateX(8px);
  3693. \t\t\t\tbox-shadow: 0 2px 8px rgba(52, 152, 219, 0.2);
  3694. \t\t\t}
  3695. \t\t\t.mega-menu .dropdown-item a i {
  3696. \t\t\t\twidth: 22px;
  3697. \t\t\t\ttext-align: center;
  3698. \t\t\t\tmargin-right: 8px;
  3699. \t\t\t\tcolor: #3498db;
  3700. \t\t\t\ttransition: color 0.3s ease;
  3701. \t\t\t}
  3702. \t\t\t.mega-menu .dropdown-item a:hover i {
  3703. \t\t\t\tcolor: #2980b9;
  3704. \t\t\t}
  3705. \t\t\t/* Animation d'apparition améliorée */
  3706. \t\t\t@keyframes slideInDown {
  3707. \t\t\t\tfrom {
  3708. \t\t\t\t\topacity: 0;
  3709. \t\t\t\t\ttransform: translateY(-20px);
  3710. \t\t\t\t}
  3711. \t\t\t\tto {
  3712. \t\t\t\t\topacity: 1;
  3713. \t\t\t\t\ttransform: translateY(0);
  3714. \t\t\t\t}
  3715. \t\t\t}
  3716. \t\t\t.mega-menu {
  3717. \t\t\t\tanimation: slideInDown 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  3718. \t\t\t}
  3719. \t\t\t/* Effet de survol sur le lien principal */
  3720. \t\t\t.nav-item.dropdown .nav-link {
  3721. \t\t\t\tposition: relative;
  3722. \t\t\t\ttransition: all 0.3s ease;
  3723. \t\t\t}
  3724. \t\t\t.nav-item.dropdown .nav-link::after {
  3725. \t\t\t\tcontent: '';
  3726. \t\t\t\tposition: absolute;
  3727. \t\t\t\tbottom: -2px;
  3728. \t\t\t\tleft: 50%;
  3729. \t\t\t\twidth: 0;
  3730. \t\t\t\theight: 2px;
  3731. \t\t\t\tbackground: linear-gradient(90deg, #3498db, #2980b9);
  3732. \t\t\t\ttransition: all 0.3s ease;
  3733. \t\t\t\ttransform: translateX(-50%);
  3734. \t\t\t}
  3735. \t\t\t.nav-item.dropdown:hover .nav-link::after {
  3736. \t\t\t\twidth: 100%;
  3737. \t\t\t}
  3738. \t\t\t.nav-item.dropdown:hover .nav-link {
  3739. \t\t\t\tcolor: #2980b9;
  3740. \t\t\t}
  3741. \t\t\t@keyframes fadeInDown {
  3742. \t\t\t\tfrom {
  3743. \t\t\t\t\topacity: 0;
  3744. \t\t\t\t\ttransform: translateY(-10px);
  3745. \t\t\t\t}
  3746. \t\t\t\tto {
  3747. \t\t\t\t\topacity: 1;
  3748. \t\t\t\t\ttransform: translateY(0);
  3749. \t\t\t\t}
  3750. \t\t\t}
  3751. \t\t\t/* Responsive */
  3752. \t\t\t@media(max-width: 768px) {
  3753. \t\t\t\t.mega-menu {
  3754. \t\t\t\t\twidth: 100%;
  3755. \t\t\t\t\tleft: 0;
  3756. \t\t\t\t\tpadding: 15px;
  3757. \t\t\t\t}
  3758. \t\t\t\t.mega-menu .row {
  3759. \t\t\t\t\tmargin: 0;
  3760. \t\t\t\t}
  3761. \t\t\t\t.mega-menu .col-md-3 {
  3762. \t\t\t\t\tmargin-bottom: 20px;
  3763. \t\t\t\t}
  3764. \t\t\t}
  3765. \t\t\t/* ============================================
  3766. \t\t\t.footer-area {
  3767. \t\t\t\tbackground: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
  3768. \t\t\t\tposition: relative;
  3769. \t\t\t\toverflow: hidden;
  3770. \t\t\t\tpadding: 50px 0 20px;
  3771. \t\t\t}
  3772. \t\t\t.footer-pattern {
  3773. \t\t\t\tposition: absolute;
  3774. \t\t\t\ttop: 0;
  3775. \t\t\t\tleft: 0;
  3776. \t\t\t\tright: 0;
  3777. \t\t\t\tbottom: 0;
  3778. \t\t\t\tbackground-image: radial-gradient(circle at 20% 50%, rgba(255, 162, 0, 0.1) 0%, transparent 50%), radial-gradient(circle at 80% 80%, rgba(255, 162, 0, 0.08) 0%, transparent 50%);
  3779. \t\t\t\tpointer-events: none;
  3780. \t\t\t}
  3781. \t\t\t.footer-area .container {
  3782. \t\t\t\tposition: relative;
  3783. \t\t\t\tz-index: 1;
  3784. \t\t\t}
  3785. \t\t\t/* Widgets */
  3786. \t\t\t.single-footer-widget {
  3787. \t\t\t\tcolor: rgba(255, 255, 255, 0.9);
  3788. \t\t\t}
  3789. \t\t\t.footer-brand {
  3790. \t\t\t\tfont-size: 1.6rem;
  3791. \t\t\t\tfont-weight: 700;
  3792. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  3793. \t\t\t\t-webkit-background-clip: text;
  3794. \t\t\t\t-webkit-text-fill-color: transparent;
  3795. \t\t\t\tbackground-clip: text;
  3796. \t\t\t\tmargin-bottom: 12px;
  3797. \t\t\t\tdisplay: inline-block;
  3798. \t\t\t}
  3799. \t\t\t.footer-widget-title {
  3800. \t\t\t\tcolor: #fff;
  3801. \t\t\t\tfont-size: 1rem;
  3802. \t\t\t\tfont-weight: 600;
  3803. \t\t\t\tmargin-bottom: 18px;
  3804. \t\t\t\tposition: relative;
  3805. \t\t\t\tpadding-bottom: 8px;
  3806. \t\t\t}
  3807. \t\t\t.footer-widget-title::after {
  3808. \t\t\t\tcontent: '';
  3809. \t\t\t\tposition: absolute;
  3810. \t\t\t\tbottom: 0;
  3811. \t\t\t\tleft: 0;
  3812. \t\t\t\twidth: 40px;
  3813. \t\t\t\theight: 3px;
  3814. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  3815. \t\t\t\tborder-radius: 2px;
  3816. \t\t\t}
  3817. \t\t\t.footer-description {
  3818. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  3819. \t\t\t\tline-height: 1.6;
  3820. \t\t\t\tfont-size: 0.9rem;
  3821. \t\t\t\tmargin-bottom: 0;
  3822. \t\t\t}
  3823. \t\t\t/* Liste de liens */
  3824. \t\t\t.footer-list {
  3825. \t\t\t\tlist-style: none;
  3826. \t\t\t\tpadding: 0;
  3827. \t\t\t\tmargin: 0;
  3828. \t\t\t}
  3829. \t\t\t.footer-list li {
  3830. \t\t\t\tmargin-bottom: 10px;
  3831. \t\t\t}
  3832. \t\t\t.footer-list li a {
  3833. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  3834. \t\t\t\ttext-decoration: none;
  3835. \t\t\t\ttransition: all 0.3s ease;
  3836. \t\t\t\tfont-size: 0.9rem;
  3837. \t\t\t\tdisplay: inline-flex;
  3838. \t\t\t\talign-items: center;
  3839. \t\t\t}
  3840. \t\t\t.footer-list li a i {
  3841. \t\t\t\tfont-size: 0.8rem;
  3842. \t\t\t\topacity: 0.6;
  3843. \t\t\t\ttransition: all 0.3s ease;
  3844. \t\t\t}
  3845. \t\t\t.footer-list li a:hover {
  3846. \t\t\t\tcolor: #ffa200;
  3847. \t\t\t\ttransform: translateX(5px);
  3848. \t\t\t}
  3849. \t\t\t.footer-list li a:hover i {
  3850. \t\t\t\topacity: 1;
  3851. \t\t\t\tcolor: #ffa200;
  3852. \t\t\t}
  3853. \t\t\t/* Newsletter */
  3854. \t\t\t.footer-newsletter-text {
  3855. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  3856. \t\t\t\tfont-size: 0.85rem;
  3857. \t\t\t\tmargin-bottom: 15px;
  3858. \t\t\t\tline-height: 1.5;
  3859. \t\t\t}
  3860. \t\t\t.footer-newsletter-wrapper {
  3861. \t\t\t\tmargin-bottom: 15px;
  3862. \t\t\t}
  3863. \t\t\t.newsletter-input-group {
  3864. \t\t\t\tdisplay: flex;
  3865. \t\t\t\talign-items: center;
  3866. \t\t\t\tbackground: rgba(255, 255, 255, 0.08);
  3867. \t\t\t\tborder-radius: 30px;
  3868. \t\t\t\tpadding: 4px 4px 4px 15px;
  3869. \t\t\t\tbackdrop-filter: blur(10px);
  3870. \t\t\t\tborder: 1px solid rgba(255, 255, 255, 0.15);
  3871. \t\t\t\ttransition: all 0.3s ease;
  3872. \t\t\t\tgap: 8px;
  3873. \t\t\t}
  3874. \t\t\t.newsletter-input-group:focus-within {
  3875. \t\t\t\tbackground: rgba(255, 255, 255, 0.12);
  3876. \t\t\t\tborder-color: rgba(255, 162, 0, 0.6);
  3877. \t\t\t\tbox-shadow: 0 0 0 2px rgba(255, 162, 0, 0.15);
  3878. \t\t\t}
  3879. \t\t\t.newsletter-icon {
  3880. \t\t\t\tcolor: rgba(255, 255, 255, 0.5);
  3881. \t\t\t\tfont-size: 0.9rem;
  3882. \t\t\t\tflex-shrink: 0;
  3883. \t\t\t}
  3884. \t\t\t.newsletter-input-group:focus-within .newsletter-icon {
  3885. \t\t\t\tcolor: #ffa200;
  3886. \t\t\t}
  3887. \t\t\t.newsletter-input {
  3888. \t\t\t\tflex: 1;
  3889. \t\t\t\tbackground: transparent;
  3890. \t\t\t\tborder: none;
  3891. \t\t\t\tcolor: #fff;
  3892. \t\t\t\tpadding: 10px 8px;
  3893. \t\t\t\tfont-size: 0.9rem;
  3894. \t\t\t\tmin-width: 0;
  3895. \t\t\t}
  3896. \t\t\t.newsletter-input::placeholder {
  3897. \t\t\t\tcolor: rgba(255, 255, 255, 0.4);
  3898. \t\t\t\tfont-size: 0.85rem;
  3899. \t\t\t}
  3900. \t\t\t.newsletter-input:focus {
  3901. \t\t\t\toutline: none;
  3902. \t\t\t\tbox-shadow: none;
  3903. \t\t\t}
  3904. \t\t\t.newsletter-btn {
  3905. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  3906. \t\t\t\tborder: none;
  3907. \t\t\t\tcolor: white;
  3908. \t\t\t\twidth: 42px;
  3909. \t\t\t\theight: 42px;
  3910. \t\t\t\tmin-width: 42px;
  3911. \t\t\t\tmin-height: 42px;
  3912. \t\t\t\tborder-radius: 50%;
  3913. \t\t\t\tdisplay: flex;
  3914. \t\t\t\talign-items: center;
  3915. \t\t\t\tjustify-content: center;
  3916. \t\t\t\tcursor: pointer;
  3917. \t\t\t\ttransition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  3918. \t\t\t\tflex-shrink: 0;
  3919. \t\t\t\tbox-shadow: 0 4px 15px rgba(255, 162, 0, 0.4), 0 0 0 0 rgba(255, 162, 0, 0.4);
  3920. \t\t\t\tfont-size: 0.9rem;
  3921. \t\t\t\tposition: relative;
  3922. \t\t\t\toverflow: hidden;
  3923. \t\t\t}
  3924. \t\t\t.newsletter-btn::before {
  3925. \t\t\t\tcontent: '';
  3926. \t\t\t\tposition: absolute;
  3927. \t\t\t\ttop: 50%;
  3928. \t\t\t\tleft: 50%;
  3929. \t\t\t\twidth: 0;
  3930. \t\t\t\theight: 0;
  3931. \t\t\t\tborder-radius: 50%;
  3932. \t\t\t\tbackground: rgba(255, 255, 255, 0.3);
  3933. \t\t\t\ttransform: translate(-50%, -50%);
  3934. \t\t\t\ttransition: width 0.6s ease, height 0.6s ease;
  3935. \t\t\t}
  3936. \t\t\t.newsletter-btn:hover::before {
  3937. \t\t\t\twidth: 100%;
  3938. \t\t\t\theight: 100%;
  3939. \t\t\t}
  3940. \t\t\t.newsletter-btn:hover {
  3941. \t\t\t\ttransform: translateX(3px) scale(1.05);
  3942. \t\t\t\tbox-shadow: 0 6px 20px rgba(255, 162, 0, 0.5), 0 0 0 8px rgba(255, 162, 0, 0.1);
  3943. \t\t\t\tbackground: linear-gradient(135deg, #e8910a 0%, #ffa200 100%);
  3944. \t\t\t}
  3945. \t\t\t.newsletter-btn:active {
  3946. \t\t\t\ttransform: translateX(3px) scale(0.98);
  3947. \t\t\t\tbox-shadow: 0 3px 10px rgba(255, 162, 0, 0.4);
  3948. \t\t\t}
  3949. \t\t\t.newsletter-btn:focus {
  3950. \t\t\t\toutline: none;
  3951. \t\t\t\tbox-shadow: 0 4px 15px rgba(255, 162, 0, 0.4), 0 0 0 3px rgba(255, 162, 0, 0.3);
  3952. \t\t\t}
  3953. \t\t\t.newsletter-btn-icon,
  3954. \t\t\t.newsletter-btn-loader {
  3955. \t\t\t\tposition: relative;
  3956. \t\t\t\tz-index: 2;
  3957. \t\t\t\tdisplay: flex;
  3958. \t\t\t\talign-items: center;
  3959. \t\t\t\tjustify-content: center;
  3960. \t\t\t\ttransition: all 0.3s ease;
  3961. \t\t\t}
  3962. \t\t\t.newsletter-btn:hover .newsletter-btn-icon {
  3963. \t\t\t\ttransform: translateX(2px) rotate(-10deg);
  3964. \t\t\t}
  3965. \t\t\t.newsletter-btn.loading .newsletter-btn-icon {
  3966. \t\t\t\topacity: 0;
  3967. \t\t\t\ttransform: scale(0);
  3968. \t\t\t}
  3969. \t\t\t.newsletter-btn.loading .newsletter-btn-loader {
  3970. \t\t\t\tdisplay: flex !important;
  3971. \t\t\t}
  3972. \t\t\t.newsletter-btn.success {
  3973. \t\t\t\tbackground: linear-gradient(135deg, #28a745 0%, #20c997 100%);
  3974. \t\t\t\tbox-shadow: 0 4px 15px rgba(40, 167, 69, 0.4);
  3975. \t\t\t}
  3976. \t\t\t.newsletter-btn.success .newsletter-btn-icon i::before {
  3977. \t\t\t\tcontent: \"\\f00c\";
  3978. \t\t\t}
  3979. \t\t\t/* Trust badges */
  3980. \t\t\t.footer-trust-badges {
  3981. \t\t\t\tdisplay: flex;
  3982. \t\t\t\tflex-direction: row;
  3983. \t\t\t\tgap: 15px;
  3984. \t\t\t\tflex-wrap: wrap;
  3985. \t\t\t}
  3986. \t\t\t.trust-item {
  3987. \t\t\t\tdisplay: flex;
  3988. \t\t\t\talign-items: center;
  3989. \t\t\t\tgap: 6px;
  3990. \t\t\t\tcolor: rgba(255, 255, 255, 0.6);
  3991. \t\t\t\tfont-size: 0.8rem;
  3992. \t\t\t}
  3993. \t\t\t.trust-item i {
  3994. \t\t\t\tcolor: #ffa200;
  3995. \t\t\t\tfont-size: 0.9rem;
  3996. \t\t\t}
  3997. \t\t\t/* Social icons */
  3998. \t\t\t.footer-social {
  3999. \t\t\t\tmargin-top: 0 !important;
  4000. \t\t\t\tposition: relative !important;
  4001. \t\t\t\twidth: 100% !important;
  4002. \t\t\t\tclear: both !important;
  4003. \t\t\t\tfloat: none !important;
  4004. \t\t\t}
  4005. \t\t\t.footer-social h6 {
  4006. \t\t\t\tcolor: #fff;
  4007. \t\t\t\tfont-size: 0.95rem;
  4008. \t\t\t\tfont-weight: 600;
  4009. \t\t\t\tmargin-bottom: 12px !important;
  4010. \t\t\t\tdisplay: block !important;
  4011. \t\t\t\twidth: 100% !important;
  4012. \t\t\t\tposition: relative !important;
  4013. \t\t\t\tclear: both !important;
  4014. \t\t\t\tfloat: none !important;
  4015. \t\t\t}
  4016. \t\t\t.footer-social-icons {
  4017. \t\t\t\tdisplay: flex !important;
  4018. \t\t\t\tgap: 12px !important;
  4019. \t\t\t\tflex-wrap: wrap !important;
  4020. \t\t\t\talign-items: center !important;
  4021. \t\t\t\tjustify-content: flex-start !important;
  4022. \t\t\t\twidth: 100% !important;
  4023. \t\t\t\tposition: relative !important;
  4024. \t\t\t\tclear: both !important;
  4025. \t\t\t\tfloat: none !important;
  4026. \t\t\t\tmargin: 0 !important;
  4027. \t\t\t\tpadding: 0 !important;
  4028. \t\t\t}
  4029. \t\t\t.social-icon {
  4030. \t\t\t\twidth: 38px !important;
  4031. \t\t\t\theight: 38px !important;
  4032. \t\t\t\tmin-width: 38px !important;
  4033. \t\t\t\tmin-height: 38px !important;
  4034. \t\t\t\tdisplay: inline-flex !important;
  4035. \t\t\t\talign-items: center !important;
  4036. \t\t\t\tjustify-content: center !important;
  4037. \t\t\t\tbackground: rgba(255, 255, 255, 0.1) !important;
  4038. \t\t\t\tborder-radius: 50% !important;
  4039. \t\t\t\tcolor: rgba(255, 255, 255, 0.8) !important;
  4040. \t\t\t\ttext-decoration: none !important;
  4041. \t\t\t\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
  4042. \t\t\t\tfont-size: 16px !important;
  4043. \t\t\t\tline-height: 1 !important;
  4044. \t\t\t\tbackdrop-filter: blur(10px) !important;
  4045. \t\t\t\tborder: 1px solid rgba(255, 255, 255, 0.1) !important;
  4046. \t\t\t\tflex-shrink: 0 !important;
  4047. \t\t\t\tposition: relative !important;
  4048. \t\t\t\tfloat: none !important;
  4049. \t\t\t\tmargin: 0 !important;
  4050. \t\t\t\tpadding: 0 !important;
  4051. \t\t\t\tvertical-align: middle !important;
  4052. \t\t\t}
  4053. \t\t\t.social-icon i {
  4054. \t\t\t\tfont-size: 16px !important;
  4055. \t\t\t\tline-height: 1 !important;
  4056. \t\t\t\tdisplay: inline-block !important;
  4057. \t\t\t\ttransition: transform 0.3s ease !important;
  4058. \t\t\t\tposition: relative !important;
  4059. \t\t\t\tz-index: 1 !important;
  4060. \t\t\t\tmargin: 0 !important;
  4061. \t\t\t\tpadding: 0 !important;
  4062. \t\t\t}
  4063. \t\t\t.social-icon:hover {
  4064. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%) !important;
  4065. \t\t\t\ttransform: translateY(-5px) scale(1.1) !important;
  4066. \t\t\t\tcolor: white !important;
  4067. \t\t\t\tborder-color: transparent !important;
  4068. \t\t\t\tbox-shadow: 0 8px 20px rgba(255, 162, 0, 0.4) !important;
  4069. \t\t\t}
  4070. \t\t\t.social-icon:hover i {
  4071. \t\t\t\ttransform: scale(1.1) !important;
  4072. \t\t\t}
  4073. \t\t\t/* Footer divider */
  4074. \t\t\t.footer-divider {
  4075. \t\t\t\theight: 1px;
  4076. \t\t\t\tbackground: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  4077. \t\t\t\tmargin: 30px 0 20px;
  4078. \t\t\t}
  4079. \t\t\t/* Footer bottom */
  4080. \t\t\t.footer-bottom {
  4081. \t\t\t\tpadding-top: 15px;
  4082. \t\t\t}
  4083. \t\t\t.footer-text {
  4084. \t\t\t\tcolor: rgba(255, 255, 255, 0.6);
  4085. \t\t\t\tfont-size: 0.9rem;
  4086. \t\t\t\tmargin: 0;
  4087. \t\t\t\ttext-align: center;
  4088. \t\t\t}
  4089. \t\t\t/* Responsive */
  4090. \t\t\t@media(max-width: 991.98px) {
  4091. \t\t\t\t.footer-area {
  4092. \t\t\t\t\tpadding: 40px 0 20px;
  4093. \t\t\t\t}
  4094. \t\t\t\t.single-footer-widget {
  4095. \t\t\t\t\tmargin-bottom: 30px;
  4096. \t\t\t\t}
  4097. \t\t\t\t.footer-social {
  4098. \t\t\t\t\tmargin-top: 15px;
  4099. \t\t\t\t}
  4100. \t\t\t}
  4101. \t\t\t@media(max-width: 767.98px) {
  4102. \t\t\t\t.footer-area {
  4103. \t\t\t\t\tpadding: 35px 0 18px;
  4104. \t\t\t\t}
  4105. \t\t\t\t.footer-brand {
  4106. \t\t\t\t\tfont-size: 1.4rem;
  4107. \t\t\t\t}
  4108. \t\t\t\t.footer-widget-title {
  4109. \t\t\t\t\tfont-size: 0.95rem;
  4110. \t\t\t\t}
  4111. \t\t\t\t.newsletter-input-group {
  4112. \t\t\t\t\tpadding: 3px 3px 3px 12px;
  4113. \t\t\t\t}
  4114. \t\t\t\t.newsletter-input {
  4115. \t\t\t\t\tpadding: 8px 6px;
  4116. \t\t\t\t\tfont-size: 0.85rem;
  4117. \t\t\t\t}
  4118. \t\t\t\t.newsletter-btn {
  4119. \t\t\t\t\twidth: 38px;
  4120. \t\t\t\t\theight: 38px;
  4121. \t\t\t\t\tmin-width: 38px;
  4122. \t\t\t\t\tmin-height: 38px;
  4123. \t\t\t\t\tfont-size: 0.85rem;
  4124. \t\t\t\t}
  4125. \t\t\t\t.footer-trust-badges {
  4126. \t\t\t\t\tflex-direction: row;
  4127. \t\t\t\t\tflex-wrap: wrap;
  4128. \t\t\t\t\tjustify-content: flex-start;
  4129. \t\t\t\t\tgap: 12px;
  4130. \t\t\t\t}
  4131. \t\t\t}
  4132. \t\t\t@media(max-width: 575.98px) {
  4133. \t\t\t\t.footer-area {
  4134. \t\t\t\t\tpadding: 40px 0 20px;
  4135. \t\t\t\t}
  4136. \t\t\t\t.footer-brand {
  4137. \t\t\t\t\tfont-size: 1.3rem;
  4138. \t\t\t\t}
  4139. \t\t\t\t.social-icon {
  4140. \t\t\t\t\twidth: 38px;
  4141. \t\t\t\t\theight: 38px;
  4142. \t\t\t\t\tfont-size: 16px;
  4143. \t\t\t\t}
  4144. \t\t\t\t.social-icon i {
  4145. \t\t\t\t\tfont-size: 16px;
  4146. \t\t\t\t}
  4147. \t\t\t}
  4148. \t\t</style>
  4149. \t\t{% block stylesheets %}
  4150. \t\t\t{{ encore_entry_link_tags('app') }}
  4151. \t\t{% endblock %}
  4152. \t\t<!-- Script pour forcer l'application des styles CSS après chargement -->
  4153. \t\t<script>
  4154. \t\t\tdocument.addEventListener('DOMContentLoaded', function () { // Forcer le masquage du toggle sur grands écrans
  4155. if (window.innerWidth >= 992) {
  4156. const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
  4157. togglers.forEach(function (toggler) {
  4158. if (toggler) {
  4159. toggler.style.display = 'none';
  4160. toggler.style.visibility = 'hidden';
  4161. toggler.style.opacity = '0';
  4162. toggler.style.width = '0';
  4163. toggler.style.height = '0';
  4164. toggler.style.padding = '0';
  4165. toggler.style.margin = '0';
  4166. toggler.style.border = 'none';
  4167. toggler.style.position = 'absolute';
  4168. toggler.style.left = '-9999px';
  4169. }
  4170. });
  4171. const iconBars = document.querySelectorAll('.navbar-toggler .icon-bar, .header_area .navbar .navbar-toggler .icon-bar, .navbar-toggler-icon');
  4172. iconBars.forEach(function (bar) {
  4173. if (bar) {
  4174. bar.style.display = 'none';
  4175. bar.style.visibility = 'hidden';
  4176. }
  4177. });
  4178. }
  4179. // Alignement des icônes navbar sur mobile
  4180. const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
  4181. navbarRight.forEach(function (nav) {
  4182. if (nav && window.innerWidth<= 991.98) {
  4183.                     // Mobile: colonne avec icônes alignées horizontalement
  4184.                     nav.style.display = 'flex';
  4185.                     nav.style.flexDirection = 'column';
  4186.                     nav.style.alignItems = 'center';
  4187.                     nav.style.textAlign = 'center';
  4188.                     
  4189.                     // Le container d'icônes reste horizontal
  4190.                     const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
  4191.                     if (iconsContainer) {
  4192.                         iconsContainer.style.display = 'flex';
  4193.                         iconsContainer.style.flexDirection = 'row';
  4194.                         iconsContainer.style.justifyContent = 'center';
  4195.                     }
  4196.                     
  4197.                     // Le bouton compte en bas
  4198.                     const accountBtn = nav.querySelector('li:last-child');
  4199.                     if (accountBtn) {
  4200.                         accountBtn.style.width = '100%';
  4201.                         accountBtn.style.display = 'flex';
  4202.                         accountBtn.style.justifyContent = 'center';
  4203.                         accountBtn.style.marginTop = '12px';
  4204.                         accountBtn.style.paddingTop = '12px';
  4205.                         accountBtn.style.borderTop = '1px solid #e0e0e0';
  4206.                     }
  4207.                 } else if (nav && window.innerWidth> 991.98) { // Desktop: alignement horizontal normal
  4208. nav.style.display = 'flex';
  4209. nav.style.flexDirection = 'row';
  4210. nav.style.alignItems = 'center';
  4211. nav.style.justifyContent = 'flex-end';
  4212. }
  4213. });
  4214. });
  4215. // Réappliquer lors du redimensionnement
  4216. window.addEventListener('resize', function () {
  4217. if (window.innerWidth >= 992) {
  4218. const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
  4219. togglers.forEach(function (toggler) {
  4220. if (toggler) {
  4221. toggler.style.display = 'none';
  4222. toggler.style.visibility = 'hidden';
  4223. }
  4224. });
  4225. }
  4226. // Réappliquer l'alignement des icônes navbar
  4227. const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
  4228. navbarRight.forEach(function (nav) {
  4229. if (nav && window.innerWidth<= 991.98) {
  4230.                     // Mobile: colonne avec icônes alignées horizontalement
  4231.                     nav.style.display = 'flex';
  4232.                     nav.style.flexDirection = 'column';
  4233.                     nav.style.alignItems = 'center';
  4234.                     nav.style.textAlign = 'center';
  4235.                     
  4236.                     // Le container d'icônes reste horizontal
  4237.                     const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
  4238.                     if (iconsContainer) {
  4239.                         iconsContainer.style.display = 'flex';
  4240.                         iconsContainer.style.flexDirection = 'row';
  4241.                         iconsContainer.style.justifyContent = 'center';
  4242.                     }
  4243.                     
  4244.                     const accountBtn = nav.querySelector('li:last-child');
  4245.                     if (accountBtn) {
  4246.                         accountBtn.style.width = '100%';
  4247.                         accountBtn.style.display = 'flex';
  4248.                         accountBtn.style.justifyContent = 'center';
  4249.                         accountBtn.style.marginTop = '12px';
  4250.                         accountBtn.style.paddingTop = '12px';
  4251.                         accountBtn.style.borderTop = '1px solid #e0e0e0';
  4252.                     }
  4253.                 } else if (nav && window.innerWidth> 991.98) { // Desktop: alignement horizontal normal
  4254. nav.style.display = 'flex';
  4255. nav.style.flexDirection = 'row';
  4256. nav.style.alignItems = 'center';
  4257. nav.style.justifyContent = 'flex-end';
  4258. }
  4259. });
  4260. });
  4261. \t\t</script>
  4262. \t</head>
  4263. \t<body
  4264. \t\t{% if current_menu is defined and current_menu == \"listing\" %} id=\"category\" {% endif %}
  4265. \t\tstyle=\"transition: background-color 0.3s ease, color 0.3s ease;\"
  4266. \t\tclass=\"theme-transition\">
  4267. \t\t<!-- Start Header Area -->
  4268. \t\t<header class=\"header_area sticky-header\">
  4269. \t\t\t<div class=\"main_menu\">
  4270. \t\t\t\t<nav class=\"navbar navbar-expand-lg navbar-light main_box\">
  4271. \t\t\t\t\t<div
  4272. \t\t\t\t\t\tclass=\"container\">
  4273. \t\t\t\t\t\t<!-- Brand and toggle get grouped for better mobile display -->
  4274. \t\t\t\t\t\t<a class=\"navbar-brand logo_h\" href=\"{{ path('ui_home') }}\"><img style=\"width: auto;height: 60px\" src=\"{{ asset('logo.png') }}\" alt=\"\"></a>
  4275. \t\t\t\t\t\t<button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarSupportedContent\" aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">
  4276. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  4277. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  4278. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  4279. \t\t\t\t\t\t</button>
  4280. \t\t\t\t\t\t<!-- Collect the nav links, forms, and other content for toggling -->
  4281. \t\t\t\t\t\t<div class=\"collapse navbar-collapse offset\" id=\"navbarSupportedContent\">
  4282. \t\t\t\t\t\t\t<ul class=\"nav navbar-nav menu_nav ml-auto\">
  4283. \t\t\t\t\t\t\t\t<li class=\"nav-item {% if current_menu is defined and current_menu == \" home\" %}active{% endif %}\">
  4284. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"{{ path('ui_home') }}\">Accueil</a>
  4285. \t\t\t\t\t\t\t\t</li>
  4286. \t\t\t\t\t\t\t\t<li class=\"nav-item {% if current_menu is defined and current_menu == \" shops\" %}active{% endif %}\">
  4287. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"{{ path('ui_shops_list') }}\">Boutiques</a>
  4288. \t\t\t\t\t\t\t\t</li>
  4289. \t\t\t\t\t\t\t\t<li class=\"nav-item {% if current_menu is defined and current_menu == \" listing\" %}active{% endif %}\">
  4290. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"{{ path('ui_listing') }}\">Produits</a>
  4291. \t\t\t\t\t\t\t\t</li>
  4292. \t\t\t\t\t\t\t\t<li class=\"nav-item {% if current_menu is defined and current_menu == \" contact\" %}active{% endif %}\">
  4293. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"{{ path('ui_contact') }}\">Contact</a>
  4294. \t\t\t\t\t\t\t\t</li>
  4295. \t\t\t\t\t\t\t</ul>
  4296. \t\t\t\t\t\t\t<ul class=\"nav navbar-nav navbar-right\">
  4297. \t\t\t\t\t\t\t\t<li class=\"nav-item\">
  4298. \t\t\t\t\t\t\t\t\t<div class=\"navbar-icons-wrapper\">
  4299. \t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_cart') }}\" class=\"cart {% if current_menu is defined and current_menu == \" cart\" %}active{% endif %}\" aria-label=\"Panier\">
  4300. \t\t\t\t\t\t\t\t\t\t\t<span class=\"ti-bag\"></span>
  4301. \t\t\t\t\t\t\t\t\t\t</a>
  4302. \t\t\t\t\t\t\t\t\t\t{% if app.user %}
  4303. \t\t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('notifications_list') }}\" class=\"notification-icon\" title=\"Notifications\" aria-label=\"Notifications\">
  4304. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"ti-bell\"></span>
  4305. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"notification-badge text-white\" id=\"notificationBadge\" style=\"display: none;color: white;\">0</span>
  4306. \t\t\t\t\t\t\t\t\t\t\t</a>
  4307. \t\t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_product_comparison') }}\" class=\"comparison-icon\" title=\"Comparaison\" aria-label=\"Comparaison\">
  4308. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"lnr lnr-sync\"></span>
  4309. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"comparison-badge text-white\" id=\"comparisonBadge\" style=\"display: none;color: white;\">0</span>
  4310. \t\t\t\t\t\t\t\t\t\t\t</a>
  4311. \t\t\t\t\t\t\t\t\t\t{% endif %}
  4312. \t\t\t\t\t\t\t\t\t\t{{ include('components/_dark_mode_toggle.html.twig') }}
  4313. \t\t\t\t\t\t\t\t\t\t<button class=\"search\" type=\"button\" aria-label=\"Recherche\">
  4314. \t\t\t\t\t\t\t\t\t\t\t<span class=\"lnr lnr-magnifier\" id=\"search\"></span>
  4315. \t\t\t\t\t\t\t\t\t\t</button>
  4316. \t\t\t\t\t\t\t\t\t</div>
  4317. \t\t\t\t\t\t\t\t</li>
  4318. \t\t\t\t\t\t\t\t<li class=\"nav-item\">
  4319. \t\t\t\t\t\t\t\t\t{% if app.user %}
  4320. \t\t\t\t\t\t\t\t\t\t<a class=\"nav-link btn btn-primary btn-account text-white\" href=\"{{ path('ui_account_index') }}\">
  4321. \t\t\t\t\t\t\t\t\t\t\t<i class=\"ti-user\"></i>
  4322. \t\t\t\t\t\t\t\t\t\t\tMon compte
  4323. \t\t\t\t\t\t\t\t\t\t</a>
  4324. \t\t\t\t\t\t\t\t\t{% else %}
  4325. \t\t\t\t\t\t\t\t\t\t<a class=\"nav-link btn btn-primary btn-account text-white\" href=\"{{ path('ui_app_login') }}\">
  4326. \t\t\t\t\t\t\t\t\t\t\t<i class=\"ti-lock\"></i>
  4327. \t\t\t\t\t\t\t\t\t\t\tSe connecter
  4328. \t\t\t\t\t\t\t\t\t\t</a>
  4329. \t\t\t\t\t\t\t\t\t{% endif %}
  4330. \t\t\t\t\t\t\t\t</li>
  4331. \t\t\t\t\t\t\t</ul>
  4332. \t\t\t\t\t\t</div>
  4333. \t\t\t\t\t</div>
  4334. \t\t\t\t</nav>
  4335. \t\t\t</div>
  4336. \t\t\t<div class=\"search_input\" id=\"search_input_box\">
  4337. \t\t\t\t<div class=\"container\">
  4338. \t\t\t\t\t<form class=\"d-flex justify-content-between\" id=\"search_form\" action=\"{{ path('ui_listing') }}\" method=\"get\">
  4339. \t\t\t\t\t\t<input type=\"text\" class=\"form-control\" id=\"search_input\" name=\"q\" placeholder=\"Rechercher un produit, une boutique, une catégorie...\" autocomplete=\"off\" value=\"{{ app.request.query.get('q', '') }}\">
  4340. \t\t\t\t\t\t<button type=\"button\" class=\"btn\" id=\"search_submit_btn\">
  4341. \t\t\t\t\t\t\t<i class=\"lnr lnr-magnifier\"></i>
  4342. \t\t\t\t\t\t</button>
  4343. \t\t\t\t\t\t{% if app.request.query.get('q') %}
  4344. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-clear-search\" id=\"clear_search_btn\" title=\"Effacer la recherche\">
  4345. \t\t\t\t\t\t\t\t<i class=\"lnr lnr-cross\"></i>
  4346. \t\t\t\t\t\t\t</button>
  4347. \t\t\t\t\t\t{% endif %}
  4348. \t\t\t\t\t\t<span class=\"lnr lnr-cross\" id=\"close_search\" title=\"Fermer la recherche\"></span>
  4349. \t\t\t\t\t</form>
  4350. \t\t\t\t\t<div id=\"search_results\" class=\"search-results-container\"></div>
  4351. \t\t\t\t</div>
  4352. \t\t\t</div>
  4353. \t\t\t<script>
  4354. \t\t\t\twindow.searchSuggestUrl = \"{{ path('ui_api_search_suggest') }}\";
  4355. \t\t\t\twindow.listingUrl = \"{{ path('ui_listing') }}\";
  4356. \t\t\t</script>
  4357. \t\t</header>
  4358. \t\t<!-- End Header Area -->
  4359. \t\t<!-- Flash Messages -->
  4360. \t\t<div class=\"container mt-3\" id=\"flash-messages-container\" style=\"position: relative; z-index: 1050;\">
  4361. \t\t\t<div class=\"row\">
  4362. \t\t\t\t<div class=\"col-12\">
  4363. \t\t\t\t\t{% for message in app.flashes('success') %}
  4364. \t\t\t\t\t\t<div class=\"alert alert-success alert-dismissible fade show flash-message\" role=\"alert\">
  4365. \t\t\t\t\t\t\t<i class=\"fa fa-check-circle\"></i>
  4366. \t\t\t\t\t\t\t<strong>{{ message }}</strong>
  4367. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  4368. \t\t\t\t\t\t</div>
  4369. \t\t\t\t\t{% endfor %}
  4370. \t\t\t\t\t{% for message in app.flashes('error') %}
  4371. \t\t\t\t\t\t<div class=\"alert alert-danger alert-dismissible fade show flash-message\" role=\"alert\">
  4372. \t\t\t\t\t\t\t<i class=\"fa fa-exclamation-circle\"></i>
  4373. \t\t\t\t\t\t\t<strong>{{ message }}</strong>
  4374. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  4375. \t\t\t\t\t\t</div>
  4376. \t\t\t\t\t{% endfor %}
  4377. \t\t\t\t\t{% for message in app.flashes('warning') %}
  4378. \t\t\t\t\t\t<div class=\"alert alert-warning alert-dismissible fade show flash-message\" role=\"alert\">
  4379. \t\t\t\t\t\t\t<i class=\"fa fa-exclamation-triangle\"></i>
  4380. \t\t\t\t\t\t\t<strong>{{ message }}</strong>
  4381. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  4382. \t\t\t\t\t\t</div>
  4383. \t\t\t\t\t{% endfor %}
  4384. \t\t\t\t\t{% for message in app.flashes('info') %}
  4385. \t\t\t\t\t\t<div class=\"alert alert-info alert-dismissible fade show flash-message\" role=\"alert\">
  4386. \t\t\t\t\t\t\t<i class=\"fa fa-info-circle\"></i>
  4387. \t\t\t\t\t\t\t<strong>{{ message }}</strong>
  4388. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  4389. \t\t\t\t\t\t</div>
  4390. \t\t\t\t\t{% endfor %}
  4391. \t\t\t\t</div>
  4392. \t\t\t</div>
  4393. \t\t</div>
  4394. \t\t{% block body %}{% endblock %}
  4395. \t\t<!-- start footer Area -->
  4396. \t\t<footer class=\"footer-area section_gap\">
  4397. \t\t\t<div class=\"footer-pattern\"></div>
  4398. \t\t\t<div class=\"container\">
  4399. \t\t\t\t<div class=\"row\">
  4400. \t\t\t\t\t<div class=\"col-lg-3 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  4401. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4402. \t\t\t\t\t\t\t<div class=\"footer-logo mb-3\">
  4403. \t\t\t\t\t\t\t\t<h4 class=\"footer-brand\">MaketOu</h4>
  4404. \t\t\t\t\t\t\t</div>
  4405. \t\t\t\t\t\t\t<p class=\"footer-description\">
  4406. \t\t\t\t\t\t\t\tMaketOu est la première marketplace haïtienne qui connecte les acheteurs et les vendeurs. 
  4407. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t                        Nous offrons une plateforme sécurisée et moderne pour le commerce en ligne en Haïti.
  4408. \t\t\t\t\t\t\t</p>
  4409. \t\t\t\t\t\t\t<div class=\"footer-social mt-3\">
  4410. \t\t\t\t\t\t\t\t<h6 class=\"mb-2\">Suivez-nous</h6>
  4411. \t\t\t\t\t\t\t\t<div class=\"footer-social-icons\">
  4412. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Facebook\" title=\"Facebook\">
  4413. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-facebook\"></i>
  4414. \t\t\t\t\t\t\t\t\t</a>
  4415. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Twitter\" title=\"Twitter\">
  4416. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-twitter\"></i>
  4417. \t\t\t\t\t\t\t\t\t</a>
  4418. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Instagram\" title=\"Instagram\">
  4419. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-instagram\"></i>
  4420. \t\t\t\t\t\t\t\t\t</a>
  4421. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"LinkedIn\" title=\"LinkedIn\">
  4422. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linkedin\"></i>
  4423. \t\t\t\t\t\t\t\t\t</a>
  4424. \t\t\t\t\t\t\t\t</div>
  4425. \t\t\t\t\t\t\t</div>
  4426. \t\t\t\t\t\t</div>
  4427. \t\t\t\t\t</div>
  4428. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  4429. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4430. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Liens rapides</h6>
  4431. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  4432. \t\t\t\t\t\t\t\t<li>
  4433. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_home') }}\">
  4434. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Accueil</a>
  4435. \t\t\t\t\t\t\t\t</li>
  4436. \t\t\t\t\t\t\t\t<li>
  4437. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_listing') }}\">
  4438. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Produits</a>
  4439. \t\t\t\t\t\t\t\t</li>
  4440. \t\t\t\t\t\t\t\t<li>
  4441. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_shops_list') }}\">
  4442. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Boutiques</a>
  4443. \t\t\t\t\t\t\t\t</li>
  4444. \t\t\t\t\t\t\t\t{% if app.user %}
  4445. \t\t\t\t\t\t\t\t\t<li>
  4446. \t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_account_index') }}\">
  4447. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Mon compte</a>
  4448. \t\t\t\t\t\t\t\t\t</li>
  4449. \t\t\t\t\t\t\t\t{% else %}
  4450. \t\t\t\t\t\t\t\t\t<li>
  4451. \t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_app_login') }}\">
  4452. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Se connecter</a>
  4453. \t\t\t\t\t\t\t\t\t</li>
  4454. \t\t\t\t\t\t\t\t\t<li>
  4455. \t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_app_register') }}\">
  4456. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;S'inscrire</a>
  4457. \t\t\t\t\t\t\t\t\t</li>
  4458. \t\t\t\t\t\t\t\t{% endif %}
  4459. \t\t\t\t\t\t\t</ul>
  4460. \t\t\t\t\t\t</div>
  4461. \t\t\t\t\t</div>
  4462. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  4463. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4464. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Pour les vendeurs</h6>
  4465. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  4466. \t\t\t\t\t\t\t\t<li>
  4467. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('seller_index') }}\">
  4468. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Ouvrir une boutique</a>
  4469. \t\t\t\t\t\t\t\t</li>
  4470. \t\t\t\t\t\t\t\t<li>
  4471. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('seller_help_how_to_sell') }}\">
  4472. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Comment vendre</a>
  4473. \t\t\t\t\t\t\t\t</li>
  4474. \t\t\t\t\t\t\t\t<li>
  4475. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('seller_help_pricing') }}\">
  4476. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Tarifs</a>
  4477. \t\t\t\t\t\t\t\t</li>
  4478. \t\t\t\t\t\t\t\t<li>
  4479. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('seller_help_support') }}\">
  4480. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Support vendeur</a>
  4481. \t\t\t\t\t\t\t\t</li>
  4482. \t\t\t\t\t\t\t</ul>
  4483. \t\t\t\t\t\t</div>
  4484. \t\t\t\t\t</div>
  4485. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  4486. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4487. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Support</h6>
  4488. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  4489. \t\t\t\t\t\t\t\t<li>
  4490. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_help') }}\">
  4491. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Centre d'Aide</a>
  4492. \t\t\t\t\t\t\t\t</li>
  4493. \t\t\t\t\t\t\t\t<li>
  4494. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_contact') }}\">
  4495. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Contactez-nous</a>
  4496. \t\t\t\t\t\t\t\t</li>
  4497. \t\t\t\t\t\t\t\t<li>
  4498. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_faq') }}\">
  4499. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;FAQ</a>
  4500. \t\t\t\t\t\t\t\t</li>
  4501. \t\t\t\t\t\t\t\t<li>
  4502. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_privacy') }}\">
  4503. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Politique de Confidentialité</a>
  4504. \t\t\t\t\t\t\t\t</li>
  4505. \t\t\t\t\t\t\t\t<li>
  4506. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_terms') }}\">
  4507. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Conditions d'Utilisation</a>
  4508. \t\t\t\t\t\t\t\t</li>
  4509. \t\t\t\t\t\t\t</ul>
  4510. \t\t\t\t\t\t</div>
  4511. \t\t\t\t\t</div>
  4512. \t\t\t\t\t<div class=\"col-lg-3 col-md-6 col-sm-6\">
  4513. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4514. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Newsletter</h6>
  4515. \t\t\t\t\t\t\t<p class=\"footer-newsletter-text\">Restez informé des dernières nouveautés</p>
  4516. \t\t\t\t\t\t\t<div class=\"footer-newsletter-wrapper\" id=\"mc_embed_signup\">
  4517. \t\t\t\t\t\t\t\t<form action=\"{{ path('ui_newsletter_subscribe') }}\" method=\"post\" class=\"footer-newsletter-form\">
  4518. \t\t\t\t\t\t\t\t\t<div class=\"newsletter-input-group\">
  4519. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope newsletter-icon\"></i>
  4520. \t\t\t\t\t\t\t\t\t\t<input class=\"form-control newsletter-input\" name=\"email\" placeholder=\"Votre email\" required type=\"email\">
  4521. \t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"newsletter-btn\" aria-label=\"S'abonner\">
  4522. \t\t\t\t\t\t\t\t\t\t\t<span class=\"newsletter-btn-icon\">
  4523. \t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paper-plane\" aria-hidden=\"true\"></i>
  4524. \t\t\t\t\t\t\t\t\t\t\t</span>
  4525. \t\t\t\t\t\t\t\t\t\t\t<span class=\"newsletter-btn-loader\" style=\"display: none;\">
  4526. \t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spinner fa-spin\" aria-hidden=\"true\"></i>
  4527. \t\t\t\t\t\t\t\t\t\t\t</span>
  4528. \t\t\t\t\t\t\t\t\t\t</button>
  4529. \t\t\t\t\t\t\t\t\t</div>
  4530. \t\t\t\t\t\t\t\t</form>
  4531. \t\t\t\t\t\t\t</div>
  4532. \t\t\t\t\t\t\t<div class=\"footer-trust-badges mt-3\">
  4533. \t\t\t\t\t\t\t\t<div class=\"trust-item\">
  4534. \t\t\t\t\t\t\t\t\t<i class=\"fa fa-shield\"></i>
  4535. \t\t\t\t\t\t\t\t\t<span>Paiement sécurisé</span>
  4536. \t\t\t\t\t\t\t\t</div>
  4537. \t\t\t\t\t\t\t\t<div class=\"trust-item\">
  4538. \t\t\t\t\t\t\t\t\t<i class=\"fa fa-truck\"></i>
  4539. \t\t\t\t\t\t\t\t\t<span>Livraison rapide</span>
  4540. \t\t\t\t\t\t\t\t</div>
  4541. \t\t\t\t\t\t\t</div>
  4542. \t\t\t\t\t\t</div>
  4543. \t\t\t\t\t</div>
  4544. \t\t\t\t</div>
  4545. \t\t\t\t<div class=\"footer-divider\"></div>
  4546. \t\t\t\t<div class=\"footer-bottom d-flex justify-content-center align-items-center flex-wrap\">
  4547. \t\t\t\t\t<p class=\"footer-text m-0\">
  4548. \t\t\t\t\t\tCopyright &copy;<script>
  4549. \t\t\t\t\t\t\tdocument.write(new Date().getFullYear());
  4550. \t\t\t\t\t\t</script>
  4551. \t\t\t\t\t\tTous droits réservés | Ce site a été fait avec
  4552. \t\t\t\t\t\t<i class=\"fa fa-heart-o\" aria-hidden=\"true\" style=\"color: #dc3545;\"></i>
  4553. \t\t\t\t\t\tpar
  4554. \t\t\t\t\t\t<a href=\"https://tech.foulgor.com\" target=\"_blank\" style=\"color: #ffa200;\">Foulgor Tech</a>
  4555. \t\t\t\t\t</p>
  4556. \t\t\t\t</div>
  4557. \t\t\t</div>
  4558. \t\t</footer>
  4559. \t\t<style>
  4560. \t\t\t.search-results-container {
  4561. \t\t\t\tposition: absolute;
  4562. \t\t\t\ttop: 100%;
  4563. \t\t\t\tleft: 15px;
  4564. \t\t\t\tright: 15px;
  4565. \t\t\t\tbackground: #fff;
  4566. \t\t\t\tborder: 1px solid #ddd;
  4567. \t\t\t\tborder-top: none;
  4568. \t\t\t\tz-index: 9999;
  4569. \t\t\t\tbox-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  4570. \t\t\t\tmax-height: 400px;
  4571. \t\t\t\toverflow-y: auto;
  4572. \t\t\t\tdisplay: none;
  4573. \t\t\t\tborder-radius: 0 0 4px 4px;
  4574. \t\t\t}
  4575. \t\t\t.search-results-container .list-group-item {
  4576. \t\t\t\tborder-left: none;
  4577. \t\t\t\tborder-right: none;
  4578. \t\t\t\tborder-radius: 0;
  4579. \t\t\t\tcursor: pointer;
  4580. \t\t\t\tpadding: 12px 15px;
  4581. \t\t\t\ttransition: background-color 0.2s ease;
  4582. \t\t\t}
  4583. \t\t\t.search-results-container .list-group-item:hover {
  4584. \t\t\t\tbackground-color: #f8f9fa;
  4585. \t\t\t}
  4586. \t\t\t.search-results-container .list-group-item i {
  4587. \t\t\t\tcolor: #777;
  4588. \t\t\t\tfont-size: 1.2rem;
  4589. \t\t\t}
  4590. \t\t\t/* Ensure container is relative for absolute positioning of results */
  4591. \t\t\t#search_input_box .container {
  4592. \t\t\t\tposition: relative;
  4593. \t\t\t}
  4594. \t\t\t#search_input_box .form-control {
  4595. \t\t\t\tflex: 1;
  4596. \t\t\t\tpadding-right: 10px;
  4597. \t\t\t}
  4598. \t\t\t#search_input_box #search_submit_btn {
  4599. \t\t\t\tbackground: transparent;
  4600. \t\t\t\tborder: 0;
  4601. \t\t\t\tcolor: #fff;
  4602. \t\t\t\tpadding: 0 15px;
  4603. \t\t\t\tcursor: pointer;
  4604. \t\t\t\ttransition: opacity 0.3s ease;
  4605. \t\t\t}
  4606. \t\t\t#search_input_box #search_submit_btn:hover {
  4607. \t\t\t\topacity: 0.8;
  4608. \t\t\t}
  4609. \t\t\t#search_input_box .btn-clear-search {
  4610. \t\t\t\tbackground: transparent;
  4611. \t\t\t\tborder: 0;
  4612. \t\t\t\tcolor: #fff;
  4613. \t\t\t\tpadding: 0 10px;
  4614. \t\t\t\tcursor: pointer;
  4615. \t\t\t\ttransition: opacity 0.3s ease;
  4616. \t\t\t\tdisplay: none;
  4617. \t\t\t}
  4618. \t\t\t#search_input_box .btn-clear-search:hover {
  4619. \t\t\t\topacity: 0.8;
  4620. \t\t\t}
  4621. \t\t\t#search_input_box .btn-clear-search i {
  4622. \t\t\t\tfont-size: 1.1rem;
  4623. \t\t\t}
  4624. \t\t\t#search_input_box form {
  4625. \t\t\t\tposition: relative;
  4626. \t\t\t\talign-items: center;
  4627. \t\t\t}
  4628. \t\t</style>
  4629. \t\t<script>
  4630. \t\t\t// Debounced autocomplete for header search
  4631. (function () {
  4632. const input = document.getElementById('search_input');
  4633. const box = document.getElementById('search_results');
  4634. const searchForm = document.getElementById('search_form');
  4635. const clearSearchBtn = document.getElementById('clear_search_btn');
  4636. const closeSearchBtn = document.getElementById('close_search');
  4637. if (! input || ! box) 
  4638. return;
  4639. // Fonction pour effacer la recherche
  4640. function clearSearch() {
  4641. input.value = '';
  4642. box.style.display = 'none';
  4643. box.innerHTML = '';
  4644. if (clearSearchBtn) {
  4645. clearSearchBtn.style.display = 'none';
  4646. }
  4647. // Si on est sur la page listing, utiliser AJAX pour mettre à jour
  4648. if (typeof currentFilters !== 'undefined') {
  4649. currentFilters.q = '';
  4650. currentFilters.page = 1;
  4651. if (typeof applyFilters === 'function') {
  4652. applyFilters();
  4653. }
  4654. if (typeof updateActiveFilters === 'function') {
  4655. updateActiveFilters();
  4656. }
  4657. } else { // Sinon, rediriger vers la page listing sans recherche
  4658. window.location.href = '{{ path('ui_listing') }}';
  4659. }
  4660. }
  4661. // Bouton pour effacer la recherche
  4662. if (clearSearchBtn) {
  4663. clearSearchBtn.addEventListener('click', function (e) {
  4664. e.preventDefault();
  4665. e.stopPropagation();
  4666. clearSearch();
  4667. });
  4668. }
  4669. // Bouton de soumission de recherche
  4670. var searchSubmitBtn = document.getElementById('search_submit_btn');
  4671. if (searchSubmitBtn) {
  4672. searchSubmitBtn.addEventListener('click', function (e) {
  4673. e.preventDefault();
  4674. e.stopPropagation();
  4675. const q = input.value.trim();
  4676. if (q.length === 0) {
  4677. clearSearch();
  4678. return false;
  4679. }
  4680. // Si on est sur la page listing, utiliser AJAX
  4681. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  4682. currentFilters.q = q;
  4683. currentFilters.page = 1;
  4684. applyFilters();
  4685. if (typeof updateActiveFilters === 'function') {
  4686. updateActiveFilters();
  4687. }
  4688. // Fermer la boîte de recherche
  4689. if (closeSearchBtn) {
  4690. closeSearchBtn.click();
  4691. }
  4692. } else { // Sinon, rediriger vers la page listing avec la recherche
  4693. const listingUrl = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4694. window.location.href = listingUrl;
  4695. }
  4696. return false;
  4697. });
  4698. }
  4699. // Gestion du formulaire de recherche
  4700. if (searchForm) {
  4701. searchForm.addEventListener('submit', function (e) {
  4702. e.preventDefault();
  4703. e.stopPropagation();
  4704. const q = input.value.trim();
  4705. if (q.length === 0) {
  4706. clearSearch();
  4707. return;
  4708. }
  4709. // Si on est sur la page listing, utiliser AJAX
  4710. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  4711. currentFilters.q = q;
  4712. currentFilters.page = 1;
  4713. applyFilters();
  4714. if (typeof updateActiveFilters === 'function') {
  4715. updateActiveFilters();
  4716. }
  4717. // Fermer la boîte de recherche
  4718. if (closeSearchBtn) {
  4719. closeSearchBtn.click();
  4720. }
  4721. } else { // Sinon, rediriger vers la page listing avec la recherche
  4722. const listingUrl = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4723. window.location.href = listingUrl;
  4724. }
  4725. return false;
  4726. });
  4727. }
  4728. let t = null;
  4729. input.addEventListener('input', function () {
  4730. const q = input.value.trim();
  4731. clearTimeout(t);
  4732. if (q.length === 0) {
  4733. box.style.display = 'none';
  4734. box.innerHTML = '';
  4735. // Afficher/masquer le bouton clear
  4736. if (clearSearchBtn) {
  4737. clearSearchBtn.style.display = 'none';
  4738. }
  4739. return;
  4740. }
  4741. // Afficher le bouton clear
  4742. if (clearSearchBtn) {
  4743. clearSearchBtn.style.display = 'block';
  4744. }
  4745. t = setTimeout(() => fetchSuggestions(q), 300);
  4746. });
  4747. function fetchSuggestions(q) {
  4748. const url = '{{ path('ui_api_search_suggest') }}' + '?q=' + encodeURIComponent(q);
  4749. fetch(url).then(r => r.json()).then(data => {
  4750. if (!data.success) {
  4751. box.style.display = 'none';
  4752. return;
  4753. }
  4754. renderSuggestions(data.results || []);
  4755. }).catch(() => {
  4756. box.style.display = 'none';
  4757. });
  4758. }
  4759. function renderSuggestions(items) {
  4760. if (! items.length) {
  4761. box.style.display = 'none';
  4762. box.innerHTML = '';
  4763. return;
  4764. }
  4765. box.innerHTML = items.map(it => suggestionItem(it)).join('');
  4766. box.style.display = 'block';
  4767. }
  4768. function suggestionItem(it) {
  4769. const icon = it.type === 'product' ? 'ti-package' : (it.type === 'shop' ? 'ti-briefcase' : (it.type === 'category' ? 'ti-layers' : 'ti-tag'));
  4770. const typeLabel = it.type === 'product' ? 'Produit' : (it.type === 'shop' ? 'Boutique' : (it.type === 'category' ? 'Catégorie' : 'Tag'));
  4771. return '<a href=\"' + it.url + '\" class=\"list-group-item list-group-item-action d-flex align-items-center\">' + '<i class=\"' + icon + ' me-3\"></i>' + '<span class=\"flex-grow-1\">' + escapeHtml(it.label) + '</span>' + '<span class=\"badge bg-light text-dark ms-2\">' + typeLabel + '</span>' + '</a>';
  4772. }
  4773. function escapeHtml(s) {
  4774. return s.replace(/[&<>\"]+/g, c => ({'&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;'}[c]));
  4775. }
  4776. document.addEventListener('click', function (e) {
  4777. if (! box.contains(e.target) && e.target !== input) {
  4778. box.style.display = 'none';
  4779. }
  4780. });
  4781. window.handleSearchSubmit = function (e) {
  4782. if (e) 
  4783. e.preventDefault();
  4784. const first = box.querySelector('a');
  4785. if (first) {
  4786. window.location.href = first.getAttribute('href');
  4787. return false;
  4788. }
  4789. // fallback to listing page search by name
  4790. const q = input.value.trim();
  4791. if (q.length) { // Si on est sur la page listing, utiliser AJAX
  4792. if (typeof currentFilters !== 'undefined') {
  4793. currentFilters.q = q;
  4794. currentFilters.page = 1;
  4795. if (typeof applyFilters === 'function') {
  4796. applyFilters();
  4797. }
  4798. if (typeof updateActiveFilters === 'function') {
  4799. updateActiveFilters();
  4800. }
  4801. } else {
  4802. window.location.href = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4803. }
  4804. }
  4805. return false;
  4806. }
  4807. // Gestion de la touche Enter dans le champ de recherche
  4808. if (input) {
  4809. input.addEventListener('keydown', function (e) {
  4810. if (e.key === 'Enter' || e.keyCode === 13) {
  4811. e.preventDefault();
  4812. e.stopPropagation();
  4813. const q = input.value.trim();
  4814. if (q.length === 0) {
  4815. clearSearch();
  4816. return false;
  4817. }
  4818. // Si on est sur la page listing, utiliser AJAX
  4819. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  4820. currentFilters.q = q;
  4821. currentFilters.page = 1;
  4822. applyFilters();
  4823. if (typeof updateActiveFilters === 'function') {
  4824. updateActiveFilters();
  4825. }
  4826. // Fermer la boîte de recherche
  4827. if (closeSearchBtn) {
  4828. closeSearchBtn.click();
  4829. }
  4830. } else { // Sinon, rediriger vers la page listing avec la recherche
  4831. const listingUrl = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4832. window.location.href = listingUrl;
  4833. }
  4834. return false;
  4835. }
  4836. });
  4837. }
  4838. // Ajouter un event listener au bouton de soumission (réutiliser la variable si elle existe déjà)
  4839. if (!searchSubmitBtn) {
  4840.     searchSubmitBtn = document.getElementById('search_submit_btn');
  4841. }
  4842. if (searchSubmitBtn) {
  4843. searchSubmitBtn.addEventListener('click', function (e) {
  4844. e.preventDefault();
  4845. e.stopPropagation();
  4846. const q = input.value.trim();
  4847. if (q.length === 0) {
  4848. clearSearch();
  4849. return false;
  4850. }
  4851. // Si on est sur la page listing, utiliser AJAX
  4852. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  4853. currentFilters.q = q;
  4854. currentFilters.page = 1;
  4855. applyFilters();
  4856. if (typeof updateActiveFilters === 'function') {
  4857. updateActiveFilters();
  4858. }
  4859. // Fermer la boîte de recherche
  4860. if (closeSearchBtn) {
  4861. closeSearchBtn.click();
  4862. }
  4863. } else { // Sinon, rediriger vers la page listing avec la recherche
  4864. const listingUrl = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4865. window.location.href = listingUrl;
  4866. }
  4867. return false;
  4868. });
  4869. }
  4870. // Afficher le bouton clear au chargement si une recherche est active
  4871. document.addEventListener('DOMContentLoaded', function () {
  4872. const q = input.value.trim();
  4873. if (q.length > 0 && clearSearchBtn) {
  4874. clearSearchBtn.style.display = 'block';
  4875. }
  4876. });
  4877. })();
  4878. // Gestion des mega-menus avec clic (comme la barre de recherche)
  4879. document.addEventListener('DOMContentLoaded', function () {
  4880. const dropdownItems = document.querySelectorAll('.nav-item.dropdown');
  4881. dropdownItems.forEach(function (item) {
  4882. const dropdownToggle = item.querySelector('.dropdown-toggle');
  4883. const dropdownMenu = item.querySelector('.mega-menu');
  4884. if (! dropdownToggle || ! dropdownMenu) 
  4885. return;
  4886. // Fermer les autres menus quand on ouvre un nouveau
  4887. function closeAllMenus() {
  4888. dropdownItems.forEach(function (otherItem) {
  4889. const otherMenu = otherItem.querySelector('.mega-menu');
  4890. if (otherMenu && otherMenu !== dropdownMenu) {
  4891. \$(otherMenu).slideUp(300);
  4892. otherMenu.classList.remove('active');
  4893. }
  4894. });
  4895. }
  4896. // Toggle au clic (comme la barre de recherche)
  4897. dropdownToggle.addEventListener('click', function (e) {
  4898. e.preventDefault();
  4899. e.stopPropagation();
  4900. closeAllMenus();
  4901. if (dropdownMenu.classList.contains('active')) { // Fermer le menu
  4902. dropdownMenu.style.opacity = '0';
  4903. dropdownMenu.style.visibility = 'hidden';
  4904. dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
  4905. setTimeout(() => {
  4906. dropdownMenu.classList.remove('active');
  4907. dropdownMenu.style.display = 'none';
  4908. }, 300);
  4909. } else { // Ouvrir le menu
  4910. dropdownMenu.style.display = 'block';
  4911. setTimeout(() => {
  4912. dropdownMenu.classList.add('active');
  4913. dropdownMenu.style.opacity = '1';
  4914. dropdownMenu.style.visibility = 'visible';
  4915. dropdownMenu.style.transform = 'translateX(-50%) translateY(0)';
  4916. }, 10);
  4917. }
  4918. });
  4919. // Fermer au clic en dehors
  4920. document.addEventListener('click', function (e) {
  4921. if (! item.contains(e.target) && dropdownMenu.classList.contains('active')) {
  4922. dropdownMenu.style.opacity = '0';
  4923. dropdownMenu.style.visibility = 'hidden';
  4924. dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
  4925. setTimeout(() => {
  4926. dropdownMenu.classList.remove('active');
  4927. dropdownMenu.style.display = 'none';
  4928. }, 300);
  4929. }
  4930. });
  4931. // Animation des éléments du menu
  4932. const menuItems = dropdownMenu.querySelectorAll('.dropdown-item a');
  4933. menuItems.forEach(function (menuItem, index) {
  4934. menuItem.style.animationDelay = (index * 0.05) + 's';
  4935. });
  4936. });
  4937. // Gestion des clics sur mobile
  4938. if (window.innerWidth <= 768) {
  4939. dropdownItems.forEach(function (item) {
  4940. const dropdownToggle = item.querySelector('.dropdown-toggle');
  4941. const dropdownMenu = item.querySelector('.mega-menu');
  4942. dropdownToggle.addEventListener('click', function (e) {
  4943. e.preventDefault();
  4944. // Fermer tous les autres menus
  4945. dropdownItems.forEach(function (otherItem) {
  4946. if (otherItem !== item) {
  4947. const otherMenu = otherItem.querySelector('.mega-menu');
  4948. otherMenu.style.opacity = '0';
  4949. otherMenu.style.visibility = 'hidden';
  4950. otherMenu.style.transform = 'translateY(-10px)';
  4951. }
  4952. });
  4953. // Toggle le menu actuel
  4954. if (dropdownMenu.style.opacity === '1') {
  4955. dropdownMenu.style.opacity = '0';
  4956. dropdownMenu.style.visibility = 'hidden';
  4957. dropdownMenu.style.transform = 'translateY(-10px)';
  4958. } else {
  4959. dropdownMenu.style.opacity = '1';
  4960. dropdownMenu.style.visibility = 'visible';
  4961. dropdownMenu.style.transform = 'translateY(0)';
  4962. }
  4963. });
  4964. });
  4965. }
  4966. // Fermer les menus quand on clique ailleurs
  4967. document.addEventListener('click', function (e) {
  4968. if (! e.target.closest('.nav-item.dropdown')) {
  4969. dropdownItems.forEach(function (item) {
  4970. const dropdownMenu = item.querySelector('.mega-menu');
  4971. dropdownMenu.style.opacity = '0';
  4972. dropdownMenu.style.visibility = 'hidden';
  4973. dropdownMenu.style.transform = 'translateY(-10px)';
  4974. });
  4975. }
  4976. });
  4977. });
  4978. \t\t</script>
  4979. \t\t<!-- End footer Area -->
  4980. \t\t<script src=\"{{ asset('ui/js/vendor/jquery-2.2.4.min.js') }}\"></script>
  4981. \t\t<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js\"></script>
  4982. \t\t<script>
  4983. \t\t\t// Initialiser le collapse Bootstrap 5 pour le menu hamburger après chargement de Bootstrap
  4984. document.addEventListener('DOMContentLoaded', function () { // Attendre que Bootstrap soit complètement chargé
  4985. if (typeof bootstrap !== 'undefined') {
  4986. const navbarToggler = document.querySelector('.navbar-toggler');
  4987. const navbarCollapse = document.getElementById('navbarSupportedContent');
  4988. if (navbarToggler && navbarCollapse) {
  4989. // Bootstrap 5 devrait gérer automatiquement avec data-bs-toggle
  4990. // Mais on s'assure que ça fonctionne en écoutant les événements
  4991. navbarCollapse.addEventListener('show.bs.collapse', function () {
  4992. navbarToggler.setAttribute('aria-expanded', 'true');
  4993. navbarToggler.classList.add('active');
  4994. });
  4995. navbarCollapse.addEventListener('hide.bs.collapse', function () {
  4996. navbarToggler.setAttribute('aria-expanded', 'false');
  4997. navbarToggler.classList.remove('active');
  4998. });
  4999. }
  5000. }
  5001. });
  5002. \t\t</script>
  5003. \t\t<script src=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.js\"></script>
  5004. \t\t<script src=\"{{ asset('ui/js/jquery.ajaxchimp.min.js') }}\"></script>
  5005. \t\t<script src=\"{{ asset('ui/js/jquery.nice-select.min.js') }}\"></script>
  5006. \t\t<script src=\"{{ asset('ui/js/jquery.sticky.js') }}\"></script>
  5007. \t\t<script src=\"{{ asset('ui/js/nouislider.min.js') }}\"></script>
  5008. \t\t<script src=\"{{ asset('ui/js/countdown.js') }}\"></script>
  5009. \t\t<script src=\"{{ asset('ui/js/jquery.magnific-popup.min.js') }}\"></script>
  5010. \t\t<script src=\"{{ asset('ui/js/owl.carousel.min.js') }}\"></script>
  5011. \t\t<script src=\"https://maps.googleapis.com/maps/api/js?key=AIzaSyCjCGmQ0Uq4exrzdcL6rvxywDDOvfAu6eE\"></script>
  5012. \t\t<script src=\"{{ asset('ui/js/gmaps.min.js') }}\"></script>
  5013. \t\t<script src=\"{{ asset('ui/js/main.js') }}\"></script>
  5014. \t\t{{ encore_entry_script_tags('app') }}
  5015. \t\t<!-- PWA Service Worker Registration -->
  5016. \t\t<script>
  5017. \t\t\t// Enregistrement du Service Worker
  5018. if ('serviceWorker' in navigator) {
  5019. window.addEventListener('load', () => {
  5020. navigator.serviceWorker.register('{{ asset('sw.js') }}').then((registration) => {
  5021. console.log('Service Worker enregistré avec succès:', registration.scope);
  5022. // Vérifie les mises à jour du service worker
  5023. registration.addEventListener('updatefound', () => {
  5024. const newWorker = registration.installing;
  5025. newWorker.addEventListener('statechange', () => {
  5026. if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { // Nouveau service worker disponible
  5027. if (confirm('Une nouvelle version de MaketOu est disponible. Voulez-vous l\\'installer maintenant ?')) {
  5028. newWorker.postMessage({type: 'SKIP_WAITING'});
  5029. window.location.reload();
  5030. }
  5031. }
  5032. });
  5033. });
  5034. }).catch((error) => {
  5035. console.log('Échec de l\\'enregistrement du Service Worker:', error);
  5036. });
  5037. // Écoute les messages du service worker
  5038. navigator.serviceWorker.addEventListener('message', (event) => {
  5039. console.log('Message du Service Worker:', event.data);
  5040. });
  5041. });
  5042. }
  5043. \t\t</script>
  5044. \t\t<!-- PWA Install Script -->
  5045. \t\t<script src=\"{{ asset('js/pwa-install.js') }}\"></script>
  5046. \t\t<script>
  5047. \t\t\t// Charger les compteurs au chargement de la page
  5048. document.addEventListener('DOMContentLoaded', function () {
  5049. {% if app.user %}
  5050. loadNotificationCount();
  5051. // Délai pour s'assurer que la session est bien établie après connexion
  5052. setTimeout(function () {
  5053. loadComparisonCount();
  5054. }, 500);{% endif %}
  5055. // Gérer le bouton de recherche mobile
  5056. const searchMobileBtn = document.getElementById('searchMobileBtn');
  5057. if (searchMobileBtn) {
  5058. searchMobileBtn.addEventListener('click', function (e) {
  5059. e.preventDefault();
  5060. // Utiliser le même comportement que le bouton desktop
  5061. const searchBox = document.getElementById('search_input_box');
  5062. if (searchBox) {
  5063. searchBox.style.display = 'block';
  5064. const searchInput = document.getElementById('search_input');
  5065. if (searchInput) {
  5066. setTimeout(() => searchInput.focus(), 100);
  5067. }
  5068. }
  5069. });
  5070. }
  5071. });
  5072. function loadNotificationCount() {
  5073. {% if app.user %}
  5074. fetch('{{ path(\"api_notifications_count\") }}').then(response => {
  5075. if (!response.ok) {
  5076. throw new Error('Erreur HTTP: ' + response.status);
  5077. }
  5078. return response.json();
  5079. }).then(data => {
  5080. const count = data.count || 0;
  5081. // Mettre à jour tous les badges de notification
  5082. const badges = [document.getElementById('notificationBadge'), document.getElementById('notificationBadgeMobile'), document.querySelector('.notification-badge')].filter(badge => badge !== null);
  5083. badges.forEach(badge => {
  5084. if (count > 0) {
  5085. badge.textContent = count;
  5086. badge.style.display = 'flex';
  5087. badge.style.color = 'white';
  5088. badge.style.backgroundColor = '#dc3545';
  5089. } else {
  5090. badge.style.display = 'none';
  5091. }
  5092. });
  5093. // Si on est sur la page des notifications, mettre à jour aussi le contenu de la page
  5094. if (typeof updateNotificationPageContent === 'function') {
  5095. updateNotificationPageContent(count);
  5096. }
  5097. }).catch(error => {
  5098. console.error('Erreur lors du chargement du compteur de notifications:', error);
  5099. });{% endif %}
  5100. }
  5101. // Exposer la fonction globalement pour qu'elle puisse être appelée depuis d'autres pages
  5102. window.loadNotificationCount = loadNotificationCount;
  5103. // Recharger le compteur toutes les 30 secondes pour garder les données à jour
  5104. {% if app.user %}
  5105. setInterval(function () {
  5106. loadNotificationCount();
  5107. }, 30000);{% endif %}function loadComparisonCount() {
  5108. {% if app.user %}
  5109. // Ne pas appeler l'API si on est sur une page d'erreur ou de redirection
  5110. if (window.location.pathname.includes('/api/') || window.location.pathname.includes('/login')) {
  5111. return;
  5112. }
  5113. // Utiliser un try-catch pour éviter toute redirection
  5114. try {
  5115. fetch('{{ path(\"ui_api_comparison_count\") }}', {
  5116. method: 'GET',
  5117. headers: {
  5118. 'X-Requested-With': 'XMLHttpRequest',
  5119. 'Accept': 'application/json'
  5120. },
  5121. credentials: 'same-origin',
  5122. redirect: 'error' // Empêcher les redirections automatiques
  5123. }).then(response => { // Vérifier si la réponse est OK
  5124. if (!response.ok) { // Si c'est une redirection (301, 302, etc.) ou une erreur d'authentification, ignorer silencieusement
  5125. if (response.status >= 300 && response.status < 400) {
  5126. console.warn('Redirection détectée, arrêt de la requête');
  5127. return null;
  5128. }
  5129. if (response.status === 401 || response.status === 403) {
  5130. console.warn('Utilisateur non authentifié pour la comparaison');
  5131. return null;
  5132. }
  5133. // Pour les autres erreurs, throw pour être capturé par catch
  5134. throw new Error('Erreur HTTP: ' + response.status);
  5135. }
  5136. // Vérifier que c'est bien du JSON
  5137. const contentType = response.headers.get('content-type');
  5138. if (! contentType || ! contentType.includes('application/json')) { // Si ce n'est pas du JSON, c'est probablement une redirection HTML
  5139. console.warn('La réponse n\\'est pas du JSON, probable redirection');
  5140. return null;
  5141. }
  5142. return response.json();
  5143. }).then(data => { // Si data est null (redirection ou erreur), ne rien faire
  5144. if (!data || typeof data.count === 'undefined') {
  5145. return;
  5146. }
  5147. // Mettre à jour les badges desktop et mobile
  5148. const badges = [document.getElementById('comparisonBadge'), document.getElementById('comparisonBadgeMobile')];
  5149. badges.forEach(badge => {
  5150. if (badge) {
  5151. if (data.count > 0) {
  5152. badge.textContent = data.count;
  5153. badge.style.display = 'flex';
  5154. } else {
  5155. badge.style.display = 'none';
  5156. }
  5157. }
  5158. });
  5159. }).catch(error => { // Ne pas afficher d'erreur si c'est juste une absence d'authentification ou une redirection
  5160. if (error.message && !error.message.includes('401') && !error.message.includes('403') && !error.message.includes('redirect')) {
  5161. console.error('Erreur lors du chargement du compteur de comparaison:', error);
  5162. }
  5163. // Empêcher toute redirection vers l'URL de l'API
  5164. return false;
  5165. });
  5166. } catch (e) { // Capturer toute erreur qui pourrait causer une redirection
  5167. console.warn('Erreur lors de l\\'appel à l\\'API de comparaison:', e);
  5168. }
  5169. {% endif %}
  5170. }
  5171. // Fonction globale pour gérer la comparaison
  5172. function toggleComparison(productId, element) {
  5173. if (! element) {
  5174. element = document.querySelector(`.comparison-btn[data-product-id=\"\${productId}\"]`);
  5175. }
  5176. if (! element) {
  5177. console.error('Bouton de comparaison non trouvé pour le produit', productId);
  5178. return;
  5179. }
  5180. const originalHtml = element.innerHTML;
  5181. // Désactiver le bouton/lien
  5182. if (element.tagName === 'BUTTON') {
  5183. element.disabled = true;
  5184. } else {
  5185. element.style.pointerEvents = 'none';
  5186. element.style.opacity = '0.6';
  5187. } element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
  5188. // Vérifier d'abord si le produit est déjà en comparaison
  5189. let isInComparison = false;
  5190. fetch(`/api/comparison/status/\${productId}`).then(response => response.json()).then(data => {
  5191. isInComparison = data.inComparison;
  5192. const url = isInComparison ? `/api/comparison/remove/\${productId}` : `/api/comparison/add/\${productId}`;
  5193. return fetch(url, {
  5194. method: 'POST',
  5195. headers: {
  5196. 'Content-Type': 'application/json',
  5197. 'X-Requested-With': 'XMLHttpRequest'
  5198. }
  5199. });
  5200. }).then(response => response.json()).then(data => {
  5201. if (data.success) { // Mettre à jour le compteur
  5202. loadComparisonCount();
  5203. // Mettre à jour l'apparence du bouton
  5204. if (element) { // Inverser l'état (car on vient de le changer)
  5205. const newState = ! isInComparison;
  5206. // Restaurer le HTML original puis mettre à jour
  5207. element.innerHTML = originalHtml;
  5208. if (newState) {
  5209. element.classList.add('active');
  5210. // Mettre à jour le texte pour les deux types de boutons
  5211. const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  5212. if (textEl) 
  5213. textEl.textContent = 'En comparaison';
  5214. // Mettre à jour l'icône si nécessaire (chercher dans span ou i)
  5215. const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
  5216. if (iconEl) {
  5217. iconEl.style.color = '#28a745';
  5218. iconEl.classList.add('active');
  5219. }
  5220. } else {
  5221. element.classList.remove('active');
  5222. const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  5223. if (textEl) 
  5224. textEl.textContent = 'Comparer';
  5225. // Restaurer la couleur de l'icône
  5226. const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
  5227. if (iconEl) {
  5228. iconEl.style.color = '';
  5229. iconEl.classList.remove('active');
  5230. }
  5231. }
  5232. }
  5233. // Afficher une notification
  5234. showNotification(data.message, 'success');
  5235. } else {
  5236. showNotification(data.message, 'error');
  5237. if (element) {
  5238. element.innerHTML = originalHtml;
  5239. }
  5240. }
  5241. }).catch(error => {
  5242. console.error('Erreur:', error);
  5243. showNotification('Une erreur est survenue', 'error');
  5244. if (element) {
  5245. element.innerHTML = originalHtml;
  5246. }
  5247. }). finally(() => {
  5248. if (element) {
  5249. if (element.tagName === 'BUTTON') {
  5250. element.disabled = false;
  5251. } else {
  5252. element.style.pointerEvents = '';
  5253. element.style.opacity = '';
  5254. }
  5255. }
  5256. });
  5257. }
  5258. // Fonction globale pour gérer les favoris
  5259. function toggleWishlist(productId, element) {
  5260. if (! element) {
  5261. element = document.querySelector(`.wishlist-btn[data-product-id=\"\${productId}\"]`);
  5262. }
  5263. if (! element) {
  5264. console.error('Bouton de wishlist non trouvé pour le produit', productId);
  5265. return;
  5266. }
  5267. const originalHtml = element.innerHTML;
  5268. // Désactiver le bouton/lien
  5269. if (element.tagName === 'BUTTON') {
  5270. element.disabled = true;
  5271. } else {
  5272. element.style.pointerEvents = 'none';
  5273. element.style.opacity = '0.6';
  5274. } element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
  5275. // Vérifier d'abord si le produit est déjà en favoris
  5276. let isInWishlist = false;
  5277. fetch(`/api/wishlist/status/\${productId}`).then(response => response.json()).then(data => {
  5278. isInWishlist = data.inWishlist;
  5279. const url = isInWishlist ? `/api/wishlist/remove/\${productId}` : `/api/wishlist/add/\${productId}`;
  5280. return fetch(url, {
  5281. method: 'POST',
  5282. headers: {
  5283. 'Content-Type': 'application/json',
  5284. 'X-Requested-With': 'XMLHttpRequest'
  5285. }
  5286. });
  5287. }).then(response => response.json()).then(data => {
  5288. if (data.success) { // Mettre à jour l'apparence du bouton
  5289. if (element) { // Inverser l'état (car on vient de le changer)
  5290. const newState = ! isInWishlist;
  5291. // Restaurer le HTML original puis mettre à jour
  5292. element.innerHTML = originalHtml;
  5293. // Chercher l'icône dans span ou i
  5294. const icon = element.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
  5295. const text = element.querySelector('.wishlist-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  5296. if (newState) {
  5297. if (icon) { // Pour les icônes linr, on change la classe
  5298. if (icon.classList.contains('lnr-heart')) {
  5299. icon.classList.remove('lnr-heart');
  5300. }
  5301. if (! icon.classList.contains('lnr-heart-filled')) {
  5302. icon.classList.add('lnr-heart-filled');
  5303. }
  5304. icon.style.color = '#dc3545';
  5305. }
  5306. element.classList.add('active');
  5307. if (text) 
  5308. text.textContent = 'Dans favoris';
  5309. } else {
  5310. if (icon) { // Restaurer l'icône originale
  5311. if (icon.classList.contains('lnr-heart-filled')) {
  5312. icon.classList.remove('lnr-heart-filled');
  5313. }
  5314. if (! icon.classList.contains('lnr-heart')) {
  5315. icon.classList.add('lnr-heart');
  5316. }
  5317. icon.style.color = '';
  5318. }
  5319. element.classList.remove('active');
  5320. if (text) 
  5321. text.textContent = 'Favoris';
  5322. }
  5323. }
  5324. // Afficher une notification
  5325. showNotification(data.message, 'success');
  5326. // Si on est sur la page wishlist, recharger la page
  5327. if (window.location.pathname.includes('/account/wishlist')) {
  5328. setTimeout(() => location.reload(), 1000);
  5329. }
  5330. } else {
  5331. showNotification(data.message, 'error');
  5332. if (element) {
  5333. element.innerHTML = originalHtml;
  5334. }
  5335. }
  5336. }).catch(error => {
  5337. console.error('Erreur:', error);
  5338. showNotification('Une erreur est survenue', 'error');
  5339. if (element) {
  5340. element.innerHTML = originalHtml;
  5341. }
  5342. }). finally(() => {
  5343. if (element) {
  5344. if (element.tagName === 'BUTTON') {
  5345. element.disabled = false;
  5346. } else {
  5347. element.style.pointerEvents = '';
  5348. element.style.opacity = '';
  5349. }
  5350. }
  5351. });
  5352. }
  5353. // Fonction pour afficher des notifications
  5354. function showNotification(message, type = 'success') { // Créer l'élément de notification
  5355. const notification = document.createElement('div');
  5356. notification.className = `alert alert-\${
  5357. type === 'success' ? 'success' : 'danger'
  5358. } alert-dismissible fade show position-fixed`;
  5359. notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);';
  5360. notification.innerHTML = `
  5361.             \${message}
  5362.             <button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\"></button>
  5363.         `;
  5364. document.body.appendChild(notification);
  5365. // Supprimer automatiquement après 3 secondes
  5366. setTimeout(() => {
  5367. notification.remove();
  5368. }, 3000);
  5369. }
  5370. // Initialiser les alertes Bootstrap 5 pour la fermeture
  5371. document.addEventListener('DOMContentLoaded', function () { // S'assurer que les alertes peuvent être fermées
  5372. const alertCloseButtons = document.querySelectorAll('.flash-message .btn-close');
  5373. alertCloseButtons.forEach(function (button) {
  5374. button.addEventListener('click', function () {
  5375. const alert = this.closest('.alert');
  5376. if (alert) {
  5377. alert.classList.remove('show');
  5378. setTimeout(function () {
  5379. alert.remove();
  5380. }, 150);
  5381. }
  5382. });
  5383. });
  5384. // Charger les statuts initiaux des produits
  5385. {% if app.user %}
  5386. // Charger les statuts de comparaison pour tous les produits visibles
  5387. document.querySelectorAll('.comparison-btn[data-product-id]').forEach(btn => {
  5388. const productId = btn.dataset.productId;
  5389. fetch(`/api/comparison/status/\${productId}`).then(response => response.json()).then(data => {
  5390. if (data.inComparison) {
  5391. btn.classList.add('active');
  5392. // Mettre à jour le texte pour les deux types de boutons
  5393. const textEl = btn.querySelector('.comparison-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
  5394. if (textEl) 
  5395. textEl.textContent = 'En comparaison';
  5396. // Mettre à jour l'icône si nécessaire
  5397. const iconEl = btn.querySelector('.lnr-sync, [class*=\"sync\"]');
  5398. if (iconEl) 
  5399. iconEl.style.color = '#28a745';
  5400. }
  5401. }).catch(() => {});
  5402. });
  5403. // Charger les statuts de wishlist pour tous les produits visibles
  5404. document.querySelectorAll('.wishlist-btn[data-product-id]').forEach(btn => {
  5405. const productId = btn.dataset.productId;
  5406. fetch(`/api/wishlist/status/\${productId}`).then(response => response.json()).then(data => {
  5407. if (data.inWishlist) {
  5408. // Chercher l'icône dans span ou i
  5409. const icon = btn.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
  5410. if (icon) {
  5411. icon.classList.remove('lnr-heart');
  5412. icon.classList.add('lnr-heart');
  5413. icon.style.color = '#ffa200';
  5414. }
  5415. // Mettre à jour le texte pour les deux types de boutons
  5416. const textEl = btn.querySelector('.wishlist-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
  5417. if (textEl) 
  5418. textEl.textContent = 'favoris';
  5419. }
  5420. }).catch(() => {});
  5421. });
  5422. // Charger le compteur de comparaison
  5423. loadComparisonCount();{% endif %}
  5424. });
  5425. \t\t</script>
  5426. \t\t<script>
  5427. \t\t\t// Loader global pour tous les boutons de formulaire
  5428. document.addEventListener('DOMContentLoaded', function () { // Intercepter tous les formulaires
  5429. const forms = document.querySelectorAll('form');
  5430. forms.forEach(function (form) {
  5431. form.addEventListener('submit', function (e) {
  5432. const submitButtons = form.querySelectorAll('button[type=\"submit\"], input[type=\"submit\"], button:not([type])');
  5433. submitButtons.forEach(function (button) { // Vérifier si le bouton n'est pas déjà désactivé
  5434. if (! button.disabled && ! button.classList.contains('loading')) {
  5435. button.classList.add('loading');
  5436. button.disabled = true;
  5437. // Sauvegarder le texte original
  5438. const originalText = button.innerHTML;
  5439. button.setAttribute('data-original-text', originalText);
  5440. // Ajouter le loader
  5441. button.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Envoi...';
  5442. // Si le formulaire n'est pas valide, réactiver le bouton après 1 seconde
  5443. setTimeout(function () {
  5444. if (! form.checkValidity()) {
  5445. button.classList.remove('loading');
  5446. button.disabled = false;
  5447. button.innerHTML = originalText;
  5448. }
  5449. }, 1000);
  5450. }
  5451. });
  5452. });
  5453. });
  5454. // Pour les boutons qui déclenchent des actions AJAX
  5455. const ajaxButtons = document.querySelectorAll('[data-ajax], .ajax-submit, button[data-submit]');
  5456. ajaxButtons.forEach(function (button) {
  5457. button.addEventListener('click', function (e) {
  5458. if (this.disabled || this.classList.contains('loading')) {
  5459. e.preventDefault();
  5460. return false;
  5461. }
  5462. this.classList.add('loading');
  5463. this.disabled = true;
  5464. const originalText = this.innerHTML;
  5465. this.setAttribute('data-original-text', originalText);
  5466. this.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Chargement...';
  5467. });
  5468. });
  5469. // Gestionnaire spécifique pour le formulaire de newsletter
  5470. const newsletterForm = document.querySelector('.footer-newsletter-form');
  5471. if (newsletterForm) {
  5472. newsletterForm.addEventListener('submit', function (e) {
  5473. const submitBtn = this.querySelector('.newsletter-btn');
  5474. if (submitBtn && ! submitBtn.disabled) {
  5475. submitBtn.classList.add('loading');
  5476. submitBtn.disabled = true;
  5477. // Afficher le loader et masquer l'icône
  5478. const icon = submitBtn.querySelector('.newsletter-btn-icon');
  5479. const loader = submitBtn.querySelector('.newsletter-btn-loader');
  5480. if (icon) 
  5481. icon.style.display = 'none';
  5482. if (loader) 
  5483. loader.style.display = 'flex';
  5484. // Réactiver le bouton après 5 secondes au cas où la requête échoue silencieusement
  5485. setTimeout(function () {
  5486. if (submitBtn.classList.contains('loading')) {
  5487. submitBtn.classList.remove('loading');
  5488. submitBtn.disabled = false;
  5489. if (icon) 
  5490. icon.style.display = 'flex';
  5491. if (loader) 
  5492. loader.style.display = 'none';
  5493. }
  5494. }, 5000);
  5495. }
  5496. });
  5497. // Gérer la réponse du formulaire (si AJAX)
  5498. newsletterForm.addEventListener('submit', function (e) {
  5499. // Si le formulaire est soumis normalement (non-AJAX), le navigateur gère la réponse
  5500. // Sinon, on peut intercepter pour gérer la réponse AJAX ici
  5501. });
  5502. }
  5503. });
  5504. // CSS pour le spinner
  5505. const style = document.createElement('style');
  5506. style.textContent = `
  5507.     .spinner-border-sm {
  5508.         width: 1rem;
  5509.         height: 1rem;
  5510.         border-width: 0.15em;
  5511.     }
  5512.     .spinner-border {
  5513.         display: inline-block;
  5514.         width: 1rem;
  5515.         height: 1rem;
  5516.         vertical-align: text-bottom;
  5517.         border: 0.15em solid currentColor;
  5518.         border-right-color: transparent;
  5519.         border-radius: 50%;
  5520.         animation: spinner-border 0.75s linear infinite;
  5521.     }
  5522.     @keyframes spinner-border {
  5523.         to { transform: rotate(360deg); }
  5524.     }
  5525.     button.loading {
  5526.         opacity: 0.7;
  5527.         cursor: not-allowed !important;
  5528.     }
  5529. `;
  5530. document.head.appendChild(style);
  5531. \t\t</script>
  5532. \t\t<!-- Cart Modal -->
  5533. \t\t<div id=\"ebay-cart-modal\" class=\"ebay-cart-modal-overlay\" style=\"display: none;\" data-url=\"\">
  5534. \t\t\t<div class=\"ebay-cart-modal\">
  5535. \t\t\t\t<div class=\"ebay-modal-header\">
  5536. \t\t\t\t\t<h3>
  5537. \t\t\t\t\t\t<i class=\"lnr lnr-checkmark-circle\"></i>
  5538. \t\t\t\t\t\tAjouté au panier !</h3>
  5539. \t\t\t\t\t<button class=\"ebay-modal-close\" onclick=\"closeEbayCartModal()\">&times;</button>
  5540. \t\t\t\t</div>
  5541. \t\t\t\t<div class=\"ebay-modal-content\">
  5542. \t\t\t\t\t<div class=\"ebay-product-info\">
  5543. \t\t\t\t\t\t<div class=\"ebay-product-image\">
  5544. \t\t\t\t\t\t\t<img id=\"ebay-modal-product-image\" src=\"\" alt=\"Produit\"/>
  5545. \t\t\t\t\t\t</div>
  5546. \t\t\t\t\t\t<div class=\"ebay-product-details\">
  5547. \t\t\t\t\t\t\t<h4 id=\"ebay-modal-product-name\">Nom du produit</h4>
  5548. \t\t\t\t\t\t\t<div class=\"ebay-product-price\" id=\"ebay-modal-product-price\">Prix</div>
  5549. \t\t\t\t\t\t\t<div class=\"ebay-product-quantity\">
  5550. \t\t\t\t\t\t\t\t<span>Quantité:
  5551. \t\t\t\t\t\t\t\t</span>
  5552. \t\t\t\t\t\t\t\t<span id=\"ebay-modal-product-quantity\">1</span>
  5553. \t\t\t\t\t\t\t</div>
  5554. \t\t\t\t\t\t</div>
  5555. \t\t\t\t\t</div>
  5556. \t\t\t\t\t<!-- Recommendations Section -->
  5557. \t\t\t\t\t<div class=\"ebay-recommendations\" style=\"display: none;\">
  5558. \t\t\t\t\t\t<h4>Les clients ont aussi acheté :</h4>
  5559. \t\t\t\t\t\t<div
  5560. \t\t\t\t\t\t\tclass=\"ebay-recommendations-grid\" id=\"ebay-modal-recommendations\"><!-- Recommendations will be injected here -->
  5561. \t\t\t\t\t\t</div>
  5562. \t\t\t\t\t</div>
  5563. \t\t\t\t\t<div class=\"ebay-modal-actions\">
  5564. \t\t\t\t\t\t<button class=\"ebay-btn-continue\" onclick=\"closeEbayCartModal()\">
  5565. \t\t\t\t\t\t\tContinuer mes achats
  5566. \t\t\t\t\t\t</button>
  5567. \t\t\t\t\t\t<a href=\"{{ path('ui_cart') }}\" class=\"ebay-btn-view-cart\">
  5568. \t\t\t\t\t\t\tVoir mon panier
  5569. \t\t\t\t\t\t</a>
  5570. \t\t\t\t\t</div>
  5571. \t\t\t\t</div>
  5572. \t\t\t</div>
  5573. \t\t</div>
  5574. \t\t<script src=\"{{ asset('ui/js/cart-modal.js') }}\"></script>
  5575. \t\t<script src=\"{{ asset('ui/js/notification-badge.js') }}\"></script>
  5576. \t\t<script src=\"{{ asset('js/dark-mode.js') }}\"></script>
  5577. \t\t{% block javascripts %}{% endblock %}
  5578. \t</body>
  5579. </html>
  5580. ""base_home.html.twig""/home/u540977899/domains/maketou-ht.com/public_html/templates/base_home.html.twig");
  5581.     }
  5582. }