/* ============================================================
   Kabana Pizz — Socle et primitives
   ============================================================
   Reset, typographie et composants transverses : boutons, champs,
   cartes, badges, statuts, modales, notifications, états vides et
   de chargement.

   Ces primitives sont partagées par le site public et le back-office.
   Elles n'ont aucune connaissance de la page qui les utilise : rien
   ici ne doit dépendre d'un identifiant ou d'une section précise.

   Avant ce fichier, .btn, .form-error et .status-chip étaient écrits
   deux fois — dans style.css et dans admin.css — avec des valeurs
   divergentes. C'est cette duplication que le fichier remplace.

   Dépend de : tokens.css
   ============================================================ */

/* ============================================================
   1. Reset et socle
   ============================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  /* Compense le header collant lors d'un saut d'ancre : sans cela le
     titre de section atterrit derrière la barre fixe. */
  scroll-padding-top: var(--header-offset, 80px);
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-lg); }

p { margin: 0 0 var(--space-4); }
p:last-child { margin-bottom: 0; }

img,
svg,
video,
iframe {
  display: block;
  max-width: 100%;
}

img { height: auto; }

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

a { color: var(--color-primary); }

ul, ol { margin: 0 0 var(--space-4); padding-left: var(--space-5); }

/* Masquage accessible : invisible à l'écran, lu par les technologies
   d'assistance. Sert aux libellés que le visuel rend redondants. */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Lien d'évitement — WCAG 2.4.1 Bypass Blocks. */
.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: var(--z-modal);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-text);
  color: var(--color-text-invert);
  font-weight: var(--weight-bold);
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform var(--duration-fast) var(--ease-out);
}

.skip-link:focus { transform: translateY(0); }

/* ============================================================
   2. Focus
   ============================================================
   Un seul style de focus pour tout le produit, en bleu : sur les
   surfaces rouges (bouton principal, badges) un halo rouge serait
   invisible. Visible au clavier uniquement — :focus-visible — pour
   ne pas parasiter le clic à la souris. */

:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

:focus:not(:focus-visible) { outline: none; }

/* ============================================================
   3. Boutons
   ============================================================
   Trois variantes seulement : primary (l'action de la page),
   outline (action secondaire), ghost (action tertiaire ou en
   barre d'outils). Toute autre intention passe par un token
   d'état, pas par une nouvelle variante. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-height);
  padding: 0 var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: none;
  color: inherit;
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  line-height: 1;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

.btn:active { transform: scale(0.98); }

.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.btn-primary {
  background: var(--color-primary);
  color: var(--color-text-invert);
  box-shadow: var(--shadow-sm);
}

.btn-primary:hover:not([disabled]) { background: var(--color-primary-hover); }
.btn-primary:active:not([disabled]) { background: var(--color-primary-active); }

.btn-outline {
  border-color: var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text);
}

.btn-outline:hover:not([disabled]) {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.btn-ghost {
  background: transparent;
  color: var(--color-text-muted);
}

.btn-ghost:hover:not([disabled]) {
  background: var(--color-surface-sunken);
  color: var(--color-text);
}

.btn-danger {
  background: var(--color-danger);
  color: var(--color-text-invert);
}

.btn-block {
  display: flex;
  width: 100%;
}

.btn-sm {
  min-height: var(--control-height-sm);
  padding: 0 var(--space-4);
  font-size: var(--text-sm);
}

/* État de chargement : le libellé reste en place (pas de saut de
   largeur) et un anneau tourne à sa gauche. aria-busy porte
   l'information pour les lecteurs d'écran. */
.btn[aria-busy="true"] {
  pointer-events: none;
  opacity: 0.75;
}

.btn[aria-busy="true"]::before {
  content: "";
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: kb-spin 700ms linear infinite;
}

@keyframes kb-spin { to { transform: rotate(360deg); } }

/* Bouton icône carré — fermeture de tiroir, navigation de calendrier. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--text-xl);
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out);
}

.icon-btn:hover {
  background: var(--color-surface-sunken);
  color: var(--color-text);
}

/* Bouton présenté comme un lien — « Mot de passe oublié ? ». Garde une
   zone tactile réelle malgré son apparence textuelle. */
.link-btn {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* ============================================================
   4. Champs de formulaire
   ============================================================
   La taille de police des champs est verrouillée à 16px : en
   dessous, iOS zoome automatiquement à la mise au point et casse
   la mise en page. */

.field,
.setting-field,
.auth-form label,
.checkout-form label {
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  color: var(--color-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.field-label { font-weight: var(--weight-semibold); }

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="password"],
input[type="search"],
input[type="number"],
input[type="date"],
select,
textarea {
  width: 100%;
  min-height: var(--control-height);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}

textarea {
  min-height: 5rem;
  line-height: var(--leading-snug);
  resize: vertical;
}

select {
  appearance: none;
  padding-right: var(--space-10);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%236b5449' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
  background-size: 12px;
}

input:hover:not([disabled]),
select:hover:not([disabled]),
textarea:hover:not([disabled]) { border-color: var(--color-text-subtle); }

input:focus,
select:focus,
textarea:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-soft);
}

input[disabled],
select[disabled],
textarea[disabled] {
  background: var(--color-surface-sunken);
  color: var(--color-text-subtle);
  cursor: not-allowed;
}

/* :user-invalid plutôt que :invalid : n'alerte qu'après une vraie
   tentative de saisie, pas au chargement du formulaire vide. */
input:user-invalid,
select:user-invalid,
textarea:user-invalid {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 3px var(--color-danger-soft);
}

.field-hint {
  color: var(--color-text-subtle);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
}

/* Piège à robots : hors flux et hors ordre de tabulation, jamais
   présenté à l'utilisateur ni annoncé. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Interrupteur libellé — « Disponible à la commande ». */
.switch-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--tap-min);
  margin-bottom: var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}

.switch-row input[type="checkbox"],
.confirm-check input[type="checkbox"] {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  accent-color: var(--color-primary);
  cursor: pointer;
}

/* ============================================================
   5. Messages d'état
   ============================================================
   Couleur + icône + texte : jamais la couleur seule (WCAG 1.4.1).
   role="alert" / role="status" est porté par le HTML. */

.form-error,
.form-success,
.form-info {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.form-error {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

.form-success {
  background: var(--color-success-soft);
  color: var(--color-success);
}

.form-info {
  background: var(--color-info-soft);
  color: var(--color-info);
}

.form-error::before { content: "⚠"; }
.form-success::before { content: "✓"; }
.form-info::before { content: "ℹ"; }

/* [hidden] doit l'emporter sur l'affichage flex/grid de ces blocs. */
[hidden] { display: none !important; }

/* ============================================================
   6. Cartes et panneaux
   ============================================================ */

.surface,
.panel {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.panel {
  padding: var(--space-5);
  box-shadow: var(--shadow-xs);
}

/* ============================================================
   7. Badges, puces et statuts
   ============================================================ */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  line-height: 1.4;
  white-space: nowrap;
}

.badge-neutral { background: var(--color-surface-sunken); color: var(--color-text-muted); }
.badge-primary { background: var(--color-primary-soft); color: var(--color-primary); }
.badge-success { background: var(--color-success-soft); color: var(--color-success); }
.badge-warning { background: var(--color-warning-soft); color: var(--color-warning); }
.badge-danger  { background: var(--color-danger-soft);  color: var(--color-danger); }
.badge-info    { background: var(--color-info-soft);    color: var(--color-info); }

/* Statuts de commande — partagés entre le back-office et l'historique
   client, donc définis ici et pas dans admin.css.

   Chaque statut porte une pastille en préfixe : la forme et le texte
   suffisent à le distinguer si la couleur n'est pas perçue (WCAG 1.4.1). */
.status-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border: 1px solid currentColor;
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  white-space: nowrap;
}

.status-chip::before {
  content: "";
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}

.status-pending   { background: var(--color-warning-soft); color: var(--color-warning); }
.status-confirmed { background: var(--color-info-soft);    color: var(--color-info); }
.status-in_prep   { background: var(--color-primary-soft); color: var(--color-primary); }
.status-delivered { background: var(--color-surface-sunken); color: var(--color-text-muted); }
.status-cancelled { background: var(--color-danger-soft);  color: var(--color-danger); }

/* « Prêt » est le statut qu'on cherche du regard en cuisine : il est
   le seul à porter un aplat plein, pour se détacher de la liste. */
.status-ready {
  border-color: transparent;
  background: var(--color-success);
  color: var(--color-text-invert);
}

/* Puce de filtre — alternative tactile au menu déroulant. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--tap-min);
  padding: 0 var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.chip:hover { border-color: var(--color-text-subtle); color: var(--color-text); }

.chip[aria-pressed="true"] {
  border-color: transparent;
  background: var(--color-text);
  color: var(--color-text-invert);
}

/* ============================================================
   8. Modales et superpositions
   ============================================================ */

.overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  background: var(--color-overlay);
}

.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: var(--color-overlay);
}

.modal-card {
  width: min(30rem, 100%);
  max-height: 90dvh;
  overflow-y: auto;
  padding: var(--space-6);
  border-radius: var(--radius-xl);
  background: var(--color-surface);
  box-shadow: var(--shadow-lg);
}

/* ============================================================
   9. Notifications
   ============================================================ */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--space-6) + env(safe-area-inset-bottom));
  z-index: var(--z-toast);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  max-width: calc(100vw - var(--space-8));
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-pill);
  background: var(--color-text);
  color: var(--color-text-invert);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  box-shadow: var(--shadow-lg);
  transform: translate(-50%, 0);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity var(--duration-base) var(--ease-out),
    transform var(--duration-base) var(--ease-out);
}

.toast.show {
  opacity: 1;
  transform: translate(-50%, calc(-1 * var(--space-2)));
}

/* ============================================================
   10. États vides, chargement, indisponibilité
   ============================================================ */

.empty-state {
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  padding: var(--space-10) var(--space-4);
  text-align: center;
  color: var(--color-text-muted);
}

.empty-state h3 { color: var(--color-text); }
.empty-state p { margin: 0; font-size: var(--text-sm); }

/* Conservé : plusieurs vues (panier, listes admin) écrivent encore ce
   libellé depuis le JS. Aligné sur .empty-state pour éviter deux
   rendus visuels du même état. */
.cart-empty {
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-8) var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  text-align: center;
}

.cart-empty__title {
  margin: 0;
  color: var(--color-text);
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
}

.cart-empty__text { margin: 0; }
.cart-empty .btn { margin-top: var(--space-2); }

/* Squelette de chargement — remplace la grille vide et muette
   pendant l'appel au catalogue. */
.skeleton {
  border-radius: var(--radius-md);
  background:
    linear-gradient(90deg,
      var(--color-surface-sunken) 25%,
      #f3e9dd 37%,
      var(--color-surface-sunken) 63%);
  background-size: 400% 100%;
  animation: kb-shimmer 1.4s ease infinite;
}

@keyframes kb-shimmer {
  from { background-position: 100% 50%; }
  to   { background-position: 0 50%; }
}

/* Produit en rupture : grisé, non cliquable, et signalé par un
   libellé — l'opacité seule ne porte pas l'information. */
.is-unavailable {
  opacity: 0.6;
  filter: saturate(0.4);
}

.is-unavailable .add-btn { pointer-events: none; }

/* ============================================================
   11. Utilitaires de gabarit
   ============================================================ */

.container {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--page-gutter);
}

.prose { max-width: var(--prose-max); }

.stack > * + * { margin-top: var(--space-4); }

/* ============================================================
   12. Garde-fou mouvement
   ============================================================
   Les durées à zéro (tokens.css) désactivent déjà les transitions
   écrites avec les tokens. Ce bloc neutralise en plus les animations
   en boucle et le défilement fluide, qui ne passent pas par une
   durée variabilisée. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
