/* ============================================================
   TOKO TO GO — Thème CI : noir profond, rouge enso, touches or
   ============================================================ */
/* Palette anthracite : fond gris foncé contrasté, marque noir/rouge */
:root {
    --toko-black:  #202327;   /* fond général : gris anthracite */
    --toko-dark:   #26292e;   /* surfaces secondaires */
    --toko-panel:  #2b2f34;   /* panneaux et cartes */
    --toko-ink:    #131416;   /* zones de marque : navbar, footer, hero */
    --toko-border: #3c4148;
    --toko-red:    #d92b2b;
    --toko-red-2:  #a31414;
    --toko-gold:   #f5c518;
    --toko-text:   #f4f4f2;
    --toko-muted:  #a4a8ad;
}

body {
    background: var(--toko-black);
    background-image: radial-gradient(ellipse at top right, rgba(217,43,43,.06), transparent 45%),
                      radial-gradient(ellipse at bottom left, rgba(217,43,43,.04), transparent 40%);
    color: var(--toko-text);
    font-family: 'Poppins', 'Noto Sans SC', sans-serif;
}
a { color: var(--toko-text); text-decoration: none; }
a:hover { color: var(--toko-red); }
.ls-2 { letter-spacing: 2px; } .ls-3 { letter-spacing: 4px; }

/* ---------- Topbar & Navbar ---------- */
.topbar { background: var(--toko-ink); color: var(--toko-muted); }
.topbar a { color: var(--toko-muted); }
.topbar a:hover { color: var(--toko-red); }
/* Fond à 97 % d'opacité : le flou d'arrière-plan était INVISIBLE — il n'y a
   quasiment rien à voir au travers — mais il maintenait la barre sur une
   couche composée par le GPU, en permanence et sur toutes les pages. Sur
   mobile, ces couches sont souvent rasterisées à résolution réduite, ce qui
   ramollit ce qu'elles contiennent. On paie donc un coût réel pour un effet
   nul. */
.main-nav { background: rgba(19,20,22,.97); border-bottom: 1px solid var(--toko-border); }
.main-nav .nav-link {
    color: var(--toko-text); text-transform: uppercase; letter-spacing: 1px; font-size: .9rem;
    position: relative; transition: color .2s;
}
.main-nav .nav-link:hover, .main-nav .nav-link.active { color: var(--toko-red); }
/* Effet hover léger : soulignement qui glisse */
.main-nav .navbar-nav .nav-link::after {
    content: ''; position: absolute; left: .5rem; right: .5rem; bottom: 2px; height: 2px;
    background: var(--toko-red); border-radius: 2px;
    transform: scaleX(0); transform-origin: left; transition: transform .25s ease;
}
.main-nav .navbar-nav .nav-link:hover::after { transform: scaleX(1); }

/* Logo centré et mis en évidence (desktop) */
@media (min-width: 992px) {
    .nav-brand-center {
        position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 5;
    }
    .nav-brand-center .nav-logo {
        height: 82px;
        filter: drop-shadow(0 3px 10px rgba(0,0,0,.55)) drop-shadow(0 0 20px rgba(217,43,43,.30));
        transition: transform .25s;
    }
    .nav-brand-center:hover .nav-logo { transform: scale(1.06); }
    .main-nav { min-height: 88px; }
}

.brand-logo { font-family: 'Caveat', cursive; font-size: 2rem; line-height: 1; }
.brand-toko { color: #fff; }
.brand-togo { color: var(--toko-red); }

.btn-toko {
    background: var(--toko-red); color: #fff; border: none;
    text-transform: uppercase; letter-spacing: 1px; font-weight: 600;
}
.btn-toko:hover { background: var(--toko-red-2); color: #fff; }
.btn-cart { color: #fff; font-size: 1.2rem; }
.btn-cart:hover { color: var(--toko-red); }
/* Bouton de langue — réservé à l'admin : couleur or distinctive */
.btn-lang {
    border: 1px solid var(--toko-gold); color: var(--toko-gold);
    background: rgba(245,197,24,.08); font-weight: 600;
}
.btn-lang:hover { background: var(--toko-gold); color: #1a1a1a; border-color: var(--toko-gold); }

/* ---------- Hero ---------- */
.hero {
    min-height: 78vh; position: relative; overflow: hidden;
    background: linear-gradient(180deg, #000 0%, var(--toko-black) 100%);
}
.hero-title { font-size: clamp(4rem, 10vw, 7.5rem); }
.enso {
    position: absolute; top: -120px; right: -120px; width: 420px; height: 420px;
    border: 26px solid rgba(217,43,43,.55); border-radius: 50%;
    border-left-color: transparent; transform: rotate(-30deg);
    filter: blur(1px); opacity: .6;
}
.sakura-1 {
    position: absolute; top: 0; left: 0; width: 260px; height: 380px;
    background:
        radial-gradient(circle at 30% 20%, rgba(217,43,43,.35) 6px, transparent 7px),
        radial-gradient(circle at 60% 35%, rgba(217,43,43,.28) 5px, transparent 6px),
        radial-gradient(circle at 20% 50%, rgba(217,43,43,.30) 7px, transparent 8px),
        radial-gradient(circle at 45% 65%, rgba(217,43,43,.22) 4px, transparent 5px),
        radial-gradient(circle at 70% 80%, rgba(217,43,43,.18) 5px, transparent 6px);
    opacity: .8;
}

/* ---------- Sections ---------- */
.section-title { font-weight: 700; text-transform: uppercase; letter-spacing: 3px; }
.page-header { background: linear-gradient(180deg, #000, transparent); }

.panel, .stat-card {
    background: var(--toko-panel); border: 1px solid #2a2a2a;
}
/* .service-card et .service-icon : voir le bloc « 3 modes de commande »
   en fin de fichier — les anciennes règles (grosse carte centrée, cercle
   de 84 px avec halo) ont été retirées pour éviter tout conflit. */

/* ---------- Produits ---------- */
.product-card { background: var(--toko-panel); border: 1px solid #2a2a2a; overflow: hidden; transition: transform .25s, box-shadow .25s, border-color .25s; }
.product-card:hover { border-color: var(--toko-red); box-shadow: 0 10px 32px rgba(217,43,43,.22); transform: translateY(-5px); }

/* Zone image : carré, PNG fond transparent = marge intégrée */
.product-img {
    position: relative; font-size: 3rem; color: #3a3a3a;
    background: radial-gradient(circle at 50% 40%, #262626, #171717);
    display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.product-img.square {
    width: 100%;
    aspect-ratio: 1 / 1;
    /* FILET DE SÉCURITÉ.
       « aspect-ratio » est la seule chose qui donnait une hauteur à ce
       cadre. Sur un moteur qui ne le connaît pas — Chrome Android
       antérieur à 88, certaines WebView de constructeur encore livrées —
       la déclaration est ignorée : le cadre retombe à une hauteur NULLE.
       Son contenu étant positionné en absolu, il n'y a alors plus rien à
       voir. Aucun filtre en cause : l'image existe, chargée, dans un bloc
       de zéro pixel de haut.
       Une hauteur minimale garantit qu'il y a toujours quelque chose à
       l'écran, quel que soit le navigateur. */
    min-height: 150px;
}
.placeholder-ico { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.product-photo {
    position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0; width: 100%; height: 100%;
    object-fit: contain;
    /* La marge suit la taille réelle de la carte : 15 % fixes rognaient
       fortement l'image sur mobile, où la carte ne fait que ~166 px. */
    padding: clamp(8px, 9%, 30px);
    z-index: 1; transition: transform .35s ease;
}
.product-card:hover .product-photo { transform: scale(1.07); }
.product-hero-img { border: 1px solid #2a2a2a; font-size: 6rem; }
.product-title { color: var(--toko-text); display: block; }
.product-title:hover { color: var(--toko-red); }
.clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

.badge-best {
    position: absolute; top: 10px; left: 10px; z-index: 2; background: var(--toko-gold); color: #000;
    font-size: .7rem; font-weight: 700; text-transform: uppercase; padding: 3px 10px; border-radius: 20px;
}
/* ============================================================
   CODE PRODUIT — repris de la carte imprimée
   ============================================================
   Le dépliant affiche la LETTRE en rouge et le NUMÉRO en noir, en grand :
   « S4 », « C12 ». Sur le site, le même code apparaissait en gris pâle,
   minuscule, dans un coin — un client tenant la carte et cherchant « le
   S4 » ne faisait pas le lien.

   Le badge passe en BAS À GAUCHE de la photo : c'est la position qu'il
   occupe sur le dépliant, et cela libère les deux coins hauts, déjà pris
   par « Best seller » et « Épuisé ». Trois pastilles dans le même angle se
   recouvriraient.
   ============================================================ */
.badge-code {
    position: absolute; bottom: 8px; left: 8px; z-index: 3;
    display: inline-flex; align-items: baseline; gap: 1px;
    /* PAS de backdrop-filter ici.
       Il ne floutait qu'un rectangle de 40 px, mais sur mobile il force le
       navigateur à composer TOUTE la carte sur une couche séparée — souvent
       rasterisée à résolution réduite pour économiser la mémoire GPU. La
       photo du plat en ressortait visiblement molle, alors que le fichier,
       lui, est net.

       Un fond opaque suffit : le badge est parfaitement lisible sans
       toucher à ce qui se trouve derrière lui. */
    background: #0d0d0d;
    border: 1px solid #3a3a3a;
    border-radius: 8px; padding: 3px 9px 4px;
    font-family: 'Segoe UI', system-ui, sans-serif;
    line-height: 1;
    /* Le code doit rester lisible sur une photo claire comme sur un fond
       sombre : le fond opaque s'en charge, l'ombre porte le relief. */
    box-shadow: 0 2px 8px rgba(0,0,0,.45);
    transition: border-color .25s, transform .25s;
}
.badge-code .code-lettre {
    color: var(--toko-red); font-weight: 800; font-size: .82rem;
    text-transform: uppercase; letter-spacing: .5px;
}
.badge-code .code-num {
    color: #fff; font-weight: 700; font-size: .95rem;
    font-variant-numeric: tabular-nums;
}
/* Au survol, le code s'anime légèrement : il devient l'élément qu'on
   retient pour dicter la commande au téléphone. */
.product-card:hover .badge-code {
    border-color: var(--toko-red); transform: scale(1.06);
}
@media (prefers-reduced-motion: reduce) {
    .product-card:hover .badge-code { transform: none; }
}
/* Fiche produit : le code est une information de tête, pas une vignette. */
.product-hero-img .badge-code {
    bottom: 14px; left: 14px; padding: 5px 14px 6px;
}
.product-hero-img .badge-code .code-lettre { font-size: 1.15rem; }
.product-hero-img .badge-code .code-num    { font-size: 1.35rem; }

@media (max-width: 575.98px) {
    /* Sur deux colonnes, la vignette fait ~166 px : le badge doit rester
       lisible sans manger la photo. */
    .badge-code { bottom: 6px; left: 6px; padding: 2px 7px 3px; }
    .badge-code .code-lettre { font-size: .74rem; }
    .badge-code .code-num    { font-size: .86rem; }
}
.badge-cat {
    background: rgba(217,43,43,.12); color: var(--toko-red); border: 1px solid rgba(217,43,43,.4);
    font-size: .78rem; text-transform: uppercase; letter-spacing: 1px; padding: 4px 12px; border-radius: 20px;
}
.price { color: var(--toko-red); font-weight: 700; font-size: 1.1rem; }
.pill-toko { background: transparent; border: 1px solid #333 !important; color: var(--toko-text) !important; text-transform: uppercase; letter-spacing: 1px; }
.pill-toko.active { background: var(--toko-red) !important; border-color: var(--toko-red) !important; }

/* ---------- Menu : barre catégories + filtres ---------- */
/* Défilement au doigt (tactile), sans barre de navigation interne */
.cat-bar {
    scrollbar-width: none; -ms-overflow-style: none; scroll-behavior: smooth; -webkit-overflow-scrolling: touch;
    /* Espace réservé au-dessus/dessous pour que l'effet hoover (translateY) ne soit jamais rogné par le cadre */
    padding-top: 10px; padding-bottom: 8px;
}
.cat-bar::-webkit-scrollbar { display: none; }
.cat-bar-wrap { padding: 4px 6px 0; }
.cat-scroll {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 6;
    width: 38px; height: 38px; border-radius: 50%;
    background: var(--toko-panel); border: 1px solid var(--toko-border); color: var(--toko-text);
    display: flex; align-items: center; justify-content: center; transition: .2s;
    box-shadow: 0 4px 14px rgba(0,0,0,.4);
}
.cat-scroll:hover { background: var(--toko-red); border-color: var(--toko-red); color: #fff; }
.cat-scroll-left  { left: -8px; }
.cat-scroll-right { right: -8px; }
.cat-scroll.d-none { display: none !important; }
.cat-pill {
    background: var(--toko-panel); border: 1px solid #2a2a2a; color: var(--toko-text);
    border-radius: 16px; padding: 10px 14px; min-width: 92px; flex: 0 0 auto;
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    transition: .2s; cursor: pointer;
}
.cat-pill:hover { border-color: var(--toko-red); transform: translateY(-2px); }
.cat-pill.active { border-color: var(--toko-red); background: rgba(217,43,43,.12); }
.cat-ico { width: 44px; height: 44px; position: relative; display: flex; align-items: center; justify-content: center; font-size: 1.4rem; color: var(--toko-red); }
.cat-ico img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; z-index: 1; }
.cat-label { font-size: .75rem; text-transform: uppercase; letter-spacing: .5px; white-space: nowrap; }

.chip {
    background: transparent; border: 1px solid #333; color: var(--toko-muted);
    border-radius: 20px; padding: 6px 14px; font-size: .85rem; transition: .2s;
}
.chip:hover { border-color: var(--toko-red); color: var(--toko-text); }
.chip.active { background: var(--toko-red); border-color: var(--toko-red); color: #fff; }

/* ---------- Breadcrumb ---------- */
.breadcrumb-toko { --bs-breadcrumb-divider-color: #555; }
.breadcrumb-toko .breadcrumb-item a { color: var(--toko-muted); }
.breadcrumb-toko .breadcrumb-item a:hover { color: var(--toko-red); }
.breadcrumb-toko .breadcrumb-item.active { color: var(--toko-text); }
.breadcrumb-toko .breadcrumb-item + .breadcrumb-item::before { color: #555; }

/* ---------- Onglets Ingrédients / Allergènes (page produit) ---------- */
.nav-tabs-toko { border-bottom: 1px solid var(--toko-border); }
.nav-tabs-toko .nav-link {
    color: var(--toko-muted); background: transparent; border: none; border-bottom: 2px solid transparent;
    font-weight: 600; text-transform: uppercase; font-size: .8rem; letter-spacing: .5px; padding: 10px 16px;
    border-radius: 0; transition: .2s;
}
.nav-tabs-toko .nav-link:hover { color: var(--toko-text); border-bottom-color: rgba(217,43,43,.4); }
.nav-tabs-toko .nav-link.active { color: var(--toko-red); background: transparent; border-bottom-color: var(--toko-red); }
.tab-content.panel { border-top: none; }

/* ---------- Quantité (stepper) ---------- */
/* Boutons +/- aux extrémités, jamais collés en bout de zone de texte */
.qty-stepper input::-webkit-outer-spin-button, .qty-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; }
.qty-stepper { gap: 0; }
.qty-stepper .qty-input { width: 46px; flex: 0 0 46px; -moz-appearance: textfield; }
.qty-stepper .cart-qty-minus, .qty-stepper .cart-qty-plus { width: 30px; flex: 0 0 30px; padding: 0; }

/* ---------- Carousel (slider 4 pages) ---------- */
/* HAUTEUR UNIQUE POUR TOUTES LES DIAPOSITIVES.
   La première portait 72vh contre 66vh aux autres, au motif qu'elle
   contient plus d'éléments. Résultat : la page se rétractait de 6vh au
   passage à la diapositive 2, puis se rallongeait au retour — tout le
   contenu situé dessous sautait à chaque défilement automatique, toutes
   les 10 secondes.

   Un carousel doit avoir une hauteur stable. On prend donc la plus haute
   des deux valeurs pour tout le monde : la diapositive la plus chargée
   dicte la hauteur, les autres respirent simplement davantage.
   Le padding reste modulable — il n'affecte pas la hauteur totale
   (box-sizing: border-box) et sert seulement à centrer le contenu. */
#heroCarousel .hero {
    min-height: 72vh;
    padding: 56px 0;
    box-sizing: border-box;
}
#heroCarousel .hero.hero-home { padding: 40px 0; }

/* La piste elle-même est verrouillée sur la plus haute diapositive :
   sans cela, une image plus courte que prévu recréerait le saut. */
#heroCarousel .carousel-inner,
#heroCarousel .carousel-item { min-height: 72vh; }
#heroCarousel .carousel-indicators [data-bs-target] { background-color: var(--toko-red); width: 26px; height: 4px; border-radius: 2px; }
#heroCarousel .carousel-control-prev, #heroCarousel .carousel-control-next { width: 8%; }
.enso-left { left: -120px; right: auto; transform: rotate(140deg); }

/* Transition stylisée : pas de fondu (carousel-fade retiré) — le fond glisse en un
   panneau uni (même dégradé sur toutes les diapos), et le contenu s'anime en cascade
   à l'arrivée, avec l'icône qui « pop » en tout premier. */
@keyframes heroContentIn {
    from { opacity: 0; transform: translateY(26px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes heroIconPop {
    0%   { opacity: 0; transform: scale(.4) rotate(-14deg); }
    55%  { opacity: 1; transform: scale(1.14) rotate(5deg); }
    100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
.carousel-item.active .hero > .container > * {
    animation: heroContentIn .65s cubic-bezier(.2,.8,.3,1) both;
}
.carousel-item.active .hero > .container > *:nth-child(1) { animation-delay: .05s; }
.carousel-item.active .hero > .container > *:nth-child(2) { animation-delay: .13s; }
.carousel-item.active .hero > .container > *:nth-child(3) { animation-delay: .21s; }
.carousel-item.active .hero > .container > *:nth-child(4) { animation-delay: .29s; }
.carousel-item.active .hero > .container > *:nth-child(5) { animation-delay: .37s; }
.carousel-item.active .hero > .container > *:nth-child(6) { animation-delay: .45s; }
/* Icône animée au tout début de la transition (pop + légère rotation) */
.carousel-item.active .hero > .container > .display-1 {
    animation: heroIconPop .75s cubic-bezier(.34,1.56,.64,1) both;
    animation-delay: 0s;
}
.carousel-item.active .hero-logo {
    animation: heroIconPop .8s cubic-bezier(.34,1.56,.64,1) both;
}
@media (prefers-reduced-motion: reduce) {
    .carousel-item.active .hero > .container > *,
    .carousel-item.active .hero > .container > .display-1,
    .carousel-item.active .hero-logo { animation: none; }
}

/* ---------- Panier flottant + offcanvas ---------- */
.float-cart-btn {
    position: fixed; bottom: 24px; right: 24px; z-index: 1040;
    width: 60px; height: 60px; border-radius: 50%;
    background: var(--toko-red); color: #fff; border: none; font-size: 1.5rem;
    box-shadow: 0 8px 28px rgba(217,43,43,.5); transition: .2s;
}
.float-cart-btn:hover { background: var(--toko-red-2); transform: scale(1.08); }
.float-cart-btn .badge { position: absolute; top: -4px; right: -4px; }
.offcanvas-toko { background: var(--toko-dark); color: var(--toko-text); border-left: 1px solid #333; }

/* ---------- Bandeau infos ---------- */
.info-band { background: linear-gradient(135deg, #1a1a1a, #101010); border: 1px solid #2a2a2a; }

/* ---------- Formulaires ---------- */
.form-control, .form-select, textarea {
    background: #111 !important; border: 1px solid #333 !important; color: var(--toko-text) !important;
}
.form-control:focus, .form-select:focus { border-color: var(--toko-red) !important; box-shadow: 0 0 0 .2rem rgba(217,43,43,.2) !important; }
.form-control::placeholder { color: #666 !important; }
.form-label { color: var(--toko-muted); font-size: .9rem; }
.btn-type { border: 1px solid #333; color: var(--toko-text); }
.btn-check:checked + .btn-type { background: var(--toko-red); border-color: var(--toko-red); color: #fff; }

/* ---------- Tables (HTML) ---------- */
.table-dark-toko { --bs-table-bg: transparent; color: var(--toko-text); }
.table-dark-toko th { color: var(--toko-muted); text-transform: uppercase; font-size: .75rem; letter-spacing: 1px; border-color: #2e2e2e; }
.table-dark-toko td { border-color: #262626; color: var(--toko-text); }

/* ---------- Statuts commandes ---------- */
.statut { padding: 3px 10px; border-radius: 20px; font-size: .75rem; text-transform: uppercase; letter-spacing: .5px; }
/* Hiérarchie de la couleur : elle appelle l'action, elle ne décore pas.
     à traiter  -> ambre, très visible
     en cours   -> bleu, présent sans crier
     prête      -> vert, le seul vert de la liste : c'est l'instant où
                   quelqu'un doit se lever pour la remettre
     terminée   -> gris, l'affaire est close
   Le vert servait aussi bien à « prête » qu'à « livrée » et « terminée » :
   en fin de service, la liste en était couverte et le seul état qui
   réclamait un geste ne se distinguait plus. */
.statut-en_attente     { background: #4d3800; color: #ffd24d; }
.statut-en_preparation { background: #00303f; color: #5ad4ff; }
.statut-prete          { background: #0a3d1e; color: #5ee08f; }
.statut-en_livraison   { background: #3d1042; color: #e09cf0; }
.statut-livree, .statut-terminee { background: #2a2a2a; color: #9a9a9a; }
.statut-annulee        { background: #3d0a0a; color: #ff8080; }

/* ---------- Admin ---------- */
.admin-sidebar { background: var(--toko-panel); border: 1px solid #2a2a2a; position: sticky; top: 90px; }
.admin-sidebar .nav-link { color: var(--toko-muted); border-radius: 8px; padding: 8px 12px; font-size: .9rem; }
.admin-sidebar .nav-link:hover { color: #fff; background: #242424; }
.admin-sidebar .nav-link.active { color: #fff; background: var(--toko-red); }
.modal-toko { background: var(--toko-dark); color: var(--toko-text); border: 1px solid #333; }

/* ---------- Alerte « nouvelle commande » (admin) ---------- */
.order-alert {
    background: var(--toko-red); color: #fff; padding: 10px 0;
    position: sticky; top: 0; z-index: 1055;
    animation: alertPulse 1.1s ease-in-out infinite;
}
@keyframes alertPulse {
    0%, 100% { background: var(--toko-red); }
    50%      { background: var(--toko-red-2); }
}
.order-alert .btn-light { color: var(--toko-red); font-weight: 600; }
.order-alert-bell { font-size: 1.4rem; animation: bellShake 1s ease-in-out infinite; display: inline-block; }
@keyframes bellShake {
    0%, 100% { transform: rotate(0); }
    25%      { transform: rotate(14deg); }
    75%      { transform: rotate(-14deg); }
}
/* Ligne de commande pas encore prise en charge : clignotement rouge */
.order-row-new > td { animation: rowBlink 1.2s ease-in-out infinite; }
@keyframes rowBlink {
    0%, 100% { background: transparent; }
    50%      { background: rgba(217,43,43,.28); }
}
.contact-link { color: var(--toko-red); }
.contact-link:hover { color: #fff; text-decoration: underline; }
.mail-body {
    background: rgba(0,0,0,.35); border: 1px solid var(--toko-border); border-radius: 8px;
    color: var(--toko-muted); font-size: .78rem; padding: 12px; max-height: 320px; overflow: auto;
    white-space: pre-wrap; word-break: break-word;
}
/* ------------------------------------------------------------------
   LIGNES CLOSES : PRÉSENTES, MAIS SILENCIEUSES
   ------------------------------------------------------------------
   Un liseré à gauche suffit à dire « celle-ci est réglée ». Un aplat de
   couleur sur toute la ligne se lit d'aussi loin qu'une alerte, alors
   qu'il n'y a rien à faire — et il fait perdre du contraste au texte.
   ------------------------------------------------------------------ */
.order-row-done > td {
    box-shadow: inset 3px 0 0 #3f8f5f;
    color: var(--toko-muted);
}
.order-row-done .chrono { display: none; }
.order-row-annule > td {
    box-shadow: inset 3px 0 0 #7a2b2b;
    color: var(--toko-muted);
}
/* Le numéro et le montant restent pleinement lisibles : c'est ce qu'on
   vient chercher quand on relit une commande passée. */
.order-row-done > td:first-child,
.order-row-done .montant { color: var(--toko-text); }

@media (prefers-reduced-motion: reduce) {
    .order-alert, .order-alert-bell, .order-row-new > td { animation: none; }
    .order-row-new > td { background: rgba(217,43,43,.22); }
}

/* ============================================================
   CAISSE / COMMANDE PAR TÉLÉPHONE — pleine largeur, sans sidebar
   Deux colonnes : produits (large) + ticket. Hauteur pleine page,
   chaque colonne défile indépendamment.
   ============================================================ */
.pos-page { display: flex; flex-direction: column; height: calc(100vh - 76px); overflow: hidden; }
.pos-topbar {
    background: var(--toko-ink); border-bottom: 1px solid var(--toko-border);
    padding: 10px 18px; flex: 0 0 auto;
}
.pos-type-btn {
    border: 1px solid var(--toko-border); color: var(--toko-text); background: var(--toko-panel);
    padding: 8px 18px; font-weight: 600; font-size: .9rem;
}
.pos-type-btn:hover { border-color: var(--toko-red); color: var(--toko-text); }
.btn-check:checked + .pos-type-btn { background: var(--toko-red); border-color: var(--toko-red); color: #fff; }
.pos-body { display: flex; flex: 1 1 auto; min-height: 0; gap: 0; }
.pos-products { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; padding: 12px 14px; }
.pos-ticket {
    flex: 0 0 340px; max-width: 340px; background: var(--toko-ink);
    border-left: 1px solid var(--toko-border); display: flex; flex-direction: column; min-height: 0;
}
.pos-ticket-scroll { flex: 1 1 auto; overflow-y: auto; padding: 14px; }
.pos-ticket-foot { flex: 0 0 auto; padding: 12px 14px; border-top: 1px solid var(--toko-border); background: var(--toko-panel); }
.pos-line-name { font-size: .8rem; color: var(--toko-text); }

/* Barre de catégories : flèches + défilement animé (plus de barre latérale) */
.pos-cats-wrap { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; margin-bottom: 10px; }
.pos-cats {
    display: flex; gap: 8px; overflow-x: auto; scroll-behavior: smooth; flex: 1 1 auto;
    scrollbar-width: none; -ms-overflow-style: none; padding: 2px 0;
}
.pos-cats::-webkit-scrollbar { display: none; }
.pos-cat-arrow {
    flex: 0 0 auto; width: 42px; height: 42px; border-radius: 50%;
    background: var(--toko-panel); border: 1px solid var(--toko-border); color: var(--toko-text);
    display: flex; align-items: center; justify-content: center; font-size: 1.2rem; transition: .15s;
}
.pos-cat-arrow:hover { background: var(--toko-red); border-color: var(--toko-red); color: #fff; }
.pos-cat-arrow.disabled { opacity: .3; pointer-events: none; }
.pos-cat-pill {
    background: var(--toko-panel); border: 1px solid var(--toko-border); color: var(--toko-text);
    border-radius: 20px; padding: 9px 18px; font-size: .88rem; white-space: nowrap; flex: 0 0 auto;
    transition: .15s;
}
.pos-cat-pill:hover { border-color: var(--toko-red); color: var(--toko-text); }
.pos-cat-pill.active { background: var(--toko-red); border-color: var(--toko-red); color: #fff; }

/* Grille produits : occupe toute la hauteur restante */
.pos-grid { flex: 1 1 auto; overflow-y: auto; min-height: 0; padding-right: 4px; }
.pos-tile {
    background: var(--toko-panel); border: 1px solid var(--toko-border); border-radius: 14px;
    padding: 12px 8px; display: flex; flex-direction: column; align-items: center; gap: 6px;
    min-height: 132px; cursor: pointer; transition: transform .12s, border-color .12s; text-align: center;
    /* Fond sombre : texte clair, casse naturelle (pas de majuscules forcées) */
    color: #fff; text-transform: none; letter-spacing: normal;
}
.pos-tile:hover { border-color: var(--toko-red); color: #fff; }
.pos-tile:active, .pos-tile.pos-tile-tap { transform: scale(.94); border-color: var(--toko-red); background: rgba(217,43,43,.15); }
.pos-tile-img { width: 68px; height: 68px; display: block; }
.pos-tile-img img { width: 100%; height: 100%; object-fit: contain; }
.pos-tile-name {
    font-size: .84rem; line-height: 1.25; max-height: 2.5em; overflow: hidden;
    color: #fff; font-weight: 500; text-transform: none;
}
.pos-tile-name b { color: var(--toko-gold); font-weight: 700; }
.pos-tile-price { font-size: .9rem; font-weight: 700; color: #ff8a8a; }

/* Sous 992 px : le ticket passe sous les produits */
@media (max-width: 991.98px) {
    .pos-page { height: auto; overflow: visible; }
    .pos-body { flex-direction: column; }
    .pos-ticket { flex: 1 1 auto; max-width: none; border-left: none; border-top: 1px solid var(--toko-border); }
    .pos-grid { max-height: 60vh; }
}
.pos-tile-mini {
    min-height: auto; padding: 4px; font-size: .72rem; flex-direction: row; justify-content: center;
    background: transparent; border-style: dashed;
}
/* Poke bowl en caisse : la vignette n'ajoute rien, ce sont les 3 sauces qui ajoutent */
.pos-tile-static { cursor: default; }
.pos-tile-static:hover { border-color: #2a2a2a; }
.pos-tile-mini.sauce-spicy  { border-color: rgba(217,67,43,.55); }
.pos-tile-mini.sauce-poke   { border-color: rgba(43,127,217,.55); }
.pos-tile-mini.sauce-sesame { border-color: rgba(201,154,46,.55); }
.pos-cta {
    background: linear-gradient(135deg, rgba(217,43,43,.18), var(--toko-panel));
    border: 1px solid var(--toko-red); display: flex;
}
.pos-cta:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(217,43,43,.25); }
.pos-cta-icon {
    width: 56px; height: 56px; flex: 0 0 56px; border-radius: 50%; background: var(--toko-red);
    color: #fff; display: flex; align-items: center; justify-content: center; font-size: 1.5rem;
}

/* ---------- Choix de la sauce (poke bowls uniquement) ----------
   Sélecteur intégré à la carte / fiche produit, sur le modèle du choix de format :
   la sauce se choisit avant l'ajout au panier, sans fenêtre intermédiaire. */
.sauce-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .5px; color: var(--toko-muted); }
.sauce-pick {
    border: 1px solid var(--toko-border); background: transparent; color: var(--toko-text);
    border-radius: 20px; padding: 4px 10px; font-size: .74rem; font-weight: 600;
    line-height: 1.2; transition: .15s; cursor: pointer;
}
.sauce-pick:hover { border-color: currentColor; }
.sauce-pick .sauce-dot {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 5px; vertical-align: 1px;
}
.sauce-spicy  .sauce-dot { background: #d9432b; }
.sauce-poke   .sauce-dot { background: #2b7fd9; }
.sauce-sesame .sauce-dot { background: #c99a2e; }
.btn-check:checked + .sauce-spicy  { background: #d9432b; border-color: #d9432b; color: #fff; }
.btn-check:checked + .sauce-poke   { background: #2b7fd9; border-color: #2b7fd9; color: #fff; }
.btn-check:checked + .sauce-sesame { background: #c99a2e; border-color: #c99a2e; color: #fff; }
.btn-check:checked + .sauce-pick .sauce-dot { background: #fff; }
/* Sauce rattachée à son poke bowl dans le panier / les commandes */
.line-sauce { font-size: .8rem; color: var(--toko-muted); padding-left: 2px; }
.line-sauce i { color: var(--toko-red); }

/* ---------- Tables restaurant ---------- */
.table-card { background: var(--toko-panel); border: 2px solid #2a2a2a; }
.table-libre    { border-color: #2e7d32; } .table-libre i    { color: #46d47e; }
.table-occupee  { border-color: var(--toko-red); } .table-occupee i  { color: var(--toko-red); }
.table-reservee { border-color: var(--toko-gold); } .table-reservee i { color: var(--toko-gold); }

/* ---------- Divers ---------- */
.alert-toko { background: #2a1212; border: 1px solid var(--toko-red); color: #ffb3b3; }
.site-footer { background: #000; border-top: 1px solid #222; }
.site-footer a { color: var(--toko-muted); } .site-footer a:hover { color: var(--toko-red); }
.newsletter-strip { background: rgba(255,255,255,.03); border: 1px solid #222; }
.newsletter-strip input { display: inline-block; }
.dropdown-menu-dark { background: var(--toko-dark); border: 1px solid #333; }
.site-main { min-height: 60vh; }

/* Toast d'ajout panier */
#toko-toast {
    position: fixed; bottom: 24px; right: 24px; z-index: 2000;
    background: var(--toko-panel); border-left: 4px solid var(--toko-red);
    color: var(--toko-text); padding: 14px 22px; border-radius: 8px;
    box-shadow: 0 10px 32px rgba(0,0,0,.6); display: none;
}

/* ---------- Logo ---------- */
/* Logo agrandi et détouré pour ressortir sur la navbar sombre.
   Le drop-shadow foncé décolle le logo du fond quelle que soit sa couleur. */
.nav-logo {
    height: 60px; width: auto;
    filter: drop-shadow(0 2px 6px rgba(0,0,0,.5));
}
.hero-logo { max-width: min(420px, 78vw); height: auto; }
.footer-logo { height: 74px; width: auto; }
.chip-ico { width: 20px; height: 20px; object-fit: contain; margin-right: 4px; vertical-align: -4px; }

/* ============================================================
   Composants v5 — anthracite, badges, confirmation, cookies
   ============================================================ */
/* Zones de marque plus sombres que le fond anthracite */
.site-footer { background: var(--toko-ink); border-top: 1px solid var(--toko-border); }
#heroCarousel { background: var(--toko-ink); }
#heroCarousel .hero { background: linear-gradient(180deg, #0c0d0e 0%, #17181b 100%); }
.hero-minis span { color: var(--toko-muted); font-size: .9rem; letter-spacing: 1px; text-transform: uppercase; }
.hero-minis i { color: var(--toko-red); margin-right: 4px; }

/* Bordures harmonisées */
.panel, .service-card, .stat-card, .product-card, .info-band, .filter-bar,
.admin-sidebar, .table-card, .cat-pill { border-color: var(--toko-border); }
.border-toko { border-color: var(--toko-border) !important; }
.form-control, .form-select, textarea { border-color: var(--toko-border) !important; }

/* Badges tags & allergènes */
.badge-tag {
    background: rgba(217,43,43,.12); color: #ff8a8a; border: 1px solid rgba(217,43,43,.35);
    font-size: .78rem; padding: 4px 12px; border-radius: 20px;
}

/* Confirmation de commande */
.confirm-check {
    width: 84px; height: 84px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    background: radial-gradient(circle, rgba(70,212,126,.18), transparent 70%);
    border: 3px solid #46d47e; color: #46d47e; font-size: 2.6rem;
    animation: pop .45s cubic-bezier(.2,1.6,.4,1);
}
@keyframes pop { from { transform: scale(.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.confirm-steps .step {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    color: var(--toko-muted); font-size: .85rem; min-width: 92px;
}
.confirm-steps .step i {
    width: 52px; height: 52px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    border: 2px solid var(--toko-border); font-size: 1.3rem; background: var(--toko-panel);
}
.confirm-steps .step.done { color: #46d47e; }
.confirm-steps .step.done i { border-color: #46d47e; color: #46d47e; }

/* Bandeau cookies */
#cookie-banner {
    position: fixed; bottom: 0; left: 0; right: 0; z-index: 1050;
    background: var(--toko-ink); border-top: 2px solid var(--toko-red);
    color: var(--toko-text); padding: 14px 22px;
    box-shadow: 0 -8px 28px rgba(0,0,0,.45);
}

/* Pages légales */
.legal h5 { color: var(--toko-red); margin-top: 1.4rem; }
.legal h5:first-child { margin-top: 0; }
.legal p, .legal li { color: var(--toko-text); }
.legal a { color: var(--toko-red); }

/* Sélections & interactions légères */
::selection { background: rgba(217,43,43,.55); color: #fff; }
.btn, .chip, .cat-pill, .product-title { transition: all .2s ease; }
.btn-toko:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(217,43,43,.35); }

/* ---------- Lisibilité des prix au survol / à la sélection ----------
   Quand un bouton passe en fond rouge (hover ou sélection), le prix
   rouge devient blanc pour rester lisible. */
.btn-check:checked + .btn-type .price,
.btn-check:checked + .btn-type,
.btn-type:hover .price,
.btn-outline-danger:hover .price,
.btn-outline-danger:hover, .btn-outline-danger:active,
.btn-toko .price, .btn-toko:hover .price { color: #fff !important; }
.btn-type:hover { background: rgba(217,43,43,.85); border-color: var(--toko-red); color: #fff; }
.chip.active .price, .cat-pill.active .price { color: #fff !important; }

/* Quantité au choix sur les cartes produit */
.card-qty {
    width: 56px; flex: 0 0 56px; text-align: center;
    -moz-appearance: textfield;
}
.card-qty::-webkit-outer-spin-button, .card-qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---------- Bandeau d'état du restaurant (fermeture / suspendu / livraison / RUSH) ---------- */
.shop-banner { color: #fff; font-weight: 600; letter-spacing: .3px; }
.shop-banner-closed   { background: #1c1c1c; color: #ff8a8a; border-bottom: 1px solid var(--toko-red); }
/* Coupure entre services : informatif, pas bloquant — donc plus doux
   visuellement qu'une fermeture, qui elle empêche de commander. */
.shop-banner-coupure  { background: #241f14; color: #ffce6b; border-bottom: 1px solid #7a6420; }
.shop-banner-paused   { background: var(--toko-red); }
.shop-banner-delivery { background: #7a3a00; color: #ffd0a8; }
.shop-banner-rush     { background: #7a5a00; color: #ffe9a8; }

/* ============================================================
   FERMETURE — ce qui se désactive, et ce qui ne doit JAMAIS l'être
   ============================================================
   L'ancienne règle estompait aussi les sélecteurs de format et de
   quantité de CHAQUE carte, à 50 %, et les boutons à 40 % avec
   désaturation. Résultat : la carte entière paraissait délavée, comme si
   le site était en panne — et sur mobile, où les vignettes sont petites et
   l'écran souvent vu en plein soleil, elle devenait franchement illisible.

   C'est un contresens. La carte d'un restaurant est une VITRINE : elle
   doit rester lisible même fermé, sinon on perd le client qui regardait ce
   qu'il commanderait demain. Seule l'ACTION d'acheter se désactive.

   Le bouton n'est plus estompé mais explicitement marqué indisponible :
   un bouton pâle se lit « affichage cassé », un bouton net et inactif se
   lit « fermé ». La différence n'est pas cosmétique. */
body.shop-blocked .add-to-cart,
body.shop-blocked .btn-cart,
body.shop-blocked #nav-cta-commander,
body.shop-blocked .float-cart-btn,
body.shop-blocked #product-form button[type="submit"] {
    background: #3a3a3a; border-color: #4a4a4a; color: #9a9a9a;
    pointer-events: none; cursor: not-allowed;
}
/* Format et quantité restent PLEINEMENT LISIBLES : ce sont des
   informations sur le produit — deux tailles, un prix chacune — et non des
   commandes d'achat. Les estomper cachait un renseignement utile.
   Ils restent inertes, sans le paraître. */
body.shop-blocked .card-fmt-radio, body.shop-blocked .card-qty { pointer-events: none; }

/* ---------- Appel direct : bouton téléphone (navbar) et liens tel: ---------- */
.btn-call {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; border-radius: 50%;
    background: transparent; border: 1px solid var(--toko-red);
    color: var(--toko-red); font-size: 1.05rem; line-height: 1;
    transition: background .2s, color .2s, transform .2s;
}
.btn-call:hover, .btn-call:focus { background: var(--toko-red); color: #fff; transform: scale(1.06); }
.topbar-tel { font-weight: 600; }
.topbar .topbar-tel { color: var(--toko-text); }
.topbar .topbar-tel:hover { color: var(--toko-red); }
.banner-tel { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.banner-tel:hover { color: inherit; opacity: .8; }

/* ============================================================
   VIEWPORT — cartes produit, CTA et zones d'image
   Cible principale : le téléphone (~380 px de large), où la grille
   affiche 2 cartes par ligne, soit ~166 px utiles par carte.
   ============================================================ */

/* ---------- Bouton d'ajout au panier (carte du menu) ---------- */
.card-actions { margin-top: auto; }          /* les boutons s'alignent en bas de carte */

.add-to-cart {
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    min-height: 44px;                        /* cible tactile confortable */
    padding: .45rem .6rem;
    line-height: 1.15;
    white-space: nowrap;
}
.add-to-cart i { font-size: 1rem; flex: 0 0 auto; }

/* Deux libellés, un seul visible selon la largeur disponible */
.add-label-short { display: none; }
.add-label-long  { display: inline; }

.card-qty {
    min-height: 44px;                        /* même hauteur que le bouton */
    font-size: .95rem; font-weight: 600;
}

/* ---------- Fiche produit : bloc d'achat ---------- */
.product-buy .qty-stepper .btn { min-width: 44px; min-height: 46px; }
.product-buy #product-qty { width: 70px; min-height: 46px; font-size: 1rem; font-weight: 600; }
.btn-buy { min-height: 50px; font-size: 1rem; }

/* ============================================================
   ≤ 575,98 px — téléphones
   ============================================================ */
@media (max-width: 575.98px) {

    /* Libellé court : « Ajouter au panier » déborde sur 166 px de carte */
    .add-label-long  { display: none; }
    .add-label-short { display: inline; }

    .add-to-cart {
        font-size: .78rem; letter-spacing: .3px; padding: .45rem .4rem; gap: .3rem;
    }
    .add-to-cart i { font-size: .95rem; }

    /* Champ quantité resserré pour laisser la place au bouton */
    .card-qty { width: 44px; flex: 0 0 44px; font-size: .88rem; padding-left: 2px; padding-right: 2px; }

    /* Cartes : padding intérieur réduit, plus de place pour le contenu */
    .product-card .p-3 { padding: .75rem !important; }
    .product-title { font-size: .88rem; line-height: 1.25; }

    /* ------------------------------------------------------------
       LE MASQUE NOIR SUR MOBILE — c'était ici.
       ------------------------------------------------------------
       Ces lignes datent d'avant le déplacement du badge du code en bas à
       gauche. Elles lui donnaient encore « top » et « right ». Le badge
       recevait donc les QUATRE côtés — top, right, bottom, left — et un
       élément en position absolue avec les quatre offsets s'étire sur
       toute la surface de son parent. Avec son fond noir opaque, il
       recouvrait la photo entière, code dans le coin, rien d'autre.

       Uniquement sous 576 px : d'où « ça marche sur ordinateur ». Et la
       photo se chargeait bel et bien : elle était juste DERRIÈRE. Aucun
       filtre, aucune opacité — un badge devenu masque.

       Le badge « best seller », lui, reste en haut à gauche. */
    .badge-best { font-size: .62rem; padding: 2px 7px; top: 6px; left: 6px; }
    .badge-code { top: auto; right: auto; }

    /* ------------------------------------------------------------
       PLUS RIEN SUR LA PHOTO (mobile)
       ------------------------------------------------------------
       Le correctif de la version 78 a supprimé le masque : le badge ne
       s'étire plus. Il reste néanmoins POSÉ SUR l'image, et sur un écran
       de téléphone une vignette fait moins de 200 px — le rectangle
       opaque y mange encore un coin du plat.

       Le badge est donc RETIRÉ sur mobile, et non déplacé. La référence
       n'est pas perdue pour autant : elle figure déjà devant le nom du
       plat, juste sous la photo (voir menu/index.php, .product-title).
       L'afficher deux fois sur un écran de 400 px n'apportait rien.

       Une première tentative le passait en « position: static » à
       l'intérieur du cadre. Le rendu à 400 px a montré que cela ne le
       sortait pas de l'image : il devenait un bloc transparent au centre
       de la photo, invisible mais interceptant les clics. Vérifié depuis
       par un nouveau rendu : au centre de l'image, l'élément le plus en
       avant est bien IMG.product-photo.

       Sur ordinateur, la vignette est assez grande : le badge y garde sa
       place, l'habitude visuelle est conservée. */
    .product-item .product-card .badge-code { display: none; }

    /* Sélecteur de format : lisible sans déborder */
    .fmt-toggle .btn { font-size: .72rem; padding: .3rem .2rem; min-height: 36px; }

    /* Fiche produit : le visuel ne doit pas repousser le CTA hors écran */
    .product-hero-img { max-width: 74%; margin-inline: auto; }

    /* Bloc d'achat empilé : quantité sur une ligne, CTA pleine largeur */
    .product-buy { gap: .75rem !important; }
    .product-buy .qty-stepper { width: 100%; justify-content: center; }
    .btn-buy { width: 100%; flex: 1 0 100%; }

    /* Hero : 78vh laissait le CTA sous la ligne de flottaison une fois
       la barre d'adresse du navigateur affichée. */
    .hero { min-height: 62vh; }
    /* Même règle en mobile : une hauteur, pour toutes les diapositives. */
    #heroCarousel .hero,
    #heroCarousel .carousel-inner,
    #heroCarousel .carousel-item { min-height: 74vh; }
    #heroCarousel .hero.hero-home { padding: 32px 0; }

    /* Panier flottant : remonté pour ne pas masquer le bandeau cookies */
    .float-cart-btn { bottom: 16px; right: 16px; width: 54px; height: 54px; font-size: 1.3rem; }

    /* Catégories iconifiées : plus compactes, davantage visibles d'un coup */
    .cat-pill { min-width: 78px; padding: 8px 10px; }
    .cat-ico { width: 38px; height: 38px; font-size: 1.2rem; }
    .cat-label { font-size: .68rem; }
}

/* ============================================================
   576 – 767,98 px — grands téléphones et petites tablettes
   ============================================================ */
@media (min-width: 576px) and (max-width: 767.98px) {
    .add-to-cart { font-size: .82rem; }
    .card-qty { width: 50px; flex: 0 0 50px; }
    .product-hero-img { max-width: 62%; margin-inline: auto; }
}

/* ============================================================
   Écrans tactiles — cibles minimales, quelle que soit la largeur
   ============================================================ */
@media (hover: none) {
    .btn-sm { min-height: 40px; }
    .qty-plus, .qty-minus { min-width: 44px; }
    /* Les effets de survol n'ont pas de sens au doigt et laissent
       les cartes « collées » en état actif après un tap. */
    .product-card:hover { transform: none; box-shadow: none; }
    /* La TRANSITION est retirée, pas seulement le survol.
       Déclarer « transition: transform » suffit à faire promouvoir l'image
       sur une couche composée par le GPU — même si aucun agrandissement ne
       se produit jamais au doigt. Cette couche est souvent rasterisée à
       résolution réduite sur mobile, et la photo paraît molle.
       Au doigt, l'agrandissement n'a de toute façon aucun sens. */
    .product-card:hover .product-photo,
    .product-photo { transform: none; transition: none; will-change: auto; }
    .btn-toko:hover { transform: none; box-shadow: none; }
}

/* ============================================================
   Très petits écrans (≤ 360 px) — iPhone SE, Galaxy A0x
   ============================================================ */
@media (max-width: 360px) {
    .add-label-short { display: none; }      /* icône seule : le texte ne rentre plus */
    .add-to-cart { padding: .45rem .3rem; }
    .add-to-cart i { font-size: 1.1rem; margin: 0; }
    .card-qty { width: 40px; flex: 0 0 40px; }
}

/* ============================================================
   Photo de fond des slides du carousel d'accueil
   Activée dès qu'un fichier existe dans assets/img/slides/
   (voir slide_hero() dans config/config.php).
   ============================================================ */
.hero-photo {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    /* Pas de background-attachment: fixed — ignoré et coûteux sur iOS. */
}

/* Voile sombre : garantit la lisibilité du texte blanc quelle que soit
   la photo. Plus dense en bas, là où se trouvent le texte et le bouton. */
.hero-photo::after {
    content: ''; position: absolute; inset: 0; z-index: 0;
    background: linear-gradient(180deg,
                rgba(10,10,12,.55) 0%,
                rgba(10,10,12,.68) 45%,
                rgba(10,10,12,.82) 100%);
}
/* Le contenu repasse au-dessus du voile */
.hero-photo > .container { position: relative; z-index: 2; }

/* Motifs décoratifs masqués quand une photo est en place : enso et sakura
   servaient à meubler un fond vide, ils surchargeraient une vraie image. */
.hero-photo .enso,
.hero-photo .sakura-1 { display: none; }

/* Grande icône estompée pour la même raison — elle reste comme repère
   visuel sans concurrencer la photo. */
.hero-photo .display-1 { opacity: .75; }

@media (max-width: 575.98px) {
    /* Sur mobile le recadrage « cover » coupe beaucoup : on privilégie
       le haut de l'image, où se trouve généralement le sujet. */
    .hero-photo { background-position: center 30%; }
}

/* ============================================================
   Barre de filtres — version discrète
   Le panneau plein (fond + bordure + 12 contrôles alignés) pesait
   autant que la grille produits. Il devient une simple ligne de
   recherche, le reste se dépliant à la demande.
   ============================================================ */
.filter-bar {
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--toko-border);
    border-radius: 0;
    padding: 0 0 .75rem;
}
.filter-bar .form-control,
.filter-bar .form-select {
    background: rgba(0,0,0,.25) !important;
    border-color: #2f343a !important;
}
.filter-bar .form-control:focus { border-color: var(--toko-red) !important; }

/* Bouton d'ouverture des filtres : discret au repos, rouge une fois des
   filtres actifs — le compteur évite d'avoir à déplier pour savoir. */
.btn-filters {
    border: 1px solid var(--toko-border); color: var(--toko-muted);
    background: transparent; font-size: .85rem; white-space: nowrap;
    display: inline-flex; align-items: center; gap: .25rem;
    padding: .3rem .75rem; min-height: 38px; border-radius: 20px;
}
.btn-filters:hover { border-color: var(--toko-red); color: var(--toko-text); }
.btn-filters[aria-expanded="true"] { border-color: var(--toko-red); color: var(--toko-text); }
.filter-count {
    background: var(--toko-red); color: #fff; font-size: .68rem; font-weight: 700;
    min-width: 18px; height: 18px; border-radius: 9px;
    display: inline-flex; align-items: center; justify-content: center; padding: 0 5px;
}

/* Chips assagis : gris au repos, la couleur ne sert qu'à l'état actif. */
.filter-more .chip { font-size: .8rem; padding: 5px 12px; border-color: #2f343a; }

/* ============================================================
   Quantité vendue — mise en évidence
   Vente alimentaire : « 8 pièces », « 33 cl », « 200 g » sont des
   informations d'achat au même titre que le prix. Affichées pour
   TOUS les produits, y compris ceux sans format saisi.
   ============================================================ */
.qty-badge {
    display: inline-flex; align-items: center; gap: .3rem;
    background: rgba(245,197,24,.10);
    border: 1px solid rgba(245,197,24,.42);
    color: var(--toko-gold);
    font-size: .76rem; font-weight: 700;
    letter-spacing: .3px; white-space: nowrap;
    padding: 3px 9px; border-radius: 20px;
    flex: 0 0 auto;
}
.qty-badge i { font-size: .8rem; opacity: .8; }
.qty-badge-lg { font-size: .92rem; padding: 6px 14px; }
.qty-badge-lg i { font-size: .95rem; }
.qty-badge-sm { font-size: .68rem; padding: 2px 7px; border-radius: 14px; }

@media (max-width: 575.98px) {
    .qty-badge { font-size: .68rem; padding: 2px 7px; gap: .2rem; }
    .qty-badge i { display: none; }        /* la carte ne fait que ~166 px */
    .qty-badge-lg { font-size: .85rem; padding: 5px 12px; }
    .qty-badge-lg i { display: inline; }
}

/* Sur grand écran, les filtres restent dépliés en permanence :
   la place ne manque pas et le repli n'aurait aucun intérêt. */
@media (min-width: 992px) {
    .filter-more { display: block !important; height: auto !important; visibility: visible !important; }
    .btn-filters { display: none; }
}

/* ============================================================
   Accueil — 3 modes de commande (livraison / emporter / sur place)
   Anciennement de grosses cartes centrées, décoratives et non
   cliquables : gros cercle d'icône 84 px bordé de rouge avec halo,
   titre en capitales, beaucoup de vide. Désormais des raccourcis
   sobres et actionnables vers le tunnel de commande.
   ============================================================ */
.services-title {
    font-size: 1.05rem; font-weight: 600; letter-spacing: 1px;
    text-transform: uppercase; color: var(--toko-muted);
}

.service-card {
    display: flex; align-items: center; gap: .9rem;
    padding: 1rem 1.1rem;
    background: rgba(255,255,255,.02);
    border: 1px solid var(--toko-border);
    border-radius: 14px;
    color: var(--toko-text); text-align: left;
    text-decoration: none;
    transition: border-color .2s, background .2s, transform .2s;
}
.service-card:hover,
.service-card:focus-visible {
    border-color: var(--toko-red);
    background: rgba(217,43,43,.07);
    color: var(--toko-text);
    transform: translateY(-2px);
}
.service-card:focus-visible { outline: 2px solid var(--toko-red); outline-offset: 2px; }

/* Icône : pastille discrète, sans halo — l'ancien cercle de 84 px
   bordé de 3 px pesait plus lourd que le texte qu'il illustrait. */
.service-ico {
    flex: 0 0 46px; width: 46px; height: 46px; border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(217,43,43,.10); border: 1px solid rgba(217,43,43,.30);
    color: var(--toko-red); font-size: 1.25rem;
    transition: background .2s, color .2s;
}
.service-card:hover .service-ico { background: var(--toko-red); color: #fff; }

.service-body { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.service-title { font-weight: 700; font-size: 1rem; letter-spacing: .3px; }
.service-text {
    color: var(--toko-muted); font-size: .82rem; line-height: 1.35;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.service-meta { color: var(--toko-gold); font-size: .72rem; font-weight: 600; letter-spacing: .3px; }

/* Flèche : signale que la carte est cliquable et glisse au survol */
.service-go {
    margin-left: auto; flex: 0 0 auto; color: var(--toko-muted);
    font-size: 1.1rem; transition: transform .2s, color .2s;
}
.service-card:hover .service-go { color: var(--toko-red); transform: translateX(4px); }

/* Mode indisponible : visible mais inerte — le masquer laisserait
   croire que le service n'existe pas. */
.service-card-off { opacity: .45; cursor: not-allowed; }
.service-card-off:hover { border-color: var(--toko-border); background: rgba(255,255,255,.02); transform: none; }
.service-card-off .service-meta { color: var(--toko-muted); }

@media (max-width: 575.98px) {
    .service-card { padding: .8rem .9rem; gap: .7rem; }
    .service-ico { flex: 0 0 40px; width: 40px; height: 40px; font-size: 1.1rem; }
    .service-text { -webkit-line-clamp: 3; }
    .services-title { font-size: .92rem; }
}

@media (hover: none) {
    .service-card:hover { transform: none; }
    .service-card:hover .service-go { transform: none; }
}

/* ============================================================
   Page carte — catégories avec photo & barre de commande
   ============================================================ */

/* Pastille de catégorie avec photo : la vignette occupe tout le haut,
   arrondie, à la place de l'icône. Repli sur l'icône Bootstrap si le
   fichier assets/img/groupes/{slug}.ext n'existe pas encore. */
.cat-pill-photo { padding-top: 0; overflow: hidden; }
.cat-pill-photo .cat-ico {
    width: 100%; height: 58px; border-radius: 14px 14px 0 0; margin-bottom: 2px;
    background: #1b1e22;
}
.cat-pill-photo .cat-ico img {
    object-fit: cover;          /* la photo remplit le cadre, pas de bandes */
    border-radius: 14px 14px 0 0;
}
.cat-pill-photo .cat-label { padding: 0 4px 2px; }

@media (max-width: 575.98px) {
    .cat-pill-photo .cat-ico { height: 48px; }
}

/* ---------- Barre de commande (bas d'écran) ---------- */
.order-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 1035;
    background: rgba(18,20,23,.97);
    border-top: 1px solid var(--toko-red);
    box-shadow: 0 -6px 20px rgba(0,0,0,.4);
    padding: .7rem 0;
    /* Même cas : fond à 97 %, flou invisible, couche composée permanente. */
    animation: order-bar-in .25s ease;
}
@keyframes order-bar-in { from { transform: translateY(100%); } to { transform: translateY(0); } }

.order-bar-info { display: flex; flex-direction: column; line-height: 1.15; margin-right: auto; }
.order-bar-count { font-size: .72rem; color: var(--toko-muted); text-transform: uppercase; letter-spacing: .5px; }
.order-bar-total { font-size: 1.15rem; color: var(--toko-text); }

/* Quand la barre est là, on remonte le contenu et on efface le bouton
   flottant : deux appels à l'action « panier » superposés brouillent le
   message, et un seul chemin doit ressortir — celui vers la commande. */
body.has-order-bar { padding-bottom: 76px; }
body.has-order-bar .float-cart-btn { display: none !important; }

@media (max-width: 575.98px) {
    .order-bar-total { font-size: 1.05rem; }
    body.has-order-bar { padding-bottom: 82px; }
}

/* ============================================================
   Admin — suivi de commande simplifié
   Un bouton « étape suivante » remplace le choix dans un menu ;
   le menu de statut reste, en repli discret (annulation, correction).
   ============================================================ */
.suivi-cell { min-width: 150px; }

/* Bouton d'avancement : proéminent, c'est l'action principale de la ligne */
.btn-next { font-weight: 600; white-space: nowrap; }
.btn-next.disabled { opacity: .65; cursor: default; }

/* Menu de repli assagi : plus petit et grisé, il ne concurrence pas le bouton */
.suivi-cell .statut-select {
    font-size: .74rem; opacity: .78; transition: opacity .15s;
}
.suivi-cell .statut-select:hover,
.suivi-cell .statut-select:focus { opacity: 1; }

/* Items du menu d'actions lisibles sur fond sombre */
.dropdown-menu-dark .dropdown-item { color: var(--toko-text); }
.dropdown-menu-dark .dropdown-item:hover { background: rgba(217,43,43,.15); color: #fff; }
.dropdown-menu-dark .dropdown-item.text-danger:hover { background: rgba(217,43,43,.25); }

@media (max-width: 575.98px) {
    .suivi-cell { min-width: 130px; }
    .btn-next { font-size: .78rem; }
}

/* ============================================================
   v7 — Pastilles de catégorie en PHOTO SEULE
   Le libellé est retiré du DOM (pas seulement masqué) : la photo
   occupe alors toute la pastille, plus haute pour rester lisible.
   Le nom reste dans title/aria-label — un menu sans texte doit
   rester utilisable au lecteur d'écran et au survol.
   ============================================================ */
.cat-pill-imgonly { padding: 0; min-width: 104px; overflow: hidden; }
.cat-pill-imgonly .cat-ico {
    width: 100%; height: 76px; border-radius: 15px; margin: 0;
    background: #1b1e22;
}
.cat-pill-imgonly .cat-ico img { object-fit: cover; border-radius: 15px; }

/* Sans photo déposée, la pastille tomberait à la hauteur d'une seule
   icône et casserait l'alignement de la barre : on la maintient. */
.cat-pill-imgonly:not(.cat-pill-photo) .cat-ico {
    font-size: 2rem; background: transparent;
}

/* Sous-catégorie en photo seule : pastille ronde, sans libellé */
.chip-imgonly {
    padding: 4px; width: 46px; height: 46px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
}
.chip-imgonly .chip-ico {
    width: 36px; height: 36px; margin: 0; border-radius: 50%; object-fit: cover;
}
.chip-imgonly i { margin: 0 !important; font-size: 1.1rem; }

@media (max-width: 575.98px) {
    .cat-pill-imgonly { min-width: 84px; }
    .cat-pill-imgonly .cat-ico { height: 62px; }
}

/* ============================================================
   v7 — Admin > Impression
   ============================================================ */
.agent-state {
    border: 1px solid var(--toko-border); border-radius: 12px;
    padding: 12px 14px; height: 100%;
}
.agent-state.agent-on   { border-color: #2c6b45; background: rgba(70,212,126,.08); }
.agent-state.agent-warn { border-color: #7a6420; background: rgba(255,193,7,.08); }
.agent-state.agent-off  { border-color: #7a2b2b; background: rgba(217,43,43,.10); }
.agent-state .small { color: var(--toko-muted); }

.printer-card {
    border: 1px solid var(--toko-border); border-radius: 14px;
    padding: 14px; background: rgba(0,0,0,.18); transition: border-color .2s;
}
.printer-card.printer-on { border-color: var(--toko-red); }
.printer-card code { color: var(--toko-muted); }

/* ============================================================
   v7 — Admin > Images
   ============================================================ */
.media-card { border: 1px solid var(--toko-border); }
.media-preview {
    width: 96px; height: 96px; flex: 0 0 96px; border-radius: 12px;
    background: #1b1e22; border: 1px solid var(--toko-border);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden; color: var(--toko-red); font-size: 1.8rem;
}
.media-preview img { width: 100%; height: 100%; object-fit: cover; }
.media-preview-sm { width: 68px; height: 68px; flex: 0 0 68px; font-size: 1.3rem; }
.min-w-0 { min-width: 0; }

.slide-preview {
    position: relative; width: 100%; aspect-ratio: 1920 / 850;
    border-radius: 12px; overflow: hidden; background: #1b1e22;
    border: 1px solid var(--toko-border);
}
.slide-preview img { width: 100%; height: 100%; object-fit: cover; }
.slide-empty {
    position: absolute; inset: 0; display: flex; align-items: center;
    justify-content: center; color: var(--toko-muted); font-size: .85rem;
}
/* Repères du recadrage mobile : tout ce qui déborde de ces traits
   disparaît en portrait. Visualiser la perte évite de placer un logo
   dans un coin qui ne sera jamais vu sur téléphone. */
.slide-safe {
    position: absolute; inset: 0 15%; pointer-events: none;
    border-left: 2px dashed rgba(217,43,43,.85);
    border-right: 2px dashed rgba(217,43,43,.85);
}

/* Onglets sombres de la page Images */
.nav-tabs { border-color: var(--toko-border); }
.nav-tabs .nav-link { color: var(--toko-muted); border: 1px solid transparent; }
.nav-tabs .nav-link:hover { border-color: var(--toko-border); color: var(--toko-text); }
.nav-tabs .nav-link.active {
    color: #fff; background: var(--toko-panel);
    border-color: var(--toko-border) var(--toko-border) var(--toko-panel);
}

/* ============================================================
   v7 — Suivi de commande : barre de progression + refus
   ============================================================ */
.suivi-cell { min-width: 168px; }

/* Progression en pastilles : l'état de la commande se lit d'un regard,
   sans avoir à décoder un libellé de statut. */
.etapes { display: flex; gap: 3px; margin-bottom: 6px; }
.etape {
    flex: 1; height: 5px; border-radius: 3px; background: #2f2f2f;
    transition: background .25s;
}
/* Une étape FRANCHIE n'a plus rien à demander : elle passe en gris clair.
   En vert, trois étapes sur quatre s'allumaient dès qu'une commande
   avançait — la couleur cessait alors de signaler quoi que ce soit, et
   l'œil ne distinguait plus la commande qui attend de celle qui roule.
   La couleur est réservée à ce qui appelle une décision. */
.etape.done   { background: #6e6e6e; }
.etape.actif  { background: var(--toko-red); animation: etapePulse 1.4s ease-in-out infinite; }
.etape.annule { background: #7a2b2b; }
/* Parcours entièrement terminé : une seule barre pleine et discrète,
   plutôt que quatre segments qui attirent le regard pour rien. */
.etapes.fini .etape { background: #3f3f3f; }
@keyframes etapePulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }

/* Chrono d'attente : c'est le temps écoulé, pas l'heure d'arrivée,
   qui dit s'il faut s'inquiéter. Il vire au rouge à 10 minutes. */
.chrono {
    font-variant-numeric: tabular-nums; font-size: .74rem;
    color: var(--toko-muted); white-space: nowrap;
}
.chrono.chrono-warn { color: #ffc107; }
.chrono.chrono-late { color: #ff6b6b; font-weight: 600; }

.btn-refuse { white-space: nowrap; }

/* Bandeau d'état de l'impression, affiché uniquement en cas de problème :
   une imprimante muette doit se voir, une imprimante qui marche non. */
.print-alert {
    background: #4d3800; color: #ffe08a; border-bottom: 1px solid #7a6420;
    padding: 6px 0; font-size: .84rem;
}
.print-alert.print-alert-ko { background: #3d0a0a; color: #ffb3b3; border-color: #7a2b2b; }

@media (prefers-reduced-motion: reduce) {
    .etape.actif { animation: none; }
}

/* ============================================================
   v9 — Interrupteur du son des alertes
   Deux états lisibles d'un coup d'œil depuis l'autre bout du
   comptoir : cloche pleine = le son passera, cloche barrée en
   gris = il est coupé. Aucun bandeau, aucune explication.
   ============================================================ */
.btn-son {
    background: rgba(255,255,255,.08); color: #ffd66b;
    border: 1px solid rgba(255,214,107,.45);
    display: inline-flex; align-items: center; white-space: nowrap;
}
.btn-son:hover  { background: rgba(255,214,107,.18); color: #ffe08a; }
.btn-son:focus  { box-shadow: 0 0 0 .2rem rgba(255,214,107,.25); }

/* Son coupé : volontairement terne. Un état désactivé ne doit pas
   attirer l'œil autant qu'un état actif, mais doit rester lisible. */
.btn-son.btn-son-off {
    background: transparent; color: #8a8a8a;
    border-color: rgba(255,255,255,.18);
}
.btn-son.btn-son-off:hover { color: #bbb; background: rgba(255,255,255,.06); }
.btn-son .son-etat { font-size: .78rem; font-weight: 600; }

/* ============================================================
   v9 — Filtre par type de commande
   Séparé visuellement du filtre par statut : ce sont deux
   questions différentes (qui traite / où ça en est), et les
   mélanger obligeait à relire toute la rangée.
   ============================================================ */
.type-filtre { flex-wrap: wrap; }
.type-filtre .btn { font-weight: 600; }
.type-filtre .btn-light { color: #1a1a1a; }
.type-filtre .badge { font-size: .68rem; vertical-align: middle; }

/* Choix du livreur : n'apparaît qu'à l'étape où il sert */
.livreur-select { font-size: .8rem; }

/* Entrées d'action du menu ⋮ : un <button> doit s'aligner sur un <a> */
.dropdown-item.btn-prev,
.dropdown-item.btn-refuse { width: 100%; text-align: left; border: 0; background: none; }

/* ============================================================
   v10 — Connexion Google
   Le bouton suit les recommandations d'aspect de Google : fond
   clair, logo officiel non déformé, libellé explicite. S'en
   écarter (le teinter en rouge, remplacer le G par une icône
   générique) nuit à la reconnaissance et sort du cadre autorisé.
   ============================================================ */
.btn-google {
    background: #fff; color: #1f1f1f; border: 1px solid #dadce0;
    font-weight: 600; display: inline-flex; align-items: center;
    justify-content: center; gap: 10px;
}
.btn-google:hover  { background: #f7f8f8; color: #1f1f1f; border-color: #d2d5d9; }
.btn-google:focus  { box-shadow: 0 0 0 .2rem rgba(66,133,244,.3); color: #1f1f1f; }
.btn-google .google-g { display: inline-flex; line-height: 0; }

/* Séparateur « ou » entre les deux modes de connexion */
.separateur-ou {
    display: flex; align-items: center; gap: 12px;
    color: var(--toko-muted); font-size: .82rem;
}
.separateur-ou::before,
.separateur-ou::after {
    content: ""; flex: 1; height: 1px; background: var(--toko-border);
}

/* ============================================================
   v11 — Rupture de stock
   ============================================================ */
/* Carte publique d'un produit épuisé : atténuée, mais toujours
   lisible. Le client doit voir que le plat existe et reviendra —
   le masquer laisserait croire qu'il a quitté la carte. */
/* Épuisé : le badge suffit à le dire. Une carte à 62 % d'opacité devient
   illisible sur un téléphone en plein jour, et le client ne sait plus s'il
   regarde un plat épuisé ou un affichage défectueux. */
.produit-epuise .product-card { opacity: .85; }
/* PAS de filter sur la photo.
   « grayscale » place elle aussi l'image sur une couche composée, avec le
   même effet de flou sur mobile — et elle rendait le plat méconnaissable
   alors que le client cherche justement à le reconnaître. Le badge
   « Épuisé » et le bouton inactif le disent déjà. */
.produit-epuise .product-card:hover { opacity: 1; }

.badge-epuise {
    position: absolute; top: 8px; left: 8px; z-index: 3;
    background: #4a4a4a; color: #fff; font-size: .68rem; font-weight: 700;
    padding: 3px 9px; border-radius: 20px; text-transform: uppercase;
    letter-spacing: .5px;
}
.btn-epuise {
    background: #3a3a3a; color: #cfcfcf; border: 1px solid #4d4d4d;
    font-weight: 600; cursor: not-allowed;
}

/* Bascule de stock dans l'admin : l'état se lit à la couleur, sans
   avoir à décoder un libellé. */
.btn-stock {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: .74rem; font-weight: 600; white-space: nowrap;
    border: 1px solid transparent;
}
.btn-stock.stock-ok {
    background: rgba(70,212,126,.10); color: #46d47e; border-color: rgba(70,212,126,.35);
}
.btn-stock.stock-ok:hover { background: rgba(70,212,126,.20); color: #6de39a; }
.btn-stock.stock-ko {
    background: rgba(255,193,7,.12); color: #ffc107; border-color: rgba(255,193,7,.45);
}
.btn-stock.stock-ko:hover { background: rgba(255,193,7,.22); color: #ffd451; }
.stock-note { max-width: 150px; line-height: 1.25; }

.rupture-bloc {
    border: 1px solid var(--toko-border); border-radius: 12px;
    padding: 12px 14px; background: rgba(255,193,7,.05);
}

/* ============================================================
   v11 — Horaires en deux services
   ============================================================ */
.service-bloc {
    border: 1px solid var(--toko-border); border-radius: 12px;
    padding: 12px 14px; transition: opacity .2s;
}
.service-bloc.service-off { opacity: .6; }
.service-titre { font-weight: 600; font-size: .9rem; }

/* ============================================================
   v14 — Prise de commande : bande client pleine largeur
   ============================================================
   Ces champs étaient comprimés dans la colonne latérale, en
   taille réduite. Or c'est ce qu'on encode PENDANT que le client
   parle : c'est là qu'il faut de la place, pas sur les vignettes
   de produits qu'on désigne au doigt.
   ============================================================ */
#phone-order-form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }

.pos-client {
    flex: 0 0 auto;
    background: var(--toko-panel);
    border-bottom: 1px solid var(--toko-border);
    padding: 10px 14px;
}
.pos-client-row {
    display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: flex-end;
}
.pc-field { display: flex; flex-direction: column; flex: 1 1 150px; min-width: 0; }
.pc-field label {
    font-size: .7rem; text-transform: uppercase; letter-spacing: .5px;
    color: var(--toko-muted); margin-bottom: 3px; white-space: nowrap;
}
/* Champs de taille NORMALE : on tape dedans en écoutant quelqu'un,
   les cibles réduites font perdre plus de temps qu'elles n'en gagnent. */
.pos-client .form-control,
.pos-client .form-select { height: 40px; font-size: .95rem; }

/* Largeurs relatives calées sur le contenu réel */
.pc-tel   { flex: 0 0 190px; }
.pc-mail  { flex: 2 1 230px; }
.pc-adr   { flex: 2 1 260px; }
.pc-cp    { flex: 0 0 110px; }
.pc-ville { flex: 1 1 160px; }
.pc-table { flex: 1 1 190px; }
.pc-note  { flex: 2 1 240px; }

/* Client reconnu : pastille discrète dans le champ téléphone */
.pc-tel-wrap { position: relative; }
.pc-badge {
    position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
    background: rgba(70,212,126,.15); color: #46d47e;
    border: 1px solid rgba(70,212,126,.4); border-radius: 20px;
    font-size: .68rem; font-weight: 600; padding: 2px 8px; white-space: nowrap;
    pointer-events: none;
}

/* ============================================================
   v14 — Saisie par code produit
   ============================================================ */
.pos-search-wrap { position: relative; margin-bottom: 10px; }
.pos-search-wrap .form-control {
    height: 44px; padding-left: 40px; padding-right: 92px;
    font-size: 1rem; font-weight: 500;
}
.pos-search-wrap .form-control:focus { border-color: var(--toko-red); }
.pos-search-ico {
    position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
    color: var(--toko-muted); font-size: 1.05rem; pointer-events: none;
}
.pos-search-clear {
    position: absolute; right: 58px; top: 50%; transform: translateY(-50%);
    background: none; border: 0; color: var(--toko-muted);
    font-size: .8rem; padding: 4px 6px; display: none;
}
.pos-search-clear:hover { color: #fff; }
.pos-search-hint {
    position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
    color: var(--toko-muted); font-size: .78rem; pointer-events: none;
    font-variant-numeric: tabular-nums;
}

@media (max-width: 991.98px) {
    /* En dessous de cette largeur, la bande ne tient plus sur une ligne :
       deux champs par ligne restent plus lisibles qu'une file étroite. */
    .pc-field { flex: 1 1 46%; }
    .pc-tel, .pc-cp { flex: 1 1 46%; }
}

/* ============================================================
   v15 — Espace livreur
   ============================================================
   Conçu pour un téléphone tenu d'une main, consulté à l'arrêt
   en pleine rue. Cibles tactiles larges, contrastes forts,
   aucune information utile en petits caractères gris.
   ============================================================ */
.liv-page { min-height: 100vh; background: var(--toko-dark); padding-bottom: 40px; }

/* Bandeau fixe : reste visible au défilement, on y revient sans
   remonter toute la liste. */
.liv-topbar {
    position: sticky; top: 0; z-index: 20;
    background: #101010; border-bottom: 1px solid var(--toko-border);
}
.liv-topbar-in {
    max-width: 640px; margin: 0 auto; padding: 10px 14px;
    display: flex; align-items: center; gap: 12px;
}
.liv-titre { display: flex; align-items: center; gap: 8px; font-weight: 700; color: #fff; }
.liv-titre i { color: var(--toko-red); font-size: 1.2rem; }

.liv-cash-total {
    margin-left: auto; text-align: right; line-height: 1.15;
}
.liv-cash-total span { display: block; font-size: .64rem; text-transform: uppercase;
                       letter-spacing: .5px; color: var(--toko-muted); }
.liv-cash-total strong { font-size: 1.05rem; color: #46d47e; }

.liv-appel {
    flex: 0 0 auto; width: 42px; height: 42px; border-radius: 50%;
    background: var(--toko-red); color: #fff;
    display: flex; align-items: center; justify-content: center; font-size: 1.05rem;
}
.liv-appel:hover { background: #a50d25; color: #fff; }

.liv-body { max-width: 640px; margin: 0 auto; padding: 14px; }
.liv-section { margin-bottom: 26px; }
.liv-h2 {
    display: flex; align-items: center; gap: 8px;
    font-size: 1rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .5px; color: #fff; margin: 0 0 12px;
}
.liv-badge {
    background: var(--toko-red); color: #fff; border-radius: 20px;
    font-size: .72rem; padding: 1px 9px; font-weight: 700;
}
.liv-vide {
    color: var(--toko-muted); font-size: .88rem; text-align: center;
    padding: 18px 0; margin: 0;
}
.liv-vide i { display: block; font-size: 1.6rem; margin-bottom: 6px; opacity: .5; }

/* ---------- Carte de course ---------- */
.liv-card {
    background: var(--toko-panel); border: 1px solid var(--toko-border);
    border-radius: 14px; padding: 12px; margin-bottom: 14px;
}
.liv-card-active { border-color: var(--toko-red); box-shadow: 0 0 0 1px rgba(200,16,46,.25); }

.liv-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
.liv-num { font-weight: 700; color: var(--toko-red); font-size: 1.05rem; }
.liv-nom { font-weight: 600; color: #fff; flex: 1 1 auto; min-width: 0;
           overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.liv-heure { font-size: .8rem; color: var(--toko-muted); white-space: nowrap;
             font-variant-numeric: tabular-nums; }
.liv-heure.liv-retard { color: #ff6b6b; font-weight: 700; }

/* Encaissement : l'erreur la plus coûteuse, donc la plus visible. */
.liv-pay {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    border-radius: 10px; padding: 10px 12px; margin-bottom: 10px;
}
.liv-pay i { font-size: 1.3rem; }
.liv-pay-cash { background: rgba(200,16,46,.14); border: 1px solid rgba(200,16,46,.5); color: #ff8a8a; }
.liv-pay-card { background: rgba(70,212,126,.10); border: 1px solid rgba(70,212,126,.35); color: #46d47e; }
.liv-pay-montant { font-size: 1.5rem; font-weight: 800; color: #fff; }
.liv-pay-txt { font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; }
.liv-pay-detail { margin-left: auto; font-size: .8rem; opacity: .85; }

/* Adresse et téléphone : des boutons pleine largeur, pas du texte. */
.liv-action {
    display: flex; align-items: center; gap: 10px;
    background: rgba(255,255,255,.045); border: 1px solid var(--toko-border);
    border-radius: 10px; padding: 11px 12px; margin-bottom: 8px;
    color: var(--toko-text); text-decoration: none; min-height: 56px;
}
.liv-action:hover, .liv-action:active { background: rgba(255,255,255,.09); color: #fff; }
.liv-action > i:first-child { font-size: 1.15rem; color: var(--toko-red); flex: 0 0 auto; }
.liv-action span { flex: 1 1 auto; min-width: 0; line-height: 1.25; }
.liv-action strong { display: block; font-size: .95rem; color: #fff; }
.liv-action em { display: block; font-style: normal; font-size: .78rem; color: var(--toko-muted); }
.liv-action-go { font-size: .8rem; color: var(--toko-muted); flex: 0 0 auto; }
.liv-tel > i:first-child { color: #46d47e; }

.liv-note {
    background: rgba(255,193,7,.10); border-left: 3px solid #ffc107;
    border-radius: 6px; padding: 8px 10px; margin: 0 0 8px;
    font-size: .86rem; color: #ffe08a;
}

.liv-contenu { margin-bottom: 10px; }
.liv-contenu summary {
    cursor: pointer; font-size: .82rem; color: var(--toko-muted);
    padding: 6px 0; list-style: none;
}
.liv-contenu summary::-webkit-details-marker { display: none; }
.liv-contenu p { font-size: .84rem; color: var(--toko-text); margin: 4px 0 0; line-height: 1.5; }

.liv-foot { display: flex; gap: 8px; }
/* 52 px : une cible qu'on atteint sans regarder, gants aux mains. */
.btn-liv-ok, .btn-liv-take, .btn-liv-rendre {
    min-height: 52px; font-weight: 700; font-size: 1rem; border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
}
.btn-liv-ok { background: #2e7d46; border: 0; color: #fff; }
.btn-liv-ok:hover { background: #379552; color: #fff; }
.btn-liv-take { background: var(--toko-red); border: 0; color: #fff; }
.btn-liv-take:hover { background: #a50d25; color: #fff; }
.btn-liv-take:disabled { background: #3a3a3a; color: #8a8a8a; }
.btn-liv-rendre {
    width: 52px; flex: 0 0 52px;
    background: transparent; border: 1px solid var(--toko-border); color: var(--toko-muted);
}
.btn-liv-rendre:hover { border-color: #ffc107; color: #ffc107; }

.liv-refresh { color: var(--toko-muted); font-size: .76rem; margin: 20px 0 0; }

@media (prefers-reduced-motion: reduce) { .liv-card { transition: none; } }

/* ============================================================
   v16 — Plan de salle
   ============================================================
   L'état d'une table se lit à la couleur, depuis l'autre bout
   du comptoir. Trois états, trois teintes, aucune ambiguïté.
   ============================================================ */
.salle-compteurs { display: flex; gap: 8px; flex-wrap: wrap; }
.sc {
    background: rgba(255,255,255,.06); border: 1px solid var(--toko-border);
    border-radius: 20px; padding: 3px 12px; font-size: .8rem; color: var(--toko-muted);
}
.sc-libre { background: rgba(70,212,126,.12); border-color: rgba(70,212,126,.4); color: #46d47e; font-weight: 600; }

.salle-card {
    border: 1px solid var(--toko-border); border-radius: 14px;
    padding: 12px; height: 100%; display: flex; flex-direction: column;
    background: var(--toko-panel); transition: border-color .2s;
}
.salle-libre    { border-color: rgba(70,212,126,.45); }
.salle-occupee  { border-color: rgba(200,16,46,.55); background: rgba(200,16,46,.07); }
.salle-reservee { border-color: rgba(255,193,7,.5);  background: rgba(255,193,7,.06); }

.salle-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.salle-num {
    width: 38px; height: 38px; flex: 0 0 38px; border-radius: 10px;
    background: rgba(255,255,255,.08); color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-weight: 800; font-size: 1.1rem;
}
.salle-libre    .salle-num { background: rgba(70,212,126,.18); color: #46d47e; }
.salle-occupee  .salle-num { background: rgba(200,16,46,.25);  color: #ff8a8a; }
.salle-reservee .salle-num { background: rgba(255,193,7,.20);  color: #ffc107; }

.salle-etat { font-size: .74rem; text-transform: uppercase; letter-spacing: .4px; font-weight: 600; }
.salle-libre .salle-etat    { color: #46d47e; }
.salle-occupee .salle-etat  { color: #ff8a8a; }
.salle-reservee .salle-etat { color: #ffc107; }

.salle-meta { font-size: .76rem; color: var(--toko-muted); margin-bottom: 8px; }

/* Commande en cours : ce qui manquait le plus — qui est là, depuis
   quand, et pour quel montant. */
.salle-cmd {
    display: block; background: rgba(0,0,0,.25); border-radius: 8px;
    padding: 7px 9px; margin-bottom: 8px; text-decoration: none;
    color: var(--toko-text); font-size: .82rem; line-height: 1.35;
}
.salle-cmd:hover { background: rgba(0,0,0,.4); color: #fff; }
.salle-cmd strong { color: var(--toko-red); margin-right: 4px; }
.salle-cmd-bas { display: block; font-size: .76rem; color: var(--toko-muted); margin-top: 2px; }

.salle-resa {
    background: rgba(255,193,7,.10); border-radius: 8px; padding: 7px 9px;
    margin-bottom: 8px; font-size: .8rem; color: #ffe08a;
}
.salle-vide { flex: 1 1 auto; font-size: .8rem; color: var(--toko-muted); padding: 6px 0 10px; }

.salle-actions { display: flex; gap: 6px; margin-top: auto; }
.salle-actions form { flex: 1 1 auto; }

/* ============================================================
   v17 — Horaires
   ============================================================ */
.hor-etat {
    display: inline-flex; align-items: center; gap: 6px;
    border-radius: 20px; padding: 4px 14px; font-size: .82rem; font-weight: 600;
}
.hor-ouvert { background: rgba(70,212,126,.14); color: #46d47e; border: 1px solid rgba(70,212,126,.4); }
.hor-ferme  { background: rgba(200,16,46,.14); color: #ff8a8a; border: 1px solid rgba(200,16,46,.45); }

.hor-table .hor-time { width: 108px; }
/* Un jour fermé n'a pas d'horaire à saisir : la ligne s'efface visuellement
   plutôt que de laisser croire que ses champs comptent encore. */
.hor-row-ferme { opacity: .42; }
.hor-row-ferme td:first-child { text-decoration: line-through; }

.hor-apercu { list-style: none; padding: 0; margin: 0; }
.hor-apercu li {
    display: flex; align-items: center; gap: 8px;
    padding: 7px 2px; border-bottom: 1px solid var(--toko-border); font-size: .86rem;
}
.hor-apercu li:last-child { border-bottom: 0; }
.ap-jour { flex: 0 0 110px; color: var(--toko-text); }
.ap-horaire { flex: 1 1 auto; color: var(--toko-muted); }
.hor-apercu .ap-ferme .ap-horaire { color: #ff8a8a; }
.hor-apercu .ap-exc { background: rgba(255,193,7,.07); }
.ap-motif { color: #ffc107; font-size: .7rem; }

/* ============================================================
   v18 — Panier visible pendant la commande
   ============================================================ */

/* ---------- Récapitulatif : lignes modifiables ---------- */
.recap-ligne {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 0; border-bottom: 1px solid var(--toko-border);
    font-size: .88rem;
}
.recap-nom { flex: 1 1 auto; min-width: 0; line-height: 1.35; }
.recap-prix { flex: 0 0 auto; min-width: 66px; text-align: right; font-weight: 600; }

.recap-qte { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }
.recap-qte button {
    width: 30px; height: 30px; border-radius: 8px;
    background: rgba(255,255,255,.07); border: 1px solid var(--toko-border);
    color: var(--toko-text); display: flex; align-items: center; justify-content: center;
    font-size: .8rem; padding: 0;
}
.recap-qte button:hover { background: rgba(255,255,255,.14); color: #fff; }
.recap-q { min-width: 26px; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---------- Barre fixe de commande (mobile) ----------
   Le total reste sous les yeux pendant toute la saisie. Sans elle, le
   récapitulatif n'apparaissait qu'APRÈS le formulaire, donc jamais avant
   la validation. */
.checkout-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 1045;
    background: #101010; border-top: 1px solid var(--toko-border);
    padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
    display: flex; align-items: center; gap: 10px;
    box-shadow: 0 -6px 24px rgba(0,0,0,.45);
}
.cb-toggle {
    flex: 1 1 auto; background: none; border: 0; padding: 0;
    display: flex; flex-direction: column; align-items: flex-start; text-align: left;
}
.cb-info { display: flex; align-items: baseline; gap: 8px; }
.cb-count { font-size: .74rem; color: var(--toko-muted); }
.cb-total { font-size: 1.15rem; color: #fff; font-weight: 800; }
.cb-voir { font-size: .72rem; color: var(--toko-red); display: flex; align-items: center; gap: 4px; }
.cb-valider { flex: 0 0 auto; min-height: 48px; padding: 0 20px; font-weight: 700; }

/* La page réserve la hauteur de la barre : sans cela, le dernier champ du
   formulaire reste caché dessous et devient inatteignable. */
@media (max-width: 991.98px) {
    body:has(.checkout-bar) { padding-bottom: 84px; }

    /* Détail déplié : panneau glissant par-dessus, la page ne défile pas.
       Retrouver sa place dans un formulaire long après un défilement
       automatique est pénible. */
    #recap-col {
        position: fixed; inset: 0; z-index: 1050;
        /* Voile assombri, sans flou : flouter TOUT l'écran sur un téléphone
           d'entrée de gamme se paie en saccades à l'ouverture, pour un
           effet que personne ne remarque derrière un voile à 60 %.
           On assombrit un peu plus, c'est aussi lisible et gratuit. */
        background: rgba(0,0,0,.72);
        display: none; align-items: flex-end;
    }
    #recap-col.recap-ouvert { display: flex; }
    #recap-col #recap-panel {
        width: 100%; max-height: 76vh; overflow-y: auto;
        border-radius: 18px 18px 0 0; margin: 0 0 76px;
        animation: recapMonte .22s ease-out;
    }
    @keyframes recapMonte { from { transform: translateY(18px); opacity: .6; } to { transform: none; opacity: 1; } }
    body.recap-visible { overflow: hidden; }
}

@media (prefers-reduced-motion: reduce) {
    #recap-col #recap-panel { animation: none; }
}

/* ============================================================
   v19 — Livreur : bilan de tournée
   ============================================================
   Le livreur remet des espèces au comptoir en fin de service.
   Sans total, le comptage se fait de mémoire, et les écarts se
   découvrent à la caisse quand plus personne ne sait d'où ils
   viennent.
   ============================================================ */
.liv-bilan {
    background: var(--toko-panel); border: 1px solid var(--toko-border);
    border-radius: 14px; padding: 14px; margin-bottom: 20px;
}
.liv-bilan-grid {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
}
.liv-bilan-grid > div {
    background: rgba(0,0,0,.22); border-radius: 10px; padding: 10px 8px; text-align: center;
}
.liv-bilan-grid span {
    display: block; font-size: .66rem; text-transform: uppercase;
    letter-spacing: .4px; color: var(--toko-muted); margin-bottom: 3px;
}
.liv-bilan-grid strong { font-size: 1.05rem; color: #fff; font-variant-numeric: tabular-nums; }
.liv-bilan-note { font-size: .74rem; color: var(--toko-muted); margin: 10px 0 0; text-align: center; }

/* Trois colonnes deviennent illisibles sous 360 px : on empile. */
@media (max-width: 359.98px) {
    .liv-bilan-grid { grid-template-columns: 1fr; }
}

/* Livreur affecté, dans la liste des commandes de l'admin */
.livreur-affecte {
    font-size: .72rem; color: #46d47e; margin-bottom: 4px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Sous-total de la fiche produit : le script le calculait déjà, plus
   rien ne l'affichait. */
.product-soustotal {
    display: flex; align-items: baseline; gap: 10px;
    font-size: 1.05rem;
}
.product-soustotal strong { font-size: 1.3rem; color: var(--toko-red); font-variant-numeric: tabular-nums; }

/* Horaires de la semaine (page contact) : une ligne par plage,
   les jours identiques regroupés. */
.horaires-semaine { margin-bottom: 1rem; }
.hs-titre { font-weight: 600; margin-bottom: 6px; }
.hs-ligne {
    display: flex; justify-content: space-between; gap: 12px;
    padding: 4px 0; border-bottom: 1px solid var(--toko-border); font-size: .92rem;
}
.hs-ligne:last-of-type { border-bottom: 0; }
.hs-ligne.hs-ferme { color: var(--toko-muted); }
.hs-ligne.hs-ferme strong { font-weight: 400; }
.hs-message { font-size: .85rem; color: #ffc107; margin: 8px 0 0; }

/* ============================================================
   v21 — Comptabilité et factures
   ============================================================ */
.badge-taux {
    background: rgba(255,193,7,.15); color: #ffc107;
    border: 1px solid rgba(255,193,7,.4); border-radius: 20px;
    padding: 2px 12px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.taux-cell { max-width: 120px; margin: 0 auto; }
.taux-cell .form-control { font-variant-numeric: tabular-nums; font-weight: 600; }

.compta-bloc {
    background: rgba(0,0,0,.22); border: 1px solid var(--toko-border);
    border-radius: 10px; padding: 10px 12px;
}
.compta-bloc span { display: block; font-size: .68rem; text-transform: uppercase;
                    letter-spacing: .4px; color: var(--toko-muted); }
.compta-bloc strong { display: block; font-size: 1.15rem; color: #fff; }
.compta-bloc em { font-style: normal; font-size: .74rem; color: var(--toko-muted); }

/* Commande professionnelle : la seule soumise à l'obligation électronique */
.ligne-pro { background: rgba(70,212,126,.06); }
.badge-pro {
    background: rgba(70,212,126,.15); color: #46d47e;
    border: 1px solid rgba(70,212,126,.4); border-radius: 20px;
    padding: 1px 9px; font-size: .68rem; font-family: monospace; margin-left: 6px;
}

/* ============================================================
   v21 — Paiement en ligne et suivi sans compte
   ============================================================ */
/* Paiement en ligne : présenté en premier, c'est le chemin le plus court
   pour le client et celui qui protège le restaurant de l'impayé. */
.btn-paiement-ligne { border-color: rgba(70,212,126,.45); }
.btn-check:checked + .btn-paiement-ligne {
    background: rgba(70,212,126,.12); border-color: #46d47e;
}
.btn-paiement-ligne i { color: #46d47e; }

/* Progression du suivi client : l'avancement se lit sans décoder un
   libellé de statut. */
.suivi-etapes { display: flex; gap: 4px; }
.se-etape { flex: 1 1 0; text-align: center; position: relative; }
.se-point {
    display: flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; margin: 0 auto 6px; border-radius: 50%;
    background: #2f2f2f; color: #fff; font-size: .8rem;
}
.se-etape.se-faite  .se-point { background: #46d47e; color: #0d0d0d; }
.se-etape.se-active .se-point { background: var(--toko-red); animation: sePulse 1.6s ease-in-out infinite; }
.se-label { font-size: .7rem; color: var(--toko-muted); line-height: 1.2; display: block; }
.se-etape.se-faite .se-label,
.se-etape.se-active .se-label { color: var(--toko-text); }
/* Le trait de liaison part du point et s'arrête au suivant */
.se-etape::before {
    content: ""; position: absolute; top: 14px; left: -50%; width: 100%; height: 2px;
    background: #2f2f2f; z-index: -1;
}
.se-etape:first-child::before { display: none; }
.se-etape.se-faite::before, .se-etape.se-active::before { background: #46d47e; }
@keyframes sePulse { 0%,100% { opacity: 1; } 50% { opacity: .5; } }

.suivi-eta {
    background: rgba(200,16,46,.08); border-left: 4px solid var(--toko-red);
    border-radius: 8px; padding: 12px 16px;
}
.suivi-eta span { display: block; font-size: .7rem; text-transform: uppercase;
                  letter-spacing: .5px; color: var(--toko-muted); }
.suivi-eta strong { font-size: 1.8rem; color: #fff; }

/* Encart interne de l'admin (bloc webhook) */
.panel-inner { background: rgba(0,0,0,.22); border: 1px solid var(--toko-border); }

@media (prefers-reduced-motion: reduce) { .se-etape.se-active .se-point { animation: none; } }

/* Bandeau « sans compte » en tête du tunnel de commande : la mention
   existait, mais enfouie au milieu du formulaire — donc lue trop tard
   pour lever l'hésitation. */
.sans-compte {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    background: rgba(70,212,126,.08); border: 1px solid rgba(70,212,126,.35);
    border-radius: 12px; padding: 12px 16px;
}
.sans-compte > i { font-size: 1.5rem; color: #46d47e; flex: 0 0 auto; }
.sans-compte div { flex: 1 1 220px; line-height: 1.35; }
.sans-compte strong { display: block; color: #fff; }
.sans-compte span { font-size: .84rem; color: var(--toko-muted); }
.sc-lien { font-size: .84rem; white-space: nowrap; }

/* Diagnostic du logo de ticket : il échoue en silence côté impression,
   l'écran doit donc dire pourquoi. */
.logo-etat { font-size: .78rem; border-radius: 8px; padding: 7px 10px; line-height: 1.4; }
.logo-success { background: rgba(70,212,126,.10); color: #46d47e; border: 1px solid rgba(70,212,126,.3); }
.logo-warning { background: rgba(255,193,7,.10);  color: #ffc107; border: 1px solid rgba(255,193,7,.35); }
.logo-danger  { background: rgba(200,16,46,.12);  color: #ff8a8a; border: 1px solid rgba(200,16,46,.4); }
.logo-info    { background: rgba(255,255,255,.05); color: var(--toko-muted); border: 1px solid var(--toko-border); }

/* Boutons du résumé comptable : la période et son détail sur deux lignes,
   pour qu'on sache ce qu'on imprime avant de cliquer. */
.btn-resume { min-width: 120px; text-align: center; line-height: 1.25; padding: 8px 14px; }
.btn-resume .small { font-size: .68rem; }

/* ============================================================
   v31 — Fonctions du navigateur
   ============================================================ */
/* Connexion perdue : les sondages en arrière-plan échouent en silence et
   l'écran se fige sur les dernières données — ce qui ressemble beaucoup à
   un soir calme. Le bandeau lève l'ambiguïté. */
.net-banner {
    position: fixed; left: 50%; transform: translateX(-50%);
    bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 2000;
    background: #7a1020; color: #fff; border: 1px solid #a5162c;
    border-radius: 24px; padding: 9px 20px; font-size: .86rem; font-weight: 600;
    box-shadow: 0 6px 22px rgba(0,0,0,.5); display: flex; align-items: center;
    max-width: calc(100vw - 24px);
}
@media (prefers-reduced-motion: reduce) { .net-banner { transition: none; } }

/* Pages légales : des blocs séparés se relisent mieux qu'un mur de texte,
   et l'on retrouve une clause sans tout parcourir. */
.legal-bloc { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--toko-border); }
.legal-bloc:last-of-type { border-bottom: 0; }
.legal-bloc h2 { font-size: 1.1rem; color: var(--toko-red); margin-bottom: .75rem; }
.legal-bloc th { white-space: nowrap; color: var(--toko-muted); font-weight: 500; }
.legal-bloc ul { padding-left: 1.2rem; }
.legal-bloc li { margin-bottom: .35rem; }

/* ============================================================
   v34 — Efficacité sur smartphone et iPhone
   ============================================================ */

/* Panier et téléphone TOUJOURS accessibles, menu replié ou non.
   Le panier vivait dans le menu déroulant : sur téléphone, le client ne
   voyait ni le bouton ni son compteur avant d'ouvrir le hamburger — donc
   aucun moyen de savoir qu'il avait déjà commandé quelque chose. */
.nav-actions-mobile { display: flex; align-items: center; gap: 8px; margin-right: 8px; }
/* 44 px : le minimum recommandé par Apple, et la valeur imposée plus bas
   aux boutons sur mobile. Les fixer à 42 ici aurait donné des boutons
   étirés en hauteur mais pas en largeur. */
.nav-actions-mobile .btn { width: 44px; height: 44px; padding: 0;
                           display: flex; align-items: center; justify-content: center; }
.nav-actions-mobile .badge { font-size: .68rem; min-width: 18px; }

@media (max-width: 991.98px) {
    /* ---------- Zoom automatique d'iOS ----------
       Safari agrandit la page dès qu'un champ de moins de 16 px reçoit le
       focus, puis ne revient pas en arrière : le formulaire se retrouve
       décalé et il faut pincer pour se repositionner. La règle vaut pour
       TOUS les champs, y compris ceux marqués « sm » — la taille réduite
       est un choix visuel, le zoom une conséquence subie. */
    input[type="text"], input[type="email"], input[type="tel"], input[type="number"],
    input[type="password"], input[type="search"], input[type="date"], input[type="time"],
    select, textarea, .form-control, .form-select,
    .form-control-sm, .form-select-sm {
        font-size: 16px;
    }

    /* Cibles tactiles : 44 px est le minimum recommandé par Apple. En
       dessous, on vise deux fois. */
    .btn, .nav-link, .form-check-input { min-height: 44px; }
    .btn-sm { min-height: 38px; }        /* boutons secondaires, en grappe */
    .form-check-input { min-width: 20px; min-height: 20px; }

    /* Suppression du voile gris au tap, qui donne une impression de lenteur */
    a, button, .btn, .nav-link { -webkit-tap-highlight-color: rgba(200,16,46,.15); }
}

/* ---------- Hauteur d'écran réelle sur iOS ----------
   100vh compte la barre d'adresse de Safari comme si elle n'existait pas :
   le bas de l'écran passe sous la barre et devient inatteignable. L'unité
   dvh suit la hauteur réellement visible. La déclaration vh reste d'abord,
   comme repli pour les navigateurs qui ignorent dvh. */
.liv-page { min-height: 100vh; }
@supports (height: 100dvh) {
    .liv-page { min-height: 100dvh; }
    .pos-page { height: calc(100dvh - 76px); }
}

/* La barre fixe du panier et le bandeau de connexion tiennent déjà compte
   de la zone sûre ; le pied de page doit en faire autant, sinon le dernier
   lien tombe derrière la barre de navigation de l'iPhone. */
@media (max-width: 991.98px) {
    footer { padding-bottom: calc(1rem + env(safe-area-inset-bottom)); }
}

/* Le bouton flottant devient redondant sur mobile : le panier est
   maintenant dans la barre, toujours visible, avec le même compteur. Deux
   pastilles rouges identiques sur un même écran ne renseignent pas
   davantage, elles font douter de celle qui compte.
   Il reste sur grand écran, où la barre est plus loin du pointeur. */
@media (max-width: 991.98px) {
    .float-cart-btn { display: none; }
}

/* Sous-titres des pages légales : une section comme « Vos droits » compte
   plusieurs points distincts qu'on doit pouvoir retrouver sans tout relire. */
.legal-h3 {
    font-size: .92rem; text-transform: uppercase; letter-spacing: .5px;
    color: var(--toko-text); margin: 1.25rem 0 .5rem;
}
/* Pied commun : même bloc, même date, sur les deux pages — elles forment un
   seul corpus opposable. */
.legal-pied {
    border-top: 1px solid var(--toko-border); padding-top: 1rem; margin-top: 2rem;
    font-size: .82rem; color: var(--toko-muted);
}
.legal-pied a { color: var(--toko-muted); }
.legal-pied a:hover { color: var(--toko-red); }

/* ============================================================
   v38 — Repères de navigation dans la carte
   ============================================================ */

/* En-tête de section : la grille alignait 129 vignettes sans repère, et
   makis, nigiris et sashimis se ressemblent tous en photo. */
.menu-section-head {
    scroll-margin-top: 150px;   /* la barre collée ne doit pas masquer le titre */
    padding: 6px 0 2px;
}
.menu-section-head h2 {
    display: flex; align-items: center; gap: 10px;
    font-size: 1.05rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .6px; color: #fff; margin: 0;
}
.menu-section-head h2::after {
    content: ""; flex: 1 1 auto; height: 1px; background: var(--toko-border);
}
.menu-section-nb {
    background: rgba(255,255,255,.08); color: var(--toko-muted);
    border-radius: 20px; padding: 1px 9px; font-size: .72rem; font-weight: 600;
}

/* Barre de sous-catégories : collée sous celle des groupes, elle indique
   en permanence la section où l'on se trouve. */
.subcat-bar {
    position: sticky; top: 62px; z-index: 15;
    background: var(--toko-dark);
    padding-top: 6px;
    scrollbar-width: none;
}
.subcat-bar::-webkit-scrollbar { display: none; }
.subcat-bar .subcat-chip { flex: 0 0 auto; white-space: nowrap; }
.subcat-bar .subcat-chip.active {
    background: var(--toko-red); border-color: var(--toko-red); color: #fff;
}

@media (max-width: 991.98px) {
    /* La navbar mobile est plus basse : la barre se cale dessous. */
    .subcat-bar { top: 56px; }
    .menu-section-head { scroll-margin-top: 130px; }
    .menu-section-head h2 { font-size: .95rem; }
}
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

/* Rappel du groupe, au changement de famille seulement. L'ordre des
   sections suit la carte du restaurant et non celui des groupes : sans ce
   repère, on passe des sushis aux entrées sans s'en apercevoir. */
.menu-section-groupe { margin-top: 1.5rem; }
.menu-groupe-label {
    display: block; font-size: .68rem; text-transform: uppercase;
    letter-spacing: 1.5px; color: var(--toko-red); font-weight: 700;
    margin-bottom: 2px;
}

/* ============================================================
   v39 — Cadre des images selon la famille de produits
   ============================================================
   Les photos sont des PNG à fond transparent, posées avec une marge : le
   fond de la vignette est donc RÉELLEMENT visible autour du plat. Il était
   identique partout — un dégradé gris neutre — et vingt vignettes voisines
   se ressemblaient d'autant plus que les plats eux-mêmes se ressemblent.

   Chaque famille reçoit sa teinte. Deux règles ont guidé le choix :

   1. TRÈS DÉSATURÉE. Le sujet est le plat, pas le cadre. Des fonds vifs
      transformeraient la carte en arc-en-ciel et rendraient les photos
      moins appétissantes — c'est le contraire du but recherché.
   2. Au niveau du GROUPE, pas de la sous-catégorie. Dix-neuf teintes
      seraient indiscernables ; cinq se retiennent.

   La teinte se déclare une fois par groupe, sous forme de variables, et
   sert ensuite au fond, au liseré et à la lueur au survol. Ajouter un
   groupe demande donc trois lignes, pas une réécriture.
   ============================================================ */

/* Les teintes par famille ont été retirées : plus aucune règle ne s'en
   sert, et laisser des variables orphelines derrière soi ne fait
   qu'égarer la prochaine lecture. */

/* ============================================================
   CADRES TEINTÉS RETIRÉS
   ============================================================
   Le fond des vignettes reprenait la teinte de la famille, par un dégradé
   construit sur des variables CSS, plus un liseré en pseudo-élément.

   Les images ne s'affichaient plus sur Chrome et Edge MOBILE — et sur eux
   seulement. Je n'ai pas pu reproduire la panne ici, donc pas l'expliquer.
   Face à un défaut que je ne comprends pas, la bonne décision n'est pas de
   deviner : c'est de retirer ce qui a été ajouté en dernier sur ces
   éléments et qui n'est pas indispensable.

   Un dégradé radial construit sur des variables héritées, recouvert d'un
   pseudo-élément positionné, est exactement le genre de superposition qui
   se comporte différemment d'un moteur à l'autre. La distinction des
   familles se lit déjà par les en-têtes de section, les photos et les
   codes produits : elle ne valait pas de risquer l'affichage.
   ============================================================ */
.product-item .product-img,
.product-hero-img {
    /* Fond uni, sans dégradé ni variable : ce qu'un navigateur ne peut pas
       interpréter de travers. */
    background: #1e1e1e;
}

/* Au survol, la lueur reprend la teinte de la famille plutôt que le rouge
   de la marque : sur une grille, elle indique alors CE QU'ON SURVOLE.
   La bordure, elle, reste rouge — c'est le retour d'interaction du site. */
.product-item .product-card:hover { box-shadow: 0 10px 32px rgba(217,43,43,.22); }

/* Fiche produit : liseré plus marqué, l'image y occupe toute la colonne. */
.product-hero-img { border-color: #2a2a2a !important; }

/* Contraste renforcé : certains écrans de cuisine ou de comptoir sont vus
   de biais, où les teintes sombres se confondent. */
@media (prefers-contrast: more) {
    /* Le liseré de famille a été retiré : plus rien à renforcer ici. */
}

/* Précommande : le restaurant est fermé, le client commande pour plus tard.
   Le bloc doit rassurer — expliquer que rien n'est préparé d'avance — plus
   qu'alerter : ce n'est pas un problème, c'est un service. */
.precommande-bloc {
    background: rgba(70,212,126,.07);
    border: 1px solid rgba(70,212,126,.35);
    border-radius: 12px; padding: 16px;
}
.pc-titre { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.pc-titre i { font-size: 1.4rem; color: #46d47e; }
.pc-titre strong { color: #fff; }
.pc-texte { font-size: .86rem; color: var(--toko-muted); margin-bottom: 14px; }

/* Fermé mais commandable : vert, pas rouge. Le rouge annoncerait un
   empêchement, alors que c'est une possibilité offerte. */
.shop-banner-precom { background: #14532d; color: #d9f5e3; }
.shop-banner-precom strong { color: #fff; }

/* ============================================================
   État de l'établissement : une seule lecture
   ============================================================
   Quatre interrupteurs se lisaient chacun isolément. Les états se
   combinent — fermé par horaire mais précommande ouverte, ouvert mais
   livraison suspendue — et c'est le résultat que voit le client qui
   compte. */
.etat-resume {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    background: var(--toko-panel); border: 1px solid var(--toko-border);
    border-radius: 14px; padding: 14px 18px;
}
.etat-pastille {
    font-weight: 800; font-size: .82rem; letter-spacing: 1.5px;
    padding: 8px 18px; border-radius: 24px; white-space: nowrap;
}
.etat-ouvert { background: rgba(70,212,126,.15); color: #46d47e; border: 1px solid rgba(70,212,126,.5); }
.etat-precom { background: rgba(70,212,126,.10); color: #8fe3b0; border: 1px solid rgba(70,212,126,.35); }
.etat-rush   { background: rgba(255,193,7,.15);  color: #ffc107; border: 1px solid rgba(255,193,7,.5); }
.etat-ferme  { background: rgba(200,16,46,.15);  color: #ff8a8a; border: 1px solid rgba(200,16,46,.5); }
.etat-detail { flex: 1 1 260px; }
.etat-mode {
    display: inline-block; margin-right: 12px; font-size: .8rem;
    padding: 1px 0; white-space: nowrap;
}
.etat-mode-ok  { color: #46d47e; }
.etat-mode-pre { color: #8fe3b0; }
.etat-mode-non { color: #ff8a8a; }

/* Jauge du seuil SCE : on doit voir d'un coup d'œil où l'on en est, sans
   lire un chiffre — l'obligation se prépare des mois à l'avance. */
.sce-jauge { height: 10px; background: rgba(0,0,0,.35); border-radius: 6px; overflow: hidden; }
.sce-barre { height: 100%; background: #46d47e; border-radius: 6px; transition: width .4s; }
.sce-proche { background: #ffc107; }
.sce-depasse { background: var(--toko-red); }
@media (prefers-reduced-motion: reduce) { .sce-barre { transition: none; } }

/* ============================================================
   v47 — Accès au poste de travail
   ============================================================
   C'était un lien orange perdu entre « Menus » et « Contact ». Rien ne le
   distinguait d'une page publique, alors que c'est le seul lien que
   l'exploitant utilise vingt fois par service.

   Il n'apparaît que pour un compte administrateur ou livreur DÉJÀ
   CONNECTÉ : le rendre visible ne l'expose à aucun visiteur. Un bouton
   « Admin » montré à tous serait une invitation, pas une commodité.
   ============================================================ */
.btn-poste {
    background: var(--toko-gold, #c9a227);
    color: #1a1a1a; font-weight: 700; font-size: .84rem;
    border: 1px solid transparent; border-radius: 22px;
    padding: 6px 16px; white-space: nowrap;
    display: inline-flex; align-items: center;
    transition: background .2s, transform .2s, box-shadow .2s;
}
.btn-poste:hover, .btn-poste:focus-visible {
    background: #e0b62c; color: #111;
    box-shadow: 0 4px 14px rgba(201,162,39,.35);
}
.btn-poste:active { transform: translateY(1px); }

/* Pastille des commandes en attente : le chiffre suit l'exploitant sur
   toute page publique. Sans lui, un administrateur qui consulte sa carte
   ignore que trois commandes attendent en cuisine. */
.poste-badge {
    background: var(--toko-red); color: #fff;
    border-radius: 20px; padding: 1px 8px; margin-left: 7px;
    font-size: .74rem; font-weight: 800; font-variant-numeric: tabular-nums;
    animation: postePulse 2s ease-in-out infinite;
}
@keyframes postePulse { 0%,100% { opacity: 1; } 50% { opacity: .55; } }

/* Version mobile : rond, dans la barre d'actions, à côté du panier. */
.btn-poste-rond {
    width: 44px; height: 44px; padding: 0; border-radius: 50%;
    justify-content: center; font-size: 1.05rem;
}
.btn-poste-rond .badge { font-size: .68rem; min-width: 18px; }

@media (prefers-reduced-motion: reduce) {
    .poste-badge { animation: none; }
}

/* Suggestions de rues : liste flottante sous le champ adresse. */
.rue-suggestions {
    display: none; position: absolute; z-index: 20; left: 12px; right: 12px;
    background: #1a1a1a; border: 1px solid var(--toko-border);
    border-radius: 0 0 10px 10px; border-top: 0;
    max-height: 240px; overflow-y: auto;
    box-shadow: 0 10px 26px rgba(0,0,0,.55);
}
.rue-item { padding: 10px 14px; cursor: pointer; font-size: .92rem; }
.rue-item:hover, .rue-item:focus { background: rgba(200,16,46,.18); color: #fff; }
.rue-item + .rue-item { border-top: 1px solid rgba(255,255,255,.05); }

/* Élément désigné au clavier : à la prise de commande téléphone,
   l'opérateur ne lâche pas le clavier pour attraper la souris. */
.rue-item.actif { background: rgba(200,16,46,.28); color: #fff; }

/* ============================================================
   v53 — Photo absente : dire pourquoi, plutôt que rien
   ============================================================
   L'attribut onerror supprimait l'image dès qu'elle échouait à charger.
   Il ne restait alors qu'une icône de police web — invisible elle aussi si
   la police n'a pas chargé. Deux replis qui échouent ensemble donnent un
   carré vide, et personne ne sait pourquoi.

   L'image reste maintenant dans la page, simplement masquée, et un repli
   TEXTUEL prend le relais. Le nom du plat s'affiche toujours : le client
   sait ce qu'il regarde même sans photo. */
/* RÈGLE GÉNÉRALE, et non limitée à .product-photo.
   En remplaçant « this.remove() » par une classe, j'avais restreint le
   masquage aux seules photos de produits. Les images des pastilles de
   catégorie et des sous-catégories, elles, restaient dans la page : le
   navigateur y affichait alors sa vignette « image cassée », à côté du
   texte. Avant, elles disparaissaient — le remplacement les a rendues
   visibles. C'était une régression, et c'est ce qu'on voyait à l'écran.

   Toute image qui échoue à charger se masque désormais, quelle qu'elle
   soit. Le texte ou l'icône de repli prend le relais. */
.photo-absente { display: none !important; }

.placeholder-ico {
    /* top/right/bottom/left en plus de « inset » : ce raccourci n'existe pas
       sur les moteurs mobiles antérieurs à 2020, où la règle entière serait
       alors ignorée. Les deux écritures coexistent sans conflit. */
    position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; padding: 10px; text-align: center;
    color: #4a4a4a;
}
.placeholder-ico .bi { font-size: 2.2rem; line-height: 1; }
.placeholder-nom {
    font-size: .72rem; line-height: 1.25; color: #6a6a6a;
    max-width: 100%; overflow: hidden;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
}
/* Une photo présente recouvre le repli : il n'apparaît que si elle manque. */
.product-photo { z-index: 1; }

/* Fichier absent, côté administration : le dire explicitement.
   Une vignette vide se confond avec « pas encore téléversé » ; le message
   distingue les deux, et c'est justement cette distinction qu'on cherche
   quand les images ne s'affichent plus sur le site. */
.media-absente { position: relative; }
.media-absente::after {
    content: "fichier absent du serveur";
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    text-align: center; padding: 8px;
    background: rgba(200,16,46,.12); border: 1px dashed rgba(200,16,46,.5);
    color: #ff8a8a; font-size: .72rem; border-radius: 8px;
}

/* ============================================================
   v57 — MOBILE : l'image produit, rien d'autre
   ============================================================
   Demande explicite : aucun traitement visuel sur les photos de produits en
   version mobile. Ces règles passent en dernier dans la feuille et portent
   « !important » — non par facilité, mais parce qu'elles doivent l'emporter
   sur tout ce qui pourrait être ajouté plus tard sans qu'on y repense.

   Sur un petit écran, chaque effet coûte deux fois : il masque une image
   déjà minuscule, et il pousse le navigateur à composer une couche
   supplémentaire, souvent rasterisée à résolution réduite.
   ============================================================ */
@media (max-width: 991.98px) {

    /* Aucun filtre, aucune opacité, aucun mélange, aucune transformation.
       La photo s'affiche telle qu'elle est dans le fichier. */
    .product-photo,
    .product-hero-img img,
    .product-item .product-photo {
        filter: none !important;
        -webkit-filter: none !important;
        backdrop-filter: none !important;
        opacity: 1 !important;
        mix-blend-mode: normal !important;
        transform: none !important;
        transition: none !important;
        will-change: auto !important;
        /* La photo occupe tout le cadre : la marge intérieure réduisait une
           vignette de 166 px à environ 140. */
        padding: 0 !important;
        /* « contain » et non « cover » : la photo est montrée ENTIÈRE.
           Rogner un plat pour remplir un carré coupe précisément ce qu'on
           voulait montrer. */
        object-fit: contain;
    }

    /* ------------------------------------------------------------
       CADRE TRANSPARENT
       ------------------------------------------------------------
       Le cadre posait un fond opaque (#141414) derrière la photo. Comme
       l'image est affichée en entier — « contain » — et qu'une photo de
       plat est rarement carrée, ce fond débordait de chaque côté : il se
       lisait comme un rectangle noir posé SUR la vignette, alors qu'il
       était dessous.

       Sur mobile il n'apporte rien : la carte a déjà son propre fond, et
       une photo détourée s'y pose très bien. On le rend transparent. */
    .product-item .product-img,
    .product-hero-img {
        background: transparent !important;
        border: 0 !important;
        box-shadow: none !important;
        filter: none !important;
    }

    /* Aucun pseudo-élément en surimpression : c'est par là qu'un voile
       s'installe sans qu'aucune règle ne nomme l'image. */
    /* On ne neutralise QUE le liseré décoratif, et non tous les
       pseudo-éléments : « content: none » sur ::before interdirait aussi
       les techniques de repli qui donnent sa hauteur au cadre. */
    .product-item .product-img::after { content: none !important; }

    /* Un produit épuisé reste PLEINEMENT visible. Le badge le dit ; estomper
       la photo empêchait de reconnaître le plat, ce que le client cherche
       précisément à faire. */
    .produit-epuise .product-card { opacity: 1 !important; }
    .produit-epuise .product-photo { filter: none !important; }

    /* Fermeture ou commandes suspendues : la carte reste une vitrine. */
    body.shop-blocked .product-photo,
    body.shop-blocked .product-img,
    body.shop-blocked .product-card { opacity: 1 !important; filter: none !important; }
}


/* ============================================================
   v59 — Le repli DOIT se voir
   ============================================================
   Le nom du plat s'affichait en #6a6a6a sur un fond #141414 : gris sombre
   sur presque noir. Sur un téléphone, souvent en plein jour, cela ne se
   distingue pas d'un carré vide — et l'on ne peut alors plus dire si
   l'image manque ou si elle s'affiche en noir. Deux pannes différentes,
   impossibles à séparer à l'œil.

   Le repli passe donc en clair, lisible. Il ne s'affiche que si l'image
   est réellement absente : quand elle est là, elle le recouvre.
   ============================================================ */
.placeholder-ico { color: #8a8a8a; z-index: 0; }
.placeholder-ico .bi { font-size: 2rem; opacity: .55; }
.placeholder-nom {
    font-size: .78rem; line-height: 1.3; color: #c9c9c9; font-weight: 600;
    padding: 0 8px;
}

/* Une image qui a échoué laisse la place au repli, sans réserver d'espace. */
.photo-absente { display: none !important; }

/* Carte PDF dans le menu déroulant. Mise en avant quand le restaurant est
   fermé : c'est le moment où le client cherche à voir ce qu'on propose,
   sans pouvoir commander tout de suite. */
.nav-pdf-actif { color: var(--toko-gold, #c9a227) !important; font-weight: 600; }
.nav-pdf-poids { font-size: .7rem; color: var(--toko-muted); margin-left: 4px; }
.banner-pdf {
    display: inline-block; margin-left: 10px; padding: 2px 12px;
    background: rgba(255,255,255,.14); border-radius: 20px;
    color: #fff; font-weight: 600; white-space: nowrap;
}
.banner-pdf:hover { background: rgba(255,255,255,.24); color: #fff; }

/* Messages de contact : répondre sans quitter l'écran. */
.msg-repondu { opacity: .72; }
.msg-coord a { color: var(--toko-red); text-decoration: none; font-size: .88rem; }
.msg-coord a:hover { text-decoration: underline; }
.msg-reponse {
    background: rgba(70,212,126,.07); border-left: 3px solid rgba(70,212,126,.5);
    border-radius: 0 8px 8px 0; padding: 10px 14px; font-size: .92rem;
}
.msg-form summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; }
.msg-form summary::-webkit-details-marker { display: none; }

/* Chiffre d'affaires du jour : lisible d'un coup d'œil, sans imprimer. */
.ca-total { display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px; }
.ca-montant { font-size: 2.1rem; font-weight: 800; color: #46d47e; line-height: 1; }
.ca-sous { color: var(--toko-muted); font-size: .88rem; }
.ca-bloc {
    background: rgba(0,0,0,.22); border: 1px solid var(--toko-border);
    border-radius: 10px; padding: 12px 14px; height: 100%;
}
.ca-bloc h6 {
    font-size: .74rem; text-transform: uppercase; letter-spacing: 1px;
    color: var(--toko-muted); margin-bottom: 10px;
}
.ca-bloc > div { font-size: .92rem; padding: 2px 0; }
/* Les espèces sont le seul montant à confronter à un comptage physique. */
.ca-espece {
    background: rgba(255,193,7,.12); border-radius: 8px; padding: 6px 10px;
    font-size: .85rem; color: #ffc107;
}

/* Précommandes : visibles, mais calmes. Elles ne réclament aucune action
   immédiate — les signaler comme une urgence apprendrait à les ignorer. */
.precom-liste { border-left: 3px solid rgba(70,212,126,.55); }
.precom-quand { white-space: nowrap; color: #8fe3b0; }
.badge-precom {
    display: inline-block; margin-left: 6px; padding: 1px 8px;
    background: rgba(70,212,126,.15); border: 1px solid rgba(70,212,126,.4);
    border-radius: 20px; color: #8fe3b0; font-size: .72rem; white-space: nowrap;
}

/* ============================================================
   v71 — MOBILE : la photo flotte, plus de cadre
   ============================================================
   Rendre le cadre image transparent (v69) ne suffisait pas : il est posé
   DANS la carte, qui a son propre fond sombre et sa bordure. Comme la
   photo est affichée en entier et qu'un plat détouré ne remplit jamais
   un carré, la carte transparaissait tout autour — c'est ce rectangle que
   l'on prend pour un cadre posé sur l'image.

   Sur mobile, la carte perd donc son fond et sa bordure : la photo flotte
   sur le fond de la page. Seul le bloc de texte garde une surface, pour
   rester lisible, avec un coin arrondi qui rappelle la carte. */
@media (max-width: 991.98px) {
    .product-item .product-card {
        background: transparent !important;
        border: 0 !important;
        box-shadow: none !important;
        overflow: visible !important;
    }
    .product-item .product-card > .product-img {
        background: transparent !important;
    }
    /* Le texte reprend une surface discrète, sans quoi il flotte lui aussi. */
    .product-item .product-card > .card-body,
    .product-item .product-card > .p-3 {
        background: var(--toko-panel);
        border: 1px solid #2a2a2a;
        border-radius: 14px;
        margin-top: 6px;
    }
    /* Le badge du code reste net : c'est lui qu'on dicte au téléphone. */
    .product-item .badge-code { bottom: 4px; left: 4px; }
}

/* Comptabilité : barre d'ancres. La page est longue ; on y saute. */
.compta-nav {
    display: flex; flex-wrap: wrap; gap: 6px;
    position: sticky; top: 62px; z-index: 5;
    background: var(--toko-dark); padding: 8px 0;
}
.compta-nav a {
    font-size: .8rem; padding: 4px 12px; border-radius: 20px;
    background: rgba(255,255,255,.06); color: var(--toko-muted); text-decoration: none;
    border: 1px solid var(--toko-border);
}
.compta-nav a:hover { color: #fff; border-color: var(--toko-red); }
#jour, #z, #journal, #periode, #sce, #tva, #identite { scroll-margin-top: 120px; }

/* Déclaration TVA : les numéros de grilles sont ceux du formulaire — on les
   rend reconnaissables d'un coup d'œil. */
.tva-grilles .grille, .tva-manque .grille {
    font-family: ui-monospace, Menlo, Consolas, monospace; font-weight: 700;
    color: var(--toko-gold, #c9a227); white-space: nowrap;
}
.tva-manque {
    background: rgba(255,255,255,.03); border: 1px dashed var(--toko-border);
    border-radius: 12px; padding: 14px;
}
#declaration { scroll-margin-top: 120px; }

/* ============================================================
   v75 — FICHE PRODUIT : la photo seule, avec son code
   ============================================================
   Trois règles empilaient un fond et une bordure sur le cadre de la fiche :
   le dégradé de base, un aplat #1e1e1e, une bordure #2a2a2a — et la version
   mobile ne les neutralisait qu'en dessous de 992 px. Sur la fiche, où la
   photo occupe toute la colonne, ce cadre était plus visible encore que sur
   la carte.

   Sur TOUTES les tailles d'écran : aucun fond, aucune bordure, aucune
   ombre. La photo flotte sur la page. Reste le code produit dans son coin,
   et le badge « best seller » s'il y a lieu.
   ============================================================ */
.product-hero-img,
.product-img.product-hero-img,
.product-img.square.product-hero-img {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
    overflow: visible;
}
/* La photo est montrée entière, sans marge intérieure : la colonne a déjà
   ses marges, une seconde marge ne faisait que rétrécir l'image. */
.product-hero-img .product-photo {
    padding: 0 !important;
    object-fit: contain;
}
/* Le repli (nom du plat) reste lisible sur le fond de page. */
.product-hero-img .placeholder-nom { color: #c9c9c9; font-size: .95rem; }
