/* 4-large.css — quand l'écran s'élargit : la barre passe en haut, les blocs se rangent côte à côte, et
 * la feuille de choix apparaît.
 *
 * ── L'ORDRE COMPTE ─────────────────────────────────────────────────────────────────
 * Ce fichier est une TRANCHE de l'ancien app.css, découpé en neuf morceaux contigus. Le
 * chiffre en tête du nom est son rang de cascade, et ce n'est pas de la décoration : lus
 * dans l'ordre, les neuf fichiers valent exactement l'ancien, à l'octet près. Les intervertir
 * change ce qui l'emporte — et une cascade inversée ne se voit pas, elle se constate trois
 * jours plus tard sur un écran précis.
 *
 * Deux raisons de ne PAS regrouper par thème en réordonnant : les paires
 * `@media`/`@container` se redoublent (chacune doit rester APRÈS la @media qu'elle double),
 * et `container-type` définit l'unité de mesure de tout ce qu'il contient. Le découpage
 * contigu rend ces deux pièges impossibles au lieu de demander qu'on y pense.
 *
 * `tests/test_feuilles_css.py` vérifie que les quatre points de chargement listent bien ces
 * neuf fichiers, dans ce rang.
 */

/* — au-delà du téléphone : la barre passe en haut —
 * En bas elle est à portée de pouce ; sur un grand écran tenu à cinquante centimètres, elle
 * est seulement loin du regard et loin du contenu. Même balisage, seule la place change. */
@media (min-width: 768px) {
  /* La barre traverse l'écran, le CONTENU reste lisible. Deux contraintes différentes pour
   * deux besoins différents : une barre à moitié large laisse un vide qui ressemble à une
   * page mal chargée, une ligne de texte à 2000 px ne se lit pas. */
  lane-app { max-width: none; }
  main { width: 100%; max-width: 1440px; margin-inline: auto; }

  /* Tout sur une ligne : la flèche, les onglets, les commandes. Le conteneur redevient une
   * boîte, et l'en-tête s'efface à son tour pour que ses propres enfants — flèche, icône,
   * réglages, thème — deviennent des éléments de CETTE ligne et puissent s'ordonner
   * indépendamment des onglets. */
  .chrome {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: var(--s2) var(--s4);
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--ground);
    border-bottom: 1px solid var(--line);
  }

  .chrome header { display: contents; }

  /* L'en-tête de l'accueil garde le même rembourrage vertical que la barre des produits.
   * Sans ça, passer de la liste des applications à l'une d'elles faisait sauter la page de
   * huit pixels — assez peu pour qu'on ne sache pas nommer ce qui a bougé, assez pour qu'on
   * le voie à chaque aller-retour. */
  lane-app > header { padding: var(--s2) var(--s4); }
  .chrome .back { order: 1; }
  .chrome .mark { order: 2; }

  /* Le nom du produit, entre son icône et les onglets. Il ne prend QUE sa place : la règle
   * générale lui donne `flex: 1`, ce qui le ferait pousser les onglets jusqu'au bord droit.
   * Et il se coupe plutôt que de rétrécir la barre — un nom long ne doit pas décider de la
   * place des onglets, qui sont le vrai objet de cette ligne. */
  .chrome .title {
    order: 3;
    flex: 0 1 auto;
    /* charte-libre: 24ch n'est pas la mesure de LECTURE (--mesure) mais une colonne
       étroite — deux contraintes différentes qui s'expriment dans la même unité. */
    max-width: 24ch;
    margin-right: var(--s2);
    font-size: var(--t5);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .chrome .icon { order: 5; }
  .chrome .avatar { order: 6; }

  nav {
    order: 4;
    flex: 1;
    position: static;
    /* Les onglets sont calés à GAUCHE, contre la flèche : étalés sur toute la largeur, ils
     * mettaient un demi-écran entre « Tâches » et « Stratégie » — on ne lit plus une barre,
     * on la parcourt. */
    justify-content: flex-start;
    gap: var(--s1);
    padding: 0;
    border: 0;
    background: none;
    backdrop-filter: none;
  }

  nav a { flex: 0 0 auto; }

  /* En haut, l'icône passe À CÔTÉ du mot : la ligne est plus compacte, et l'œil suit
   * l'horizontale au lieu de descendre. */
  nav a {
    grid-auto-flow: column;
    justify-content: center;
    align-items: center;
    gap: var(--s2);
    padding: var(--s2) var(--s4);
  }

  nav a span { font-size: var(--t3); }

  /* Plus de décalage à calculer : il n'y a plus deux barres empilées mais une seule, et
   * c'est elle qui colle. `--nav-h` a disparu avec le problème qu'elle mesurait. */
}

/* — au-delà de l'ordinateur portable : les blocs se rangent côte à côte —
 * Même balisage qu'au téléphone, seule la place change — comme la barre juste au-dessus.
 * Stratégie tenait trois blocs courts (Vision, Comment, Jalons) l'un SOUS l'autre sur une
 * colonne de 1100 px : des lignes de texte à cent dix caractères, un titre de jalon à
 * gauche et ses flèches neuf cents pixels plus loin, et un écran qui défile pour ce qui
 * tient sur une ligne.
 *
 * Des COLONNES, et non une grille — c'est le contraire de ce qu'on croit en l'écrivant.
 * Une grille aligne ses lignes : la hauteur d'une rangée est celle de son bloc le plus
 * grand, donc une vision de trois lignes posée à côté d'une liste de jalons laisse deux
 * cent cinquante pixels de vide sous elle, et le bloc suivant commence tout en bas. Mesuré
 * sur Stratégie : 740 px de haut en grille, 468 px en colonnes, pour les mêmes cinq blocs.
 * Les colonnes empilent au plus près et ne laissent aucun trou.
 *
 * Et AUCUN bloc ne traverse les colonnes. `column-span: all` avait l'air fait pour la
 * galerie de composants et le verdict ; il coupe en réalité le flot en deux, et les blocs
 * d'avant ne peuvent plus partager de ligne avec ceux d'après — l'Identité restait seule
 * dans sa colonne, mille pixels de vide à sa droite. Produit : 1865 px avec, 1162 px sans.
 *
 * Ce qu'on redoutait d'elles — un bloc qui saute d'une colonne à l'autre pendant qu'on
 * écrit — ne se produit pas : l'édition en place se fait dans un `<textarea rows="4">` ou
 * un `<input>`, tous deux de hauteur FIXE. Rien ne grandit sous les doigts. Si un jour un
 * champ devient extensible, c'est ici qu'il faudra revenir.
 *
 * Il n'y a PLUS DE SEUIL ici, et c'est le cœur du changement. `column-width` demande une
 * largeur souhaitée, pas un nombre de colonnes : il en rend une quand il n'y a pas la place
 * pour deux, et autant que l'écran en tient sinon. Une colonne à 390 px, deux à 768, trois
 * à 1180, quatre à 1440 — sans rupture, et sans qu'un nombre décide où le téléphone
 * s'arrête et où la tablette commence. C'est un seuil retiré, pas un seuil déplacé.
 *
 * 320 px de colonne, là où le plancher était à 420 : ce plancher n'existait que parce que
 * les règles de repli d'une ligne écoutaient la FENÊTRE, qui reste large quand la colonne
 * ne l'est plus. Elles écoutent maintenant leur conteneur (`@container`, plus bas), donc
 * une colonne étroite se replie au lieu d'être écrasée. */
lane-pillar {
  column-width: 320px;
  column-gap: var(--s5);
  /* L'air au-dessus du premier bloc vient du CONTENEUR, et surtout pas d'une marge sur le
   * premier bloc : en colonnes, celui-ci n'est le premier que de la colonne 1, et les autres
   * démarreraient 24 px plus haut. Un désalignement qu'on voit sans savoir le nommer. */
  padding-top: var(--s5);
}

/* `flow-root` et pas le bloc par défaut : il faut que la marge basse appartienne au bloc
 * (sinon elle traverse et se colle à la colonne) et que `break-inside` ait une boîte entière
 * à ne pas couper. Un bloc coupé en deux colonnes est le seul vrai accident de cette mise en
 * page — un titre en bas d'une colonne, sa liste en haut de la suivante.
 *
 * `container-type: inline-size` fait de chaque bloc l'unité de mesure de ce qu'il contient.
 * C'est ce qui permet aux lignes de se replier selon LEUR largeur : sans ça, un `.ds-row`
 * dans une colonne de 453 px croyait vivre dans une fenêtre de 1440, ne se repliait pas, et
 * dépassait de 92 px — que `overflow-x: clip` tranchait en silence.
 *
 * Il crée un bloc conteneur pour les descendants positionnés en absolu. Les quatre concernés
 * (`.gal-tag`, `.pal i::after`, `.pastille.on::after`, le bandeau du bouton collant) ont
 * tous déjà un parent `position: relative` : aucun ne remonte jusqu'ici. */
.bloc {
  container-type: inline-size;
  display: flow-root;
  break-inside: avoid;
  margin: 0 0 var(--s5);
}

/* L'exception, et une seule : un bloc qui EST l'écran plutôt qu'une section parmi d'autres.
 *
 * `column-span: all` est déconseillé quelques lignes plus haut, et la raison tient toujours :
 * il coupe le flot en deux, donc les blocs d'avant ne peuvent plus partager de colonne avec
 * ceux d'après. C'est précisément ce qu'on veut ici. Les tâches sont une GRILLE de cartes —
 * elles se répartissent d'elles-mêmes en autant de colonnes que la place en tient — et une
 * grille enfermée dans une colonne de 320 px n'est jamais qu'une pile. Mesuré sur Tâches à
 * 1440 px : quatre cartes en pile sur 1100 px de haut, contre une rangée de quatre.
 *
 * Il ne coupe rien d'autre : l'onglet qui le porte tient en deux blocs, les jalons et les
 * tâches, et les jalons passent AVANT. */
.bloc.large { column-span: all; }

/* L'écart entre blocs est celui de leur marge basse. Laisser en plus la marge haute du titre
 * l'ajouterait à celle du bloc précédent — `flow-root` empêche justement les deux de se
 * confondre en une seule, comme elles le faisaient quand les sections étaient des frères
 * plats. */
.bloc > :first-child,
/* Deux niveaux, ici comme pour la marge basse : `lane-jalons`, `lane-verdict` et
 * `lane-backlog` portent leur propre titre, donc la marge à neutraliser est celle du premier
 * enfant DU COMPOSANT. Sans cette seconde ligne, quatre onglets décalaient de 24 px tout ce
 * qui suit leur première section déléguée — sur un téléphone, où rien ne devait bouger. */
.bloc > :first-child > :first-child { margin-top: 0; }

/* Le bloc possède son espacement EXTÉRIEUR ; son contenu n'en pose pas.
 *
 * `.ds` et `.vitaux` portent une marge basse de leur côté. Tant que les sections étaient des
 * frères plats, elle se fondait avec la marge haute du titre suivant — deux marges de 24 px
 * qui n'en font qu'une, c'est la règle du flux normal. `flow-root` empêche justement cette
 * fusion : la marge restait à l'intérieur, celle du bloc s'ajoutait par-dessus, et l'écart
 * passait à 48 px. Mesuré : trois onglets décalés de 24 px à partir de leur deuxième
 * section, sur un téléphone, alors que rien n'aurait dû y bouger. */
.bloc > :last-child,
/* Deux niveaux, parce que trois sections délèguent leur contenu à un composant :
 * `<lane-verdict>`, `<lane-backlog>`, `<lane-gallery>`. Le dernier enfant du bloc est alors
 * l'élément sur mesure, et la marge à neutraliser est celle de SON dernier enfant. */
.bloc > :last-child > :last-child { margin-bottom: 0; }

/* — feuille de choix : une parenthèse, pas une destination — */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: flex-end;
  background: var(--scrim);
}

.sheet-body {
  width: 100%;
  max-height: 85dvh;
  overflow-y: auto;
  padding: var(--s5) var(--s4) calc(var(--s5) + env(safe-area-inset-bottom));
  background: var(--ground);
  border-radius: var(--radius) var(--radius) 0 0;
  display: grid;
  gap: var(--s3);
}

/* La sortie, toujours sous le pouce.
 *
 * Une feuille de choix peut être longue — dix-neuf pistes de logo, douze directions
 * visuelles. Le bouton de sortie était le dernier élément du flux : pour renoncer, il fallait
 * faire défiler jusqu'en bas TOUT ce qu'on venait de décider de ne pas prendre. Un écran dont
 * on ne peut pas sortir sans le lire en entier finit par être fermé en rechargeant la page.
 *
 * `sticky` et pas `fixed` : le bouton reste dans le flux, donc il ne recouvre jamais le
 * dernier choix de la liste — il se pose dessus seulement quand il y a de quoi défiler.
 * Le fond opaque, étendu par une ombre de la largeur d'une gouttière, est ce qui empêche le
 * contenu de transparaître sous ses bords arrondis pendant le défilement. */
.sheet-body > [data-act="close"],
.sheet-body > [data-act="aiClose"] {
  position: sticky;
  bottom: 0;
  z-index: 1;
}

/* La bande opaque sous le bouton, en pseudo-élément : elle doit couvrir toute la largeur de
 * la feuille, gouttières comprises, sinon les cartes défilent visiblement de part et d'autre
 * d'un bouton qui semble flotter. Les marges négatives annulent le padding du corps —
 * `inset` les reprend dans l'ordre haut / droite-gauche / bas. */
.sheet-body > [data-act="close"]::before,
.sheet-body > [data-act="aiClose"]::before {
  content: "";
  position: absolute;
  inset: calc(var(--s3) * -1) calc(var(--s4) * -1)
         calc((var(--s5) + env(safe-area-inset-bottom)) * -1);
  z-index: -1;
  background: var(--ground);
  /* Un liseré, pas une ombre portée : il dit qu'il reste du contenu au-dessus sans salir le
   * bas de l'écran d'un dégradé qu'on remarque plus que le bouton. */
  border-top: 1px solid var(--line);
}

.sheet h2 { font-size: var(--t6); }
.sheet .muted { background: none; padding: 0; font-size: var(--t4); }

/* L'enveloppe d'une liste d'items. Au téléphone elle ne doit RIEN changer : les items étaient
 * des enfants directs de `.sheet-body`, qui est une grille à gouttière — les envelopper sans
 * rendre cette gouttière les aurait collés les uns aux autres. C'est le premier essai qui l'a
 * dit, en comparant les positions avant et après : quatre écrans sur huit avaient bougé.
 * Une colonne à la même gouttière que le parent, donc, et rien de plus. */
.sheet-body .liste { display: grid; gap: var(--s3); }

