/* ── Dashboard desktop (≥1024px) — écran "Aujourd'hui" ────────────────────
   4 zones dans le contenu de #screen-today, grille 2x2 : calendrier éditorial
   (haut gauche), idée de Story du jour (haut droite), historique compact (bas
   gauche), épinglés (bas droite). Les .dash-panel sont masqués par défaut
   (mobile) et n'apparaissent qu'à partir de 1024px ; l'écran "Aujourd'hui"
   mobile (today-alert/nudge/tâche du jour/événements) est inchangé en dessous
   de ce seuil et masqué au-dessus. */

/* Les 4 cadrans du dashboard desktop sont masqués par défaut (mobile), qui garde
   l'écran "Aujourd'hui" classique en dessous. Les stats (#brief-bar/#network-stats-cards)
   ont déménagé dans le header (desktop, voir layout-desktop.css) — plus besoin
   d'exception ici, #dash-events n'enveloppe plus rien de partagé avec mobile. */
#dash-story, #dash-calendar, #dash-history, #dash-events { display: none; }

/* Angle animable pour le liseret dégradé des cadrans (voir .dash-panel::before
   plus bas) — @property est nécessaire pour que le navigateur interpole un
   angle de conic-gradient ; sans ça l'anneau reste figé (dégradation propre
   sur les navigateurs qui ne le supportent pas). */
@property --dash-border-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}
@keyframes dash-border-spin {
  to { --dash-border-angle: 360deg; }
}

@media (min-width: 1024px) {
  /* La grille remplace le scroll de page classique : chaque cadran scrolle
     pour son propre compte (voir min-height:0 plus bas, même piège CSS Grid
     que pour #main-app/.screen dans layout-desktop.css). */
  #screen-today.screen.active {
    overflow: hidden;
    padding: 0;
    display: grid;
    grid-template-columns: 1.7fr 1fr;
    grid-template-rows: 1fr 1fr;
    grid-template-areas: "cal story" "hist stats";
    gap: 16px;
    padding: 20px 24px;
    box-sizing: border-box;
  }

  #screen-today > #today-alert,
  #screen-today > #today-nudge,
  #screen-today > .section:not(#events-section),
  #screen-today > #events-section {
    display: none;
  }

  /* IDs répétés ici (pas juste .dash-panel) : la règle de masquage mobile plus
     haut cible #dash-story/#dash-calendar/#dash-history par ID (specificité
     1,0,0), qui battrait un simple sélecteur de classe même dans cette media
     query — la specificité ne dépend pas de la media query, seulement du
     sélecteur et de l'ordre. */
  .dash-panel, #dash-story, #dash-calendar, #dash-history, #dash-events {
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 0;
    /* Glass panel (voir glass.css .glass-panel) : légèrement transparent,
       floute le fond de #main-app (var(--bg), voir index.css) qui se
       devine à travers plutôt que d'être caché derrière une card opaque. */
    background: var(--glass-bg);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-radius: var(--radius-xl);
    overflow: hidden;
    /* filter: drop-shadow, pas box-shadow — clippé par le overflow:hidden ci-dessus sinon
       (cf. --shadow-card-filter, theme.css). C'est le panneau lui-même qui doit se détacher
       du fond de #screen-today, pas son contenu interne (.dash-cal-day, .dash-hist-card...). */
    filter: var(--shadow-card-filter);
  }
  #dash-story { grid-area: story; }
  #dash-calendar { grid-area: cal; }
  #dash-history { grid-area: hist; }
  #dash-events { grid-area: stats; }

  .dash-story-content {
    flex: 1; min-height: 0; overflow-y: auto;
    padding: 0 16px 16px;
  }
  .dash-story-content .card { margin-bottom: 0; }

  /* Liseret dégradé animé — boucle toutes les couleurs de la palette (+ le
     rose f94989) autour de chaque cadran. Double masque (mask-composite:
     exclude) : ne peint que l'anneau, sans déborder du cadre du panneau —
     reste compatible avec l'overflow:hidden ci-dessus, requis pour les coins
     arrondis du contenu (photos de l'historique, etc.).

     z-index explicite, sinon les cards qui défilent passent PAR-DESSUS l'anneau :
     .screen.active .card (glass.css) pose `animation: fadeUp ... both`, et le
     fill-mode `both` laisse `transform: translateY(0)` sur la card une fois
     l'animation finie. Un transform non-none crée un contexte d'empilement au
     même niveau (z-index 0) que ce ::before positionné en z-index:auto — à
     égalité, c'est l'ordre du DOM qui tranche, et les cards viennent après. */
  .dash-panel::before {
    z-index: 1;
    content: "";
    position: absolute; inset: 0;
    border-radius: inherit;
    padding: 1.5px;
    background: conic-gradient(from var(--dash-border-angle),
      var(--card-border-base) 0%, var(--card-border-base) 42%,
      var(--card-border-shine) 50%, var(--card-border-base) 58%, var(--card-border-base) 100%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    animation: dash-border-spin 12s linear infinite;
    pointer-events: none;
  }

  .dash-panel-head {
    font-family: var(--font-display);
    font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.06em; color: rgba(var(--text-rgb),0.45);
    padding: 14px 16px 10px; flex-shrink: 0;
  }

  /* Événements locaux — liste verticale des événements à venir (voir week.js
     loadTrendingEvents, qui alimente ce conteneur en même temps que #events-list
     côté mobile). Même conteneur/scroll que #dash-history-list ; les cards
     gardent leur style .card défini dans index.css. */
  #dash-events-list {
    flex: 1; min-height: 0; overflow-y: auto;
    padding: 0 16px 16px;
  }
  #dash-events-list .card { margin-bottom: 8px; }

  /* Calendrier — 6 cards en grille 3x2 (une par jour), chacune scrollable */
  .dash-calendar-grid {
    flex: 1; min-height: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(2, 1fr);
    gap: 12px;
    padding: 0 16px 16px;
  }
  .dash-cal-day {
    background: var(--surface-alt);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    display: flex; flex-direction: column; min-height: 0;
    overflow: hidden;
  }
  .dash-cal-day.today { background: rgba(var(--accent-rgb),0.08); border-color: var(--accent-pink-muted); border-width: 2px; }
  /* Le libellé du jour partage sa ligne avec les pastilles d'avancement (voir
     _dashDayStatusBadges) : flex centré plutôt que text-align, pour qu'elles restent collées au
     libellé et passent à la ligne ensemble sur une colonne étroite. */
  .dash-cal-day-head {
    font-size: 12px; font-weight: 700; color: rgba(var(--text-rgb),0.5);
    display: flex; align-items: center; justify-content: center; gap: 5px; flex-wrap: wrap;
    padding: 8px 4px; flex-shrink: 0;
    border-bottom: 1px solid var(--border-subtle);
    text-transform: capitalize;
  }
  .dash-cal-day-head .badge { font-size: 9px; padding: 1px 6px; letter-spacing: 0.03em; }
  .dash-cal-day.today .dash-cal-day-head { color: var(--accent-pink-muted); }
  .dash-cal-day-tasks { flex: 1; overflow-y: auto; padding: 6px; display: flex; flex-direction: column; gap: 6px; }
  /* Chaque tâche affiche : format (photo/reel/carrousel), famille de post,
     réseau(x) cible(s), début de la description et l'action du jour — assez
     de place pour ça vu que le calendrier est passé de 7 colonnes étroites à
     6 cards plus larges. */
  .dash-cal-chip {
    display: flex; flex-direction: column; gap: 3px;
    background: var(--bg-card); border-radius: 6px;
    padding: 6px 7px; cursor: pointer; transition: background 0.15s;
  }
  /* États AVANT le :hover : à spécificité égale (une classe + une pseudo-classe contre deux
     classes), c'est le dernier déclaré qui gagne — dans l'autre ordre, une vignette publiée ou
     programmée ne réagissait plus du tout au survol. */
  .dash-cal-chip.done { opacity: 0.55; background: rgba(80,200,120,0.16); }
  .dash-cal-chip.programme { background: rgba(242,165,76,0.18); }
  .dash-cal-chip:hover { background: rgba(var(--accent-rgb),0.12); }
  .dash-cal-chip-meta { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
  .dash-cal-chip-meta .badge { font-size: 9.5px; padding: 1px 6px; }
  .dash-cal-chip-nets { display: inline-flex; gap: 2px; margin-left: auto; }
  /* Texte complet, sans troncature — chaque card grandit avec son contenu,
     .dash-cal-day-tasks scrolle déjà si une journée déborde. */
  .dash-cal-chip-title {
    font-size: 12.5px; font-weight: 600; color: var(--text); line-height: 1.3;
    white-space: normal; word-break: break-word;
  }
  .dash-cal-chip-desc {
    font-size: 11.5px; color: rgba(var(--text-rgb),0.55); line-height: 1.35;
    white-space: normal; word-break: break-word;
  }
  .dash-cal-chip-action {
    font-size: 10.5px; color: var(--accent); line-height: 1.3;
    white-space: normal; word-break: break-word;
  }
  .dash-cal-empty { font-size: 11px; color: rgba(var(--text-rgb),0.2); text-align: center; padding: 8px 0; }
  /* Pendant le chargement, .card-loading est seul dans ces grilles (voir index.html) — sans ça
     il ne remplit que la 1re cellule (même piège que .stats-grid, voir stats-desktop.css) au
     lieu d'être centré dans tout le panneau. */
  .dash-calendar-grid .card-loading { grid-column: 1 / -1; grid-row: 1 / -1; min-height: 0; }
  /* .dash-history-pills est en flex et non en grid (voir plus bas) : grid-column/grid-row y sont
     inertes, le loader restait donc collé en haut à gauche. On lui donne la ligne entière — son
     propre centrage interne s'occupe de l'horizontale — et on recentre cette ligne, sinon
     align-content:start (utile aux cards) la plaque en haut. */
  .dash-history-pills > .card-loading { flex: 1 0 100%; min-height: 0; }
  .dash-history-pills:has(> .card-loading) { align-content: center; }

  /* Historique — grille 4x2 de mini-cards, les 8 dernières publications : juste l'image et le
     début de la légende, rien d'autre. Clic → lightbox détaillée (voir plus bas, hors media
     query). Chaque card est coupée en deux parts égales, moitié image / moitié légende. */
  /* flex-wrap plutôt que CSS Grid : avec un enfant dimensionné par aspect-ratio dans une card
     flex-column, le calcul de hauteur "auto" des lignes de grille se trompe (mesure la card
     plus petite que sa propre photo — bug d'intrinsic sizing, pas un souci de flex-shrink),
     et la légende passait sous l'overflow:hidden de la card, invisible. flex-wrap donne à
     chaque ligne la hauteur réelle de son item le plus grand, sans ce piège. */
  .dash-history-pills {
    flex: 1; min-height: 0; overflow-y: auto;
    display: flex; flex-wrap: wrap;
    align-content: start;
    gap: 10px; padding: 0 16px 16px;
  }
  /* Hauteur explicite sur la CARD : c'est elle qui permet de donner exactement 50% à l'image et
     50% à la légende via flex: 1 1 50% sur les deux enfants — avec une hauteur dictée par le
     contenu, "la moitié" n'a pas de référence.
     Exprimée en % de la hauteur du conteneur plutôt qu'en px ou en aspect-ratio, pour que les
     deux rangées remplissent le panneau au pixel près sans jamais déclencher l'ascenseur : la
     hauteur suit le panneau quelle que soit la taille de la fenêtre, là où un aspect-ratio suit
     la LARGEUR et redevient trop haut dès que la fenêtre s'élargit. Le % se résout sur la
     content-box de .dash-history-pills (hauteur définie par flex:1), d'où le retrait du seul
     gap inter-rangées. */
  .dash-hist-card {
    width: calc(25% - 7.5px);
    height: calc((100% - 10px) / 2);
    display: flex; flex-direction: column; cursor: pointer;
    background: var(--surface-alt); border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg); overflow: hidden; transition: background 0.15s;
  }
  .dash-hist-card:hover { background: rgba(var(--accent-rgb),0.08); }
  /* Moitié haute de la card, croppée via object-fit:cover ; logo du réseau posté en overlay
     coin haut droit de la photo.
     L'image reste en position:absolute (hors flux) : si elle était en flux normal, son ratio
     intrinsèque (souvent 9/16, portrait) fuiterait dans le calcul de taille de ce flex item et
     écraserait le partage 50/50 — la photo imposerait sa propre hauteur et repousserait la
     légende sous l'overflow:hidden de la card, invisible. En absolute elle ne contribue plus à
     la taille intrinsèque du wrap : seul flex-basis décide, et inset:0 + object-fit assurent le
     crop. min-height:0 pour la même raison, il neutralise le min-height:auto des flex items. */
  .dash-hist-photo-wrap { position: relative; flex: 1 1 50%; min-height: 0; overflow: hidden; }
  .dash-hist-photo {
    position: absolute; inset: 0;
    width: 100%; height: 100%; object-fit: cover;
    background: #111; display: block;
  }
  /* Miniature indisponible : la publication a bien eu lieu, seul le visuel a expiré (URL S3
     pré-signée + objet purgé au bout de 7 jours). La coche verte le dit, plutôt que de laisser
     un carré vide ambigu. Vert littéral : le thème n'expose aucune variable de succès, et
     celui-ci tient sur --bg-card en clair (#ffffff) comme en sombre (#131c2e). */
  .dash-hist-photo-empty {
    background: var(--bg-card);
    display: flex; align-items: center; justify-content: center;
  }
  .dash-hist-photo-empty::after {
    content: '✓';
    color: #22c55e;
    font-size: 26px; font-weight: 700; line-height: 1;
  }
  .dash-hist-net-badge {
    position: absolute; top: 4px; right: 4px;
    display: flex; padding: 2px;
    background: rgba(0,0,0,0.55); border-radius: 4px; backdrop-filter: blur(4px);
  }
  /* Moitié basse. Clamp à 4 lignes : c'est ce qui tient dans la moitié d'une card réduite
     (~75px moins les 12px de padding, pour une interligne de 13.5px). En laisser plus ferait
     déborder le texte sous l'overflow:hidden, en laisser moins gâcherait la place gagnée. */
  .dash-hist-caption {
    flex: 1 1 50%; min-height: 0;
    padding: 6px 8px;
    font-size: 10px; color: rgba(var(--text-rgb),0.75); line-height: 1.35;
    display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
  }
}

/* ── Lightbox historique — visualisation d'un post publié ─────────────────
   Calquée sur l'aperçu de publication fourni en référence (avatar+pseudo,
   photo, icônes cœur/commentaire/signet, légende, bloc hashtags), moins le
   chrome d'éditeur (barre de statut/POST, bandeau d'avertissement, bouton +,
   rail d'icônes latéral) qui n'a pas de sens pour visualiser un post déjà en
   ligne. Pas de media query : uniquement déclenchée depuis les cards du
   dashboard desktop (#dash-hist-card), jamais atteignable sur mobile. */
#dash-hist-lightbox .dash-hist-lightbox-modal {
  position: relative;
  width: 480px; max-width: 90vw; max-height: 85vh;
  background: var(--bg-elevated); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl); overflow: hidden;
  display: flex; flex-direction: column;
}
/* Zone scrollable indépendante de la topbar (croix/badge réseau, position
   absolute) et des actions (toujours visibles en bas) — une légende longue
   scrolle ici sans faire disparaître le bouton de fermeture ni Copier/Republier. */
.dash-hist-lightbox-scroll { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
.dash-hist-lightbox-topbar {
  position: absolute; top: 10px; right: 10px; z-index: 1;
  display: flex; align-items: center; gap: 8px;
}
.dash-hist-lightbox-net-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--surface-alt); border: 1px solid var(--border-subtle);
}
.dash-hist-lightbox-close {
  width: 30px; height: 30px; border-radius: 50%; border: none;
  background: rgba(0,0,0,0.55); color: #fff; font-size: 15px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; backdrop-filter: blur(3px);
}
.dash-hist-lightbox-header { display: flex; align-items: center; gap: 8px; padding: 14px 16px 0; }
.dash-hist-lightbox-header .dash-hist-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  background: var(--accent-magenta); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
}
.dash-hist-lightbox-header .dash-hist-avatar-net { background: transparent; }
.dash-hist-lightbox-header .dash-hist-username { font-size: 13px; font-weight: 700; color: var(--text); }
.dash-hist-lightbox-media-wrap { width: 100%; aspect-ratio: 4/3; background: #111; margin-top: 12px; flex-shrink: 0; }
.dash-hist-lightbox-media { width: 100%; height: 100%; object-fit: cover; display: block; }
.dash-hist-lightbox-icons { display: flex; align-items: center; gap: 12px; padding: 10px 16px 0; color: var(--text); }
.dash-hist-lightbox-icons svg { display: block; }
.dash-hist-lightbox-icon-spacer { margin-left: auto; }
.dash-hist-lightbox-caption {
  padding: 8px 16px 0; font-size: 13px; color: var(--text); line-height: 1.5;
  white-space: pre-wrap;
}
.dash-hist-lightbox-hashtags {
  margin: 10px 16px 12px; padding: 8px 10px;
  background: var(--surface-alt); border-radius: 8px;
  font-size: 11.5px; color: rgba(var(--text-rgb),0.55); line-height: 1.4;
}
.dash-hist-lightbox-actions {
  display: flex; gap: 10px; padding: 12px 16px 16px; flex-shrink: 0;
  border-top: 1px solid var(--border-subtle);
}
/* aspect-ratio (pas juste height fixe) pour rester presque carrés quel que
   soit l'espace pris par le texte des boutons. */
.dash-hist-lightbox-btn {
  flex: 1;
  display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 6px;
  padding: 9px 12px;
  background: var(--surface-alt); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg);
  color: var(--text); font-size: 12px; font-weight: 600; cursor: pointer; transition: background 0.15s;
}
.dash-hist-lightbox-btn:hover { background: rgba(var(--text-rgb),0.06); }
/* Rose pâle (var(--accent), comme .btn-primary / .btn-full-soft) et non le magenta d'identité :
   « Republier » est une action courante de l'Historique, pas un CTA de connexion/onboarding. */
.dash-hist-lightbox-btn-primary {
  background: var(--accent); border-color: transparent; color: var(--bg-elevated);
  box-shadow: none;
}
.dash-hist-lightbox-btn-primary:hover { background: var(--accent); filter: brightness(1.12); }
