/* =====================================================================
   HomeShopping — feuille de style unique.
   Sections : 1. Reset · 2. Tokens · 3. Gabarit · 4. Composants · 5. Desktop
   Mobile first : on écrit pour petit écran, on élargit en section 5.
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. Reset
   --------------------------------------------------------------------- */

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

* {
  margin: 0;
}

/* La page elle-même ne défile jamais — seul .app__main défile. C'est la
   condition pour qu'iOS ne fasse pas glisser tout l'écran quand le clavier
   s'ouvre : sans document à faire défiler, il ne reste que le décalage de la
   zone visible, que trackKeyboard (app.js) annule. */
html,
body {
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

html {
  -webkit-text-size-adjust: 100%; /* iOS : pas de redimensionnement auto du texte */
}

body {
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;

  /* Plus de zoom au double-tap : le second tap est traité comme un clic
     immédiat, comme dans une app native. Posé sur <body>, cela vaut pour tout
     le contenu — le navigateur croise la valeur avec celle des ancêtres.
     `manipulation` conserve le défilement et le zoom au pincement. */
  touch-action: manipulation;
}

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

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

/* iOS zoome sur les champs dont la police fait moins de 16px. */
input,
textarea,
select {
  font-size: max(1rem, 16px);
}

button {
  background: none;
  border: 0;
  cursor: pointer;
  touch-action: manipulation; /* redit ici : c'est sur les boutons qu'on tape vite */
  -webkit-tap-highlight-color: transparent;
}

p,
h1,
h2,
h3,
h4 {
  overflow-wrap: break-word;
}

ul[role='list'],
ol[role='list'] {
  list-style: none;
  padding: 0;
}

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

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

/* ---------------------------------------------------------------------
   2. Tokens — aucune couleur en dur ailleurs que dans ce bloc
   --------------------------------------------------------------------- */

:root {
  /* Thème clair uniquement, quel que soit le réglage du système : les
     contrôles du navigateur (cases à cocher, roulettes, ascenseurs) suivent. */
  color-scheme: light;

  /* Couleurs — fond ambre. Accent : terracotta. */
  --color-bg: #fdf5e8;
  --color-surface: #fffcf6;
  --color-surface-alt: #f6ead6;
  --color-border: #ecdcc3;
  --color-text: #251c14;
  --color-text-muted: #7d6c58;
  --color-accent: #b0522e;
  --color-accent-soft: #f8e2d6;
  --color-accent-contrast: #ffffff;
  /* Orange chaud, plus clair que l'accent : pour les états positifs (un repas
     retenu au menu). Le terracotta foncé, lui, tire sur le rouge et se lit
     comme une alerte. */
  --color-warm: #d9773f;
  --color-warm-soft: #fdead9;
  --color-danger: #a81f2d;
  --color-overlay: rgb(40 27 16 / 0.35); /* fond des modales */

  /* Typographie */
  --font-sans:
    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
    sans-serif;
  --text-xs: 0.8125rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.5rem;

  /* Espacements */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;

  /* Formes */
  --radius-sm: 0.5rem;
  --radius-md: 0.875rem;
  --radius-full: 999px;
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.05);
  --shadow-up: 0 -1px 12px rgb(0 0 0 / 0.04);
  /* Éléments qui flottent au-dessus du reste (suggestions, modale) : ombre
     symétrique, pour qu'elle tienne au-dessus comme en dessous. */
  --shadow-pop: 0 2px 24px rgb(0 0 0 / 0.14);

  /* Gabarit */
  --content-max: 40rem;
  --tap-target: 2.75rem; /* 44px */
  --header-height: 3.75rem;
  --nav-height: 3.5rem;

  /* Zones sûres iPhone (encoche, barre d'accueil) */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

/* ---------------------------------------------------------------------
   3. Gabarit
   Mobile : titre · contenu · saisie · navigation basse.
   --------------------------------------------------------------------- */

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  background: var(--color-bg);
  color: var(--color-text);
}

/* Coquille figée à la hauteur de l'écran : seul .app__main défile. C'est ce
   qui garde la saisie et la navigation en place quand la liste est longue.
   `fixed` : elle ne dépend plus du défilement du document, elle se recale sur
   la zone visible (voir --app-height / --app-offset). */
.app {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  /* minmax(0, 1fr) : sans ça, la colonne s'élargit au min-content des
     champs de saisie et la page déborde horizontalement sur iPhone. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    'header'
    'main'
    'composer'
    'nav';
  /* Clavier ouvert, la coquille se replie sur la zone visible : la barre de
     saisie remonte au ras des touches sans que la page entière défile. */
  height: var(--app-height, 100dvh);
  /* iOS fait glisser l'écran vers le haut pour dégager le champ, qu'on le lui
     demande ou non. On replace la coquille au ras de la zone restée visible :
     vu de l'écran, rien n'a bougé. Inconditionnel, comme --app-height : la
     mise en page ne doit dépendre d'aucune détection de clavier. */
  transform: translateY(var(--app-offset, 0px));
}

.app__header {
  grid-area: header;
  display: flex;
  align-items: center;
  min-height: var(--header-height);
  padding: var(--space-3) var(--space-4);
  padding-top: calc(var(--space-3) + var(--safe-top));
  padding-left: calc(var(--space-4) + var(--safe-left));
  padding-right: calc(var(--space-4) + var(--safe-right));
}

.app__heading {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
}

.app__titles {
  flex: 1;
  min-width: 0;
}

.app__back {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--tap-target);
  block-size: var(--tap-target);
  margin-left: calc(var(--space-3) * -1);
  border-radius: 50%;
  font-size: var(--text-xl);
  line-height: 1;
  color: var(--color-text);
}

.app__back[hidden] {
  display: none;
}

/* Boutons d'en-tête (rechargement, ajustement des quantités, duplication).
   Discrets : ce sont des outils, pas les actions principales de l'écran. */
.app__action {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--tap-target);
  block-size: var(--tap-target);
  /* Ils ne s'affichent jamais ensemble : chacun peut mordre sur la
     marge droite du header. */
  margin-right: calc(var(--space-2) * -1);
  border-radius: 50%;
  font-size: var(--text-lg);
  line-height: 1;
  color: var(--color-text-muted);
}

.app__action[hidden] {
  display: none;
}

.app__action:hover {
  background: var(--color-surface-alt);
  color: var(--color-text);
}

/* En cours d'ajustement : la coche est l'action qui enregistre, elle se voit. */
.app__action.is-active {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
}

/* Le réseau peut prendre une seconde en 4G : il faut voir qu'il se passe
   quelque chose avant que la page ne reparte. */
#reload-button:disabled {
  color: var(--color-accent);
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}

@media (prefers-reduced-motion: reduce) {
  #reload-button:disabled {
    animation: none;
    opacity: 0.5;
  }
}

.app__title {
  font-size: var(--text-xl);
  font-weight: 650;
  letter-spacing: -0.02em;
}

.app__title[hidden] {
  display: none;
}

/* Titre éditable : se fond dans le header jusqu'au focus. */
.app__title--input {
  width: 100%;
  padding: 0 var(--space-2);
  margin-left: calc(var(--space-2) * -1);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
}

.app__title--input:focus {
  outline: none;
  background: var(--color-surface);
  border-color: var(--color-border);
}

.app__subtitle {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.app__main {
  grid-area: main;
  overflow-y: auto;
  /* Le geste de retour fait glisser la page vers la droite : elle se coupe au
     bord de l'écran au lieu d'y ajouter une barre de défilement. */
  overflow-x: hidden;
  overscroll-behavior: contain;
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding: 0 var(--space-4) var(--space-5);
  padding-left: calc(var(--space-4) + var(--safe-left));
  padding-right: calc(var(--space-4) + var(--safe-right));
}

.app__nav {
  grid-area: nav;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  padding-bottom: var(--safe-bottom);
}

/* Clavier ouvert, la navigation s'efface : on ne peut pas s'en servir sans
   fermer le clavier, et elle mangerait la place au-dessus des touches. */
.has-keyboard .app__nav {
  display: none;
}

/* Icône seule, largement entourée de vide : la cible tactile occupe toute la
   colonne, et la barre respire. */
.nav-item {
  display: grid;
  place-items: center;
  min-height: var(--nav-height);
  padding: var(--space-3) var(--space-2);
  color: var(--color-text-muted);
  transition: color 0.15s ease;
}

.nav-item.is-active {
  color: var(--color-accent);
}

/* ---------------------------------------------------------------------
   4. Composants
   --------------------------------------------------------------------- */

/* Saisie rapide — collée au pouce sur mobile, juste au-dessus de la nav. */

.composer {
  grid-area: composer;
  position: relative; /* ancre la liste de suggestions */
  display: flex;
  gap: var(--space-2);
  align-items: center;
  padding: var(--space-3) var(--space-4);
  padding-left: calc(var(--space-4) + var(--safe-left));
  padding-right: calc(var(--space-4) + var(--safe-right));
  background: var(--color-bg);
  border-top: 1px solid var(--color-border);
  box-shadow: var(--shadow-up);
}

.composer[hidden] {
  display: none;
}

.composer__input {
  flex: 1;
  min-width: 0;
  min-height: var(--tap-target);
  padding: 0 var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
}

.composer__input::placeholder {
  color: var(--color-text-muted);
}

.composer__input:focus {
  outline: none;
  border-color: var(--color-accent);
}

.composer__submit {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--tap-target);
  block-size: var(--tap-target);
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-size: var(--text-xl);
  line-height: 1;
  transition: opacity 0.15s ease;
}

.composer__submit:disabled {
  opacity: 0.35;
  cursor: default;
}

/* Autocomplétion — sur mobile la liste sort vers le haut, sinon le clavier
   iOS la recouvrirait. Elle repasse en dessous sur desktop (section 5). */

.suggestions {
  position: absolute;
  bottom: calc(100% - var(--space-2));
  left: calc(var(--space-4) + var(--safe-left));
  right: calc(var(--space-4) + var(--safe-right));
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: 1px;
  /* Jamais plus haute que la place laissée par le clavier : sur petit écran
     elle passerait par-dessus l'en-tête. Le retrait couvre l'en-tête, la
     barre de saisie elle-même et une marge de respiration. */
  max-height: min(15rem, calc(var(--app-height, 100dvh) - var(--header-height) - 5.5rem));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-1);
  list-style: none;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
}

.suggestions[hidden] {
  display: none;
}

/* Dans la liste des ingrédients, les propositions descendent sous le champ :
   il y a de la place en dessous, et le clavier est encore plus bas. */
.suggestions--below {
  top: calc(100% - var(--space-1));
  bottom: auto;
  left: 0;
  right: 0;
}

.suggestion {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--tap-target);
  padding-inline: var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.suggestion.is-active,
.suggestion:hover {
  background: var(--color-surface-alt);
}

.suggestion__name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.suggestion__aisle {
  flex: none;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* Liste d'articles */

.items {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

.item__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Renommage en place : le champ se fond dans la ligne jusqu'au focus.
   width:0 + flex:1 pour que l'input n'impose pas sa largeur intrinsèque. */
.item__name--editable {
  width: 0;
  padding: var(--space-1) var(--space-2);
  margin-left: calc(var(--space-2) * -1);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
}

.item__name--editable:focus {
  outline: none;
  background: var(--color-bg);
  border-color: var(--color-border);
}

/* Réordonnancement à la poignée (rayons) : l'ordre des lignes est l'ordre de
   parcours du magasin, on le règle en glissant. */

/* La poignée prend la place du retrait gauche habituel. */
.item--sortable {
  padding-left: var(--space-2);
}

.item__grip {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  inline-size: 1.75rem;
  block-size: 2.25rem;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  cursor: grab;
  /* Sans ça, le glissement du doigt ferait défiler la page au lieu de
     déplacer la ligne. */
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Les six points sont dessinés en segments de longueur nulle : c'est le trait
   qui fait leur diamètre, d'où cette épaisseur inhabituelle. */
.item__grip svg {
  stroke-width: 3;
}

/* Même parti pris que .chip__select : zone tactile de 44 px sans grossir. */
.item__grip::after {
  content: '';
  position: absolute;
  inset: -0.25rem -0.5rem;
}

.item__grip:hover {
  background: var(--color-surface-alt);
  color: var(--color-text);
}

/* La ligne saisie flotte au-dessus des autres et suit le pointeur. */
.item.is-dragging {
  position: relative;
  z-index: 2;
  border-color: var(--color-accent);
  box-shadow: var(--shadow-pop);
}

.item.is-dragging .item__grip {
  cursor: grabbing;
}

/* Pendant le glissement, plus rien d'autre ne se sélectionne. */
body.is-reordering {
  cursor: grabbing;
  -webkit-user-select: none;
  user-select: none;
}

/* Ligne entière cliquable (recettes). */
.item__open {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--tap-target);
  text-align: left;
}

/* Repas au menu : la ligne se détache franchement des repas non retenus —
   c'est le seul état à lire d'un coup d'œil sur cet écran. Orange chaud et
   nom en texte plein : retenir un plat est une bonne nouvelle, pas une
   suppression. */
.item.is-picked {
  background: var(--color-warm-soft);
  border-color: var(--color-warm);
}

.item.is-picked .item__name {
  font-weight: 600;
}

/* Sur fond d'accent, le compteur a besoin de son propre fond pour rester net. */
.item.is-picked .stepper {
  background: var(--color-surface);
}

/* Ramenée à zéro, une ligne ne s'évapore pas sous le doigt : elle s'efface et
   ne part qu'au bout de deux secondes. La transparence annonce le départ ; le
   « + » le rattrape, et reste assez lisible pour être visé. */
.item.is-leaving {
  opacity: 0.5;
  box-shadow: none;
}

/* Pastille de sélection : libellé visible à la largeur de la valeur courante,
   avec un <select> natif transparent par-dessus. Sur iPhone, la roulette iOS
   s'ouvre normalement — aucun clavier, aucun picker maison. */
.chip {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  max-width: 9rem;
  min-height: 1.75rem;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  background: var(--color-accent-soft);
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: 500;
}

.chip__label {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.chip__select {
  position: absolute;
  /* Débordement vertical : la zone tactile atteint 44 px sans grossir la
     pastille. */
  top: -0.5rem;
  bottom: -0.5rem;
  left: 0;
  right: 0;
  width: 100%;
  appearance: none;
  border: 0;
  background: none;
  opacity: 0;
}

/* Tant qu'aucun rayon n'est choisi, la pastille reste discrète. */
.chip[data-empty] {
  background: none;
  color: var(--color-text-muted);
  font-weight: 400;
}

/* Sélecteur de quantité — remplace la croix de suppression : à 1, le « − »
   supprime la ligne. C'est le geste le plus répété de l'app, il vise large. */
.stepper {
  flex: none;
  display: inline-grid;
  grid-auto-flow: column;
  align-items: center;
  background: var(--color-surface-alt);
  border-radius: var(--radius-full);
}

.stepper__button {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  border-radius: 50%;
  color: var(--color-text-muted);
  font-size: var(--text-xl);
  line-height: 1;
}

/* Le petit reste à déborder pour atteindre les 44 px réglementaires. */
.stepper__button::after {
  content: '';
  position: absolute;
  inset: -0.125rem 0;
}

.stepper__button:hover {
  color: var(--color-text);
}

/* À 1, ce bouton supprime : on l'annonce par la couleur. */
.stepper__button[data-role='remove']:hover {
  color: var(--color-danger);
}

/* Déjà à zéro : plus rien à retirer. */
.stepper__button:disabled {
  opacity: 0.3;
  cursor: default;
}

.stepper__button:disabled:hover {
  color: var(--color-text-muted);
}

.stepper__value {
  min-inline-size: 1.5rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.item__remove {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--tap-target);
  block-size: var(--tap-target);
  border-radius: 50%;
  color: var(--color-text-muted);
  font-size: var(--text-lg);
  line-height: 1;
}

.item__remove:hover {
  color: var(--color-danger);
  background: var(--color-surface-alt);
}

/* Sous-navigation du garde-manger */

.segmented {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--space-1);
  padding: var(--space-1);
  margin-bottom: var(--space-4);
  background: var(--color-surface-alt);
  border-radius: var(--radius-full);
}

.segment {
  min-height: 2.25rem;
  padding-inline: var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  transition: background 0.15s ease, color 0.15s ease;
}

.segment.is-active {
  background: var(--color-surface);
  color: var(--color-accent);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

/* Groupe de produits sous un rayon */

.group + .group {
  margin-top: var(--space-5);
}

.group__title {
  padding: 0 var(--space-2) var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* Produits sans rayon : en tête et sur fond d'accent. Faute de rayon, ils
   tombent en fin de liste de courses, dans un groupe du même nom — c'est la
   seule chose à corriger dans cet onglet, elle doit sauter aux yeux. */
.group--todo {
  padding: var(--space-3) var(--space-2);
  background: var(--color-accent-soft);
  border-radius: var(--radius-md);
}

.group--todo .group__title {
  padding-bottom: var(--space-1);
  color: var(--color-accent);
}

.group__hint {
  padding: 0 var(--space-2) var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  line-height: 1.5;
}

/* Ici, choisir un rayon est l'action attendue : la pastille vide se voit. */
.group--todo .chip[data-empty] {
  border: 1px dashed var(--color-accent);
  color: var(--color-accent);
}

/* Ingrédients « à confirmer » : la section coiffe la liste de courses, qui
   n'est pas un groupe frère — d'où l'écart posé ici. */
.group--pending {
  margin-bottom: var(--space-5);
}

.group--pending[hidden] {
  display: none;
}

/* Oui / non d'un ingrédient à confirmer. Pas de survol pour les départager sur
   iPhone : chacun porte sa couleur au repos. */
.decide {
  flex: none;
  display: flex;
  gap: var(--space-1);
}

.decide__button {
  display: grid;
  place-items: center;
  inline-size: var(--tap-target);
  block-size: var(--tap-target);
  background: var(--color-surface);
  border: 1px solid currentcolor;
  border-radius: 50%;
}

.decide__button--yes {
  color: var(--color-warm);
}

.decide__button--no {
  color: var(--color-danger);
}

.decide__button:hover {
  background: currentcolor;
}

.decide__button:hover svg {
  stroke: var(--color-accent-contrast);
}

/* Liste de courses : lignes à cocher */

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.toolbar[hidden] {
  display: none;
}

.toolbar__count {
  flex: none;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* Toute la ligne est cliquable : en magasin, on vise large. */
.pick {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--tap-target);
  cursor: pointer;
}

.item:has(.pick) {
  padding-right: var(--space-4);
}

.pick__box {
  flex: none;
  inline-size: 1.375rem;
  block-size: 1.375rem;
  accent-color: var(--color-accent);
}

/* Nom sur la 1re ligne, recettes d'origine en dessous. */
.item__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
}

.item__text .item__name {
  flex: none;
}

.item__sources {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}

.item__amount {
  flex: none;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

/* Pris : la ligne se met en retrait, mais la coche reste franche. */
.item.is-checked {
  background: var(--color-bg);
  box-shadow: none;
}

.item.is-checked .item__name,
.item.is-checked .item__amount {
  color: var(--color-text-muted);
  text-decoration: line-through;
}

.item.is-checked .item__sources {
  opacity: 0.6;
}

/* Ajustement des quantités.
   Une ligne réglée à la main ne vient plus du calcul : elle se signale, en
   édition comme dans la liste normale. Ramenée à zéro, elle vire au rouge
   barré : à la validation, elle quittera la liste pour de bon. */
.item.is-tuned {
  border-color: var(--color-accent);
}

.item.is-tuned .item__amount {
  color: var(--color-accent);
  font-weight: 600;
}

.item.is-removed {
  background: var(--color-bg);
  border-color: var(--color-danger);
  box-shadow: none;
}

.item.is-removed .item__name,
.item.is-removed .item__amount {
  color: var(--color-danger);
  text-decoration: line-through;
}

.item.is-removed .item__sources {
  opacity: 0.6;
}

/* Bandeau de rappel du mode édition, juste au-dessus de la liste. */
.hint--banner {
  padding: var(--space-3);
  margin-bottom: var(--space-3);
  background: var(--color-accent-soft);
  border-radius: var(--radius-md);
  color: var(--color-accent);
}

.hint--banner[hidden] {
  display: none;
}

/* Ingrédients d'une recette : produit sur la 1re ligne, mesure sur la 2e. */

.ingredients {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.ingredient {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-2);
  align-items: center;
  padding: var(--space-2) var(--space-2) var(--space-3) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

/* Le champ porte sa liste de propositions : c'est lui qui l'ancre. */
.ingredient__field {
  position: relative;
  display: flex;
  min-width: 0;
}

/* Le nom se tape à la main, comme un renommage en place : le champ se fond
   dans la ligne jusqu'au focus. */
.ingredient__product {
  width: 100%;
  min-width: 0;
  appearance: none;
  padding: var(--space-1) var(--space-2);
  margin-left: calc(var(--space-2) * -1);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  font-weight: 500;
  text-overflow: ellipsis;
}

.ingredient__product:focus {
  outline: none;
  background: var(--color-bg);
  border-color: var(--color-border);
}

.ingredient__measure {
  grid-column: 1 / -1;
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

.ingredient__quantity {
  inline-size: 5rem;
  min-height: var(--tap-target);
  padding-inline: var(--space-3);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.ingredient__unit {
  min-height: var(--tap-target);
  appearance: none;
  padding-inline: var(--space-3);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
}

/* « À confirmer » : produit qu'on n'achète pas à chaque fois. Éteint, l'état
   normal, le bouton reste discret ; allumé, il prend l'accent. */
.ingredient__toggle {
  margin-left: auto;
  min-height: var(--tap-target);
  padding-inline: var(--space-3);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.ingredient__toggle[aria-pressed='true'] {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
  color: var(--color-accent);
  font-weight: 600;
}

.ingredient__quantity:focus,
.ingredient__unit:focus {
  outline: none;
  border-color: var(--color-accent);
}

/* Boutons */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--tap-target);
  padding-inline: var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-size: var(--text-sm);
  font-weight: 600;
}

/* Action secondaire pleine, sans la charge visuelle de l'accent. */
.button--soft {
  background: var(--color-accent-soft);
  color: var(--color-accent);
}

/* Confirmation d'une suppression : la couleur dit ce qui va se passer. */
.button--danger {
  background: var(--color-danger);
  color: var(--color-accent-contrast);
}

.button:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Modale de confirmation */

.dialog {
  width: min(24rem, calc(100vw - 2 * var(--space-5)));
  margin: auto;
  padding: 0;
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
}

.dialog::backdrop {
  background: var(--color-overlay);
}

.dialog__panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
}

.dialog__title {
  font-size: var(--text-lg);
  font-weight: 650;
  letter-spacing: -0.01em;
}

.dialog__message {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  line-height: 1.6;
}

.dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

/* Textes secondaires */

.empty {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  line-height: 1.7;
}

.hint {
  padding-top: var(--space-3);
  text-align: center;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* ---------------------------------------------------------------------
   5. Desktop / tablette
   La navigation remonte dans le header, la saisie passe au-dessus de la liste.
   --------------------------------------------------------------------- */

@media (min-width: 48rem) {
  .app {
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      'header nav'
      'composer composer'
      'main main';
  }

  /* Header et nav occupent la même rangée : la bordure les relie en une
     seule barre d'application qui court sur toute la largeur. */
  .app__header,
  .app__nav {
    border-bottom: 1px solid var(--color-border);
  }

  .app__header {
    padding-right: var(--space-2);
  }

  /* La navigation est juste à côté : le bouton reprend sa marge. */
  .app__action {
    margin-right: 0;
  }

  .app__heading {
    margin-inline: 0;
    max-width: none;
  }

  .app__nav {
    grid-auto-columns: auto;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-3) var(--space-4) var(--space-3) 0;
    padding-top: calc(var(--space-3) + var(--safe-top));
    padding-right: calc(var(--space-4) + var(--safe-right));
    background: none;
    border-top: 0;
  }

  /* Ici la navigation est dans la barre du haut : un clavier logiciel de
     tablette ne la gêne pas, elle reste. */
  .has-keyboard .app__nav {
    display: grid;
  }

  .nav-item {
    min-height: var(--tap-target);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
  }

  .nav-item:hover:not(.is-active) {
    background: var(--color-surface-alt);
    color: var(--color-text);
  }

  .composer {
    width: 100%;
    max-width: var(--content-max);
    margin-inline: auto;
    padding-block: var(--space-2) var(--space-4);
    background: none;
    border-top: 0;
    box-shadow: none;
  }

  .app__main {
    padding-bottom: var(--space-6);
  }

  /* La saisie est ici au-dessus de la liste : ses suggestions descendent.
     Celles d'un ingrédient descendent déjà, on ne les vise pas. */
  .composer .suggestions {
    top: calc(100% - var(--space-3));
    bottom: auto;
  }

  /* Assez large pour tout mettre sur une seule ligne. */
  .ingredient {
    grid-template-columns: minmax(0, 1fr) auto auto;
    padding-bottom: var(--space-2);
  }

  /* Ligne et colonne explicites : l'ordre du DOM (produit, ×, mesure) ne
     correspond pas à l'ordre visuel voulu (produit, mesure, ×). */
  .ingredient__field {
    grid-area: 1 / 1;
  }

  .ingredient__measure {
    grid-area: 1 / 2;
  }

  .ingredient .item__remove {
    grid-area: 1 / 3;
  }

  /* Au pointeur, la suppression ne se révèle qu'au survol de la ligne.
     Sur mobile elle reste visible : il n'y a pas de survol. */
  .item .item__remove,
  .ingredient .item__remove {
    opacity: 0;
    transition: opacity 0.15s ease;
  }

  .item:hover .item__remove,
  .ingredient:hover .item__remove,
  .item__remove:focus-visible {
    opacity: 1;
  }
}
