/*
 * Feuille de style du socle. Bootstrap fait l'essentiel : on ne surcharge que
 * ce qui appartient en propre au foyer, à commencer par la couleur de compte
 * qui sert à savoir d'un coup d'oeil si l'autre est déjà passé (section 04).
 */

:root {
    --foyer-aubergine: #5b2c6f;
    --foyer-cresson: #4f7942;
}

body {
    -webkit-text-size-adjust: 100%;
}

/* Pastille de couleur d'un compte, dans la barre de navigation. */
.pastille-compte {
    display: inline-block;
    width: 0.9rem;
    height: 0.9rem;
    border-radius: 50%;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}

/*
 * La pastille de catégorie d'un plat, dans le planning.
 *
 * Plus petite que celle d'un compte : elle vit contre un titre, dans une case
 * de tableau, et il y en a une par plat sur une semaine entière. Le liseré
 * intérieur la détache d'un fond clair comme d'un fond foncé, sans quoi une
 * catégorie de couleur pâle disparaîtrait.
 *
 * La couleur ne porte aucune information à elle seule : le gabarit met le
 * libellé en `title` et en `aria-label`. Un daltonien, et un lecteur d'écran,
 * lisent « Poisson » là où l'on voit du bleu.
 */
.pastille-categorie {
    display: inline-block;
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
    vertical-align: 0.05rem;
    margin-right: 0.15rem;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
}

/* Tuile de module sur l'écran d'accueil (maquette M8). */
.tuile-module {
    color: inherit;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.tuile-module:hover,
.tuile-module:focus-visible {
    transform: translateY(-2px);
}

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

    .tuile-module:hover,
    .tuile-module:focus-visible {
        transform: none;
    }
}

/*
 * Le tableau du planning, maquette M1.
 *
 * Un liseré coloré à gauche de chaque créneau dit son état sans qu'on ait à
 * lire : vide, ouvert, proposé, validé, ou repas particulier.
 */
.creneau {
    border-left: 3px solid var(--bs-border-color);
    padding: 0.35rem 0.5rem;
    border-radius: 0.25rem;
    background-color: var(--bs-tertiary-bg);
    cursor: pointer;
    display: block;
    min-height: 3.2rem;
}

.creneau:hover,
.creneau:focus-visible {
    background-color: var(--bs-secondary-bg);
}

.creneau-moment {
    display: block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bs-secondary-color);
}

.creneau-plat {
    display: block;
    font-size: 0.85rem;
    line-height: 1.25;
    margin-top: 0.15rem;
}

.creneau-vide-texte {
    display: block;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
    margin-top: 0.15rem;
}

.creneau-vide { border-left-color: var(--bs-border-color); }
.creneau-ouvert { border-left-color: var(--bs-warning); }
.creneau-propose { border-left-color: var(--bs-info); border-left-style: dashed; }
.creneau-valide { border-left-color: var(--bs-success); }
.creneau-particulier { border-left-color: var(--bs-purple, #6f42c1); }

/* Liste des recettes dans le panneau de saisie. */
.liste-recettes {
    max-height: 16rem;
    overflow-y: auto;
}

.liste-recettes button {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    background: none;
    padding: 0.4rem 0.5rem;
    border-radius: 0.25rem;
}

.liste-recettes button:hover,
.liste-recettes button:focus-visible {
    background-color: var(--bs-secondary-bg);
}

/* Sept colonnes sur écran large : Bootstrap s'arrête à six. */
@media (min-width: 768px) {
    .row-cols-md-7 > * {
        flex: 0 0 auto;
        width: 14.2857%;
    }
}

/*
 * Liste de courses : une ligne déjà prise (FN-36).
 *
 * Barrée mais toujours visible, exigence de la maquette M6 : on veut pouvoir
 * vérifier qu'on a bien pris ce qu'on croit avoir pris, sans que la ligne
 * disparaisse du regroupement par rayon.
 */
.ligne-cochee {
    background-color: var(--bs-tertiary-bg);
}

.ligne-cochee input[data-champ="libelle"],
.ligne-cochee input[data-champ="quantite"],
.ligne-cochee input[data-champ="unite"] {
    text-decoration: line-through;
    opacity: 0.6;
}

/*
 * Liste de courses : une ligne, deux presentations, un seul balisage.
 *
 * CE QUI EST ILLISIBLE, ET POURQUOI.
 *
 * Une ligne est une rangee de huit commandes : coche, quantite, unite,
 * libelle, lieu, rayon, pastilles, suppression. Les largeurs reunies
 * demandent environ 48rem. Sur un telephone de 375 pixels il reste 21rem,
 * donc `flex-wrap` empile trois rangees de champs SANS ETIQUETTE, quarante
 * fois de suite. C'est correct au clavier et impraticable au pouce, alors
 * que l'usage reel sur mobile est la relecture avant de partir.
 *
 * LE SEUIL EST CELUI DE BOOTSTRAP, ET CE N'EST PAS UN HASARD.
 *
 * 768 pixels valent 48rem : exactement ce que la rangee demande pour tenir
 * sur une ligne. Le point de rupture du cadre est donc aussi celui du
 * contenu, et il n'y a aucun nombre invente a maintenir.
 *
 * CE QUI EST DEPLACE, ET CE QUI NE L'EST PAS.
 *
 * Rien n'est deplace dans le gabarit : `order` reordonne a l'affichage. Le
 * groupement par lieu puis par rayon est intact, c'est l'ordre du magasin et
 * c'est lui qui rend la liste parcourable. Le detail du calcul reste replie
 * sous la carte, il ne disparait pas.
 *
 * CE QUE CELA COUTE, ET QUI EST ASSUME.
 *
 * `order` change l'ordre VU, jamais l'ordre de tabulation ni celui que lit
 * un lecteur d'ecran. Sur mobile, la coche se voit en bas et se tabule en
 * premier. L'ordre du balisage suit donc l'ecran large, ou l'on edite au
 * clavier et ou la tabulation compte ; le telephone, lui, sert a relire.
 */
/*
 * TOUTES CES REGLES SONT PORTEES PAR `.ligne-corps`, ET C'EST OBLIGATOIRE.
 *
 * `data-champ="libelle"`, `"quantite"`, `"unite"` et `"rayon_id"` vivent
 * aussi sur les ingredients, les listes types, la fiche recette, les
 * referentiels et le calendrier des saisons. Une regle non portee y changerait
 * les largeurs sans que personne l'ait demande, sur cinq ecrans que cette
 * etape ne doit pas toucher.
 */
.ligne-corps input[data-champ="quantite"] { width: 6rem; }
.ligne-corps input[data-champ="unite"] { width: 5rem; }
.ligne-corps input[data-champ="libelle"] { min-width: 12rem; flex: 1 1 auto; }
.ligne-corps select[data-champ="lieu_id"],
.ligne-corps select[data-champ="rayon_id"] { width: 11rem; }

@media (max-width: 767.98px) {
    .ligne-corps {
        row-gap: 0.4rem;
    }

    /* Ce qu'on vient verifier, en premier et a bout de bras. */
    .ligne-corps input[data-champ="libelle"] {
        order: 1;
        flex: 1 0 100%;
        min-width: 0;
        font-size: 1.05rem;
        font-weight: 500;
    }

    .ligne-corps input[data-champ="quantite"] {
        order: 2;
        width: auto;
        flex: 0 0 5.5rem;
        font-size: 1.05rem;
    }

    .ligne-corps input[data-champ="unite"] {
        order: 3;
        width: auto;
        flex: 1 1 6rem;
        font-size: 1.05rem;
    }

    /* Le rangement : present, plus discret, deux par rangee. */
    .ligne-corps select[data-champ="lieu_id"],
    .ligne-corps select[data-champ="rayon_id"] {
        order: 4;
        width: auto;
        flex: 1 1 40%;
        font-size: 0.8125rem;
        color: var(--bs-secondary-color);
    }

    .ligne-corps .badge {
        order: 5;
    }

    /* Les actions en bas, la coche a portee de pouce et loin du reste. */
    .ligne-corps input[data-action="cocher"] {
        order: 6;
        width: 1.35rem;
        height: 1.35rem;
    }

    .ligne-corps button[data-action="supprimer-ligne"] {
        order: 7;
        margin-left: auto;
    }

    /*
     * Le bouton du samedi matin, pleine largeur.
     *
     * C'est le seul geste qu'on vient faire depuis le téléphone une fois la
     * liste relue. Vise par l'adresse plutôt que par une classe : il n'y a
     * qu'un lien vers le mode magasin sur cet écran, et l'adresse le dit
     * mieux qu'un nom de classe à inventer.
     */
    a[href^="/menus/courses/magasin"] {
        flex: 1 0 100%;
    }
}

/*
 * Mode magasin, maquette M6.
 *
 * Trois règles fixées par la maquette et non négociables :
 * zone de touche d'au moins 44 pixels de haut sur toute la largeur,
 * ligne prise barrée mais visible, aucune action destructive à portée de
 * pouce. Tout le reste de cette section n'est que la mise en œuvre.
 */
body.magasin {
    background-color: var(--bs-body-bg);
    padding-bottom: 4rem;
}

.magasin-tete {
    position: sticky;
    top: 0;
    z-index: 3;
    background-color: var(--bs-body-bg);
    border-bottom: 1px solid var(--bs-border-color);
    padding-top: env(safe-area-inset-top);
}

.magasin-onglets {
    display: flex;
    gap: 0.35rem;
    overflow-x: auto;
    scrollbar-width: none;
}

.magasin-onglets::-webkit-scrollbar {
    display: none;
}

.magasin-onglet {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0.4rem 0.8rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 999px;
    background-color: var(--bs-body-bg);
    font-size: 0.95rem;
    white-space: nowrap;
}

.magasin-onglet.actif {
    background-color: var(--foyer-aubergine);
    border-color: var(--foyer-aubergine);
    color: #fff;
}

.magasin-onglet.clos {
    text-decoration: line-through;
    opacity: 0.65;
}

.magasin-compte {
    display: inline-block;
    margin-left: 0.35rem;
    font-variant-numeric: tabular-nums;
    opacity: 0.75;
}

.magasin-rayon {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color);
    background-color: var(--bs-tertiary-bg);
    margin: 0;
    padding: 0.4rem 1rem;
    position: sticky;
    top: 0;
    z-index: 1;
}

/*
 * La ligne entière est le bouton. Viser une case de 20 pixels en marchant
 * avec un chariot ne marche pas ; viser la ligne, si.
 */
.magasin-ligne {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    min-height: 56px;
    padding: 0.6rem 1rem;
    border: 0;
    border-bottom: 1px solid var(--bs-border-color);
    background-color: transparent;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}

.magasin-ligne:active {
    background-color: var(--bs-secondary-bg);
}

.magasin-case {
    flex: 0 0 auto;
    width: 1.5rem;
    height: 1.5rem;
    border: 2px solid var(--bs-border-color);
    border-radius: 0.35rem;
}

.magasin-ligne.prise .magasin-case {
    background-color: var(--foyer-cresson);
    border-color: var(--foyer-cresson);
}

.magasin-texte {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
    line-height: 1.3;
}

.magasin-quantite {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.magasin-quantite:empty {
    display: none;
}

/* Barrée, jamais masquée : on revient en arrière tout le temps. */
.magasin-ligne.prise .magasin-quantite,
.magasin-ligne.prise .magasin-libelle {
    text-decoration: line-through;
    opacity: 0.55;
}

.magasin-mention {
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
}

.magasin-mention:empty {
    display: none;
}

.magasin-mention.alerte {
    color: var(--bs-warning-text-emphasis);
    background-color: var(--bs-warning-bg-subtle);
    border-radius: 0.25rem;
    padding: 0 0.35rem;
    text-decoration: none;
    opacity: 1;
}

.magasin-pied {
    padding: 1.25rem 1rem calc(1.5rem + env(safe-area-inset-bottom));
}

.magasin-bouton {
    min-height: 48px;
}

/* Repas reporté (FN-07) et case en cours de déplacement (FN-08). */
.creneau-reporte {
    display: inline-block;
    margin-left: 0.25rem;
    padding: 0 0.25rem;
    border-radius: 0.2rem;
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
    text-transform: none;
    letter-spacing: 0;
}

.creneau.en-deplacement {
    opacity: 0.4;
}

.creneau.cible-deplacement {
    outline: 2px dashed var(--foyer-aubergine);
    outline-offset: 1px;
}

/*
 * Plat déjà servi trop récemment (FN-09).
 *
 * Un signal, pas une interdiction : il se lit d'un coup d'œil et ne bloque
 * rien. Servir deux fois la même chose dans la semaine est une décision.
 */
.creneau-repetition {
    display: inline-block;
    font-size: 0.7rem;
    padding: 0 0.25rem;
    border-radius: 0.2rem;
    background-color: var(--bs-info-bg-subtle);
    color: var(--bs-info-text-emphasis);
}

/*
 * « Cet écran n'a pas démarré » (B125).
 *
 * Rendu par le serveur sur toutes les pages, retiré par app.js au
 * chargement. S'il se voit, c'est que le JavaScript n'a jamais commencé :
 * une politique de sécurité qui refuse un script, un fichier absent, une
 * erreur de syntaxe. C'est le seul garde-fou possible pour ce cas, parce
 * qu'il ne demande rien au code qui a échoué.
 */
.js-absent {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1080;
    margin: 0;
    padding: 0.6rem 1rem calc(0.6rem + env(safe-area-inset-bottom));
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
    border-top: 2px solid var(--bs-warning-border-subtle);
    font-size: 0.9rem;
}

/*
 * UN TABLEAU LARGE DÉFILE DANS SON CADRE. TROISIÈME TENTATIVE, ET LA CAUSE
 * N'ÉTAIT AUCUNE DES DEUX PREMIÈRES.
 *
 * CE QUI EMPÊCHAIT DE DÉFILER, ET QUI EST ÉCRIT DANS BOOTSTRAP.
 *
 * `.table` porte `width: 100%`. `.table-responsive` porte `overflow-x: auto`
 * et fait exactement la largeur de son parent. Le cadre dit donc au tableau
 * « tu fais ma largeur », et un tableau qui fait la largeur de son cadre ne
 * déborde pas — il n'y a rien à faire défiler. Les colonnes se serrent
 * jusqu'à devenir des filets d'une lettre de large, et sur un téléphone il
 * n'y a pas de geste qui les rende lisibles.
 *
 * Les deux règles de Bootstrap se contredisent : le cadre existe pour qu'un
 * tableau puisse être plus large que lui, et la largeur imposée le lui
 * interdit. On lève l'interdiction plutôt que de l'accommoder.
 *
 *   width: max-content  le tableau prend sa largeur naturelle, celle où ses
 *                       colonnes sont lisibles. C'est elle qui déborde, donc
 *                       c'est elle qui fait défiler le cadre.
 *   min-width: 100%     et un tableau étroit remplit quand même le cadre, au
 *                       lieu de flotter à gauche sur un écran large.
 *
 * CE QUE CETTE RÈGLE REMPLACE, ET POURQUOI.
 *
 * Elle remplace `min-width: 0` sur `.table-responsive`, posée en 2.ux-a
 * (B227) sur un diagnostic faux : une carte serait un conteneur flexible en
 * colonne dont l'enfant refuserait de rétrécir. Deux choses le démentent, et
 * toutes deux se lisent dans `bootstrap.min.css` : la taille minimale
 * automatique d'un élément flexible ne joue QUE sur l'axe principal, ici le
 * vertical, jamais sur la largeur ; et `.card` porte déjà `min-width: 0`
 * elle-même. La ligne ne faisait donc rien, et le harnais vérifiait sa
 * présence.
 *
 * CE QUI SE VÉRIFIE ICI, ET CE QUI NE SE VÉRIFIE QUE SUR UN TÉLÉPHONE.
 *
 * Aucune vérification automatique ne prouve qu'un doigt fait glisser un
 * tableau : le harnais lit du texte, il ne met rien en page. Il peut dire que
 * la règle existe et que rien ne la recouvre — c'est ce que fait
 * `tests/socle/05_vues_sans_script.php`. Le geste est dans
 * `docs/controles-manuels.md`, et c'est lui qui tranche.
 */
.table-responsive > table {
    width: max-content;
    min-width: 100%;
}
