/* ═══════════════════════════════════════════════════════════════════
   Tableau de bord : trois niveaux (DESIGN.md, section « Tableau de bord :
   trois niveaux »). L'ecran repond a une seule question : qu'est-ce que je
   fais maintenant ? La hierarchie passe par le fond et l'espace, jamais
   par un filet : le maintenant sur --surface (la surface la plus haute
   dans les quatre themes), la suite sur le fond nu, le contexte sur --bg2
   (entre les deux dans les quatre themes).
   Le contenu decide de la mise en page : le DOM est construit par
   App.renderDashboard, une zone sans contenu n'existe pas, et la bascule
   mono / deux colonnes est posee en data-layout depuis le contenu reel.
   Aucune valeur en dur : couleurs, typo, rayons, durees et espacement
   viennent de variables.css. L'echelle --space-* est nee dans ce fichier.
   Les seules tailles en px sont des largeurs de pastille et de glyphe
   deplacees telles quelles (pas de token de taille dans le systeme).
   ═══════════════════════════════════════════════════════════════════ */

/* ── Composition : le contenu decide (DESIGN.md, « le contenu decide de
   la mise en page »). App.renderDashboard construit le DOM et pose
   data-layout : "mono" tant que le contexte n'a pas de quoi remplir une
   colonne, "two" quand le jour a quelque chose a gauche ET que le contexte
   a plus d'un bloc. Le responsive n'est qu'une couche par-dessus : sous
   1024px tout est en colonne, sous 720px les blocs de contexte s'empilent. ── */
.dash-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
}

.dash-main {
  min-width: 0;
  display: grid;
  gap: var(--space-5);
  align-content: start;
}

/* Contexte en rangee (mono) : chaque bloc prend une part egale de la
   largeur, la rangee se remplit avec ce qui existe. Un bloc seul est
   pleine largeur, deux se partagent la ligne, trois aussi : aucune grille
   fixe, aucun trou. */
.dash-body[data-layout="mono"] .dash-ctx {
  display: flex;
  gap: var(--space-4);
  align-items: stretch;
}

.dash-body[data-layout="mono"] .dash-ctx > * {
  flex: 1 1 0;
  min-width: 0;
}

@media (max-width: 719px) {
  .dash-body[data-layout="mono"] .dash-ctx {
    flex-direction: column;
  }
}

/* Contexte en colonne (two) : le rail, a droite du jour a partir de 1024px. */
.dash-body[data-layout="two"] .dash-ctx {
  min-width: 0;
  display: grid;
  gap: var(--space-4);
  align-content: start;
}

@media (min-width: 1024px) {
  .dash-body[data-layout="two"] {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    column-gap: var(--space-6);
    align-items: start;
  }
}

/* Etat vide : une seule carte d'invitation, centree. A partir de 720px
   elle occupe la moitie de la largeur (memes rapports fr que la grille,
   aucune largeur en dur) ; en dessous, toute la largeur. */
.dash-empty {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 720px) {
  .dash-empty {
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr);
  }

  .dash-empty > .dash-now {
    grid-column: 2;
  }
}

.dash-now[data-kind="courses"] {
  text-align: center;
}

.dash-now[data-kind="courses"] .dash-now-actions {
  justify-content: center;
}

/* ── Niveau 1 : maintenant ──
   Seul bloc pose sur la surface la plus haute, seul element qui cumule
   taille, graisse et contraste, une seule action pleine. */
.dash-now {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  margin-bottom: var(--space-6);
}

@media (min-width: 720px) {
  .dash-now {
    padding: var(--space-6);
  }
}

/* Le salut n'est plus un hero : une ligne de contexte, la plus discrete
   du bloc. */
.dash-now-context {
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
  color: var(--muted2);
}

.dash-now-eyebrow {
  margin: 0 0 var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-emphasis);
  color: var(--muted);
}

/* L'accent appartient a ce qui EST dans un etat : un cours qui tourne,
   une echeance qui approche. Jamais au bouton, jamais au titre. */
.dash-now[data-kind="active"] .dash-now-eyebrow {
  color: var(--green-text);
}

.dash-now[data-kind="deadline"] .dash-now-eyebrow {
  color: var(--orange);
}

.dash-now-title {
  margin: 0;
  font-family: var(--font-display), sans-serif;
  font-size: var(--text-lg);
  font-weight: var(--weight-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--text);
  overflow-wrap: anywhere;
}

@media (min-width: 720px) {
  .dash-now-title {
    font-size: var(--text-xl);
  }
}

.dash-now-meta {
  margin: var(--space-2) 0 0;
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--muted);
}

/* Avancement du cours en cours : la barre partagee .bar-track / .bar-fill
   (layout.css), inchangee ; ici seulement son espace. */
.dash-now-progress {
  margin-top: var(--space-4);
}

.dash-now-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

/* Le seul bouton plein poids de l'ecran. Marge interne et interlignage
   le portent a la hauteur tactile sans valeur de hauteur en dur. */
.dash-now .dash-now-cta {
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
}

@media (max-width: 479px) {
  .dash-now .dash-now-cta {
    width: 100%;
    justify-content: center;
  }
}

/* Un seul bouton plein poids par ecran : le Planifier de la topbar est
   secondaire (.btn-ghost) sur toutes les pages, chaque page porte son
   propre bouton plein (DESIGN.md, « Un seul bouton plein poids par
   ecran »). */

/* ── Niveau 2 : la suite ──
   Attenue par construction : --muted, pose sur le fond, separe par
   l'espace seul. Present si on le cherche, ne reclame rien. */
.dash-next-title {
  margin: 0 0 var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-emphasis);
  color: var(--muted);
}

/* Colonne des heures alignee sur toute la liste : sous-grille, sans
   largeur fixe. Sans sous-grille, chaque ligne s'empile, rien ne casse. */
.dash-next-list {
  display: grid;
  grid-template-columns: auto max-content minmax(0, 1fr);
  row-gap: var(--space-3);
  column-gap: var(--space-3);
}

.dash-next-item {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
  align-items: start;
  width: 100%;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.dash-next-time {
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.dash-next-body {
  min-width: 0;
  display: grid;
}

.dash-next-name {
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  font-weight: var(--weight-emphasis);
  color: var(--muted);
  transition: color var(--dur-fast) var(--ease-out);
}

.dash-next-item:hover .dash-next-name {
  color: var(--text);
}

.dash-next-detail {
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--muted2);
}

/* ── Niveau 3 : contexte ──
   Le fond. --bg2, --muted2, consultable sans effort, aucune action. */
.dash-ctx-block {
  background: var(--bg2);
  border-radius: var(--radius);
  padding: var(--space-4);
  color: var(--muted2);
}

.dash-ctx-title {
  margin: 0 0 var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-emphasis);
  color: var(--muted2);
}

.dash-ctx-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.dash-ctx-note {
  font-size: var(--text-xs);
  color: var(--muted2);
  font-variant-numeric: tabular-nums;
}

.dash-ctx-list {
  display: grid;
  gap: var(--space-2);
}

.dash-ctx-item {
  min-width: 0;
  display: grid;
}

.dash-ctx-item-name {
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  font-weight: var(--weight-emphasis);
  color: var(--muted2);
}

.dash-ctx-item-detail {
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--muted2);
}

/* Reperes : quatre chiffres calmes. */
.dash-ctx-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-content: start;
  gap: var(--space-3) var(--space-4);
}

@media (min-width: 540px) and (max-width: 1023px) {
  .dash-ctx-stats {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.dqs-item {
  min-width: 0;
  display: grid;
  align-content: start;
  gap: var(--space-1);
}

.dqs-value {
  font-family: var(--font-display), sans-serif;
  font-weight: var(--weight-heading);
  font-size: var(--text-lg);
  line-height: var(--leading-tight);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

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

/* Prochains jours (DESIGN.md, section Tableau de bord : liste des prochains
   jours) : liste verticale groupee par jour, facon liste groupee iOS. Un
   en-tete par jour en --muted, des lignes de hauteur tactile sur --surface,
   separees par un ecart de fond, jamais par un filet. Code a gauche,
   horaire a droite en chiffres tabulaires. */
.day-list {
  display: grid;
  gap: var(--space-3);
}

.day-group {
  display: grid;
  gap: var(--space-2);
}

.day-group-title {
  font-size: var(--text-xs);
  font-weight: var(--weight-emphasis);
  color: var(--muted);
}

.day-rows {
  display: grid;
  gap: var(--space-1);
}

.day-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--tap-min);
  padding: var(--space-2) var(--space-3);
  background: var(--surface);
  border: none;
  border-radius: var(--radius-sm);
  color: var(--muted2);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
}

.day-row:hover,
.day-row:focus-visible {
  color: var(--text);
}

.day-row-code {
  font-family: var(--font-display), sans-serif;
  font-size: var(--text-sm);
  font-weight: var(--weight-emphasis);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.day-row-time {
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* Revision par UE (DESIGN.md, section Tableau de bord : revision par UE) :
   une barre par UE, sa longueur est la couverture, sa couleur l'urgence
   (retard --red, a surveiller --orange, sous controle --green) ; la valeur
   suit la couleur, l'etat est nomme en toutes lettres sous la barre avec
   l'echeance. Voir tout est le seul lien du contexte. */
.dash-ctx-link {
  position: relative;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: var(--text-xs);
  font-weight: var(--weight-emphasis);
  color: var(--green-text);
  cursor: pointer;
}

/* Zone de toucher de --tap-min autour du lien, sans changer son dessin. */
.dash-ctx-link::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, var(--tap-min));
  height: var(--tap-min);
  transform: translate(-50%, -50%);
}

.ue-rate-list {
  display: grid;
  gap: var(--space-4);
}

.ue-rate {
  display: grid;
  gap: var(--space-1);
}

.ue-rate-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.ue-rate-code {
  font-family: var(--font-display), sans-serif;
  font-size: var(--text-sm);
  font-weight: var(--weight-emphasis);
  color: var(--muted);
  flex-shrink: 0;
}

.ue-rate-name {
  font-size: var(--text-xs);
  color: var(--muted2);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ue-rate-value {
  font-size: var(--text-sm);
  font-weight: var(--weight-emphasis);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.ue-rate-due {
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--muted2);
}

.ue-rate[data-tone="late"] .ue-rate-value {
  color: var(--red);
}

.ue-rate[data-tone="late"] .bar-fill {
  background: var(--red);
}

.ue-rate[data-tone="watch"] .ue-rate-value {
  color: var(--orange);
}

.ue-rate[data-tone="watch"] .bar-fill {
  background: var(--orange);
}

.ue-rate[data-tone="ok"] .ue-rate-value {
  color: var(--green-text);
}

.ue-rate[data-tone="ok"] .bar-fill {
  background: var(--green);
}

/* Serie : elle informe, elle ne reclame rien (a 0 le bloc disparait). */
.streak-inner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.streak-icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  color: var(--orange);
}

.streak-content {
  flex: 1;
}

.streak-value {
  font-family: var(--font-display), sans-serif;
  font-weight: var(--weight-heading);
  font-size: var(--text-lg);
  line-height: var(--leading-tight);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.streak-label {
  font-size: var(--text-xs);
  color: var(--muted2);
  margin-top: var(--space-1);
}

.streak-dots {
  display: flex;
  gap: var(--space-1);
  margin-top: var(--space-2);
  width: 100%;
}

/* Taille de pastille deplacee telle quelle (pas de token de taille). */
.streak-dot {
  width: 10px;
  height: 10px;
  border-radius: var(--radius-pill);
  background: var(--border);
  transition: background-color var(--dur-slow) var(--ease-out);
}

.streak-dot.lit {
  background: var(--orange);
}

/* Citation : contexte, pas d'opacite sur un glyphe, une couleur dediee. */
.dash-quote {
  display: flex;
  align-items: center;
}

.quote-inner {
  display: grid;
  gap: var(--space-3);
  width: 100%;
}

/* Taille de glyphe deplacee telle quelle (pas de token de taille). */
.quote-mark {
  width: 26px;
  height: 26px;
  color: var(--muted2);
}

.quote-text {
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--leading-loose);
  font-style: italic;
  color: var(--muted);
}

.quote-author {
  font-size: var(--text-xs);
  font-weight: var(--weight-emphasis);
  font-style: normal;
  color: var(--muted2);
}

/* ── Invitation a poser un widget (lot 4 de la 2.11) ──
   Une carte de contexte comme les autres, jamais un bandeau : elle se
   propose une fois et disparait. Le fond doux la distingue sans la faire
   crier, elle ne doit pas concurrencer le bloc « maintenant ». */
.dash-widget-invite {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.dash-widget-invite__titre {
  margin: 0;
  font-family: var(--font-display), sans-serif;
  font-size: var(--text-sm);
  font-weight: var(--weight-heading);
  line-height: var(--leading-tight);
  color: var(--text);
}

.dash-widget-invite__sous {
  margin: var(--space-2) 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--muted);
}

.dash-widget-invite__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

/* Lien secondaire : souligne, pas un second bouton. Une seule action
   principale par carte. */
.dash-widget-invite__lien {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--text-xs);
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.dash-widget-invite__lien:hover {
  color: var(--text);
}

/* ── Liste des trois widgets (modale) ── */
.widget-liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.widget-liste__item {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.widget-liste__texte {
  flex: 1;
  min-width: 0;
}

.widget-liste__nom {
  margin: 0;
  font-family: var(--font-display), sans-serif;
  font-size: var(--text-sm);
  font-weight: var(--weight-heading);
  color: var(--text);
}

.widget-liste__quoi {
  margin: var(--space-2) 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--muted);
}
