/* Composants web. Toutes les valeurs viennent de tokens.css. Voir COMPOSANTS.md. */

/* Base */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  color: var(--text);
  font: 400 var(--fs-body) / 1.5 var(--font);
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
}
/* Fond de page, avec le motif de l'ambiance s'il y en a un. */
body, .fond { background-color: var(--bg); background-image: var(--motif); background-size: var(--motif-size); }
h1, h2, h3 { margin: 0; font-family: var(--font-display); font-weight: 650; letter-spacing: calc(-0.02em * var(--track-k)); line-height: 1.15; text-wrap: balance; }
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); letter-spacing: calc(-0.01em * var(--track-k)); }
p { margin: 0; }
small, .small { font-size: var(--fs-small); }
.muted { color: var(--text-2); }
.num { font-variant-numeric: tabular-nums; }
.big-num { font-size: var(--fs-num); font-weight: 600; letter-spacing: calc(-0.02em * var(--track-k)); line-height: 1.1; font-variant-numeric: tabular-nums; }
.section-title { font-size: var(--fs-small); font-weight: 500; color: var(--text-2); }
:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }

/* Structure d'un écran : un bloc n'a pas de marge propre. */
.page { display: flex; flex-direction: column; gap: var(--block-gap); max-width: var(--measure); margin-inline: auto; padding-inline: max(var(--gutter), env(safe-area-inset-left, 0px)) max(var(--gutter), env(safe-area-inset-right, 0px)); }
.block { display: flex; flex-direction: column; gap: var(--head-gap); }
.list { display: flex; flex-direction: column; gap: var(--list-gap); }

/* Tuile : pas de bordure, le fond suffit à la détacher. */
.card { background: var(--surface); border: var(--card-edge); border-radius: var(--r-lg); box-shadow: var(--shadow-card); padding: var(--s-4); }
.card--sm { border-radius: var(--r-md); }

/* Ligne de liste */
.row { display: flex; align-items: center; gap: var(--s-3); min-height: var(--row-min); padding: 10px var(--s-4); background: var(--surface); border: var(--card-edge); border-radius: var(--r-md); box-shadow: var(--shadow-card); }
a.row, button.row { width: 100%; color: inherit; font: inherit; text-align: left; text-decoration: none; cursor: pointer; transition: transform var(--t-press) var(--ease-press); }
a.row:active, button.row:active { transform: scale(var(--press-scale)); }
.row__main { flex: 1; min-width: 0; font-weight: 500; }
.row__sub { display: block; font-size: var(--fs-small); font-weight: 400; color: var(--text-2); }
.row__value { font-variant-numeric: tabular-nums; font-weight: 500; }

/* Boutons : une seule action en accent par écran. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  --b: var(--surface-2);
  min-height: var(--tap); padding: 0 18px 0 14px; border: 0; border-radius: var(--r-btn);
  background: var(--b); color: var(--text);
  font: 500 var(--fs-body) / 1 var(--font); text-decoration: none; cursor: pointer;
  transition: transform var(--t-press) var(--ease-press), opacity var(--t-fast);
}
@media (hover: hover) { .btn:hover:not(:disabled) { background: color-mix(in srgb, var(--b) 88%, var(--text)); } }
.btn:active { transform: scale(var(--press-scale)); }
.btn:disabled { opacity: 0.45; cursor: default; transform: none; }
.btn[aria-busy='true'] { pointer-events: none; }
.btn--primary { --b: var(--accent); color: var(--on-accent); }
.btn--danger { --b: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.btn--ghost { --b: transparent; }
.btn--small { min-height: var(--tap-small); padding: 0 14px 0 10px; font-size: var(--fs-small); }
.btn--small .icon { width: var(--icon-sm); height: var(--icon-sm); }
.btn--block { width: 100%; min-height: var(--tap-block); }
.spinner { width: var(--icon-sm); height: var(--icon-sm); flex: none; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: socle-spin 0.8s linear infinite; }
.icon-btn { display: inline-grid; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--text-2); cursor: pointer; transition: transform var(--t-press) var(--ease-press); }
.icon-btn:active { transform: scale(0.92); }

/* Icône Lucide au trait, depuis le sprite : <svg class="icon"><use href="web/icones.svg#plus"/></svg> */
.icon { width: var(--icon); height: var(--icon); flex: none; fill: none; stroke: currentColor; stroke-width: var(--icon-stroke); stroke-linecap: round; stroke-linejoin: round; }

/* Puces, badges */
.chip { display: inline-flex; align-items: center; min-height: var(--tap-small); padding: 0 14px; border: 0; border-radius: var(--r-sm); background: var(--surface); color: var(--text-2); font: 500 var(--fs-small) / 1 var(--font); cursor: pointer; transition: transform var(--t-press) var(--ease-press); }
.chip:active { transform: scale(var(--press-scale)); }
.chip[aria-pressed='true'] { background: var(--text); color: var(--bg); }
.badge { --c: var(--text-2); display: inline-flex; align-items: center; padding: 2px 8px; border-radius: var(--r-pill); background: color-mix(in srgb, var(--c) 14%, transparent); color: var(--c); font-size: var(--fs-caption); font-weight: 500; }
.badge--ok { --c: var(--ok); }
.badge--warn { --c: var(--warn); }
.badge--danger { --c: var(--danger); }

/* Champs : 16 px pour éviter le zoom automatique d'iOS. */
.field { display: flex; flex-direction: column; gap: var(--s-1); font-size: var(--fs-small); color: var(--text-2); }
.input { width: 100%; min-height: var(--tap); padding: 0 var(--s-3); border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); color: var(--text); font: 400 var(--fs-input) / 1.2 var(--font); }
.input:focus { outline: 2px solid var(--accent-text); outline-offset: -1px; border-color: transparent; }
.input:disabled, .check:disabled, .switch--desactive { opacity: 0.45; cursor: default; }

/* Curseur : --piste donne un fond à la barre, un dégradé de couleur par exemple. */
.range { appearance: none; width: 100%; height: var(--tap-small); margin: 0; background: transparent; cursor: pointer; }
.range::-webkit-slider-runnable-track { height: var(--gauge); border-radius: var(--r-pill); background: var(--piste, var(--surface-2)); box-shadow: inset 0 0 0 1px var(--line); }
.range::-moz-range-track { height: var(--gauge); border-radius: var(--r-pill); background: var(--piste, var(--surface-2)); box-shadow: inset 0 0 0 1px var(--line); }
.range::-webkit-slider-thumb { appearance: none; width: var(--check); height: var(--check); margin-top: calc((var(--gauge) - var(--check)) / 2); border-radius: 50%; background: var(--surface); box-shadow: 0 0 0 2px var(--text); }
.range::-moz-range-thumb { width: var(--check); height: var(--check); border: 0; border-radius: 50%; background: var(--surface); box-shadow: 0 0 0 2px var(--text); }
.range:disabled { opacity: 0.45; cursor: default; }

/* Contrôle segmenté : une icône et un libellé par option. */
.seg { display: inline-flex; max-width: 100%; overflow-x: auto; padding: 3px; gap: 2px; border-radius: var(--r-btn); background: var(--surface-2); }
.seg button { display: inline-flex; flex: none; align-items: center; gap: var(--s-1); min-height: calc(var(--tap-small) - 2px); padding: 0 14px 0 10px; border: 0; border-radius: calc(var(--r-btn) - 3px); background: transparent; color: var(--text-2); font: 500 var(--fs-small) / 1 var(--font); cursor: pointer; }
.seg .icon { width: var(--icon-sm); height: var(--icon-sm); }
.seg button[aria-pressed='true'] { background: var(--surface); color: var(--text); box-shadow: var(--shadow-card); }

/* Jauge : scaleX plutôt que width, pour rester sur le compositeur. */
.gauge { height: var(--gauge); overflow: hidden; border-radius: var(--r-pill); background: var(--surface-2); }
.gauge > i { display: block; height: 100%; background: var(--accent); border-radius: inherit; transform-origin: left; transform: scaleX(var(--v, 0)); transition: transform var(--t-slow) var(--ease-out); }

/* Pastille de début de ligne : icône, ou initiale pour une personne. --c donne la couleur de catégorie. */
.pastille { --c: var(--text-2); display: grid; place-items: center; width: var(--pastille); height: var(--pastille); flex: none; border-radius: 50%; background: color-mix(in srgb, var(--c) 16%, var(--surface)); color: var(--c); font-size: calc(var(--pastille) * 0.39); font-weight: 600; }
.pastille .icon { width: var(--icon-md); height: var(--icon-md); }

/* Champ en erreur et messages : toujours une icône et une phrase qui dit quoi faire. */
.field--error .input { border-color: var(--danger); }
.field__msg { display: flex; align-items: center; gap: var(--s-1); color: var(--danger); }
.field__msg .icon { width: calc(var(--icon-sm) - 2px); height: calc(var(--icon-sm) - 2px); }
.notice { --c: var(--text-2); display: flex; gap: var(--s-3); padding: var(--s-3) var(--s-4); border-radius: var(--r-md); background: color-mix(in srgb, var(--c) 12%, var(--surface)); color: var(--text); }
.notice > .icon { color: var(--c); }
.notice--ok { --c: var(--ok); }
.notice--warn { --c: var(--warn); }
.notice--danger { --c: var(--danger); }

/* Indicateur de contraste : icône, ratio et phrase, jamais la couleur seule. */
.contrast { --c: var(--text-2); display: inline-flex; align-items: center; gap: var(--s-1); color: var(--c); font-size: var(--fs-caption); font-weight: 500; font-variant-numeric: tabular-nums; }
.contrast .icon { width: calc(var(--icon-sm) - 2px); height: calc(var(--icon-sm) - 2px); }
.contrast--ok { --c: var(--ok); }
.contrast--warn { --c: var(--warn); }
.contrast--danger { --c: var(--danger); }
.contrast--herite { --c: currentColor; }

/* Lien dans un texte */
.lien { color: var(--accent-text); text-decoration: underline; }

/* Choix de couleur et d'ambiance sur mesure, voir web/personnalisation.js. */
.choix { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.couleur-bloc { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); min-height: 84px; padding: var(--s-3) var(--s-4); border-radius: var(--r-md); font-weight: 600; box-shadow: inset 0 0 0 1px var(--line); }
.couleur-bloc__aa { font-size: var(--fs-h2); }
.couleur-bloc__texte { flex: 1 1 auto; }
.couleur-point { flex: none; width: var(--tap-small); height: var(--tap-small); padding: 0; border: 0; border-radius: 50%; cursor: pointer; box-shadow: inset 0 0 0 1px var(--line); }
.couleur-point--vide { background: var(--surface-2); cursor: default; }
.couleur-point[aria-pressed='true'] { outline: 2px solid var(--text); outline-offset: 2px; }
.apercus { position: sticky; z-index: 2; top: calc(var(--s-5) * -1); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); margin-inline: calc(var(--s-2) * -1); padding: var(--s-2); background: var(--surface); }
[data-density='large'] .apercus { position: static; grid-template-columns: minmax(0, 1fr); }
.apercu { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; padding: var(--s-3); border-radius: var(--r-md); font-size: var(--fs-small); box-shadow: inset 0 0 0 1px var(--line); }
.apercu__scene { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-1); }
.apercu__scene .gauge { width: 100%; }
.apercu__mesure { display: flex; flex-direction: column; gap: 2px; }
.sheet__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s-2); }

/* Interrupteur : piste, couche d'accent et pouce à deux faces. Seuls transform et opacity s'animent. */
.switch { position: relative; display: inline-block; flex: none; width: var(--switch-w); height: var(--switch-h); border-radius: var(--r-pill); background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--line-strong); }
.switch input { position: absolute; z-index: 3; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: inherit; }
.switch__actif { position: absolute; inset: 0; border-radius: inherit; background: var(--accent); opacity: 0; transition: opacity var(--t-fast); }
.switch__pouce { position: absolute; top: 3px; left: 3px; width: calc(var(--switch-h) - 6px); height: calc(var(--switch-h) - 6px); transition: transform var(--t-base) var(--ease-spring); will-change: transform; }
.switch__forme { position: absolute; inset: 0; }
.switch__face { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%; transition: opacity var(--t-fast), transform var(--t-base) var(--ease-spring); }
.switch__face .icon { width: 68%; height: 68%; stroke-width: calc(var(--icon-stroke) * 1.5); }
.switch__face--off { background: var(--text-2); color: var(--surface); }
.switch__face--on { background: var(--on-accent); color: var(--accent); opacity: 0; transform: rotate(-90deg) scale(0.6); }
.switch input:checked ~ .switch__actif { opacity: 1; }
.switch input:checked ~ .switch__pouce { transform: translateX(calc(var(--switch-w) - var(--switch-h))); }
.switch input:checked ~ .switch__pouce .switch__face--on { opacity: 1; transform: none; }
.switch input:checked ~ .switch__pouce .switch__face--off { opacity: 0; transform: rotate(90deg) scale(0.6); }
.switch input:focus-visible ~ .switch__pouce { outline: 2px solid var(--accent-text); outline-offset: 2px; border-radius: 50%; }

/* Tuile de choix : tout filtre ou réglage se choisit sur un aperçu de ce qu'il donne. */
.tuiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(calc(var(--tap) * 2.2), 1fr)); gap: var(--s-2); }
.tuile-choix { position: relative; display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; padding: var(--s-2); border: 0; border-radius: var(--r-md); background: var(--surface-2); color: var(--text-2); font: 500 var(--fs-caption) / 1.2 var(--font); text-align: center; cursor: pointer; transition: transform var(--t-press) var(--ease-press); }
.tuile-choix:active { transform: scale(var(--press-scale)); }
.tuile-choix[aria-pressed='true'] { background: color-mix(in srgb, var(--accent-text) 12%, var(--surface)); color: var(--accent-text); box-shadow: inset 0 0 0 2px var(--accent-text); }
.tuile-choix__apercu { position: relative; display: grid; overflow: hidden; height: calc(var(--tap) * 1.5); border-radius: calc(var(--r-md) * 0.6); background: var(--bg); box-shadow: inset 0 0 0 1px var(--line); }
.tuile-choix__nom { overflow-wrap: anywhere; }
.tuile-choix__coche { position: absolute; z-index: 1; top: 4px; right: 4px; display: grid; place-items: center; width: var(--icon-md); height: var(--icon-md); border-radius: 50%; background: var(--accent-text); color: var(--surface); transform: scale(0); opacity: 0; transition: transform var(--t-base) var(--ease-spring), opacity var(--t-fast); }
.tuile-choix__coche .icon { width: 70%; height: 70%; stroke-width: calc(var(--icon-stroke) * 1.5); }
.tuile-choix[aria-pressed='true'] .tuile-choix__coche { transform: none; opacity: 1; }

/* Petits aperçus, dessinés avec les vraies variables : ils montrent la vraie ambiance, le vrai accent. */
.mini { display: flex; flex-direction: column; justify-content: center; gap: 4px; min-width: 0; padding: var(--s-2); color: var(--text); }
.mini__aa { font-size: var(--fs-small); font-weight: 650; line-height: 1; }
.mini__trait { width: 70%; height: 3px; border-radius: var(--r-pill); background: var(--text-2); }
.mini__bouton { width: 60%; height: 10px; border-radius: calc(var(--r-btn) * 0.5); background: var(--accent); }
.mini__plein { display: block; width: 60%; height: 100%; border-radius: inherit; background: var(--accent); }
.mini .gauge { height: 5px; }
.mini-duo { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.mini-duo .mini { padding: var(--s-1); }
.mini--arc { align-items: center; background: conic-gradient(in hsl longer hue, hsl(0 90% 55%), hsl(0 90% 55%)); color: #ffffff; }
.mini--densite i { display: block; height: 3px; border-radius: var(--r-pill); background: var(--text-2); }
.mini--compact { gap: 2px; }
.mini--normale i:nth-child(n + 4) { display: none; }
.mini--large { gap: 5px; }
.mini--large i { height: 8px; }
.mini--large i:nth-child(n + 3) { display: none; }
.mini-coin { place-self: center; width: 56%; height: 62%; border-radius: calc(24px * var(--r-k)) 0 0 0; background: var(--surface-2); box-shadow: inset 2px 2px 0 var(--text-2); }
.mini-police { place-self: center; color: var(--text); font-size: var(--fs-h2); line-height: 1; }

/* Case : contrôle natif redessiné, clavier et lecteur d'écran compris. */
.choice { display: flex; align-items: center; gap: var(--s-3); min-height: var(--tap); cursor: pointer; }
.check { appearance: none; flex: none; margin: 0; cursor: pointer; background: var(--surface-2); }
.check { display: grid; place-items: center; width: var(--check); height: var(--check); border-radius: calc(var(--check) * 0.32); box-shadow: inset 0 0 0 1px var(--line-strong); }
.check::after { content: ''; width: calc(var(--check) * 0.5); height: calc(var(--check) * 0.27); border: solid var(--on-accent); border-width: 0 0 2px 2px; rotate: -45deg; translate: 0 -1px; scale: 0; transition: scale var(--t-fast) var(--ease-spring); }
.check:checked { background: var(--accent); box-shadow: none; }
.check:checked::after { scale: 1; }

/* État vide : une icône, une phrase, l'action suivante. */
.empty { display: flex; flex-direction: column; align-items: center; gap: var(--s-3); padding: var(--s-6) var(--s-4); text-align: center; color: var(--text-2); }

/* Tableau : à placer dans un conteneur à défilement horizontal. */
.table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.table th { text-align: left; font-size: var(--fs-small); font-weight: 500; color: var(--text-2); }
.table th, .table td { padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); white-space: nowrap; }
.table tr:last-child td { border-bottom: 0; }

/* Menu latéral : à partir de 900 px, à la place des onglets du bas. */
.side-link { display: flex; align-items: center; gap: var(--s-3); min-height: var(--tap); padding: 0 var(--s-3); border-radius: var(--r-sm); color: var(--text-2); font-weight: 500; text-decoration: none; }
.side-link[aria-current='page'] { background: var(--surface-2); color: var(--text); }

/* Titre de site vitrine : seule taille qui suit la largeur de l'écran. */
.display { font-family: var(--font-display); font-size: var(--fs-display); font-weight: 650; letter-spacing: calc(-0.03em * var(--track-k)); line-height: 1.02; text-wrap: balance; }

/* Barre d'onglets flottante : seul endroit où le flou est permanent. */
.tabbar { display: flex; justify-content: space-around; align-items: center; height: var(--tabbar); padding-inline: var(--s-2); border-radius: var(--r-lg); background: var(--glass); box-shadow: var(--shadow-float); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
.tab { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: var(--tap); border: 0; background: none; color: var(--text-2); font: 500 var(--fs-caption) / 1.2 var(--font); cursor: pointer; }
.tab[aria-current='page'] { color: var(--text); }

/* Message et feuille basse */
.toast { position: fixed; z-index: 30; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); display: flex; align-items: center; gap: var(--s-3); width: max-content; max-width: calc(100vw - 32px); padding: 10px var(--s-4); border-radius: var(--r-md); background: var(--text); color: var(--bg); font-size: var(--fs-small); font-weight: 500; box-shadow: var(--shadow-float); transform: translateX(-50%); animation: socle-rise var(--t-base) var(--ease-out); }
.toast .btn { --b: transparent; color: inherit; }
dialog.sheet { width: 100%; max-width: 480px; margin: auto auto 0; padding: var(--s-5) var(--s-4) calc(var(--s-4) + env(safe-area-inset-bottom, 0px)); border: 0; border-radius: var(--r-lg) var(--r-lg) 0 0; background: var(--surface); color: var(--text); }
dialog.sheet .chip:not([aria-pressed='true']) { background: var(--surface-2); }
dialog.sheet[open] { animation: socle-rise var(--t-slow) var(--ease-out); }
dialog.sheet::backdrop { background: var(--scrim); }
@media (min-width: 900px) { dialog.sheet { margin: auto; border-radius: var(--r-lg); } }

/* Squelette de chargement */
.skeleton { border-radius: var(--r-sm); background: var(--surface-2); animation: socle-pulse 1.4s ease-in-out infinite; }

@keyframes socle-rise { from { opacity: 0; translate: 0 12px; } }
@keyframes socle-pulse { 50% { opacity: 0.5; } }
@keyframes socle-spin { to { rotate: 360deg; } }

@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; }
}
