u003cstyleu003en* { box-sizing:border-box; margin:0; padding:0; }n n#abd-wrapper { background:#F5F4F0; min-height:100vh; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; }n n/* ── Header ── */n#abd-header {n background:#C44E1E; padding:14px 20px;n display:flex; justify-content:space-between; align-items:center;n position:sticky; top:0; z-index:200;n box-shadow:0 2px 8px rgba(0,0,0,0.2);n}n#abd-logo { color:#fff; font-size:18px; font-weight:700; }n#abd-badge {n background:rgba(255,255,255,0.18); color:#fff;n font-size:12px; padding:5px 13px; border-radius:20px; font-weight:500;n display:flex; align-items:center; gap:6px;n}n.abd-dot { width:7px; height:7px; background:#4ADE80; border-radius:50%; flex-shrink:0; }n n/* ── Tabs ── */n#abd-tabs-wrap {n background:#fff; border-bottom:1px solid #E8E4DC;n position:sticky; top:52px; z-index:150;n}n#abd-tabs {n max-width:1100px; margin:0 auto;n display:flex; overflow-x:auto; scrollbar-width:none;n}n#abd-tabs::-webkit-scrollbar { display:none; }n.abd-tab {n white-space:nowrap; padding:13px 18px; font-size:13px; font-weight:500;n color:#999; border:none; background:none; cursor:pointer;n border-bottom:2px solid transparent; flex-shrink:0; transition:all 0.15s;n}n.abd-tab.active { color:#C44E1E; border-bottom-color:#C44E1E; }n n/* ── Products ── */n#abd-inner { max-width:1100px; margin:0 auto; padding:0 16px; }n#abd-products { padding:16px 0 110px; display:grid; gap:12px; grid-template-columns:repeat(2,1fr); }n@media(min-width:640px) { #abd-products { grid-template-columns:repeat(3,1fr); } }n@media(min-width:960px) { #abd-products { grid-template-columns:repeat(4,1fr); } }n n.abd-cat-header {n grid-column:1/-1; font-size:16px; font-weight:700; color:#1A1A1A;n margin:12px 0 6px; padding-bottom:8px; border-bottom:2px solid #C44E1E;n}n#abd-loading { grid-column:1/-1; text-align:center; padding:52px 16px; color:#999; font-size:14px; }n n/* ── Card ── */n.abd-card {n background:#fff; border-radius:14px; overflow:hidden;n box-shadow:0 1px 5px rgba(0,0,0,0.07); transition:transform 0.15s, box-shadow 0.15s;n}n.abd-card:hover { transform:translateY(-2px); box-shadow:0 4px 14px rgba(0,0,0,0.1); }n.abd-card-img {n width:100%; aspect-ratio:4/3; background:#F0E8D8;n display:flex; align-items:center; justify-content:center;n font-size:36px; overflow:hidden;n}n.abd-card-img img { width:100%; height:100%; object-fit:cover; }n.abd-card-body { padding:10px 12px 12px; }n.abd-card-name { font-size:13px; font-weight:600; color:#1A1A1A; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-bottom:3px; }n.abd-card-desc { font-size:11px; color:#999; line-height:1.4; height:30px; overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; margin-bottom:10px; }n.abd-card-footer { display:flex; justify-content:space-between; align-items:center; }n.abd-price { font-size:13px; font-weight:700; color:#C44E1E; }n.abd-add-btn {n background:#C44E1E; color:#fff; border:none; border-radius:50%;n width:28px; height:28px; font-size:20px; line-height:1; cursor:pointer;n display:flex; align-items:center; justify-content:center;n transition:background 0.15s, transform 0.1s; flex-shrink:0;n}n.abd-add-btn:active { transform:scale(0.88); }n n/* ── Cart bar ── */n#abd-cart-bar {n position:fixed; bottom:0; left:0; right:0; background:#1A1A1A; color:#fff;n padding:14px 20px; display:flex; justify-content:space-between; align-items:center;n z-index:300; box-shadow:0 -4px 20px rgba(0,0,0,0.2); transition:transform 0.3s ease;n}n#abd-cart-bar.hidden { transform:translateY(110%); }n#abd-cart-info { line-height:1; }n#abd-cart-count-label { font-size:11px; color:rgba(255,255,255,0.5); margin-bottom:3px; display:block; }n#abd-cart-total { font-size:17px; font-weight:700; }n#abd-cart-btn { background:#C44E1E; color:#fff; border:none; border-radius:24px; padding:11px 24px; font-size:13px; font-weight:700; cursor:pointer; }n n/* ── Modal ── */n#abd-modal-bg {n display:none; position:fixed; inset:0;n background:rgba(0,0,0,0.45); z-index:400;n align-items:flex-end; justify-content:center;n}n#abd-modal-bg.open { display:flex; }n#abd-modal { background:#fff; border-radius:20px 20px 0 0; padding:20px 20px 36px; width:100%; max-width:520px; animation:slideUp 0.25s ease; }n@keyframes slideUp { from{transform:translateY(100%)} to{transform:translateY(0)} }n.abd-modal-hd { display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:14px; }n#abd-modal-title { font-size:17px; font-weight:700; color:#1A1A1A; }n#abd-modal-close { background:#F0EDE8; border:none; width:30px; height:30px; border-radius:50%; font-size:16px; cursor:pointer; display:flex; align-items:center; justify-content:center; flex-shrink:0; }n#abd-modal-desc { font-size:12px; color:#999; margin-bottom:16px; line-height:1.5; }n.abd-variation { display:flex; justify-content:space-between; align-items:center; padding:13px 0; border-bottom:1px solid #F3F0EB; }n.abd-variation:last-child { border-bottom:none; }n.abd-var-name { font-size:14px; font-weight:500; color:#1A1A1A; }n.abd-var-price { font-size:14px; font-weight:700; color:#C44E1E; margin-right:12px; }n.abd-var-add { background:#C44E1E; color:#fff; border:none; border-radius:20px; padding:8px 18px; font-size:12px; font-weight:600; cursor:pointer; }n.abd-var-add:disabled { background:#ccc; cursor:not-allowed; }n n/* ── Toast ── */n#abd-toast { position:fixed; bottom:80px; left:50%; transform:translateX(-50%) translateY(16px); background:#1A1A1A; color:#fff; padding:10px 20px; border-radius:20px; font-size:13px; z-index:500; opacity:0; transition:opacity 0.25s,transform 0.25s; pointer-events:none; white-space:nowrap; }n#abd-toast.show { opacity:1; transform:translateX(-50%) translateY(0); }n n/* ── Error ── */n.abd-error { grid-column:1/-1; text-align:center; padding:32px 16px; color:#C44E1E; font-size:13px; line-height:1.8; }nu003c/styleu003enu003c/headu003enu003cbodyu003en nu003cdiv id=u0022abd-wrapperu0022u003en n u003cdiv id=u0022abd-headeru0022u003en u003cdiv id=u0022abd-logou0022u003e🍕 Au Blé d'Oru003c/divu003en u003cdiv id=u0022abd-badgeu0022u003eu003cspan class=u0022abd-dotu0022u003eu003c/spanu003eOuvert · Retrait 20 minu003c/divu003en u003c/divu003en n u003cdiv id=u0022abd-tabs-wrapu0022u003en u003cdiv id=u0022abd-tabsu0022u003eu003c/divu003en u003c/divu003en n u003cdiv id=u0022abd-inneru0022u003en u003cdiv id=u0022abd-productsu0022u003en u003cdiv id=u0022abd-loadingu0022u003eChargement du menu…u003c/divu003en u003c/divu003en u003c/divu003en n u003cdiv id=u0022abd-cart-baru0022 class=u0022hiddenu0022u003en u003cdiv id=u0022abd-cart-infou0022u003en u003cspan id=u0022abd-cart-count-labelu0022u003eu003c/spanu003en u003cspan id=u0022abd-cart-totalu0022u003e0,00 €u003c/spanu003en u003c/divu003en u003cbutton id=u0022abd-cart-btnu0022u003eVoir mon panier →u003c/buttonu003en u003c/divu003en nu003c/divu003en nu003cdiv id=u0022abd-modal-bgu0022u003en u003cdiv id=u0022abd-modalu0022u003en u003cdiv class=u0022abd-modal-hdu0022u003en u003cdiv id=u0022abd-modal-titleu0022u003eu003c/divu003en u003cbutton id=u0022abd-modal-closeu0022u003e✕u003c/buttonu003en u003c/divu003en u003cdiv id=u0022abd-modal-descu0022u003eu003c/divu003en u003cdiv id=u0022abd-modal-variationsu0022u003eu003c/divu003en u003c/divu003enu003c/divu003en nu003cdiv id=u0022abd-toastu0022u003eu003c/divu003en nu003cscriptu003en(function(){n const SITE = 'https://aubledor.fr';n const CART_URL = SITE + '/panier/';n const EMOJI = { pizzas:'🍕', boulangerie:'🥐', desserts:'🍰', pains:'🥖', default:'🍽️' };n n let allProducts=[], categories=[], activeCategory='all', cartNonce=null;n n /* ── INIT ───────────────────────────────── */n async function init() {n try {n await fetchCartNonce();n await fetchProducts();n renderTabs();n renderProducts();n } catch(e) {n document.getElementById('abd-loading').innerHTML =n `u003cdiv class=u0022abd-erroru0022u003e❌ Impossible de charger le menu.u003cbru003eu003csmallu003e${e.message}u003c/smallu003eu003c/divu003e`;n }n }n n /* ── NONCE ──────────────────────────────── */n async function fetchCartNonce() {n const res = await fetch(`${SITE}/wp-json/wc/store/v1/cart`, {credentials:'include'});n cartNonce = res.headers.get('Nonce') || res.headers.get('X-WC-Store-API-Nonce');n updateCartBar(await res.json());n }n n /* ── PRODUCTS ───────────────────────────── */n async function fetchProducts() {n const res = await fetch(`${SITE}/wp-json/wc/store/v1/products?per_page=100u0026orderby=menu_orderu0026order=asc`, {credentials:'include'});n if (!res.ok) throw new Error('HTTP ' + res.status);n const data = await res.json();n const seen = new Set();n data.forEach(p =u003e (p.categories||[]).forEach(cat =u003e {n if (!seen.has(cat.slug)) { seen.add(cat.slug); categories.push(cat); }n }));n allProducts = data;n }n n /* ── TABS ───────────────────────────────── */n function renderTabs() {n const wrap = document.getElementById('abd-tabs');n wrap.innerHTML = '';n const all = [{slug:'all', name:'Tout', e:'🍽️'}]n .concat(categories.map(c=u003e({slug:c.slug, name:c.name, e:EMOJI[c.slug]||EMOJI.default})));n all.forEach((cat, i) =u003e {n const btn = document.createElement('button');n btn.className = 'abd-tab' + (i===0?' active':'');n btn.textContent = cat.e + ' ' + cat.name;n btn.dataset.cat = cat.slug;n btn.addEventListener('click', () =u003e {n activeCategory = cat.slug;n document.querySelectorAll('.abd-tab').forEach(t =u003e t.classList.toggle('active', t.dataset.cat===cat.slug));n renderProducts();n });n wrap.appendChild(btn);n });n }n n /* ── RENDER ─────────────────────────────── */n function renderProducts() {n const container = document.getElementById('abd-products');n container.innerHTML = '';n const list = activeCategory==='all' ? allProductsn : allProducts.filter(p=u003e(p.categories||[]).some(c=u003ec.slug===activeCategory));n if (!list.length) { container.innerHTML='u003cdiv id=u0022abd-loadingu0022u003eAucun produit dans cette catégorie.u003c/divu003e'; return; }n if (activeCategory==='all') {n categories.forEach(cat =u003e {n const prods = allProducts.filter(p=u003e(p.categories||[]).some(c=u003ec.slug===cat.slug));n if (!prods.length) return;n const h = document.createElement('div'); h.className='abd-cat-header';n h.textContent = (EMOJI[cat.slug]||'🍽️') + ' ' + cat.name;n container.appendChild(h);n prods.forEach(p=u003econtainer.appendChild(buildCard(p)));n });n } else {n list.forEach(p=u003econtainer.appendChild(buildCard(p)));n }n }n n function priceLabel(p) {n const r = p.prices?.price_range;n if (r u0026u0026 r.min_amount !== r.max_amount) return fmt(r.min_amount)+' – '+fmt(r.max_amount)+' €';n return fmt(p.prices?.price||'0')+' €';n }n function fmt(minor) { return (parseInt(minor,10)/100).toFixed(2).replace('.',','); }n function strip(html) { const d=document.createElement('div'); d.innerHTML=html||''; return d.textContent||''; }n n function buildCard(p) {n const card = document.createElement('div'); card.className='abd-card';n const emoji = EMOJI[(p.categories||[])[0]?.slug]||EMOJI.default;n const img = p.images?.[0]?.src ? `u003cimg src=u0022${p.images[0].src}u0022 alt=u0022${p.name}u0022 loading=u0022lazyu0022/u003e` : `u003cspanu003e${emoji}u003c/spanu003e`;n card.innerHTML = `n u003cdiv class=u0022abd-card-imgu0022u003e${img}u003c/divu003en u003cdiv class=u0022abd-card-bodyu0022u003en u003cdiv class=u0022abd-card-nameu0022u003e${p.name}u003c/divu003en u003cdiv class=u0022abd-card-descu0022u003e${strip(p.short_description)}u003c/divu003en u003cdiv class=u0022abd-card-footeru0022u003en u003cspan class=u0022abd-priceu0022u003e${priceLabel(p)}u003c/spanu003en u003cbutton class=u0022abd-add-btnu0022 aria-label=u0022Ajouteru0022u003e+u003c/buttonu003en u003c/divu003en u003c/divu003e`;n card.querySelector('.abd-add-btn').addEventListener('click', e =u003e {n e.stopPropagation();n p.type==='variable' ? openModal(p) : addToCart(p.id, null, p.name);n });n return card;n }n n /* ── ADD TO CART ────────────────────────── */n async function addToCart(productId, variationId, name) {n const itemId = variationId || productId;n try {n if (!cartNonce) await fetchCartNonce();n const res = await fetch(`${SITE}/wp-json/wc/store/v1/cart/add-item`, {n method:'POST', credentials:'include',n headers:{'Content-Type':'application/json','Nonce':cartNonce,'X-WC-Store-API-Nonce':cartNonce},n body: JSON.stringify({id:itemId, quantity:1})n });n const newN = res.headers.get('Nonce')||res.headers.get('X-WC-Store-API-Nonce');n if (newN) cartNonce = newN;n const data = await res.json();n if (res.ok u0026u0026 !data.code) {n updateCartBar(data);n showToast('✓ ' + name + ' ajouté !');n } else { fallbackCart(productId, variationId); }n } catch(e) { fallbackCart(productId, variationId); }n }n n function fallbackCart(productId, variationId) {n // Pour les variations : passer l'ID de variation directement via add-to-cartn // WooCommerce accepte les variation IDs directement avec ?add-to-cart=varIdn window.location.href = variationIdn ? `${SITE}/?add-to-cart=${productId}u0026variation_id=${variationId}u0026quantity=1`n : `${SITE}/?add-to-cart=${productId}u0026quantity=1`;n }n n /* ── CART BAR ───────────────────────────── */n function updateCartBar(d) {n const count = d.items_count||0;n const total = (parseInt(d.totals?.total_price||0,10)/100).toFixed(2).replace('.',',');n document.getElementById('abd-cart-count-label').textContent = count ? count+(countu003e1?' articles':' article') : '';n document.getElementById('abd-cart-total').textContent = total+' €';n document.getElementById('abd-cart-bar').classList.toggle('hidden', count===0);n }n document.getElementById('abd-cart-btn').addEventListener('click', ()=u003ewindow.location.href=CART_URL);n n /* ── MODAL VARIATIONS ───────────────────── */n // Utilise ?wc-ajax=get_variation pour récupérer le vrai prix + variation_idn // C'est l'endpoint natif WooCommerce, plus fiable que Store API pour les variationsn n let curProduct = null;n n function openModal(p) {n curProduct = p;n document.getElementById('abd-modal-title').textContent = p.name;n document.getElementById('abd-modal-desc').textContent = strip(p.short_description);n document.getElementById('abd-modal-variations').innerHTML =n 'u003cp style=u0022text-align:center;color:#999;padding:16px 0;font-size:13px;u0022u003eChargement des options…u003c/pu003e';n document.getElementById('abd-modal-bg').classList.add('open');n loadVariations(p);n }n n async function loadVariations(p) {n const c = document.getElementById('abd-modal-variations');n try {n // Récupère le produit parent pour avoir les attributs et leurs valeursn const res = await fetch(`${SITE}/wp-json/wc/store/v1/products/${p.id}`, {credentials:'include'});n const full = await res.json();n const attributes = full.attributes || [];n n if (!attributes.length) {n c.innerHTML = `u003cp style=u0022text-align:center;u0022u003eu003ca href=u0022${SITE}/?p=${p.id}u0022 style=u0022color:#C44E1E;font-weight:600;u0022u003eVoir les options →u003c/au003eu003c/pu003e`;n return;n }n n const attr = attributes[0]; // ex: { slug: u0022pa_tailleu0022, name: u0022Tailleu0022, terms: [...] }n const terms = attr.terms || [];n n if (!terms.length) {n c.innerHTML = `u003cp style=u0022text-align:center;color:#999;font-size:13px;u0022u003eAucune option disponible.u003c/pu003e`;n return;n }n n // Pour chaque option (ex: Petite 25cm), appelle wc-ajax=get_variationn // Cet endpoint natif WooCommerce retourne variation_id + display_pricen const fetches = terms.map(async term =u003e {n const body = new URLSearchParams();n body.append('product_id', p.id);n body.append('attribute_' + attr.slug, term.slug);n try {n const r = await fetch(`${SITE}/?wc-ajax=get_variation`, {n method:'POST', credentials:'include',n headers:{'Content-Type':'application/x-www-form-urlencoded'},n body: body.toString()n });n const d = await r.json();n return { term, varId: d?.variation_id||null, price: d?.display_price??null };n } catch(e) {n return { term, varId:null, price:null };n }n });n n const results = await Promise.all(fetches);n c.innerHTML = '';n n results.forEach(({ term, varId, price }) =u003e {n const priceStr = price!=null ? price.toFixed(2).replace('.',',')+' €' : priceLabel(p);n const row = document.createElement('div'); row.className='abd-variation';n row.innerHTML = `n u003cspan class=u0022abd-var-nameu0022u003e${term.name}u003c/spanu003en u003cdiv style=u0022display:flex;align-items:center;gap:10px;u0022u003en u003cspan class=u0022abd-var-priceu0022u003e${priceStr}u003c/spanu003en u003cbutton class=u0022abd-var-addu0022${!varId?' disabled':''}u003eAjouteru003c/buttonu003en u003c/divu003e`;n if (varId) {n row.querySelector('.abd-var-add').addEventListener('click', () =u003e {n closeModal();n addToCart(p.id, varId, p.name + ' – ' + term.name);n });n }n c.appendChild(row);n });n n } catch(e) {n c.innerHTML = `u003cp style=u0022color:#C44E1E;text-align:center;font-size:13px;u0022u003eErreur de chargement.u003c/pu003e`;n console.error('[ABD]', e);n }n }n n function closeModal() { document.getElementById('abd-modal-bg').classList.remove('open'); curProduct=null; }n document.getElementById('abd-modal-close').addEventListener('click', closeModal);n document.getElementById('abd-modal-bg').addEventListener('click', e =u003e {n if (e.target===document.getElementById('abd-modal-bg')) closeModal();n });n n /* ── TOAST ──────────────────────────────── */n function showToast(msg) {n const t=document.getElementById('abd-toast'); t.textContent=msg; t.classList.add('show');n setTimeout(()=u003et.classList.remove('show'),2200);n }n n init();n})();nu003c/scriptu003e
Croissant 1,20€
Croissant au beurre
Adding... Added
4 fromages €12.50 - €18.50
Crème fraîche, mozzarella, chèvre, gorgonzola, emmental
Margherita €10.90 - €16.90
Tomate, mozzarella, basilic frais