PageSourceSearch

https://www.combak.co/ask?source=homepage&from=%2F&via=header

html combak.co collected 2026-10-05 01:31:33 UTC 21,031 bytes, 232 lines download raw bytes

1<!DOCTYPE html><html lang="fr"><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><title data-next-head="">Ask Combak — Trouve ton bonheur</title><meta name="robots" content="noindex, nofollow" data-next-head=""/><meta name="viewport" content="width=device-width, initial-scale=1"/><meta name="p:domain_verify" content="b973e190377c1f96e6542bc642322eee"/><link rel="alternate" type="application/rss+xml" title="Combak Blog RSS Feed" href="/api/rss"/><style>/* antd brand colors — inlined to win against antd CSS-in-JS defaults
2injected at SSR. Without this, sliders render in #1677ff blue and checkboxes
3have #d9d9d9 grey borders (antd defaults) at first paint, then flip to brand
4green after hydration. Cause: the antd theme tokens (themeConfig.ts) are not
5captured by extractStyle() reliably for some components in dev OR prod. */
6.ant-slider .ant-slider-track{background-color:#02422a!important}
7.ant-slider .ant-slider-handle::after{background-color:#bef06d!important;border-radius:50px!important}
8.ant-slider .ant-slider-rail{background-color:rgba(0,0,0,0.06)!important}
9.ant-checkbox .ant-checkbox-inner{border-color:#02422a!important}
10.ant-checkbox-checked .ant-checkbox-inner{background-color:#bef06d!important;border-color:#02422a!important}
11.ant-checkbox-checked .ant-checkbox-inner::after{border-color:#02422a!important}
12.ant-checkbox-wrapper:hover .ant-checkbox-inner,.ant-checkbox:hover .ant-checkbox-inner{border-color:#02422a!important}
13.ant-checkbox-wrapper-checked:hover .ant-checkbox-inner,.ant-checkbox-checked:hover .ant-checkbox-inner{background-color:#bef06d!important;border-color:#02422a!important}
14/* Breadcrumb tailles inline pour éviter le shrink &quot;gros → normal&quot; sur mobile.
15   En dev mode, le CSS module Breadcrumb.module.scss n&#x27;est pas chargé synchrone
16   → la règle media @max-width 767px {font-size:13px} arrive après hydratation
17   → le breadcrumb apparait gros (16px) puis shrink. Ces règles couvrent les
18   2 breakpoints sans dépendre du CSS module. */
19.ant-breadcrumb{font-size:16px;line-height:24px;color:var(--text-secondary)}
20.ant-breadcrumb a{color:var(--text-primary);font-weight:500}
21@media(max-width:767px){.ant-breadcrumb{font-size:13px;line-height:20px}}
22:root{--almost-black:#20201e;--seasalt:#f7f7f7;--lime:#bef06d;--dark-green:#02422a;--white-100:#fff;--black-100:#e6e6e5;--black-300:#b7b7b3;--black-400:#9f9f98;--black-700:#54544f;--black-900:#20201e;--lime-500:#bef06d;--green-800:#02422a;--surface-primary:var(--seasalt);--surface-secondary:var(--white-100);--text-primary:var(--black-900);--text-secondary:var(--black-700);--text-tertiary:var(--black-400);--text-brand:var(--green-800);--padding-lg:8px;--padding-xl:12px;--padding-2xl:16px;--padding-3xl:24px;--horizontal-spacing-lg:16px;
22--horizontal-spacing-2xl:40px;--horizontal-spacing-4xl:64px;--vertical-spacing-4xl:40px;--vertical-spacing-6xl:80px;--radius-2xl:16px;--radius-3xl:24px;--shadow-sm:1px 1px 16px hsla(60,3%,12%,.08);--text-body-md:16px;--text-body-sm:14px;--text-heading-1:36px;--text-heading-2:32px}*{box-sizing:border-box;padding:0;margin:0}html,body{width:100%;height:100vh;font-family:&quot;Manrope&quot;,-apple-system,BlinkMacSystemFont,&quot;Segoe UI&quot;,Roboto,Oxygen,Ubuntu,Cantarell,&quot;Helvetica Neue&quot;,Arial,sans-serif;font-weight:400;line-height:1.4;font-synthesis-weight:none;font-synthesis-style:none}body{color:var(--text-primary);position:relative;background-color:var(--surface-primary)}main{min-height:calc(100vh - 110px)}@media (min-width:1000px){main{min-height:calc(100vh - 90px)}}a{color:inherit;font-weight:500;text-decoration:none}h1,h2,h3,h4,h5,h6{color:var(--text-brand);margin-bottom:0;font-weight:700;font-family:&quot;Rubik&quot;,sans-serif;text-transform:uppercase}header{z-index:999;position:sticky;top:0;left:0;right:0;background-color:#fff}header .Logo{width:150px;height:100%;padding:0;margin:0}@media (min-width:1000px){header .DesktopWrapper{display:block}header .MobileWrapper{display:none}header .Row{height:80px;display:flex;align-items:center;justify-content:space-between;gap:var(--vertical-spacing-4xl)}}@media (max-width:999px){header .DesktopWrapper{display:none}header .MobileWrapper{display:block}}.container{width:100%;max-width:1440px;margin:0 auto;padding:0 var(--padding-2xl)}@media (min-width:768px){.container{padding:0 var(--padding-3xl)}}article{position:relative;padding:var(--padding-2xl) var(--padding-xl) var(--padding-lg) var(--padding-xl);display:flex;flex-direction:column;gap:var(--horizontal-spacing-lg);
22min-width:200px;border-radius:var(--radius-2xl);background-color:var(--surface-secondary);box-shadow:var(--shadow-sm)}figure{margin:0;position:relative;aspect-ratio:1/1;overflow:hidden;border-radius:8px;max-height:135px}.products-grid{display:grid;gap:var(--horizontal-spacing-2xl);grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}.body-md{font-size:var(--text-body-md)}.body-sm{font-size:var(--text-body-sm)}.w-700{font-weight:700}.w-500{font-weight:500}.overline{font-size:12px;font-weight:500;text-transform:uppercase;letter-spacing:.5px}.color-tertiary{color:var(--text-tertiary)}.ant-btn{font-family:&quot;Rubik&quot;,sans-serif}.grecaptcha-badge{visibility:hidden}.hero-critical,h1.hero-critical,section h1.hero-critical{font-family:&quot;Rubik&quot;,-apple-system,BlinkMacSystemFont,&quot;Segoe UI&quot;,Roboto,sans-serif!important;font-size:2.5rem!important;font-weight:700!important;line-height:1.2!important;color:#02422a!important;margin:0!important}.hero-critical mark::before,.hero-critical [class*=&quot;Mark_&quot;]::before,.hero-critical [class*=&quot;HightlightWavy&quot;]::before,.hero-critical [class*=&quot;Mark_Pink&quot;]::before{display:none!important}.hero-critical mark,.hero-critical [class*=&quot;Mark_&quot;]{background:transparent!important;color:inherit!important;position:relative!important}.hero-critical mark::after,.hero-critical [class*=&quot;Mark_&quot;]::after{content:&quot;&quot;!important;position:absolute!important;top:20%!important;left:-2px!important;right:-2px!important;bottom:10%!important;background:rgba(26,26,26,.08)!important;border-radius:4px!important;z-index:-1!important}@media (min-width:768px){.hero-critical,h1.hero-critical,section h1.hero-critical{font-size:3rem!important}}</style><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous"/><link rel="dns-prefetch" href="//fonts.gstatic.com"/><link rel="preconnect" href="https://www.google.com"/><link rel="preconnect" href="https://www.gstatic.com" crossorigin="anonymous"/><link rel="dns-prefetch" href="//www.googletagmanager.com"/><link rel="preconnect" href="https://xfpsta639gh5iu7jp-1.a1.typesense.net"/><link rel="dns-prefetch" href="//xfpsta639gh5iu7jp-1.a1.typesense.net"/><link rel="preconnect" href="https://d2e6ccujb3mkqf.cloudfront.net"/><link rel="dns-prefetch" href="//d2e6ccujb3mkqf.cloudfront.net"/><link rel="preconnect" href="https://oggoqwmaeps6otwt.public.blob.vercel-storage.com" crossorigin="anonymous"/><link rel="dns-prefetch" href="//oggoqwmaeps6otwt.public.blob.vercel-storage.com"/><link rel="preconnect" href="https://www.googletagmanager.com"/><link rel="preconnect" href="https://www.google-analytics.com"/><link rel="dns-prefetch" href="//www.google-analytics.com"/><link rel="preconnect" href="https://cdn.cookie-script.com"/><link rel="preconnect" href="https://consent.cookie-script.com"/><link rel="dns-prefetch" href="//cdn.cookie-script.com"/><link rel="dns-prefetch" href="//consent.cookie-script.com"/><link rel="preload" href="/fonts/rubik-variable.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="/fonts/manrope-variable.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous"/><link rel="preload" href="https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxK.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fBBc4.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><link rel="shortcut icon" href="/favicon.ico"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/><meta name="apple-mobile-web-app-title" content="Combak"/><link rel="manifest" href="/site.webmanifest"/><link rel="preload" href="/_next/static/css/e705428f2ee24242.css" as="style"/><link rel="stylesheet" href="/_next/static/css/e705428f2ee24242.css" data-n-g=""/><link rel="preload" href="/_next/static/css/dc9e572b0f9edb48.css" as="style"/><link rel="stylesheet" href="/_next/static/css/dc9e572b0f9edb48.css"/><link rel="preload" href="/_next/static/css/17b4ab0f710c9b7a.css" as="style"/><link rel="stylesheet" href="/_next/static/css/17b4ab0f710c9b7a.css"/><link rel="preload" href="/_next/static/css/12e3ce1ceec88404.css" as="style"/><link rel="stylesheet" href="/_next/static/css/12e3ce1ceec88404.css"/><noscript data-n-css=""></noscript>
22<script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script>
22<script src="/_next/static/chunks/webpack-2186dca6759fa6f3.js" defer=""></script>
22<script src="/_next/static/chunks/framework-7c3854d185585de2.js" defer=""></script>
22<script src="/_next/static/chunks/main-ad142f15e75f7f25.js" defer=""></script>
22<script src="/_next/static/chunks/pages/_app-86d8575ccc234e6a.js" defer=""></script>
22<script src="/_next/static/chunks/07877efe-e2f122407ac86ead.js" defer=""></script>
22<script src="/_next/static/chunks/7112-5160b2a7f98a41d1.js" defer=""></script>
22<script src="/_next/static/chunks/3451-68a1093c3aab0cc7.js" defer=""></script>
22<script src="/_next/static/chunks/5704-75817181e4423432.js" defer=""></script>
22<script src="/_next/static/chunks/6094-0bc8a57d9aa15214.js" defer=""></script>
22<script src="/_next/static/chunks/3670-0770986bfb97bd89.js" defer=""></script>
22<script src="/_next/static/chunks/8644-5d5c5b9c1217589d.js" defer=""></script>
22<script src="/_next/static/chunks/3377-5c01ffcae47b6bf4.js" defer=""></script>
22<script src="/_next/static/chunks/7000-b83dbd2e170ba792.js" defer=""></script>
22<script src="/_next/static/chunks/2736-b9ed53ecd4fd2da0.js" defer=""></script>
22<script src="/_next/static/chunks/593-2acb89f4414480a4.js" defer=""></script>
22<script src="/_next/static/chunks/9054-133cc8e46b5004a0.js" defer=""></script>
22<script src="/_next/static/chunks/7104-b7d8ccc477bdecca.js" defer=""></script>
22<script src="/_next/static/chunks/7903-45fccf2945391f71.js" defer=""></script>
22<script src="/_next/static/chunks/1289-90471dc52f3fa58d.js" defer=""></script>
22<script src="/_next/static/chunks/1885-68eceb667613da9b.js" defer=""></script>
22<script src="/_next/static/chunks/4099-2ae1b1d49cc3d876.js" defer=""></script>
22<script src="/_next/static/chunks/6634-97e7c4bad38b42eb.js" defer=""></script>
22<script src="/_next/static/chunks/pages/ask-eead7d7e7a7cb51c.js" defer=""></script>
22<script src="/_next/static/A9dYD1Ef65ujfvdKyI6Bz/_buildManifest.js" defer=""></script>
22<script src="/_next/static/A9dYD1Ef65ujfvdKyI6Bz/_ssgManifest.js" defer=""></script>
22<style>.anticon{display:inline-flex;align-items:center;color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-0.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}.anticon >*{line-height:1;}.anticon svg{display:inline-block;}.anticon .anticon .anticon-icon{display:block;}.data-ant-cssinjs-cache-path{content:"21mfza|ant-design-icons|anticon:139pitw";}</style></head><body>
22<script>
23// ✅ Initialiser Consent Mode v2 AVANT GTM
24window.dataLayer = window.dataLayer || [];
25function gtag(){dataLayer.push(arguments);}
26
27// Définir le consentement par défaut (denied pour tout sauf security)
28gtag('consent', 'default', {
29  'ad_storage': 'denied',
30  'ad_user_data': 'denied',
31  'ad_personalization': 'denied',
32  'analytics_storage': 'denied',
33  'functionality_storage': 'denied',
34  'personalization_storage': 'denied',
35  'security_storage': 'granted',  // Toujours autorisé
36  'wait_for_update': 500  // Attendre max 500ms pour Cookie-Script
37});
38
39// ✅ Écouter les changements de consentement Cookie-Script
40//
41// ⚠️ BUG CORRIGÉ (audit 2026-07-27) : l'ancienne version lisait le format
42// CookieScript v1 (state.targeting / state.performance, booléens). La prod est
43// en v2 (currentState() = { action, categories: [] }) → tous les champs lus
44// valaient undefined → cet update poussait TOUT en 'denied', APRÈS (et donc
45// par-dessus) l'update 'granted' de l'intégration Google Consent Mode native
46// de CookieScript. Résultat : GA4/Ads en consent denied même après acceptation
47// complète (vérifié en prod via dataLayer). On parse maintenant les DEUX
48// formats ; l'update devient redondant-mais-cohérent avec l'intégration native
49// (double push identique = inoffensif, et on reste protégé si l'intégration
50// native est désactivée côté dashboard CookieScript).
51function updateConsentFromCookieScript() {
52  if (typeof window.CookieScript === 'undefined') return;
53  if (typeof window.CookieScript.instance === 'undefined') return;
54
55  try {
56    const state = window.CookieScript.instance.currentState();
57    // v2 : { action, categories: ['performance','targeting','functionality',…] }
58    const cats = Array.isArray(state.categories) ? state.categories : null;
59    const inCats = function (keys) {
60      for (var i = 0; i < keys.length; i++) {
61        if (cats.indexOf(keys[i]) !== -1) return true;
62      }
63      return false;
64    };
65    // v1 (legacy) : booléens à plat sur l'objet state.
66    const targeting = cats ? inCats(['targeting', 'advertisement']) : !!state.targeting;
67    const performance = cats
68      ? inCats(['performance', 'analytics', 'statistics'])
69      : !!state.performance;
70    const functionality = cats
71      ? inCats(['functionality', 'personalization'])
72      : !!state.functionality;
73
74    gtag('consent', 'update', {
75      'ad_storage': targeting ? 'granted' : 'denied',
76      'ad_user_data': targeting ? 'granted' : 'denied',
77      'ad_personalization': targeting ? 'granted' : 'denied',
78      'analytics_storage': performance ? 'granted' : 'denied',
79      'functionality_storage': functionality ? 'granted' : 'denied',
80      'personalization_storage': functionality ? 'granted' : 'denied',
81    });
82
83    console.log('✅ Consent Mode v2 updated:', { targeting: targeting, performance: performance, functionality: functionality });
84  } catch (error) {
85    console.error('❌ Failed to update consent:', error);
86  }
87}
88
89// Écouter les événements Cookie-Script (Save = choix partiels, Reject = refus :
90// absents avant, le refus/choix partiel ne re-synchronisait jamais le consent).
91if (typeof window !== 'undefined') {
92  window.addEventListener('CookieScriptLoaded', updateConsentFromCookieScript);
93  window.addEventListener('CookieScriptAccept', updateConsentFromCookieScript);
94  window.addEventListener('CookieScriptAcceptAll', updateConsentFromCookieScript);
95  window.addEventListener('CookieScriptSave', updateConsentFromCookieScript);
96  window.addEventListener('CookieScriptReject', updateConsentFromCookieScript);
97
98  // Vérifier aussi après un court délai (si Cookie-Script était déjà chargé)
99  setTimeout(updateConsentFromCookieScript, 100);
100}
101</script>
101<script>
102              (function() {
103                document.documentElement.classList.add('js-enabled');
104
105                // ✅ Cacher immédiatement avec CSS pour éviter FOUC
106                var style = document.createElement('style');
107                style.id = 'ssr-hide-style';
108                style.innerHTML = 'html.js-enabled .ssr-only, html.js-enabled aside.ssr-only, html.js-enabled div.ssr-only { display: none !important; visibility: hidden !important; }';
109                document.head.appendChild(style);
110
111                // ✅ Supprimer du DOM après l'hydratation React (éviter contenu dupliqué SEO)
112                // Attendre 100ms après le chargement complet pour laisser React s'hydrater
113                window.addEventListener('load', function() {
114                  setTimeout(function() {
115                    document.querySelectorAll('.ssr-only').forEach(function(el) {
116                      el.remove();
117                    });
118                  }, 100);
119                });
120              })();
121            </script>
121<script>
122(function fixCookieScript() {
123  var fixAttempts = 0;
124  var MAX_ATTEMPTS = 50;
125
126  function applyFix() {
127    fixAttempts++;
128    var allCookieElements = Array.from(document.querySelectorAll('[id*="cookie"]'));
129
130    if (allCookieElements.length > 0) {
131      // La fenêtre de détails plein écran ouverte par l'utilisateur
132      // (« Afficher les détails ») : c'est un VRAI modal, il ne faut JAMAIS
133      // le neutraliser ni neutraliser ses descendants, sinon ses boutons
134      // (Accepter / Refuser / Sauvegarder), son close X et ses toggles
135      // deviennent non cliquables.
136      var fsd = document.getElementById('cookiescript_injected_fsd');
137
138      allCookieElements.forEach(function(el) {
139        // Ne pas toucher la fenêtre de détails ni son contenu.
140        if (fsd && (el === fsd || fsd.contains(el))) return;
141
142        var style = window.getComputedStyle(el);
143        var rect = el.getBoundingClientRect();
144        var coversScreen = rect.width > window.innerWidth - 100 && rect.height > window.innerHeight - 100;
145
146        if (coversScreen && style.position === 'fixed') {
147          el.style.pointerEvents = 'none';
148          el.style.setProperty('pointer-events', 'none', 'important');
149        }
150
151        var children = el.querySelectorAll('*');
152        children.forEach(function(child) {
153          // Idem : ne jamais désactiver un descendant de la fenêtre de détails.
154          if (fsd && (child === fsd || fsd.contains(child))) return;
155
156          var childStyle = window.getComputedStyle(child);
157          var childRect = child.getBoundingClientRect();
158          var childCoversScreen = childRect.width > window.innerWidth - 100 && childRect.height > window.innerHeight - 100;
159
160          if (childCoversScreen && childStyle.position === 'fixed') {
161            child.style.pointerEvents = 'none';
162            child.style.setProperty('pointer-events', 'none', 'important');
163          }
164        });
165      });
166
167      // S'assurer que la fenêtre de détails et tout son contenu restent cliquables.
168      if (fsd) {
169        fsd.style.setProperty('pointer-events', 'auto', 'important');
170        fsd.querySelectorAll('*').forEach(function(child) {
171          child.style.setProperty('pointer-events', 'auto', 'important');
172        });
173      }
174
175      var cookieScriptMain = document.getElementById('cookiescript_injected');
176      if (cookieScriptMain) {
177        cookieScriptMain.style.zIndex = '10000';
178        cookieScriptMain.style.setProperty('z-index', '10000', 'important');
179
180        var visibleBanners = cookieScriptMain.querySelectorAll('[class*="banner"], [class*="dialog"], [id*="dialog"]');
181        visibleBanners.forEach(function(banner) {
182          banner.style.pointerEvents = 'auto';
183          banner.style.setProperty('pointer-events', 'auto', 'important');
184        });
185      }
186
187      return true;
188    }
189
190    if (fixAttempts < MAX_ATTEMPTS) {
191      setTimeout(applyFix, 100);
192    }
193
194    return false;
195  }
196
197  var observer = new MutationObserver(function(mutations) {
198    mutations.forEach(function(mutation) {
199      mutation.addedNodes.forEach(function(node) {
200        if (node.nodeType === 1) {
201          var el = node;
202          // el.id n'est pas toujours une string : sur certains noeuds (SVG hérités,
203          // DOM clobbering d'un descendant name="id"...) c'est un objet sans .includes
204          // → TypeError répété dans le MutationObserver. On garde-type avant l'appel.
205          if (el.id && typeof el.id === 'string' && el.id.includes('cookiescript')) {
206            setTimeout(applyFix, 50);
207          }
208        }
209      });
210    });
211  });
212
213  if (document.body) {
214    observer.observe(document.body, {
215      childList: true,
216      subtree: false
217    });
218  }
219
220  if (document.readyState === 'loading') {
221    document.addEventListener('DOMContentLoaded', applyFix);
222  } else {
223    applyFix();
224  }
225
226  window.addEventListener('load', function() {
227    setTimeout(applyFix, 100);
228    setTimeout(applyFix, 500);
229    setTimeout(applyFix, 1000);
230  });
231})();
232</script>
vendor: 67 bytes, line 232
232<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
232GTM-TGT8LCMF
vendor: 82 bytes, line 232
232" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
232<div id="__next"></div>
232<script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/ask","query":{},"buildId":"A9dYD1Ef65ujfvdKyI6Bz","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[{"src":"https://www.dwin2.com/pub.1579424.min.js","strategy":"lazyOnload"}]}</script>
232</body></html>

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