/* Chrome projet.undust.co — chrome v3 (N11) rendu par la gem undust-charte
   (CH-21 b) : canvas, chrome haut flottant, fenêtre, bande basse collée.
   Cette feuille n'adapte que la MESURE de la fenêtre et les pièces du
   portal (flash, menu compte, accueil) ; aucune barre, aucun filet. */

html {
  text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  overflow-x: clip;
}

.chrome-body { margin: 0; }

/* Nav de l'espace, au centre de la bande basse. */
.chrome-nav-links {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
}

.chrome-nav-link {
  font: 500 13px/1 var(--font-sans, Aspekta, sans-serif);
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
}
.chrome-nav-link:hover { color: var(--text-accent); }

.chrome-user-btn {
  color: var(--text-secondary);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.chrome-user-btn:hover { color: var(--text-primary); }
.chrome-user-avatar {
  display: grid; place-items: center;
  width: 32px; height: 32px; border-radius: 9999px;
  background: var(--surface-raised);
  box-shadow: inset 0 0 0 var(--border-width-hairline) var(--border-control);
  font: 700 12px/1 var(--font-sans); letter-spacing: .02em; color: var(--text-primary);
}
.chrome-user-btn:hover .chrome-user-avatar,
.chrome-user-btn:focus-visible .chrome-user-avatar { box-shadow: inset 0 0 0 var(--border-width-hairline) var(--accent); }

/* La fenêtre (gem `.chrome-fenetre`) garde la mesure du portal : 80rem
   (accueil 90rem), étroite pour les pages publiques ; bord à bord ≤ 640. */
.chrome-main {
  width: min(80rem, calc(100% - 2 * var(--space-8)));
  max-width: none;
  margin: var(--space-6) auto var(--space-6);
  padding: var(--space-6) var(--space-8);
  box-sizing: border-box;
  min-width: 0;
}
.chrome-main--flush { padding: var(--space-6) var(--space-4); }
.chrome-main--narrow { width: min(42rem, calc(100% - 2 * var(--space-8))); }
@media (max-width: 640px) {
  .chrome-main, .chrome-main--narrow { width: 100%; margin-top: var(--space-3); padding: var(--space-4); }
}
/* Centré : la variante étroite (28rem, pages anonymes) reste axée dans la fenêtre. */
.chrome-flash { margin: 0 auto var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
/* Cibles d'une fiche (R15, mobile) dans la bande basse de la gem. */
.chrome-barre-fiche > div { display: flex; gap: var(--space-4); height: auto; }
.chrome-barre-fiche a { flex-direction: row; gap: var(--space-1); }

.chrome-flash--narrow { max-width: 28rem; }

.chrome-legal {
  margin: 0;
  padding: var(--space-4);
  text-align: center;
  font: 400 12px/1.4 var(--font-sans, Aspekta, sans-serif);
  color: var(--text-secondary);
}

/* ——— Accueil — une seule colonne de lecture ———
   Décision Luc 16/10 (feedback desktop sur la PR 291) : l'ossature
   3 colonnes (rail gauche de boutons + centre + rail « Mon activité »)
   serrait les blocs de pilotage dans ~360 px, les mots débordaient
   (« découpage ») et la colonne droite restait vide la plupart du
   temps. On retient UNE colonne centrée, largeur de lecture
   confortable, avec les actions « Nouveau projet / Inviter / Admin »
   dans la ligne de recherche. */
.home-v2 { display: block; }

/* Accueil : la fenêtre a une largeur de lecture — ni étroite comme un
   article (640), ni large comme un dashboard sans contenu (1440).
   `min(…, 100% - gouttière)` plafonne sans jamais déborder du canvas. */
.chrome-canvas:has(.home-v2) .chrome-main {
  width: min(68rem, calc(100% - 2 * var(--space-8)));
}

.home-center {
  min-width: 0;
  background: var(--c-fenetre, var(--surface));
  border-radius: var(--radius-window, 16px);
  padding: var(--space-6, 24px);
}

/* Accueil « aller à l'essentiel » (flkIQEG6 §A.3, 07/10) : sur téléphone la
   fenêtre est bord à bord (N11) et la zone centrale n'ajoute plus sa propre
   marge — avant, 32 + 16 + 24 px de chaque côté laissaient 249 px de contenu
   sur un Pixel 4 (393 px). Il en reste 361. */
@media (max-width: 640px) {
  .chrome-canvas:has(.home-v2) .chrome-main { width: 100%; }
  .home-v2 .home-center { padding: 0; }
}

/* C5 — cartes projets : grille façon Basecamp. Une colonne sous 360 px,
   DEUX colonnes dès 360 px (téléphone), plus dès qu'il y a la place ;
   minmax 240 px dès --breakpoint-poste. Piles et cartes ont le même pas. */
.home-card-grid,
.home-stack-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  align-items: stretch;
}
.home-card-grid > *,
.home-stack-grid > * { min-width: 0; }
@media (min-width: 360px) {
  .home-card-grid,
  .home-stack-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}
@media (min-width: 960px) {
  .home-card-grid,
  .home-stack-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-4); }
}
/* La tuile (.stack-tile) porte la pile ET son engrenage : la pile ouverte
   prend toute la ligne. */
.home-stack-grid > .stack-tile:has(> .stack-deck[open]) { grid-column: 1 / -1; }
/* Pile ouverte : la face redevient une barre d'en-tête (jamais height:100%
   dans un details ouvert — le corps passerait sous la ligne suivante). */
.stack-deck[open] > .stack-deck__face {
  height: auto; min-height: 0; flex-direction: row; align-items: center; gap: 12px;
  border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
.stack-deck[open] > .stack-deck__face .stack-deck__head { order: 2; margin-left: auto; gap: 10px; }
.stack-deck[open] > .stack-deck__face .stack-deck__heading { order: 1; }
.stack-deck[open] .stack-deck__preview { display: none; }
.stack-deck[open] > .stack-deck__body {
  padding: 16px; border: 1px solid var(--border); border-top: 0;
  border-radius: 0 0 var(--radius-card, 8px) var(--radius-card, 8px);
  background: var(--surface);
}
html.dark .stack-deck[open] > .stack-deck__body, html[data-theme="dark"] .stack-deck[open] > .stack-deck__body {
  background: color-mix(in srgb, var(--surface-raised) 93%, var(--gray-50));
  border-color: color-mix(in srgb, var(--border) 45%, var(--surface-raised));
}
.home-projects { display: grid; gap: var(--space-6); margin-top: var(--space-6); }

/* Ligne de recherche + actions discrètes (décision 7908mny5, feedback
   16/10) : « Nouveau projet », « Inviter », « Admin » vivent ICI, en
   boutons compacts, plutôt que dans un rail gauche fixe. Téléphone :
   seul le « + » reste (icône seule 44 px, les actions texte sont
   `.home-desktop-only`). Ligne cassée en wrap si la fenêtre est très
   étroite — jamais de débordement. */
.home-center { position: relative; }
.home-top { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.home-top .home-search { flex: 1 1 240px; min-width: 0; margin-top: 0; }
.home-top .home-new-project { flex-shrink: 0; white-space: nowrap; text-decoration: none; }
.home-new-project__icon { width: 16px; height: 16px; flex-shrink: 0; }
.home-top .home-action {
  flex-shrink: 0; display: inline-flex; align-items: center;
  min-height: 32px; padding: 0 var(--space-3);
  border-radius: var(--radius-interactive);
  font: 500 14px/1 var(--font-sans, Aspekta, sans-serif);
  color: var(--text-secondary); text-decoration: none;
}
.home-top .home-action:hover { color: var(--text-primary); background: var(--surface-raised); }
@media (max-width: 640px) {
  .home-top .home-new-project { width: 44px; padding: 0; }
  .home-new-project__label { display: none; }
}

/* Couleur de carte par projet (roue façon Basecamp, vocal Luc 04/09) :
   une CLÉ (Project::COLORS) → un token charte, le CSS mixe. Jamais un hex. */
[data-project-color="orange"] { --pc: var(--orange-500); }
[data-project-color="yellow"] { --pc: var(--chart-3); }
[data-project-color="red"]    { --pc: var(--chart-1); }
[data-project-color="salmon"] { --pc: var(--chart-5); }
[data-project-color="purple"] { --pc: var(--chart-6); }
[data-project-color="blue"]   { --pc: var(--chart-2); }
[data-project-color="green"]  { --pc: var(--chart-7); }
[data-project-color="teal"]   { --pc: var(--chart-4); }
[data-project-color="gray"]   { --pc: var(--gray-400); }
.card[data-project-color] {
  background: color-mix(in srgb, var(--pc) 16%, var(--surface));
  border-color: color-mix(in srgb, var(--pc) 45%, var(--border));
}
html.dark .card[data-project-color], html[data-theme="dark"] .card[data-project-color] {
  background: color-mix(in srgb, var(--pc) 30%, var(--surface-raised));
  border-color: color-mix(in srgb, var(--pc) 55%, var(--surface-raised));
}
.card-color { position: absolute; right: 12px; bottom: 12px; z-index: 2; }
.card-color__ring {
  display: block; width: 18px; height: 18px; border-radius: 9999px; cursor: pointer;
  list-style: none; opacity: .55; transition: opacity .15s ease, transform .15s ease;
  background: conic-gradient(var(--orange-500), var(--chart-3), var(--chart-7),
              var(--chart-4), var(--chart-2), var(--chart-6), var(--orange-500));
  /* La teinte du masque n'est pas rendue — seul le canal alpha compte (gradient
     avec `mask-mode: match-source` par défaut). On passe un token opaque pour
     ne jamais réintroduire un hex. */
  -webkit-mask: radial-gradient(circle, transparent 4px, var(--gray-900) 4.5px);
  mask: radial-gradient(circle, transparent 4px, var(--gray-900) 4.5px);
}
.card-color__ring::-webkit-details-marker { display: none; }
.card-color__ring::marker { content: ""; }
.card:hover .card-color__ring, .card-color[open] .card-color__ring, .card-color__ring:focus-visible { opacity: 1; transform: scale(1.1); }
.card-color__ring:focus-visible, .card-color__swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* La carte est draggable (T14) : aucun drag ne part de la roue. */
.card-color, .card-color * { -webkit-user-drag: none; }
.card-color__panel {
  position: absolute; right: 0; bottom: 26px; z-index: 3;
  display: grid; grid-template-columns: repeat(5, 26px); gap: 8px;
  padding: 10px; border-radius: var(--radius-8, 8px);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: 0 12px 28px -8px color-mix(in srgb, var(--gray-925) 35%, transparent);
}
html.dark .card-color__panel, html[data-theme="dark"] .card-color__panel { background: var(--surface-raised); }
.card-color__swatch {
  display: block; width: 26px; height: 26px; border-radius: 9999px; cursor: pointer;
  border: 2px solid transparent; background: var(--pc, var(--gray-300)); padding: 0;
}
.card-color__swatch:hover, .card-color__swatch.is-current { border-color: var(--text-primary); }
.card-color__swatch--none {
  background: transparent; border-color: var(--border-control);
  background-image: linear-gradient(135deg, transparent 45%, var(--border-control) 45%, var(--border-control) 55%, transparent 55%);
}


/* Retrait My Bar + Up Next + sheet modal (décision Luc 16/10, `7908mny5`) :
   `.my-bar*`, `.my-sheet*`, `.my-up-next*`, `.my-remove`, `.my-note*`,
   `.my-event__join`, `.key-chip`, `.my-page__tabs`, `.my-page__tab*` et
   leur @keyframes `my-sheet-in` sont supprimés — avec les contrôleurs
   `app/controllers/my/*`, les vues `app/views/my/*`, le layout
   `app/views/layouts/my_sheet.html.erb`, les contrôleurs Stimulus
   `my_bar_controller.js` et `sheet_controller.js`. Les tables
   `bookmarks` / `personal_notes` restent (action `LRfiGcXW`).

   Classes PRÉSERVÉES ici parce qu'elles portent AUSSI la page `/search`
   (repli sans JS de la palette, mêmes gabarits) : `.my-page`,
   `.my-page__nav/back/title/empty/filter/search/group*`, `.my-todo*`.
   Dette : les renommer en `.lite-page*` / `.lite-row*` quand on y
   retouche (petite note dette, non bloquant). */
.my-page { max-width: 480px; margin: 0 auto; }
.my-page__nav { margin-bottom: var(--space-4, 16px); }
.my-page__back { display: inline-flex; align-items: center; gap: 4px; font: 500 14px/1 var(--font-sans, Aspekta, sans-serif); color: var(--text-secondary); text-decoration: none; }
.my-page__back:hover { color: var(--text-primary); }
.my-page__title { margin: 0; font: 800 18px/1.15 var(--font-sans, Aspekta, sans-serif); letter-spacing: -0.024em; color: var(--text-primary); }
.my-page__filter { margin-top: var(--space-4, 16px); }
.my-page__group { margin-top: var(--space-6, 24px); }
.my-page__group-title { margin: 0 0 8px; font: 700 12px/1 var(--font-sans, Aspekta, sans-serif); text-transform: uppercase; letter-spacing: .05em; color: var(--text-secondary); }
.my-page__empty { margin-top: var(--space-6, 24px); font: 400 14px/1.4 var(--font-sans, Aspekta, sans-serif); color: var(--text-secondary); }
.my-page__search {
  width: 100%; padding: 8px 10px; border-radius: var(--radius-interactive);
  border: 1px solid var(--border-color-strong);
  background: var(--surface); color: var(--text-primary);
  font: 400 14px/1.4 var(--font-sans, Aspekta, sans-serif);
}
.my-todo-list { list-style: none; margin: 0; padding: 0; }
.my-todo { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0; }
.my-todo + .my-todo { border-top: 1px solid var(--surface-raised); }
.my-todo__body { min-width: 0; flex: 1; }
.my-todo__title { margin: 0; font: 500 14px/1.4 var(--font-sans, Aspekta, sans-serif); color: var(--text-primary); }
.my-todo__link { color: inherit; text-decoration: none; }
.my-todo__link:hover { text-decoration: underline; }
.my-todo__meta { margin: 2px 0 0; font: 400 12px/1.4 var(--font-sans, Aspekta, sans-serif); color: var(--text-secondary); }

/* ——— T11d — palette « Search or jump » de l'accueil (Penpot 01 board 01, I0mOF1SY) ——— */
.home-search { position: relative; margin-top: var(--space-4, 16px); }
.home-search__input {
  width: 100%; padding: 8px 12px; border-radius: var(--radius-interactive);
  border: 1px solid var(--border-color-strong);
  background: var(--surface); color: var(--text-primary);
  font: 400 14px/1.4 var(--font-sans, Aspekta, sans-serif);
}
/* Panneau palette « Search or jump » retiré — décision 7908mny5 (16/10) :
   la recherche en haut est un simple formulaire GET /search. */

/* ——— Accueil « aller à l'essentiel » (flkIQEG6 §A.3, Luc 07/10) ———
   Tokens seulement (Pby1980e N7/N16) : aucun hex, rayons par rôle (cartes
   = --radius-card via .card, contrôles = --radius-interactive, avatars
   carrés comme le menu utilisateur de la trousse). */

/* Gestes d'ORDINATEUR (My Bar, ligne utile des cartes) : absents sous
   768 px et sur écran tactile — Luc : « raccourcis clavier (smartphone !) ». */
@media (max-width: 767px), (pointer: coarse) {
  .home-desktop-only[data-desktop-only] { display: none; }
}

/* Un <details> fermé de l'accueil (pile, roue de couleur, projets terminés)
   n'affiche RIEN d'autre que son résumé. Chromium calcule encore la boîte
   du contenu replié (content-visibility) : sans cette règle, le formulaire
   d'une pile fermée et les pastilles de la roue sont mesurés hors écran ou
   recouverts par le contrat mobile. */
.home-v2 details:not([open]) > :not(summary) { display: none; }

/* Titres de section : 12/700 capitales secondaires (même voix que le rail). */
.home-section { margin-top: var(--space-6); }
.home-section__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.home-section__title {
  margin: 0 0 var(--space-3);
  font: 700 12px/1.3 var(--font-sans);
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-secondary);
}
.home-section__head .home-section__title { margin: 0; }
.home-section__title--toggle { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; list-style: none; }
.home-section__title--toggle::-webkit-details-marker { display: none; }
.home-section__chevron { display: inline-block; transition: transform var(--motion-duree-1) var(--motion-courbe-entree); }
details[open] > .home-section__title--toggle .home-section__chevron { transform: rotate(90deg); }
.home-section__more {
  flex-shrink: 0; display: inline-flex; align-items: center; min-height: 24px;
  font: 600 13px/1.3 var(--font-sans); color: var(--text-accent); text-decoration: none;
}
.home-section__more:hover { text-decoration: underline; }

/* Prochains rendez-vous : une ligne par rendez-vous, tenue à 320 px. */
.home-meetings.card { margin: 0; padding: 0; list-style: none; }
.home-meeting { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); }
.home-meeting + .home-meeting { border-top: var(--border-width-hairline) solid color-mix(in srgb, var(--border) 40%, transparent); }
.home-meeting__date { flex-shrink: 0; width: 36px; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.home-meeting__month { font: 700 11px/1 var(--font-sans); text-transform: uppercase; letter-spacing: .06em; color: var(--text-accent); }
.home-meeting__day { font: 800 20px/1 var(--font-sans); color: var(--text-primary); }
.home-meeting__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.home-meeting__title {
  font: 600 14px/1.35 var(--font-sans); color: var(--text-primary);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1;
  overflow: hidden; overflow-wrap: anywhere;
}
.home-meeting__meta { font: 400 12px/1.35 var(--font-sans); color: var(--text-secondary); overflow-wrap: anywhere; }
.home-meeting__join {
  flex-shrink: 0; display: inline-flex; align-items: center; gap: var(--space-1);
  min-height: 32px; padding: 0 var(--space-3);
  border-radius: var(--radius-interactive);
  background: var(--accent); color: var(--on-accent);
  font: 700 13px/1 var(--font-sans); text-decoration: none;
}
.home-meeting__join:hover { background: var(--accent-hover); color: var(--on-accent-hover); }
.home-meeting__join--secondary {
  background: transparent; color: var(--text-primary);
  box-shadow: inset 0 0 0 var(--border-width-hairline) var(--border-color-strong);
}
.home-meeting__join--secondary:hover { background: transparent; color: var(--text-accent); box-shadow: inset 0 0 0 var(--border-width-hairline) var(--accent); }
.home-meeting__join svg { width: 16px; height: 16px; }
/* Occurrence annulée (contrat v4 §K.1) : titre barré, encre secondaire —
   même règle que `.upcoming-meeting--cancelled` dans pilotage.css. */
.home-meeting--cancelled .home-meeting__title { text-decoration: line-through; color: var(--text-secondary); }
.home-meeting--cancelled .home-meeting__day,
.home-meeting--cancelled .home-meeting__month { color: var(--text-secondary); }

/* Deux colonnes sous la recherche (ordre Luc 22/10) : rendez-vous et
   échéances à gauche, actions et décisions à droite, chacune une moitié de
   la fenêtre. Empilées sous le palier poste (960 px), gauche d'abord. */
.home-columns {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6);
  margin-top: var(--space-6);
}
@media (min-width: 960px) {
  .home-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.home-column { min-width: 0; }
.home-column__empty { margin: 0; font: 400 13px/1.4 var(--font-sans); color: var(--text-secondary); }
/* Titres longs (jalons, décisions) : ils passent à la ligne, jamais coupés
   par des points de suspension. */
.home-meeting--wrap { align-items: flex-start; }
.home-meeting--wrap .home-meeting__title { display: block; -webkit-line-clamp: unset; line-clamp: none; overflow: visible; }
.home-meeting--wrap .home-meeting__join { align-self: center; }
.home-meeting[data-overdue="true"] :is(.home-meeting__month, .home-meeting__day) { color: var(--status-critical); }
/* Page « Rendez-vous et échéances » (Voir tout). */
.home-agenda__back { margin: 0 0 var(--space-2); }
.home-agenda__title { margin: 0 0 var(--space-4); font: 700 20px/1.3 var(--font-sans); color: var(--text-primary); }

/* Carte projet façon Basecamp : nom, description sur une ligne, personnes. */
/* `.card.home-card` : la feuille Tailwind (chargée après) pose `.card { padding }`. */
.card.home-card {
  --home-card-pad: var(--space-3);
  display: flex; flex-direction: column; gap: var(--space-1);
  padding: var(--home-card-pad);
}
@media (min-width: 641px) {
  .card.home-card { --home-card-pad: var(--space-4); gap: var(--space-2); }
}
.home-card__etat { align-self: flex-start; min-height: 0; padding: 1px 6px; }
.home-card__name {
  margin: 0;
  font: 700 15px/1.3 var(--font-sans); color: var(--text-primary);
  overflow-wrap: anywhere;
}
.home-card__name .project-card__link { color: inherit; text-decoration: none; }
.home-card__name .project-card__link:focus-visible { outline: none; }
.home-card:has(.project-card__link:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
/* Carte teintée en sombre (lavage 30 % de la couleur du projet) : le texte
   secondaire y tombe sous 4,5:1 (vert 3,0 · violet 3,3 · saumon 3,5) ;
   l'état passe à l'encre principale (≥ 6,3:1 partout). */
html.dark .card[data-project-color] .home-card__etat,
html[data-theme="dark"] .card[data-project-color] .home-card__etat { color: var(--text-primary); }
.home-card__foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  margin-top: auto; padding-top: var(--space-2);
}
.home-card__people { display: flex; gap: 2px; min-width: 0; margin: 0; padding: 0; list-style: none; }
.home-card__person {
  flex-shrink: 0; display: grid; place-items: center;
  width: 24px; height: 24px; box-sizing: border-box;
  background: var(--surface-raised);
  border: var(--border-width-hairline) solid var(--border-control);
  font: 700 10px/1 var(--font-mono); color: var(--text-primary);
}
.home-card__person--more { color: var(--text-secondary); }
a.home-card--link { color: inherit; text-decoration: none; }
a.home-card--link .home-card__name { font-weight: 600; }
.project-card__actions { margin-top: var(--space-1); }
.project-card__unstack {
  display: inline-flex; align-items: center; min-height: 24px; padding: 0;
  background: none; border: 0; cursor: pointer; text-align: left;
  font: 500 12px/1.3 var(--font-sans); color: var(--text-secondary);
}
.project-card__unstack:hover { color: var(--text-primary); text-decoration: underline; }

/* Roue de couleur DANS le pied de carte : l'anneau reste au-dessus du lien
   étendu ; le panneau se pose dans la largeur de la carte (jamais hors de
   l'écran en grille deux colonnes). */
.home-card .card-color { position: static; flex-shrink: 0; margin-left: auto; }
.home-card .card-color__ring { position: relative; z-index: 2; }
.home-card .card-color__panel {
  left: var(--space-2); right: var(--space-2); bottom: calc(var(--home-card-pad) + 28px);
  grid-template-columns: repeat(auto-fill, 26px); justify-content: center;
}

/* ——— T14 Δ 03/09 — stack = pile de cartes façon Basecamp (validation
   staging Luc 02/09, défaut b) : la face fermée est un deck — deux cartes
   empilées derrière en pseudo-éléments, glyphe SVG, aucun chevron
   d'accordéon. details natif = repli sans JS (R5). Tokens charte N11,
   deux thèmes (N8/N9). ——— */
.stack-tile { position: relative; margin-top: 14px; }
.stack-deck { position: relative; height: 100%; }
.stack-deck[open] { height: auto; }
.stack-deck::before, .stack-deck::after {
  content: ""; position: absolute; z-index: 0; height: 20px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-bottom: none; border-radius: var(--radius-card, 8px) var(--radius-card, 8px) 0 0;
}
.stack-deck::before { top: -6px; left: 8px; right: 8px; }
.stack-deck::after { top: -12px; left: 16px; right: 16px; }
.stack-deck[open]::before, .stack-deck[open]::after { content: none; }
.stack-deck__face {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: 8px;
  min-height: 132px; height: 100%;
  list-style: none; cursor: pointer;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card, 8px); padding: 14px 16px;
  transition: border-color .2s ease, box-shadow .2s ease;
}
.stack-deck__head { display: flex; align-items: center; justify-content: space-between; }
.stack-deck__face::-webkit-details-marker { display: none; }
.stack-deck__face:hover {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  box-shadow: 0 8px 20px -5px color-mix(in srgb, var(--accent) 12%, transparent);
}
.stack-deck__glyph {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--radius-card);
  background: var(--surface-raised);
  color: var(--text-secondary);
}
.stack-deck__glyph svg { width: 16px; height: 16px; }
.stack-deck__heading { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
.stack-deck__name {
  font: 700 16px/1.2 var(--font-sans, Aspekta, sans-serif);
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
/* Aperçu : un nom par ligne, entier — jamais d'ellipse (vocal Luc 04/09). */
.stack-deck__preview {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
  font: 400 13px/1.35 var(--font-sans, Aspekta, sans-serif);
  color: var(--text-secondary);
}
.stack-deck__preview-item { overflow-wrap: anywhere; }
/* « + N autres » : même encre que l'aperçu (gray-400 tombait à 2,5:1). En
   sombre, l'aperçu monte d'un cran : --text-secondary seul ne donne que
   4,29:1 sur la face sans couleur ; le mélange 30 % d'encre principale
   tient ≥ 5,46:1 sur les 8 faces. */
.stack-deck__preview-more { color: inherit; }
html.dark .stack-deck__preview, html[data-theme="dark"] .stack-deck__preview {
  color: color-mix(in srgb, var(--text-primary) 30%, var(--text-secondary));
}
.stack-deck__count {
  flex-shrink: 0;
  font: 600 12px/1 var(--font-sans, Aspekta, sans-serif);
  padding: 3px 8px; border-radius: 9999px;
  background: var(--surface-raised);
  color: var(--text-secondary);
}
.stack-deck__body { padding-top: 16px; }
.stack-deck__empty { margin: 0; font: 400 14px/1.4 var(--font-sans); color: var(--text-secondary); }

/* Badge « liée » (flkIQEG6 §A.5, Luc 07/10 : « couleur incohérente ; pas
   méga clean ») : plus de cyan en dur posé sur des faces de teintes
   différentes. Encre --text-primary, fond transparent, filet currentColor :
   le badge prend la teinte de SA pile. Contraste mesuré ≥ 8,9:1 sur les 8
   teintes × 2 thèmes (l'ancien cyan-700 sur cyan-50 : 4,45:1). */
.stack-deck__linked {
  flex-shrink: 0; display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 2px 6px;
  border: var(--border-width-hairline) solid currentColor;
  color: var(--text-primary);
  font: 700 10px/1.2 var(--font-mono); letter-spacing: .08em; text-transform: uppercase;
}
.stack-deck__linked-glyph { width: 12px; height: 12px; flex-shrink: 0; }

/* Réglages de la pile (flkIQEG6 §A.4) : un engrenage discret sur la face
   (staff / admin) ouvre la fenêtre — rien d'autre n'est visible avant. */
/* L'engrenage occupe le coin haut droit : seule la rangée de tête lui fait
   place (le nom et l'aperçu gardent toute la largeur de la face). */
.stack-tile--manage .stack-deck__head { padding-right: 36px; }
.stack-deck__settings {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: var(--radius-interactive);
  background: transparent; color: var(--text-secondary); cursor: pointer;
}
.stack-deck__settings:hover { color: var(--text-primary); background: color-mix(in srgb, var(--text-primary) 8%, transparent); }
.stack-deck__settings svg { width: 18px; height: 18px; }

/* La fenêtre = dialog.dialogue de la gem (bordure forte, carte 8 px,
   voile --scrim) ; le portal n'en règle que la mesure et le contenu. */
/* Le préflight Tailwind remet `margin: 0` partout : la fenêtre modale
   retrouve son centrage natif (margin auto). */
.stack-tile dialog.dialogue { margin: auto; width: min(440px, calc(100vw - 2 * var(--space-4))); }
.stack-tile dialog.dialogue h3 { overflow-wrap: anywhere; }
.stack-tile dialog.dialogue:focus { outline: none; }
.stack-settings__form { display: grid; gap: var(--space-4); margin-top: var(--space-4); }
.stack-settings__field { max-width: none; }
.stack-settings__colors { min-width: 0; margin: 0; padding: 0; border: 0; }
.stack-settings__colors legend { margin-bottom: var(--space-2); padding: 0; font: 700 13px var(--font-sans); color: var(--text-primary); }
/* Huit pastilles sur une ligne, de 320 px au desktop (≥ 24 px, ≤ 40 px). */
.stack-settings__swatches { display: grid; grid-template-columns: repeat(8, minmax(24px, 40px)); gap: 6px; }
.stack-swatch { position: relative; display: block; cursor: pointer; }
.stack-swatch__input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.stack-swatch__chip {
  display: grid; place-items: center;
  width: 100%; aspect-ratio: 1; box-sizing: border-box;
  border: var(--border-width-hairline) solid var(--border-control);
  border-radius: var(--radius-interactive);
  background: color-mix(in srgb, var(--stack-tint-ink, var(--surface)) 55%, var(--surface));
  color: var(--text-primary);
}
.stack-swatch__chip--none {
  background: var(--surface);
  background-image: linear-gradient(135deg, transparent 46%, var(--border-control) 46%, var(--border-control) 54%, transparent 54%);
}
.stack-swatch__input:checked + .stack-swatch__chip { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--text-primary); }
/* Coche TRACÉE, pas un caractère (R7). */
.stack-swatch__input:checked + .stack-swatch__chip::after {
  content: ""; width: 6px; height: 11px; border: solid currentColor; border-width: 0 2px 2px 0;
  transform: translateY(-2px) rotate(45deg);
}
.stack-swatch__input:focus-visible + .stack-swatch__chip { outline: 2px solid var(--focus-ring); outline-offset: 4px; }
.stack-settings__danger {
  margin-top: var(--space-4); padding-top: var(--space-4);
  border-top: var(--border-width-hairline) solid color-mix(in srgb, var(--border) 40%, transparent);
}
.stack-settings__danger form { margin: 0; }
.stack-settings__delete.btn--discret { padding-left: 0; color: var(--status-critical); text-decoration-color: currentColor; }
/* `.btn:hover` (gem) pose l'aplat accent même sur `.btn--discret` : le geste
   destructeur garde son encre d'écart, sans aplat. */
.stack-settings__delete.btn--discret:hover { background: none; color: var(--status-critical); text-decoration-thickness: 3px; }
.stack-settings__note { margin: 0; font: 500 13px/1.4 var(--font-sans); color: var(--text-secondary); }
.stack-tile .dialogue-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-6); }
/* Sombre = tokens charte (vocal Luc 04/09 : fin des hex 242424/1f1f1f
   hors charte). La face est la carte (un cran plus clair que la fenêtre),
   les feuilles derrière un demi-cran. */
html.dark .stack-deck::before, html.dark .stack-deck::after,
html[data-theme="dark"] .stack-deck::before, html[data-theme="dark"] .stack-deck::after {
  background: color-mix(in srgb, var(--surface-raised) 92%, var(--gray-50));
  border-color: color-mix(in srgb, var(--border) 45%, var(--surface-raised));
}
html.dark .stack-deck__face, html[data-theme="dark"] .stack-deck__face {
  background: color-mix(in srgb, var(--surface-raised) 86%, var(--gray-50));
  border-color: color-mix(in srgb, var(--border) 45%, var(--surface-raised));
}
html.dark .stack-deck__glyph, html[data-theme="dark"] .stack-deck__glyph,
html.dark .stack-deck__count, html[data-theme="dark"] .stack-deck__count {
  background: var(--surface-raised);
}

/* ——— T15 — motion Feuille (spec pack couloir 3, 4mfprzlh §A + §C) ——— */

/* Ouverture du deck de stack : fondu + montée 18 px + léger scale .97→1,
   240 ms courbe Feuille — la seule « vraie » animation du geste (§A.2.1).
   Fermeture = details natif, instantanée : asymétrie BC « entrée animée,
   sortie décisive ». prefers-reduced-motion : tué par la règle globale de
   tokens.css (durées → 0). */
.stack-deck__body { transform-origin: center 70%; }
.stack-deck[open] .stack-deck__body {
  animation: stack-deck-open var(--motion-duree-2, 240ms) var(--motion-courbe-entree, cubic-bezier(0.22, 1, 0.36, 1));
}
@keyframes stack-deck-open {
  from { opacity: 0; transform: translateY(18px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

/* Drag & drop de l'accueil — norme Q34 (§C.2) :
   1. la carte saisie garde un ghost d'origine à ~27 % : l'élément RÉEL,
      fantômé, qui reste dans le flux (pas de reflow de la grille) ;
   2. survol d'une autre carte = signal « empiler » : cadre pointillé
      débordant ~8 px + invite texte, contenu de la cible fondu à 0
      en 120 ms (§A.1.2) ;
   3. survol d'un deck de stack ou de la zone « Projets » = signal
      « ranger » : même cadre pointillé mais contenu conservé, atténué
      à ~60 %, sans invite (§A.4). Les deux signaux ne s'affichent
      jamais ensemble (le contrôleur ne porte qu'une cible à la fois). */
[data-project-card] { position: relative; }

/* ——— T18c — C4 accueil v3 (vocal Luc 03/09 07:25Z) : carte projet entière
   cliquable. Le lien du titre étend sa zone de clic à toute la carte
   (::after en stretched-link — la carte est en position:relative) ; la
   rangée d'actions reste cliquable au-dessus de l'overlay (z 1, sous le
   cadre de drop T15 z 2 et l'invite z 3). ——— */
.project-card__link { -webkit-user-drag: none; }
.project-card__link::after { content: ""; position: absolute; inset: 0; }
.project-card__actions { position: relative; z-index: 1; }

.project-card-drag-origin { opacity: 0.27; }

/* Cadre pointillé débordant — carte libre ::after ; pour le deck (dont les
   ::before/::after dessinent la pile) et la zone « Projets », outline à
   décalage équivalent. */
[data-project-card].stack-target-frame::after {
  content: ""; position: absolute; inset: -8px; z-index: 2;
  border: 2px dashed var(--border-control);
  border-radius: var(--radius-card); pointer-events: none;
}
.stack-deck.stack-target-frame .stack-deck__face,
[data-unstacked-zone].stack-target-frame {
  outline: 2px dashed var(--border-control);
  outline-offset: 8px; border-radius: var(--radius-card);
}

/* Contenu de la cible « empiler » fondu à 0 ; invite centrée apparaissant
   en 120 ms ease-out Feuille (§A.6.2). */
[data-project-card].stack-target-frame > *:not(.project-card__stack-hint) {
  opacity: 0;
  transition: opacity var(--motion-duree-1, 120ms) var(--motion-courbe-entree, cubic-bezier(0.22, 1, 0.36, 1));
}
.project-card__stack-hint {
  position: absolute; inset: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  font: 400 14px/1.3 var(--font-sans, Aspekta, sans-serif);
  color: var(--text-secondary);
  opacity: 0; pointer-events: none;
  transition: opacity var(--motion-duree-1, 120ms) var(--motion-courbe-entree, cubic-bezier(0.22, 1, 0.36, 1));
}
[data-project-card].stack-target-frame .project-card__stack-hint { opacity: 1; }

/* Cibles « ranger » (deck, zone Projets) : contenu atténué, pas d'invite. */
.stack-deck.stack-target-frame > *,
[data-unstacked-zone].stack-target-frame > * {
  opacity: 0.6;
  transition: opacity var(--motion-duree-1, 120ms) var(--motion-courbe-entree, cubic-bezier(0.22, 1, 0.36, 1));
}
html.dark .project-card__stack-hint, html[data-theme="dark"] .project-card__stack-hint {
  color: var(--text-secondary);
}

/* ——— T18e / C2 — teinte métier de la pile (vocal Luc 03/09) ———
   Choix user, PAS du chrome : aucune pastille n'introduit d'hex. Les
   clés data-stack-color / data-color mappent un accent sémantique déjà
   tokenisé ; le lavage = color-mix 18 % sur --surface (Q13 i21FdYE2 :
   punchy existants rendus transparents, jamais une palette BC importée).
   Analogie UI : pastilles discrètes Card Table (4mfprzlh Q25), pas un
   theme picker. La face fermée ET les feuilles ::before/::after portent
   la teinte — c'est ce qui se lit sur l'accueil. */
.stack-deck[data-stack-color="accent"],
.stack-swatch[data-color="accent"] { --stack-tint-ink: var(--accent); }
.stack-deck[data-stack-color="tension"],
.stack-swatch[data-color="tension"] { --stack-tint-ink: var(--tension); }
.stack-deck[data-stack-color="success"],
.stack-swatch[data-color="success"] { --stack-tint-ink: var(--status-success); }
.stack-deck[data-stack-color="warning"],
.stack-swatch[data-color="warning"] { --stack-tint-ink: var(--status-warning); }
.stack-deck[data-stack-color="info"],
.stack-swatch[data-color="info"] { --stack-tint-ink: var(--status-info); }
.stack-deck[data-stack-color="pending"],
.stack-swatch[data-color="pending"] { --stack-tint-ink: var(--status-pending); }
.stack-deck[data-stack-color="critical"],
.stack-swatch[data-color="critical"] { --stack-tint-ink: var(--status-critical); }

.stack-deck[data-stack-color] {
  --stack-tint: color-mix(in srgb, var(--stack-tint-ink) 18%, var(--surface));
}
.stack-deck[data-stack-color] .stack-deck__face,
.stack-deck[data-stack-color]::before,
.stack-deck[data-stack-color]::after {
  background: var(--stack-tint);
}
html.dark .stack-deck[data-stack-color] .stack-deck__face,
html[data-theme="dark"] .stack-deck[data-stack-color] .stack-deck__face,
html.dark .stack-deck[data-stack-color]::before,
html.dark .stack-deck[data-stack-color]::after,
html[data-theme="dark"] .stack-deck[data-stack-color]::before,
html[data-theme="dark"] .stack-deck[data-stack-color]::after {
  background: var(--stack-tint);
}

/* ——— T15b — motion drag kanban & listes (spec pack 4mfprzlh §B + Q34) ——— */

/* Ghost à 27 % (Q34.1) : l'élément RÉEL, dans le flux — SortableJS déplace
   l'élément lui-même à la position prospective (insertion live, Q34.4,
   jamais de boîte vide abstraite). Aucune transformation : ni scale, ni
   rotation (Q34.1) ; l'image qui suit le curseur est l'image de drag
   native (modèle BC Card Table, §B.0). */
.feuille-drag-ghost { opacity: 0.27; }

/* Élément posé : fondu 27 % → 1 en 120 ms courbe Feuille (Q34.6) — la
   continuité est visuelle : l'élément quitte l'état ghost sans saut.
   prefers-reduced-motion : durée tuée par la règle globale tokens.css. */
.feuille-drop-fade {
  animation: feuille-drop-fade var(--motion-duree-1, 120ms) var(--motion-courbe-entree, cubic-bezier(0.22, 1, 0.36, 1));
}
@keyframes feuille-drop-fade {
  from { opacity: 0.27; }
  to   { opacity: 1; }
}

/* Feedback de pose (Q34.8) : cadre pointillé conservé 400 ms après le drop
   — délai d'ÉTAT tenu par le contrôleur (setTimeout), pas un tween : il
   n'entre pas dans la grille de tokens et survit à reduced-motion, comme
   la bordure dashed persistante mesurée chez BC (~300-500 ms, §B.4). */
.feuille-drop-pose {
  outline: 2px dashed var(--border-control);
  outline-offset: 2px;
}

/* ——— Launchpad /espaces (vocal Luc 04/09) : tuiles de MÊME taille, nom
   entier jamais tronqué, mini-logo carré 64 px. ——— */
.espaces-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4, 16px); grid-auto-rows: 1fr; }
@media (min-width: 640px) { .espaces-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.espace { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.espace form.contents { display: contents; }
/* Espace de rattachement (flkIQEG6 §A.2) : une ligne sous chaque tuile —
   « Espace par défaut » ou le geste pour le devenir. Même hauteur des deux
   côtés : la grille garde des tuiles égales. */
.espace-default__form { display: flex; }
.espace-default {
  display: flex; align-items: center; justify-content: center; width: 100%; min-height: 32px;
  font: 400 12px/1.2 var(--font-sans, Aspekta, sans-serif); text-align: center;
}
.espace-default--set { color: var(--text-accent); font-weight: 600; }
.espace-default--action {
  color: var(--text-secondary); background: transparent; border: 0; border-radius: var(--radius-interactive, 0); cursor: pointer;
}
.espace-default--action:hover, .espace-default--action:focus-visible { color: var(--text-accent); text-decoration: underline; }
.espace-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 12px;
  width: 100%; min-height: 188px; padding: 20px 16px; cursor: pointer; text-align: center;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card, 8px); transition: border-color .2s ease, box-shadow .2s ease, transform .15s ease;
}
html.dark .espace-tile, html[data-theme="dark"] .espace-tile {
  background: var(--surface-raised);
  border-color: color-mix(in srgb, var(--border) 45%, var(--surface-raised));
}
.espace-tile:hover { border-color: var(--accent); box-shadow: 0 8px 20px -5px color-mix(in srgb, var(--accent) 14%, transparent); transform: translateY(-1px); }
.espace-tile.is-current { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.espace-tile__logo {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 64px; height: 64px; padding: 6px; border-radius: var(--radius-card);
  background: var(--white); border: 1px solid var(--border); overflow: hidden;
}
.espace-tile__logo img { max-width: 100%; max-height: 100%; object-fit: contain; }
.espace-tile__initial {
  display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; border-radius: var(--radius-card);
  font: 700 22px/1 var(--font-sans, Aspekta, sans-serif); color: var(--gray-700); background: var(--gray-50);
}
.espace-tile.is-current .espace-tile__initial { background: var(--accent); color: var(--white); }
.espace-tile__name {
  font: 600 14px/1.3 var(--font-sans, Aspekta, sans-serif); color: var(--text-primary);
  overflow-wrap: anywhere; text-wrap: balance;
}
.espace-tile:hover .espace-tile__name { color: var(--text-accent); }
.espace-tile__meta { font: 400 12px/1.2 var(--font-sans, Aspekta, sans-serif); margin-top: auto; }
.espace-tile__meta--current { color: var(--text-accent); }
.espace-tile__meta--partner { color: var(--status-warning); }

@media (max-width: 640px) {
  .chrome-main .truncate,
  .chrome-main .line-clamp-2,
  .chrome-main .line-clamp-4 {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    overflow-wrap: anywhere;
    -webkit-line-clamp: unset;
    line-clamp: unset;
  }
}

[data-lineage-panel-target="panel"][aria-hidden="true"] { visibility: hidden; }
@media (max-width: 640px) {
  .timeline-meta { flex-wrap: wrap; }
  .timeline-meta > .flex { min-width: 0; flex-wrap: wrap; }
}

@media (max-width: 640px) {
  #project-people, #project-people tbody, #project-people tr, #project-people td { display: block; width: 100%; }
  #project-people { min-width: 0; }
  #project-people thead { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); }
  #project-people td { box-sizing: border-box; padding: var(--space-2) var(--space-4); overflow-wrap: anywhere; }
  #project-people td::before { content: attr(data-label); display: block; font-weight: 600; color: var(--text-secondary); }
}

/* Impersonation staff (layout application) : bande d'état COLLÉE en haut de
   l'écran — le chrome v3 de la gem défile, et « vous agissez à la place de… »
   + « Revenir admin » doivent rester visibles sur une page longue (revue
   Codex 203). Sous les modales, au-dessus du contenu. */
.chrome-impersonation {
  position: sticky;
  top: 0;
  z-index: var(--layer-collant);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2) var(--space-3);
  padding-inline: var(--space-4);
}
.chrome-impersonation form { display: inline-flex; margin: 0; }
