/* ══════════════════════════════════════════════════════════════════════════
   Socle commun : jetons de style et primitives partagées.
   Chargé avant la feuille propre à chaque page.

   Les trois feuilles répétaient les mêmes valeurs à la main, avec des écarts
   involontaires : #4F4F4F et #4F4F4E pour le même gris, huit valeurs
   d'espacement entre 5 et 25px, cinq tailles de police. Tout est nommé ici.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Couleurs ──────────────────────────────────────────────────────────
     Une seule teinte d'accent. L'ancien survol faisait passer les boutons
     du bleu au vert vif, ce qui attirait l'oeil sur l'action la moins
     importante de la page. */
  --ink:          #1F2328;   /* titres */
  --text:         #4A4F55;   /* corps */
  --muted:        #6E767F;   /* secondaire */
  --faint:        #9AA1A9;   /* étiquettes, mentions */

  --line:         #ECEEF1;   /* séparateurs internes */
  --line-strong:  #D9DDE2;   /* bordures de carte, filets de total */

  --surface:      #FFFFFF;
  --surface-veil: rgba(255, 255, 255, 0.97);
  --surface-hover:#F5F8FC;

  --accent:       #2A6FC9;
  --accent-dark:  #1E568F;
  --accent-soft:  #EFF5FC;

  --ok:           #3E8E5A;   /* sobre : sert au repérage, pas à l'emphase */
  --ok-soft:      #F1F8F3;
  --warn:         #B0780C;
  --warn-soft:    #FCF6E8;
  --danger:       #C0392B;

  /* ── Typographie ───────────────────────────────────────────────────── */
  --font: "Google Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
          Roboto, Arial, sans-serif;

  --fs-xs:   11px;   /* étiquettes en majuscules */
  --fs-sm:   12.5px; /* détails, mentions */
  --fs-base: 14px;   /* corps, tableaux */
  --fs-md:   15px;   /* titres de plat */
  --fs-lg:   17px;   /* titres de panneau */
  --fs-xl:   21px;   /* titre de la page de connexion */

  --lh-tight: 1.3;
  --lh-base:  1.5;

  /* ── Espacement ────────────────────────────────────────────────────── */
  --s-1:  4px;
  --s-2:  8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-6: 24px;

  /* ── Formes ────────────────────────────────────────────────────────── */
  --radius:    6px;
  --radius-lg: 10px;
  --shadow:    0 1px 2px rgba(16, 24, 40, 0.04),
               0 8px 24px rgba(16, 24, 40, 0.07);

  --panel-width: 440px;

  /* Largeur de la page, commune à « Menu » et à « Edition » : les deux
     faisaient 1180 et 1360px, et passer de l'une à l'autre décalait tout.
     Elle vaut ici la grille du menu, gouttière comprise :
     catalogue + panier + --s-5. */
  --layout-width: 1280px;
}

/* Une seule colonne : on garde une largeur de lecture confortable plutôt que
   d'étirer le texte sur toute la fenêtre. */
@media (max-width: 899px) {
  :root { --layout-width: 680px; }
}

*, *::before, *::after { box-sizing: border-box; }

/* ── Coquille : barre fixe, contenu défilant ────────────────────────────────
   La barre du haut ne défile pas, mais elle ne passe pas non plus PAR-DESSUS
   le contenu : c'est le contenu qui défile dans sa propre zone, en dessous.

   `position: sticky` aurait été plus simple, mais un en-tête collant recouvre
   ce qui passe dessous, et l'écart entre la barre et la première carte
   disparaissait à mesure qu'on défilait. Ici la zone de défilement commence
   sous la barre ET sous sa marge : l'écart ne bouge jamais.

   Le fond de page cesse de défiler, ce qui est un effet secondaire voulu :
   le motif reste en place pendant que les cartes glissent devant. */
html { height: 100%; }

body {
  height: 100vh;
  height: 100dvh;   /* tient compte de la barre d'adresse mobile */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.app-header { flex: none; padding: var(--s-3) 0 var(--s-5) 0; }

.app-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;

  /* `none` et non `contain` : les deux empêchent le défilement de se propager
     à la page, mais `contain` laisse le rebond élastique de macOS et d'iOS.
     Pendant ce rebond, tout le contenu de la zone glisse — le panier collant
     compris, qui paraissait alors bouger « un peu » au début et à la fin du
     défilement alors qu'il est fixe le reste du temps. */
  overscroll-behavior: none;
}

body {
  margin: 0;
  padding: 0;
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-image: url('../img/splash.webp');
  background-repeat: repeat;
  background-position: top left;
  background-size: 1920px 1920px;   /* tuile source 1280px, rendue à 1920px */
}

/* Le crénage négatif était appliqué à `*`, donc aussi aux étiquettes en
   majuscules espacées, où il travaillait contre l'interlettrage voulu. */
h1, h2, h3, h4, strong { letter-spacing: -0.01em; }

h1, h2, h3, h4 {
  margin: 0;
  color: var(--ink);
  line-height: var(--lh-tight);
  font-weight: 600;
}

:where(a, button, input, select, textarea):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* L'attribut `hidden` doit gagner contre nos propres règles d'affichage :
   sans cela `.ing-new-fields { display: inline-flex }` l'emporte sur le
   display:none de la feuille par défaut du navigateur, et les champs de
   création restent visibles pour un ingrédient déjà connu. */
[hidden] { display: none !important; }

/* ── Messages ───────────────────────────────────────────────────────────────
   UN seul composant pour tous les retours de l'application. Il y en avait
   sept définitions réparties sur trois feuilles, avec des écarts qui ne
   voulaient rien dire : rembourrages de 8, 10 et 12px, tailles de 13 et 14px,
   moitié en gras, moitié non. Pire, « aucun plat ne correspond » portait sur
   les deux pages une classe de SUCCÈS, qu'une règle d'identifiant repeignait
   ensuite en avertissement.

   Trois natures, et rien d'autre :
     is-ok    ce qui a réussi
     is-warn  ce qui demande une correction ou une vérification
     is-info  ce qui renseigne, sans jugement
   Chacune garde le filet à gauche, qui distingue un message d'un paragraphe
   même pour un oeil qui ne perçoit pas la couleur. */
.message {
  margin: var(--s-3) 0 0 0;
  padding: var(--s-2) var(--s-3);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 400;
  line-height: 1.4;
  border-radius: var(--radius);
  border-left: 3px solid transparent;
}

.message.is-ok {
  background-color: var(--ok-soft);
  color: var(--ok);
  border-left-color: var(--ok);
}
.message.is-warn {
  background-color: var(--warn-soft);
  color: var(--warn);
  border-left-color: var(--warn);
}
.message.is-info {
  background-color: var(--accent-soft);
  color: var(--accent-dark);
  border-left-color: var(--accent);
}

/* Messages éphémères, posés par lib/toast.js. `backwards` et non `opacity: 0`
   en état de repos : un message doit rester lisible même si l'animation ne
   joue pas, par exemple dans un onglet d'arrière-plan où le navigateur gèle
   la ligne de temps. */
.message.is-transient { animation: fadeIn 0.3s ease backwards; }
.message.fade-out { opacity: 0; transition: opacity 0.3s ease; }

/* ── Pagination ─────────────────────────────────────────────────────────────
   Composant commun au catalogue de menu.php, au panier et au tableau de
   edition.php. Il vivait dans css/menu.css, que edition.php ne charge pas :
   les mêmes contrôles y arrivaient donc sans mise en forme, « 35 plats par
   page 10 » serré sur une ligne au lieu du compteur à gauche et du sélecteur
   à droite. Le JavaScript est partagé depuis js/lib/pagination.js ; la
   feuille devait suivre. */

/* Un seul style pour les trois paginations : catalogue, panier, édition. */
/* Pied de liste : compteur, pages, taille — sur une seule ligne. Le compteur
   et le sélecteur prennent des parts égales, ce qui centre les numéros entre
   eux sans avoir à les positionner. Ils passent à la ligne sur écran étroit,
   où trois groupes ne tiennent plus. */
.list-footer {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-top: var(--s-4);
  padding-top: var(--s-3);
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm);
  color: var(--muted);
}
.list-footer .result-count { flex: 1 1 0; min-width: 0; }
.list-footer .page-size-controls { flex: 1 1 0; justify-content: flex-end; }

/* Le filet et l'espacement appartiennent au pied ; le bloc de pages ne les
   reprend que lorsqu'il vit seul, comme dans le panier. */
.list-footer .pagination-controls {
  flex: 0 0 auto;
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.pagination-controls {
  display: none;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-1);
  margin-top: var(--s-4);
  padding-top: var(--s-3);
  border-top: 1px solid var(--line);
}

.pagination-controls button {
  min-width: 30px;
  padding: 5px 9px;
  font-family: inherit;
  font-size: var(--fs-sm);
  color: var(--text);
  background-color: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.pagination-controls button:hover:not(:disabled) {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-dark);
}
.pagination-controls button:disabled {
  color: var(--faint);
  border-color: var(--line);
  cursor: not-allowed;
}

.page-size-controls {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--muted);
}
/* Sur téléphone, trois groupes ne tiennent pas sur une ligne : au tiers de la
   largeur chacun, « par page » se séparait de sa liste déroulante. Le compteur
   et la taille se partagent donc la première ligne, les numéros de page
   passent dessous sur toute la largeur. Deux lignes ici sont légitimes ; c'est
   sur grand écran qu'elles ne l'étaient pas. */
@media (max-width: 599px) {
  .app-header { padding: var(--s-3) 0; }

  .list-footer { justify-content: space-between; }
  .list-footer .result-count,
  .list-footer .page-size-controls { flex: 0 1 auto; }
  .list-footer .pagination-controls { order: 1; flex: 1 0 100%; }
  .page-size-controls { flex-wrap: nowrap; }
}

.page-size {
  font-family: inherit;
  font-size: var(--fs-sm);
  color: var(--text);
  padding: 3px 6px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface);
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fadeOut {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(4px); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
