/* Socle visuel commun.
 *
 * Deux contraintes d'usage dictent tout : le passager lit son téléphone dans
 * un train qui bouge, le restaurateur regarde une tablette de loin avec les
 * mains occupées. D'où les grandes cibles tactiles, les contrastes francs et
 * l'absence d'information décorative.
 */

:root {
  --fond: #0f1115;
  --carte: #191d24;
  --carte-haute: #222836;
  --trait: #2c3444;
  --texte: #f2f5f9;
  --texte-faible: #9aa6b8;
  --accent: #3ba7ff;
  --accent-fonce: #1d7fd1;
  --ok: #35c77b;
  --attente: #f2b23c;
  --erreur: #f4614f;
  --rayon: 14px;
  --espace: 16px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.app {
  max-width: 640px;
  margin: 0 auto;
  padding: var(--espace);
  padding-bottom: 96px;
}

header.bandeau {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px var(--espace);
  background: rgba(15, 17, 21, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--trait);
}

header.bandeau h1 { font-size: 18px; margin: 0; letter-spacing: -0.01em; }

.titre-marque {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 11px;
}

.logo-entete {
  display: block;
  width: clamp(138px, 28vw, 166px);
  height: auto;
}

.contexte-marque {
  padding-left: 11px;
  border-left: 1px solid var(--trait);
  color: var(--texte-faible);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .05em;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
}

#entete-actions { flex: none; display: flex; align-items: center; gap: 8px; }
.controle-son {
  width: 40px;
  height: 40px;
  padding: 0;
  font-size: 18px;
  line-height: 1;
}

h2 { font-size: 20px; margin: 0 0 4px; letter-spacing: -0.01em; }
p.sous-titre { color: var(--texte-faible); margin: 0 0 20px; }

.carte {
  background: var(--carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  padding: var(--espace);
  margin-bottom: 12px;
}

.carte.cliquable { cursor: pointer; transition: border-color .15s, transform .05s; }
.carte.cliquable:hover { border-color: var(--accent); }
.carte.cliquable:active { transform: scale(.995); }
.carte.desactivee { opacity: .55; cursor: not-allowed; }
.carte.desactivee:hover { border-color: var(--trait); }

label { display: block; font-size: 14px; color: var(--texte-faible); margin-bottom: 6px; }

input, select {
  width: 100%;
  padding: 14px;
  font-size: 17px;
  color: var(--texte);
  background: var(--carte-haute);
  border: 1px solid var(--trait);
  border-radius: 10px;
  margin-bottom: 14px;
}
input:focus, select:focus { outline: 2px solid var(--accent); border-color: transparent; }

button {
  width: 100%;
  padding: 16px;
  font-size: 17px;
  font-weight: 600;
  color: #04131f;
  background: var(--accent);
  border: 0;
  border-radius: 10px;
  cursor: pointer;
}
button:hover { background: var(--accent-fonce); color: #fff; }
button:disabled { opacity: .5; cursor: not-allowed; }
button.secondaire { background: transparent; color: var(--texte); border: 1px solid var(--trait); }
button.secondaire:hover { background: var(--carte-haute); color: var(--texte); }
button.danger { background: transparent; color: var(--erreur); border: 1px solid var(--erreur); }

/* Un lien-bouton : bascule une question, ne valide rien. Il ne doit donc pas
 * porter le poids visuel d'une action. */
button.lien {
  width: auto;
  padding: 4px 0;
  margin: 0;
  background: none;
  color: var(--accent);
  font-size: 14px;
  font-weight: 500;
  text-decoration: underline;
}
button.lien:hover { background: none; color: var(--accent-fonce); }

.rang { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.pile { display: flex; flex-direction: column; gap: 8px; }
.faible { color: var(--texte-faible); font-size: 14px; }
.gros { font-size: 22px; font-weight: 700; }

.etiquette {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.etiquette.ok { background: rgba(53,199,123,.15); color: var(--ok); }
.etiquette.attente { background: rgba(242,178,60,.15); color: var(--attente); }
.etiquette.erreur { background: rgba(244,97,79,.15); color: var(--erreur); }
.etiquette.neutre { background: var(--carte-haute); color: var(--texte-faible); }

.message { padding: 12px 14px; border-radius: 10px; margin-bottom: 14px; font-size: 15px; }
.message.erreur { background: rgba(244,97,79,.12); color: var(--erreur); border: 1px solid rgba(244,97,79,.3); }
.message.info { background: rgba(59,167,255,.1); color: var(--accent); border: 1px solid rgba(59,167,255,.25); }

/* Le code de remise : c'est l'écran que le passager tend sur le quai. */
.code-remise {
  font-size: 46px;
  font-weight: 800;
  letter-spacing: .18em;
  text-align: center;
  padding: 22px;
  background: var(--carte-haute);
  border: 2px dashed var(--accent);
  border-radius: var(--rayon);
  margin: 8px 0 4px;
}

/* Progression d'une commande. */
.etapes { list-style: none; padding: 0; margin: 0; }
.etapes li {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0; color: var(--texte-faible);
}
.etapes li .puce {
  width: 26px; height: 26px; flex: none;
  border-radius: 50%; border: 2px solid var(--trait);
  display: grid; place-items: center; font-size: 13px;
}
.etapes li.faite { color: var(--texte); }
.etapes li.faite .puce { background: var(--ok); border-color: var(--ok); color: #04131f; }
.etapes li.courante .puce { border-color: var(--accent); color: var(--accent); }
.etapes li.courante { color: var(--texte); font-weight: 600; }

/* Conversation sur une réclamation : passager d'un côté, support de l'autre.
 * Partagé par l'app passager et l'écran support pour que les deux parties
 * lisent exactement le même fil, disposé de la même façon. */
.fil { display: flex; flex-direction: column; gap: 10px; margin: 6px 0 16px; }
.bulle {
  max-width: 82%;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--carte-haute);
  border: 1px solid var(--trait);
  word-break: break-word;
}
.bulle .qui { font-size: 12px; color: var(--texte-faible); margin-bottom: 4px; }
/* Les retours à la ligne écrits par l'auteur comptent — l'indentation du
 * gabarit, non : le pré-formatage ne s'applique qu'au texte du message. */
.bulle .texte { white-space: pre-wrap; }
.bulle.support { align-self: flex-start; }
.bulle.courier { align-self: flex-start; }
.bulle.moi {
  align-self: flex-end;
  background: rgba(59, 167, 255, .12);
  border-color: rgba(59, 167, 255, .3);
}

textarea {
  width: 100%;
  min-height: 92px;
  padding: 14px;
  font: inherit;
  color: var(--texte);
  background: var(--carte-haute);
  border: 1px solid var(--trait);
  border-radius: 10px;
  margin-bottom: 14px;
  resize: vertical;
}
textarea:focus { outline: 2px solid var(--accent); border-color: transparent; }

.chat-livraison { border-left: 3px solid var(--accent); }
.chat-livraison h3 { margin: 0 0 4px; font-size: 17px; }
.chat-livraison .fil {
  max-height: 280px;
  overflow-y: auto;
  padding: 4px 2px;
  scroll-behavior: smooth;
}
.chat-livraison textarea { min-height: 74px; }
.chat-livraison .composer { margin-top: 12px; }

.chargement { text-align: center; padding: 40px; color: var(--texte-faible); }

@media (max-width: 420px) {
  .app { padding: 12px; padding-bottom: 96px; }
  .code-remise { font-size: 38px; }
  header.bandeau { padding-inline: 12px; }
  .logo-entete { width: 132px; }
  .contexte-marque { display: none; }
}


/* ---------------------------------------------------------------------------
 * Téléphone tenu d'une main, dans un train qui bouge.
 * ------------------------------------------------------------------------ */

/* `viewport-fit=cover` était déclaré sans que personne ne tienne compte des
 * encoches : sur iPhone, le bas d'écran passait sous la barre d'accueil et le
 * dernier bouton d'une page devenait difficile à atteindre. */
.app {
  padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
  padding-left: max(var(--espace), env(safe-area-inset-left, 0px));
  padding-right: max(var(--espace), env(safe-area-inset-right, 0px));
}
header.bandeau { padding-top: calc(14px + env(safe-area-inset-top, 0px)); }

/* Le focus doit se voir : sans lui, naviguer au clavier revient à avancer les
 * yeux fermés. */
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* Une carte qui se clique est un bouton — il ne doit pas pour autant ressembler
 * au bouton d'action principal. */
button.carte {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  color: var(--texte);
  background: var(--carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  padding: var(--espace);
}
button.carte:hover { background: var(--carte); border-color: var(--accent); color: var(--texte); }

/* Un arrêt : l'heure d'abord, parce que c'est elle qui décide. */
.liste-arrets { display: flex; flex-direction: column; gap: 12px; margin-bottom: 20px; }
.liste-arrets .carte { margin-bottom: 0; }
.arret .rang { align-items: flex-start; gap: 14px; }
.corps-arret { flex: 1; min-width: 0; }
.nom-arret { font-weight: 600; }
.heure-arret {
  flex: none;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 17px;
  padding-top: 1px;
  min-width: 3.4em;
}
.heure-arret.vide { color: var(--texte-faible); font-weight: 400; }

/* Barre d'action collante : sur une carte longue, le bouton de commande
 * disparaissait sous le pouce et il fallait remonter pour payer. */
.barre-action {
  position: sticky;
  bottom: 0;
  z-index: 5;
  margin: 20px calc(-1 * var(--espace)) 0;
  padding: 12px var(--espace) calc(12px + env(safe-area-inset-bottom, 0px));
  background: linear-gradient(to top, var(--fond) 72%, rgba(15, 17, 21, 0));
}
.barre-action .rang { margin-bottom: 10px; }
.barre-action button { margin: 0; }

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


/* ---------------------------------------------------------------------------
 * La convergence : un train et un repas qui vont à la même gare.
 *
 * C'est ce que fait le produit, et ce que l'écran de suivi ne montrait pas —
 * il ne racontait que le repas. Les deux voies encadrent le point de
 * rendez-vous, qui est l'information que le passager cherche vraiment.
 * ------------------------------------------------------------------------ */

.convergence { padding: 18px var(--espace); }

.voie-titre {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texte-faible);
  margin-bottom: 4px;
}
.voie-etat { font-size: 17px; }
.voie-etat strong { font-variant-numeric: tabular-nums; }

.rendez-vous {
  text-align: center;
  padding: 12px 14px;
  background: var(--carte-haute);
  border: 1px solid var(--trait);
  border-radius: 10px;
}
.gare-libelle {
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texte-faible);
}
.gare-nom { font-size: 18px; font-weight: 700; letter-spacing: -.01em; }

/* Les deux flèches se font face de part et d'autre de la gare : le train y
 * descend, le repas y monte. C'est tout le propos, dit sans une phrase — à
 * condition qu'elles soient dans le flux vertical. Sur les côtés, elles ne se
 * lisaient plus que comme de la décoration. */
.fleche {
  display: block;
  width: 0; height: 0;
  margin: 8px auto;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
}
.fleche.descend { border-top: 10px solid var(--accent); }
.fleche.monte { border-bottom: 10px solid var(--ok); }

.jauge {
  height: 6px;
  margin-top: 10px;
  background: var(--carte-haute);
  border-radius: 999px;
  overflow: hidden;
}
.jauge span {
  display: block;
  height: 100%;
  background: var(--ok);
  border-radius: 999px;
  transition: width .4s ease;
}

/* ---------------------------------------------------------------------------
 * Mode remise : le train entre en gare, l'écran ne sert plus qu'à une chose.
 * ------------------------------------------------------------------------ */

.mode-remise .carte.convergence,
.mode-remise .carte-etapes { display: none; }

.remise-imminente {
  padding: 18px var(--espace) 20px;
  border-color: var(--accent);
  background: linear-gradient(180deg, rgba(59,167,255,.10), var(--carte) 60%);
}
.remise-imminente .gare-nom { font-size: 22px; }
.remise-imminente .compte {
  font-size: 15px;
  font-weight: 600;
  color: var(--accent);
  text-align: center;
  margin-top: 2px;
}
.remise-imminente .consigne {
  text-align: center;
  color: var(--texte-faible);
  font-size: 15px;
  margin: 14px 0 0;
}

/* T-5 : le train entre en gare. Il ne reste qu'une phrase à lire debout, avec
 * un sac dans une main — et c'est elle qui évite qu'un passager descende,
 * s'éloigne et bloque une porte au moment du départ. */
/* La liste d'étapes est déjà partie avec `mode-remise` ; ce qui reste à
 * retirer, c'est la ligne « gare · prix », que le bloc de code redit en plus
 * gros. Le bouton de sortie reste : un écran sans issue est un piège. */
.mode-quai .sous-titre { display: none; }

.remise-imminente .consigne.forte {
  color: var(--texte);
  font-size: 17px;
  font-weight: 600;
  line-height: 1.35;
}
.remise-imminente .consigne.en-position {
  color: var(--ok);
  font-weight: 600;
  margin-top: 12px;
}

/* L'état de la commande est déjà lisible dans la liste d'étapes ; cette ligne
 * n'existe que pour être *dite* — un lecteur d'écran annonçait jusqu'ici les
 * changements d'état par le silence. */
.annonce {
  position: absolute;
  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;
}


/* ---------------------------------------------------------------------------
 * « Où êtes-vous dans le train ? »
 *
 * Deux réponses possibles selon le billet — une place attribuée, ou rien —, et
 * la seconde doit être aussi facile à donner que la première : c'est celle des
 * TER, des trains de nuit et des billets sans réservation, donc celle qui
 * décide si le champ arrive rempli ou vide chez le livreur.
 * ------------------------------------------------------------------------ */

.ou-suis-je { border-left: 3px solid var(--accent); }

.deux-champs { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.deux-champs input { margin-bottom: 6px; }

.positions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.positions .position {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 8px;
  background: var(--carte-haute);
  color: var(--texte);
  border: 1px solid var(--trait);
  text-align: center;
}
.positions .position strong { font-size: 15px; }
.positions .position .faible { font-size: 12px; line-height: 1.3; }
.positions .position:hover { background: var(--carte-haute); border-color: var(--accent); }
.positions .position.choisie {
  border-color: var(--accent);
  background: rgba(59,167,255,.12);
}

.ou-suis-je .message { margin: 12px 0 0; }
input::placeholder { color: #8b8b91; opacity: 1; }

/* Horaires et consignes partagés entre cuisine et livreur. */
.horaire-ligne { display: flex; flex-wrap: wrap; gap: 12px; align-items: end; margin: 12px 0; }
.horaire-ligne label { flex: 1 1 120px; }
.horaire-ligne button { width: auto; }
.train-guidance { margin: 14px 0; padding: 14px; border: 1px solid var(--bordure, #777); border-radius: 10px; }
.train-guidance .consigne-depart { font-weight: 700; margin: 10px 0; }
