:root{
  --bg-void:#050810;
  --bg-void-2:#080d1a;
  --bg-panel:#0a1526;
  --bg-panel-2:#0d1b33;
  --border-soft:rgba(120,170,255,0.14);
  --border-glow:rgba(47,213,255,0.45);
  --neon-cyan:#2fd5ff;
  --neon-blue:#4c7cff;
  --neon-violet:#8b7bff;
  --text-primary:#eaf3ff;
  --text-secondary:#8aa3c7;
  --text-dim:#526488;
  --font-display:'Sora',sans-serif;
  --font-body:'Inter',sans-serif;
  --font-mono:'JetBrains Mono',monospace;
  --radius:14px;
  --article-w:860px;
  --header-h:72px;
  --ticker-h:44px;
  /* Gouttière latérale du conteneur principal. Il n'y a volontairement plus de
     largeur maximale : le contenu occupe toute la fenêtre, comme le bandeau de
     news, pour éviter l'écart visuel entre les deux sur les grands écrans.
     Une gouttière étroite suffit à décoller le contenu du bord de l'écran, sans
     rétablir l'effet de colonne centrée. */
  --wrap-pad:10px;
  /* Force de la teinte de fond des cartes par catégorie (voir .card[data-type]) :
     un même pourcentage de couleur mélangé à du quasi-noir se voit beaucoup
     moins qu'à du blanc — l'œil perçoit mal les écarts de teinte à faible
     luminosité. Le thème sombre a donc besoin d'un pourcentage bien plus élevé
     que le thème clair pour un résultat visuellement équivalent. */
  --card-tint-bg:22%;
  --card-tint-border:46%;
}

/* Thème clair — le site est conçu à l'origine comme un tableau de bord "mission
   control" tout en néon sur fond noir, sans variante claire. Plutôt que d'inventer
   une palette déconnectée, on garde la même famille de teintes (cyan/bleu/violet)
   mais assombries pour rester lisibles (contraste AA) sur des fonds clairs, et on
   bascule les surfaces void/panel vers du blanc cassé / bleu-gris très pâle. */
:root[data-theme="light"]{
  --bg-void:#f3f6fc;
  --bg-void-2:#e8eefb;
  --bg-panel:#ffffff;
  --bg-panel-2:#f7f9fd;
  --border-soft:rgba(30,58,110,0.13);
  --border-glow:rgba(11,120,168,0.55);
  --neon-cyan:#0b78a8;
  --neon-blue:#3453c4;
  --neon-violet:#6a3fc9;
  --text-primary:#101a2c;
  --text-secondary:#4c5b78;
  --text-dim:#7c8aa3;
  /* Sur fond quasi blanc, la même teinte se voit beaucoup plus fort qu'en sombre —
     on redescend donc le pourcentage pour éviter des cartes trop criardes. */
  --card-tint-bg:9%;
  --card-tint-border:28%;
}

*{box-sizing:border-box;margin:0;padding:0;}
html{scroll-behavior:smooth;}

/* Visible des seuls lecteurs d'écran : porte le mot "vues" que l'icône remplace. */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;
}

body{
  background:
    radial-gradient(ellipse 1200px 600px at 15% -10%, rgba(76,124,255,0.16), transparent 60%),
    radial-gradient(ellipse 900px 500px at 100% 10%, rgba(47,213,255,0.10), transparent 55%),
    var(--bg-void);
  color:var(--text-primary);
  font-family:var(--font-body);
  line-height:1.5;
  min-height:100vh;
  transition:background-color .25s ease, color .25s ease;
}
:root[data-theme="light"] body{
  background:
    radial-gradient(ellipse 1200px 600px at 15% -10%, rgba(76,124,255,0.07), transparent 60%),
    radial-gradient(ellipse 900px 500px at 100% 10%, rgba(11,120,168,0.05), transparent 55%),
    var(--bg-void);
}

a{color:inherit;text-decoration:none;}
button{font-family:inherit;cursor:pointer;}
ul{list-style:none;}

::selection{background:rgba(47,213,255,0.35);color:#fff;}

/* Conteneur principal, sans largeur maximale : il suit la fenêtre, à l'image du
   bandeau de news. Un seul bloc s'en écarte, juste en dessous : le corps des
   articles, où une largeur illimitée nuirait à la lecture. */
.wrap{margin:0 auto;padding:0 var(--wrap-pad);}

/* Corps d'article : une ligne de texte reste lisible jusqu'à ~90 caractères.
   Seule exception à la pleine largeur — au-delà, l'œil perd la ligne en revenant
   à la marge. Ne concerne que la prose des articles, pas la grille de cartes.
   --article-w est la source unique de cette largeur : le bandeau de titre s'y
   aligne aussi (voir article.php), pour que titre, méta et texte partagent un
   même axe. */
.wrap.article-content{max-width:var(--article-w);}

/* ---------- Progress bar ---------- */
.progress-bar{
  position:fixed;top:0;left:0;right:0;height:3px;
  background:rgba(120,170,255,0.08);z-index:100;
}
.progress-bar-fill{
  height:100%;width:0%;
  background:linear-gradient(90deg,var(--neon-cyan),var(--neon-blue));
  box-shadow:0 0 8px rgba(47,213,255,0.6);
  transition:width .25s ease;
}
/* Le pourcentage vit dans le header, juste avant le bouton de thème : posé sur
   une surface connue plutôt que par-dessus le contenu qui défile, il reste
   lisible quel que soit l'article sous lui. Hauteur et rayon alignés sur
   .theme-toggle et .lang-btn pour que les trois forment une même rangée. */
.progress-bar-label{
  display:flex;align-items:center;
  height:38px;padding:0 11px;
  font-family:var(--font-mono);font-size:0.72rem;
  font-variant-numeric:tabular-nums;
  color:var(--neon-cyan);
  background:var(--bg-panel);border:1px solid var(--border-soft);
  border-radius:9px;pointer-events:none;white-space:nowrap;
  transition:opacity .2s ease;
}
/* Sous 520px, le header doit loger logo, langue et menu : le pourcentage est le
   premier élément sacrifiable, la barre colorée continue d'indiquer la
   progression. */
@media (max-width:520px){
  .progress-bar-label{display:none;}
}

header.site-header{
  position:sticky;top:0;z-index:60;
  height:var(--header-h);
  display:flex;align-items:center;
  border-bottom:1px solid var(--border-soft);
}
/* Fond et flou portés par un pseudo-élément plutôt que par le header lui-même :
   un élément avec `backdrop-filter` devient le bloc conteneur de ses descendants
   `position:fixed`. Le tiroir du menu mobile, qui vit dans le header, se calculait
   donc dans une boîte de 72px de haut — il s'ouvrait sur 36px et son contenu
   restait hors champ, au lieu d'occuper la fenêtre. */
header.site-header::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:rgba(5,8,16,0.82);
  backdrop-filter:blur(14px) saturate(140%);
}
:root[data-theme="light"] header.site-header::before{background:rgba(255,255,255,0.82);}
.header-inner{
  width:100%;display:flex;align-items:center;justify-content:space-between;gap:24px;
}
.logo{
  display:flex;align-items:center;
  font-family:var(--font-display);font-weight:800;font-size:1.15rem;
  letter-spacing:0.01em;
}
/* Badge "IA" façon puce/circuit imprimé, avec le tiret et le point de "AM-IA.EU"
   intégrés directement comme des pistes du circuit plutôt qu'en texte séparé —
   la composition se lit AM[badge]EU. */
.logo-lockup{display:flex;align-items:center;color:var(--text-primary);}
.logo-badge{display:inline-flex;margin:0 4px 0 -3px;flex:0 0 auto;}
.logo-badge svg{
  display:block;height:30px;width:auto;
  filter:drop-shadow(0 0 5px rgba(47,213,255,0.4));
}
.footer-logo .logo-badge svg{height:22px;}

nav.main-nav{display:flex;gap:6px;}
nav.main-nav a{
  font-size:0.88rem;font-weight:500;color:var(--text-secondary);
  padding:9px 14px;border-radius:8px;transition:color .18s ease, background .18s ease;
}
nav.main-nav a:hover{color:var(--text-primary);background:rgba(120,170,255,0.08);}
nav.main-nav a.active{color:var(--neon-cyan);}

/* Deux jeux de liens dans le même tiroir : le court (Actualités/Essais/Apps/
   Vidéos) pour le bureau, la liste complète des catégories pour le mobile —
   voir @media (max-width:860px) plus bas pour le bascule d'affichage. Sur
   bureau .nav-desktop-links doit garder le comportement de rangée de
   nav.main-nav (display:flex hérité ne s'applique pas à travers un wrapper). */
.nav-desktop-links{display:flex;gap:6px;}
.nav-mobile-links{display:none;}
.nav-archives-toggles{display:none;}
nav.main-nav a.nav-account-link{color:var(--text-dim);}

.header-actions{display:flex;align-items:center;gap:10px;position:relative;}

.theme-toggle{
  display:flex;align-items:center;justify-content:center;
  width:38px;height:38px;padding:0;
  background:var(--bg-panel);
  border:1px solid var(--border-soft);
  border-radius:9px;color:var(--text-secondary);
  transition:border-color .18s ease, box-shadow .18s ease, color .18s ease;
}
.theme-toggle:hover{border-color:var(--border-glow);box-shadow:0 0 14px rgba(47,213,255,0.18);color:var(--text-primary);}
.theme-toggle svg{width:19px;height:19px;}
/* Par défaut (sombre) : soleil visible = clic pour passer au clair.
   En thème clair (attribut data-theme="light") : lune visible = clic pour repasser au sombre. */
.theme-toggle .icon-sun{display:block;}
.theme-toggle .icon-moon{display:none;}
:root[data-theme="light"] .theme-toggle .icon-sun{display:none;}
:root[data-theme="light"] .theme-toggle .icon-moon{display:block;}

.lang-btn{
  display:flex;align-items:center;gap:8px;
  background:var(--bg-panel);
  border:1px solid var(--border-soft);
  padding:8px 12px;border-radius:9px;
  font-size:0.85rem;color:var(--text-primary);
  transition:border-color .18s ease, box-shadow .18s ease;
}
.lang-btn:hover{border-color:var(--border-glow);box-shadow:0 0 14px rgba(47,213,255,0.18);}
.lang-btn .flag{font-size:1.25rem;line-height:1;}
.flag-holder{display:flex;flex:0 0 auto;}
.lang-btn .chev{font-size:0.6rem;color:var(--text-dim);transition:transform .18s ease;}
.lang-btn[aria-expanded="true"] .chev{transform:rotate(180deg);}

.lang-panel{
  position:absolute;top:calc(var(--header-h) - 8px);right:0;
  width:340px;max-height:420px;overflow-y:auto;overflow-x:hidden;
  background:var(--bg-panel-2);
  border:1px solid var(--border-soft);
  border-radius:var(--radius);
  box-shadow:0 20px 50px rgba(0,0,0,0.55), 0 0 0 1px rgba(47,213,255,0.06);
  padding:10px;
  grid-template-columns:repeat(3, minmax(0,1fr));
  gap:4px;
  /* `display:grid` en permanence, visibilité pilotée par opacity/transform :
     un toggle display:none/grid ne peut pas s'animer, d'où l'apparition
     brutale des drapeaux. `visibility` + `pointer-events` gardent le panneau
     hors du tabulateur et des clics tant qu'il est fermé, comme le ferait
     display:none. */
  display:grid;
  opacity:0;visibility:hidden;pointer-events:none;
  transform:translateY(-6px) scale(0.97);
  transition:opacity .16s ease, transform .16s cubic-bezier(.32,.72,0,1), visibility .16s;
}
.lang-panel.open{
  opacity:1;visibility:visible;pointer-events:auto;transform:none;
}
.lang-option{
  display:flex;align-items:center;gap:6px;min-width:0;
  padding:8px 8px;border-radius:7px;font-size:0.76rem;color:var(--text-secondary);
  transition:background .15s ease,color .15s ease;
  background:transparent;border:none;text-align:left;width:100%;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  cursor:pointer;
}
.lang-option:hover{background:rgba(47,213,255,0.10);color:var(--text-primary);}
.lang-option.current{color:var(--neon-cyan);background:rgba(47,213,255,0.08);}
.lang-note{
  grid-column:1/-1;padding:8px 9px 2px;font-size:0.68rem;color:var(--text-dim);
  font-family:var(--font-mono);border-top:1px solid var(--border-soft);margin-top:4px;padding-top:10px;
}

/* Bouton menu mobile — trois barres qui se replient en croix à l'ouverture.
   Un glyphe texte (☰) ne peut pas s'animer : d'où les trois <span>. */
.menu-toggle{
  display:none;width:42px;height:42px;padding:0;
  align-items:center;justify-content:center;
  background:var(--bg-panel);
  border:1px solid var(--border-soft);
  border-radius:10px;cursor:pointer;
  transition:border-color .18s ease, box-shadow .18s ease;
}
.menu-toggle:hover{border-color:var(--border-glow);box-shadow:0 0 14px rgba(47,213,255,0.18);}
.burger{position:relative;display:block;width:19px;height:14px;}
.burger span{
  position:absolute;left:0;width:100%;height:2px;border-radius:2px;
  background:var(--text-primary);
  transition:transform .3s cubic-bezier(.4,0,.2,1), opacity .2s ease, background .18s ease;
}
.burger span:nth-child(1){top:0;}
.burger span:nth-child(2){top:6px;}
.burger span:nth-child(3){top:12px;}
.menu-toggle[aria-expanded="true"]{border-color:var(--border-glow);}
.menu-toggle[aria-expanded="true"] .burger span{background:var(--neon-cyan);}
.menu-toggle[aria-expanded="true"] .burger span:nth-child(1){transform:translateY(6px) rotate(45deg);}
.menu-toggle[aria-expanded="true"] .burger span:nth-child(2){opacity:0;transform:scaleX(.2);}
.menu-toggle[aria-expanded="true"] .burger span:nth-child(3){transform:translateY(-6px) rotate(-45deg);}

/* Fond assombri derrière le tiroir. Démarre sous le header pour que celui-ci
   — et donc le bouton de fermeture — reste visible et cliquable.
   z-index sous celui du header (60) : le tiroir vit à l'intérieur du header, dont
   le contexte d'empilement plafonne son z-index à 60. Au-dessus, ce fond passait
   par-dessus le tiroir, qui apparaissait alors flouté et ne recevait plus les clics.
   Au-dessus du bandeau de news (55), qu'il doit assombrir comme le reste. */
.nav-backdrop{
  display:none;position:fixed;inset:var(--header-h) 0 0 0;z-index:56;
  background:rgba(4,8,17,0.66);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  opacity:0;pointer-events:none;transition:opacity .3s ease;
}
.nav-backdrop.open{opacity:1;pointer-events:auto;}
body.nav-open{overflow:hidden;}

.ticker{
  position:sticky;top:var(--header-h);z-index:55;
  height:var(--ticker-h);
  display:flex;align-items:center;
  /* Aucune gouttière : le bandeau va d'un bord à l'autre de l'écran. */
  background:linear-gradient(90deg, #0b1c33, #0a1a30 55%, #0b1830);
  border-bottom:1px solid rgba(47,213,255,0.3);
  box-shadow:0 14px 24px -14px rgba(0,0,0,0.85), 0 1px 0 rgba(47,213,255,0.15) inset;
  overflow:hidden;
}
:root[data-theme="light"] .ticker{
  background:linear-gradient(90deg, #eef3fc, #e4ecfa 55%, #eef3fc);
  box-shadow:0 14px 24px -14px rgba(30,58,110,0.18), 0 1px 0 rgba(11,120,168,0.15) inset;
}
.ticker::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:linear-gradient(90deg, transparent, rgba(47,213,255,0.7), transparent);
}
.ticker-label{
  flex:0 0 auto;display:flex;align-items:center;gap:7px;
  height:100%;padding:0 16px;
  background:var(--bg-void-2);
  border-right:1px solid var(--border-soft);
  font-family:var(--font-mono);font-size:0.6375rem;letter-spacing:0.08em;
  color:var(--neon-cyan);white-space:nowrap;
}
.pulse-dot{
  width:7px;height:7px;border-radius:50%;background:var(--neon-cyan);
  box-shadow:0 0 8px var(--neon-cyan);
  animation:pulse 1.6s ease-in-out infinite;
}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1);}50%{opacity:0.4;transform:scale(0.75);}}

.ticker-track-wrap{flex:1;overflow:hidden;position:relative;height:100%;}
.ticker-track{
  display:flex;align-items:center;gap:0;
  position:absolute;white-space:nowrap;
  animation:scroll-left 58s linear infinite;
  height:100%;
}
.ticker-track:hover{animation-play-state:paused;}
.ticker-item{
  display:flex;align-items:center;gap:10px;
  padding:0 22px;font-size:0.82rem;color:var(--text-secondary);
  border-right:1px solid var(--border-soft);
  height:100%;text-decoration:none;transition:color .15s ease, background .15s ease;
  cursor:pointer;
}
.ticker-item:hover{color:var(--text-primary);background:rgba(47,213,255,0.06);}
.ticker-item:hover span:not(.tag){text-decoration:underline;text-underline-offset:3px;}
.ticker-item b{color:var(--text-primary);font-weight:600;}
.ticker-item .tag{
  font-family:var(--font-mono);font-size:0.62rem;color:var(--neon-blue);
  border:1px solid rgba(76,124,255,0.4);padding:1px 6px;border-radius:4px;
}
@keyframes scroll-left{
  from{transform:translateX(0);}
  to{transform:translateX(-50%);}
}
@media (prefers-reduced-motion:reduce){
  .ticker-track{animation:none;}
  .ticker-track-wrap{overflow-x:auto;}
  /* Le tiroir reste fonctionnel, mais apparaît sans glissement ni décalage. */
  nav.main-nav,
  nav.main-nav a,
  .nav-backdrop,
  .burger span{
    transition-duration:.01ms !important;
    transition-delay:0s !important;
  }
}

.hero{
  /* Marge haute calée pour que l'eyebrow et le titre tombent dans la bande
     animée de 150 px, sans quoi le titre flotterait sous elle. Marge basse
     réduite au minimum : la recherche doit toucher la rangée de catégories,
     dont le propre padding haut complète le peu d'air nécessaire. */
  padding:34px 0 14px;
  position:relative;
  overflow:hidden;
  border-bottom:1px solid var(--border-soft);
}
/* Hero centré : le texte n'est plus une colonne collée au bord gauche mais un
   bloc au milieu de la page, le visuel passant dessous en bandeau. La gouttière
   du site est volontairement étroite (--wrap-pad) pour que le flux de cartes
   occupe toute la largeur ; le hero, lui, a besoin d'une colonne de lecture
   bornée, d'où le max-width local. */
.hero-grid{
  /* z-index 1 : le contenu passe devant le bandeau animé, posé en fond du hero. */
  position:relative;z-index:1;
  display:grid;grid-template-columns:1fr;gap:40px;justify-items:center;
}
.hero-copy{
  min-width:0;max-width:760px;width:100%;
  display:flex;flex-direction:column;align-items:center;text-align:center;
}
.eyebrow{
  display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-family:var(--font-mono);font-size:0.72rem;letter-spacing:0.12em;
  color:var(--neon-cyan);text-transform:uppercase;
  border:1px solid rgba(47,213,255,0.3);
  padding:6px 12px;border-radius:20px;
  background:rgba(47,213,255,0.06);
  margin-bottom:22px;
  max-width:100%;
}
.eyebrow .acro{color:var(--text-primary);font-weight:800;font-size:1.35em;vertical-align:middle;line-height:1;}
.hero h1{
  font-family:var(--font-display);font-weight:800;
  font-size:clamp(1.4rem,2.6vw,2.1rem);line-height:1.12;letter-spacing:-0.01em;
  margin-bottom:20px;
}
.hero h1 .grad{
  background:linear-gradient(100deg,var(--neon-cyan),var(--neon-blue) 60%,var(--neon-violet));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
/* La description suit la largeur de sa colonne, sans limite propre. */
.hero p.sub{color:var(--text-secondary);font-size:1.02rem;margin-bottom:30px;}
.hero-stats{display:flex;flex-wrap:wrap;gap:14px 30px;justify-content:center;}

/* La recherche vit dans le hero, sous les statistiques. Le rythme vertical
   d'origine (20px/30px) séparait les filtres du flux : ici elle clôt la colonne
   de texte, d'où le padding bas nul. flex-wrap parce que la colonne est étroite
   sur desktop — le compteur de résultats passe alors sous le champ. */
.hero-copy .search-wrap{padding:26px 0 0;flex-wrap:wrap;justify-content:center;width:100%;}
.stat b{
  display:block;font-family:var(--font-display);font-size:1.5rem;font-weight:700;color:var(--text-primary);
}
.stat span{font-size:0.75rem;color:var(--text-dim);font-family:var(--font-mono);}

/* Sous le texte plutôt qu'à sa droite : en bandeau large et bas, il souligne le
   hero au lieu de lui disputer la moitié de la largeur. */
/* Bandeau animé en fond du hero : pleine largeur de fenêtre, calé en haut pour
   passer derrière l'eyebrow et le titre, qui se superposent dessus. Plus de
   cadre ni de coins arrondis — ce n'est plus une vignette mais une toile. */
.scan-visual{
  position:absolute;top:0;left:0;right:0;height:160px;
  width:100%;max-width:none;margin:0;
  border:none;border-radius:0;
  background:radial-gradient(ellipse 60% 100% at 50% 0%, rgba(76,124,255,0.10), transparent 70%);
  overflow:hidden;pointer-events:none;z-index:0;
}
/* Le champ d'étoiles occupe tout le cadre. Le SVG et son faisceau balayant ont
   été retirés : l'animation est désormais dessinée sur ce canvas. */
.starfield{position:absolute;inset:0;width:100%;height:100%;display:block;}
/* Deux fondus : latéral, pour que les traînées s'éteignent au lieu d'être
   coupées net par le bord de la fenêtre ; vertical, pour que le bandeau se
   dissolve dans la page — et, accessoirement, pour poser un voile sous le titre
   qui garantit sa lisibilité par-dessus les étoiles. */
.scan-visual::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(180deg, transparent 0%, transparent 45%, var(--bg-void) 100%),
    linear-gradient(90deg, var(--bg-void) 0%, transparent 12%, transparent 88%, var(--bg-void) 100%);
}
.scan-caption{
  position:absolute;top:10px;left:0;right:0;z-index:1;
  padding:0 max(var(--wrap-pad), 18px);
  font-family:var(--font-mono);font-size:0.58rem;color:var(--text-dim);
  display:flex;justify-content:space-between;opacity:0.75;
}

.filters{
  display:flex;gap:8px;padding:14px 0 26px;flex-wrap:wrap;justify-content:center;
  border-bottom:1px solid var(--border-soft);
}
.filter-btn{
  background:var(--bg-panel);border:1px solid var(--border-soft);color:var(--text-secondary);
  font-size:0.82rem;padding:8px 16px;border-radius:20px;transition:all .18s ease;
  cursor:pointer;
}
.filter-btn:hover{color:var(--text-primary);border-color:var(--border-glow);}
.filter-btn.active{
  color:var(--bg-void);background:linear-gradient(100deg,var(--neon-cyan),var(--neon-blue));
  border-color:transparent;font-weight:600;box-shadow:0 0 16px rgba(47,213,255,0.35);
}
.filter-count{
  display:inline-block;margin-left:6px;vertical-align:1px;
  font-family:var(--font-mono);font-size:0.68rem;font-weight:600;
  padding:1px 7px;border-radius:10px;
  background:rgba(120,170,255,0.14);color:var(--text-dim);
  transition:background .18s ease, color .18s ease;
}
.filter-btn:hover .filter-count{color:var(--text-secondary);}
.filter-btn.active .filter-count{background:rgba(5,8,16,0.22);color:var(--bg-void);}

/* Bouton de filtre teinté par catégorie : mêmes couleurs que --card-accent
   et .badge ci-dessus (voir plus bas), pour que le bouton sélectionné dans
   les filtres corresponde visuellement aux cartes qu'il fait apparaître. Le
   bouton "Tout" (pas de data-type connu) garde le dégradé cyan/bleu générique. */
.filter-btn[data-type="essay"]{color:#4c83f0;border-color:rgba(76,131,240,0.35);}
.filter-btn[data-type="essay"]:hover{border-color:rgba(76,131,240,0.7);}
.filter-btn[data-type="essay"].active{color:var(--bg-void);background:#4c83f0;border-color:transparent;box-shadow:0 0 16px rgba(76,131,240,0.4);}
.filter-btn[data-type="app"]{color:#945fdd;border-color:rgba(148,95,221,0.35);}
.filter-btn[data-type="app"]:hover{border-color:rgba(148,95,221,0.7);}
.filter-btn[data-type="app"].active{color:var(--bg-void);background:#945fdd;border-color:transparent;box-shadow:0 0 16px rgba(148,95,221,0.4);}
.filter-btn[data-type="website"]{color:#26bbd9;border-color:rgba(38,187,217,0.35);}
.filter-btn[data-type="website"]:hover{border-color:rgba(38,187,217,0.7);}
.filter-btn[data-type="website"].active{color:var(--bg-void);background:#26bbd9;border-color:transparent;box-shadow:0 0 16px rgba(38,187,217,0.4);}
.filter-btn[data-type="video"]{color:#3ea2ea;border-color:rgba(62,162,234,0.35);}
.filter-btn[data-type="video"]:hover{border-color:rgba(62,162,234,0.7);}
.filter-btn[data-type="video"].active{color:var(--bg-void);background:#3ea2ea;border-color:transparent;box-shadow:0 0 16px rgba(62,162,234,0.4);}
.filter-btn[data-type="thesis"]{color:#f47434;border-color:rgba(244,116,52,0.35);}
.filter-btn[data-type="thesis"]:hover{border-color:rgba(244,116,52,0.7);}
.filter-btn[data-type="thesis"].active{color:var(--bg-void);background:#f47434;border-color:transparent;box-shadow:0 0 16px rgba(244,116,52,0.4);}
.filter-btn[data-type="medical"]{color:#e64ca6;border-color:rgba(230,76,166,0.35);}
.filter-btn[data-type="medical"]:hover{border-color:rgba(230,76,166,0.7);}
.filter-btn[data-type="medical"].active{color:var(--bg-void);background:#e64ca6;border-color:transparent;box-shadow:0 0 16px rgba(230,76,166,0.4);}
.filter-btn[data-type="research"]{color:#9f3fcf;border-color:rgba(159,63,207,0.35);}
.filter-btn[data-type="research"]:hover{border-color:rgba(159,63,207,0.7);}
.filter-btn[data-type="research"].active{color:var(--bg-void);background:#9f3fcf;border-color:transparent;box-shadow:0 0 16px rgba(159,63,207,0.4);}
.filter-btn[data-type="podcast"]{color:#ba39c6;border-color:rgba(186,57,198,0.35);}
.filter-btn[data-type="podcast"]:hover{border-color:rgba(186,57,198,0.7);}
.filter-btn[data-type="podcast"].active{color:var(--bg-void);background:#ba39c6;border-color:transparent;box-shadow:0 0 16px rgba(186,57,198,0.4);}
.filter-btn[data-type="architecture"]{color:#cb9d4d;border-color:rgba(203,157,77,0.35);}
.filter-btn[data-type="architecture"]:hover{border-color:rgba(203,157,77,0.7);}
.filter-btn[data-type="architecture"].active{color:var(--bg-void);background:#cb9d4d;border-color:transparent;box-shadow:0 0 16px rgba(203,157,77,0.4);}
.filter-btn[data-type="climate"]{color:#4dd68a;border-color:rgba(77,214,138,0.35);}
.filter-btn[data-type="climate"]:hover{border-color:rgba(77,214,138,0.7);}
.filter-btn[data-type="climate"].active{color:var(--bg-void);background:#4dd68a;border-color:transparent;box-shadow:0 0 16px rgba(77,214,138,0.4);}
.filter-btn[data-type="learning"]{color:#c945b3;border-color:rgba(201,69,179,0.35);}
.filter-btn[data-type="learning"]:hover{border-color:rgba(201,69,179,0.7);}
.filter-btn[data-type="learning"].active{color:var(--bg-void);background:#c945b3;border-color:transparent;box-shadow:0 0 16px rgba(201,69,179,0.4);}
.filter-btn[data-type="science"]{color:#e8c930;border-color:rgba(232,201,48,0.35);}
.filter-btn[data-type="science"]:hover{border-color:rgba(232,201,48,0.7);}
.filter-btn[data-type="science"].active{color:var(--bg-void);background:#e8c930;border-color:transparent;box-shadow:0 0 16px rgba(232,201,48,0.4);}
.filter-btn[data-type="space"]{color:#515dec;border-color:rgba(81,93,236,0.35);}
.filter-btn[data-type="space"]:hover{border-color:rgba(81,93,236,0.7);}
.filter-btn[data-type="space"].active{color:var(--bg-void);background:#515dec;border-color:transparent;box-shadow:0 0 16px rgba(81,93,236,0.4);}
.filter-btn[data-type="security"]{color:#ff5c5c;border-color:rgba(255,92,92,0.35);}
.filter-btn[data-type="security"]:hover{border-color:rgba(255,92,92,0.7);}
.filter-btn[data-type="security"].active{color:var(--bg-void);background:#ff5c5c;border-color:transparent;box-shadow:0 0 16px rgba(255,92,92,0.4);}
.filter-btn[data-type="business"]{color:#a6b946;border-color:rgba(166,185,70,0.35);}
.filter-btn[data-type="business"]:hover{border-color:rgba(166,185,70,0.7);}
.filter-btn[data-type="business"].active{color:var(--bg-void);background:#a6b946;border-color:transparent;box-shadow:0 0 16px rgba(166,185,70,0.4);}
.filter-btn[data-type="policy"]{color:#a1a9ba;border-color:rgba(161,169,186,0.35);}
.filter-btn[data-type="policy"]:hover{border-color:rgba(161,169,186,0.7);}
.filter-btn[data-type="policy"].active{color:var(--bg-void);background:#a1a9ba;border-color:transparent;box-shadow:0 0 16px rgba(161,169,186,0.4);}
.filter-btn[data-type="robotics"]{color:#745fdd;border-color:rgba(116,95,221,0.35);}
.filter-btn[data-type="robotics"]:hover{border-color:rgba(116,95,221,0.7);}
.filter-btn[data-type="robotics"].active{color:var(--bg-void);background:#745fdd;border-color:transparent;box-shadow:0 0 16px rgba(116,95,221,0.4);}

/* ---------- Archives (articles de plus de 6 mois) ---------- */
.archives-bar{
  display:flex;gap:14px;align-items:center;justify-content:center;flex-wrap:wrap;
  padding:10px 0 20px;font-size:0.8rem;
}
.archives-toggle-btn{
  background:var(--bg-panel);border:1px solid var(--border-soft);color:var(--text-dim);
  font-size:0.78rem;padding:6px 14px;border-radius:16px;transition:all .18s ease;cursor:pointer;
}
.archives-toggle-btn:hover{color:var(--text-primary);border-color:var(--border-glow);}
.archives-toggle-btn.active{color:var(--neon-cyan);border-color:var(--border-glow);}
.archives-only-link{color:var(--text-dim);text-decoration:underline;text-underline-offset:3px;font-size:0.78rem;}
.archives-only-link:hover{color:var(--text-primary);}
.archives-label{font-weight:600;color:var(--text-primary);}
.archives-link{color:var(--neon-cyan);text-decoration:underline;text-underline-offset:3px;}
.archives-link:hover{color:var(--text-primary);}

/* ---------- Search ---------- */
.search-wrap{
  position:relative;display:flex;align-items:center;gap:10px;
  padding:20px 0 30px;
}
/* L'icône est ancrée au champ, pas au conteneur : le bloc de recherche est
   centré, et un positionnement relatif au conteneur exigerait un décalage en
   pixels dépendant de la largeur du champ. */
.search-field{position:relative;display:flex;align-items:center;width:100%;max-width:420px;}
.search-icon{position:absolute;left:16px;font-size:0.9rem;opacity:0.6;pointer-events:none;}
.search-input{
  width:100%;
  background:var(--bg-panel);border:1px solid var(--border-soft);color:var(--text-primary);
  font-family:inherit;font-size:0.88rem;
  padding:11px 14px 11px 40px;border-radius:12px;
  outline:none;transition:border-color .18s ease, box-shadow .18s ease;
}
.search-input::placeholder{color:var(--text-dim);}
.search-input:focus{border-color:var(--border-glow);box-shadow:0 0 14px rgba(47,213,255,0.18);}
.search-input::-webkit-search-cancel-button{cursor:pointer;}
.search-hint{font-size:0.78rem;color:var(--text-dim);font-family:var(--font-mono);}

#feed-wrap{transition:opacity .2s ease, transform .2s ease;opacity:1;transform:translateY(0);}
#feed-wrap.feed-transitioning{opacity:0;transform:translateY(10px);}

#scrollSentinel{height:1px;}

.infinite-loader,.infinite-end{
  display:none;align-items:center;justify-content:center;gap:8px;
  padding:26px 0;font-family:var(--font-mono);font-size:0.78rem;color:var(--text-dim);
}
.infinite-loader.visible,.infinite-end.visible{display:flex;}

/* Chargement du lot suivant : le repère doit se voir sans être cherché.
   Panneau plein cadre plutôt qu'une ligne de texte discrète, avec trois
   signaux redondants (anneau qui tourne, points animés, barre indéterminée)
   pour que le message « ça travaille, patientez » passe même en vision
   périphérique, pendant que le lecteur regarde encore la dernière carte. */
.infinite-loader{
  position:relative;overflow:hidden;
  gap:16px;margin:10px 0 4px;padding:22px 26px;
  border:1px solid var(--border-soft);border-radius:var(--radius);
  background:var(--bg-panel);
  box-shadow:0 0 0 1px rgba(47,213,255,0.06), 0 10px 30px rgba(0,0,0,0.28);
  animation:infinite-loader-in .28s ease both;
}
@keyframes infinite-loader-in{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:translateY(0);}}

.infinite-loader-spinner{
  flex:0 0 auto;width:26px;height:26px;border-radius:50%;
  border:2px solid rgba(47,213,255,0.18);
  border-top-color:var(--neon-cyan);
  box-shadow:0 0 12px rgba(47,213,255,0.35);
  animation:infinite-spin .8s linear infinite;
}
@keyframes infinite-spin{to{transform:rotate(360deg);}}

.infinite-loader-text{display:flex;flex-direction:column;gap:4px;text-align:left;}
.infinite-loader-title{
  font-weight:600;font-size:0.86rem;letter-spacing:0.02em;color:var(--neon-cyan);
  animation:infinite-title-glow 1.6s ease-in-out infinite;
}
@keyframes infinite-title-glow{0%,100%{opacity:1;}50%{opacity:0.55;}}
.infinite-loader-hint{font-size:0.74rem;color:var(--text-dim);}

/* Les points s'allument l'un après l'autre : une horloge visible qui dit que
   l'attente est normale et en cours, là où un « … » figé ne dit rien. */
.infinite-loader-dots i{font-style:normal;opacity:0.2;animation:infinite-dot 1.2s infinite;}
.infinite-loader-dots i:nth-child(2){animation-delay:.2s;}
.infinite-loader-dots i:nth-child(3){animation-delay:.4s;}
@keyframes infinite-dot{0%,60%,100%{opacity:0.2;}30%{opacity:1;}}

/* Mini barre de progression au bas du panneau. La durée du fetch n'est pas connue
   à l'avance : le remplissage est piloté en JS (voir startLoaderProgress), il avance
   vite au début puis ralentit sans jamais atteindre 100 % tant que la réponse n'est
   pas là. Une barre qui bouge dit « ça avance » là où une barre figée dit « c'est
   planté » — et le reflet qui balaye le remplissage garde du mouvement même pendant
   les paliers, quand le pourcentage stagne. */
.infinite-loader-bar{
  position:absolute;left:0;right:0;bottom:0;height:3px;
  background:rgba(47,213,255,0.10);overflow:hidden;
}
.infinite-loader-bar-fill{
  display:block;width:0;height:100%;
  background:linear-gradient(90deg,rgba(47,213,255,0.55),var(--neon-cyan));
  box-shadow:0 0 10px var(--neon-cyan);
  transition:width .35s cubic-bezier(.22,.61,.36,1);
  position:relative;overflow:hidden;
}
.infinite-loader-bar-fill::after{
  content:"";position:absolute;top:0;bottom:0;width:45%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,0.45),transparent);
  animation:infinite-bar-sheen 1.1s ease-in-out infinite;
}
@keyframes infinite-bar-sheen{0%{left:-45%;}100%{left:100%;}}

/* Cartes fantômes ajoutées au flux pendant le chargement : la page grandit
   tout de suite, donc le scroll ne bute pas sur un vide et l'utilisateur voit
   où le contenu va apparaître. */
.card-skeleton{
  border:1px dashed var(--border-soft);background:var(--bg-panel);
  border-radius:var(--radius);padding:22px;display:flex;flex-direction:column;gap:14px;
  min-height:190px;pointer-events:none;
}
.card-skeleton span{
  display:block;height:12px;border-radius:6px;
  background:linear-gradient(90deg,rgba(255,255,255,0.04),rgba(47,213,255,0.16),rgba(255,255,255,0.04));
  background-size:200% 100%;
  animation:skeleton-shimmer 1.4s linear infinite;
}
.card-skeleton span:nth-child(1){width:35%;height:16px;}
.card-skeleton span:nth-child(2){width:100%;height:20px;}
.card-skeleton span:nth-child(3){width:82%;height:20px;}
.card-skeleton span:nth-child(4){width:60%;}
@keyframes skeleton-shimmer{0%{background-position:200% 0;}100%{background-position:-200% 0;}}

@media (max-width:600px){
  .infinite-loader{padding:18px;gap:12px;}
  .infinite-loader-title{font-size:0.8rem;}
}

/* Mouvement réduit : on garde le panneau et le message, on coupe les boucles. */
@media (prefers-reduced-motion:reduce){
  .infinite-loader,
  .infinite-loader-spinner,
  .infinite-loader-title,
  .infinite-loader-dots i,
  .infinite-loader-bar-fill::after,
  .card-skeleton span{animation:none;}
  .infinite-loader-spinner{border-top-color:var(--neon-cyan);}
  .infinite-loader-dots i{opacity:1;}
}

/* Grille fluide : le nombre de colonnes découle de la largeur disponible plutôt
   que de paliers figés. Avec un minimum de 380px et une gouttière de 22px :
   2 colonnes dès ~1000px, 3 à partir de 1280px (largeur d'écran courante),
   4 au-delà de ~1700px, puis plafonnement par le max-width de .wrap. */
.feed{
  padding:36px 0 70px;
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(380px, 1fr));
  gap:22px;
}

.card{
  /* position:relative ancre le lien étiré de .card-link : c'est la carte entière
     qui devient la zone de clic, sans bouton dédié. */
  position:relative;
  background:var(--bg-panel);border:1px solid var(--border-soft);border-radius:var(--radius);
  transition:border-color .2s ease, transform .35s ease, box-shadow .2s ease, opacity .35s ease;
  opacity:1;
  /* Coupe .card-inner (et le cœur qu'il révèle) aux coins arrondis pendant
     le glissement tactile — voir setupCardSwipeReveal() dans app.js. */
  overflow:hidden;
}
.card:hover{border-color:var(--border-glow);transform:translateY(-2px);box-shadow:0 12px 30px rgba(0,0,0,0.4);}
/* La carte se pilote au clavier via le lien du titre : on remonte l'état de
   focus sur la carte pour que la cible soit visible, pas juste le mot souligné. */
.card:focus-within{border-color:var(--border-glow);box-shadow:0 0 0 2px rgba(47,213,255,0.25);}
.card.card-enter{opacity:0;transform:translateY(22px);}

/* Couche de révélation, posée derrière .card-inner (même fond que la carte,
   donc invisible tant qu'on ne glisse pas). Purement décorative pour
   l'instant : aucune gestion des favoris n'y est encore branchée. */
.card-fav-reveal{
  position:absolute;inset:0;z-index:0;
  /* `align-items:flex-end` (et non `center`) : la bande révélée par le
     glissement ne fait que 76px de large sur le bord droit (voir REVEAL dans
     setupCardSwipeReveal()) — centrer horizontalement plaçait le cœur hors
     de cette bande, caché sous .card-inner resté opaque par-dessus. */
  display:flex;flex-direction:column;align-items:flex-end;gap:8px;
  padding:18px 22px 0 0;
  background:linear-gradient(90deg, transparent, rgba(255,77,122,0.12));
  pointer-events:none;
}
/* Repris du .card-meta d'origine, mais posé sur le fond de la couche de
   révélation plutôt que sur celui de la carte : couleur neutre relevée pour
   rester lisible sur le dégradé rosé. */
.card-fav-reveal .card-views{
  flex-direction:column;align-items:center;gap:3px;
  width:38px; /* même largeur que .fav-heart, pour que le centrage tombe pile sous lui */
  font-family:var(--font-mono);font-size:0.86rem;font-weight:600;color:var(--text-secondary);
  opacity:0;transition:opacity .2s ease .05s;
}
.card.swipe-active .card-fav-reveal .card-views{opacity:1;}
.card-fav-reveal .card-views svg{width:16px;height:16px;opacity:0.85;}
.fav-heart{
  display:flex;align-items:center;justify-content:center;
  width:38px;height:38px;border-radius:50%;
  background:rgba(255,255,255,0.07);
  color:var(--text-secondary);
  transform:scale(0.4) translateY(-6px);opacity:0;
  transition:transform .3s cubic-bezier(.34,1.56,.64,1), opacity .2s ease, color .2s ease, background .2s ease, box-shadow .2s ease;
  pointer-events:auto;cursor:pointer;
}
/* Vide par défaut (contour seul) ; `.filled` bascule sur un remplissage plein,
   persisté côté compte particulier (voir account/favorite-toggle.php et
   assets/js/auth.js — FAVORITES.toggle()). */
.fav-heart svg{
  width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linejoin:round;
  filter:drop-shadow(0 1px 2px rgba(0,0,0,0.35));
  transition:fill .16s ease;
}
.card.swipe-active .fav-heart{opacity:1;transform:scale(1) translateY(0);}
.fav-heart.filled{
  color:#ff4d7a;background:rgba(255,77,122,0.18);
  box-shadow:0 0 0 1px rgba(255,77,122,0.35), 0 4px 14px rgba(255,77,122,0.3);
}
.fav-heart.filled svg{fill:currentColor;}
.fav-heart.pop{transform:scale(1.3) translateY(0);}

/* Bouton favori "principal" : visible au survol sur desktop (souris) —
   masqué sur tactile (voir @media(hover:none) plus bas), où le cœur
   .fav-heart révélé par le glissement du pouce vers la gauche
   (setupCardSwipeReveal(), app.js) sert déjà de contrôle équivalent ; les
   deux resteraient sinon visibles en même temps sur la carte. Mêmes classes
   .filled/.pop que .fav-heart pour partager exactement la même animation. */
.fav-btn{
  position:absolute;top:14px;right:14px;z-index:2;
  display:flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:50%;border:none;
  background:rgba(8,13,26,0.55);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
  color:var(--text-secondary);cursor:pointer;
  opacity:0;transform:scale(0.85);
  transition:opacity .18s ease, transform .18s cubic-bezier(.34,1.56,.64,1), color .18s ease, background .18s ease, box-shadow .18s ease;
}
.fav-btn svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linejoin:round;transition:fill .16s ease;}
.card:hover .fav-btn, .fav-btn:focus-visible{opacity:1;transform:scale(1);}
.fav-btn.filled{opacity:1;color:#ff4d7a;background:rgba(255,77,122,0.18);box-shadow:0 0 0 1px rgba(255,77,122,0.35);}
.fav-btn.filled svg{fill:currentColor;}
.fav-btn.pop{transform:scale(1.25);}
@media (hover:none){
  /* Redondant avec .fav-heart (glissement tactile) : sans ce masquage, les
     deux cœurs étaient visibles/actionnables en même temps sur la carte. */
  .fav-btn{display:none;}
}

.card-inner{
  position:relative;z-index:1;
  background:inherit;border-radius:inherit;
  padding:22px;display:flex;flex-direction:column;gap:14px;
  touch-action:pan-y;
  transition:transform .28s cubic-bezier(.32,.72,0,1);
}

/* Lien étiré : la surface cliquable couvre la carte, le texte reste sélectionnable
   ailleurs. z-index 1 pour passer sous les éléments interactifs qui montent à 2
   (miniature vidéo), qui gardent ainsi leur propre destination. */
.card-link{color:inherit;text-decoration:none;}
.card-link::after{content:"";position:absolute;inset:0;z-index:1;border-radius:var(--radius);}
.card-link:focus-visible{outline:none;}
.card:hover .card-link{color:var(--neon-cyan);}

.card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;}
.badge{
  font-family:var(--font-mono);font-size:0.62rem;letter-spacing:0.06em;text-transform:uppercase;
  padding:4px 10px;border-radius:6px;border:1px solid;
}
.badge.essay{color:#4c83f0;border-color:rgba(76,131,240,0.4);background:rgba(76,131,240,0.06);}
.badge.app{color:#945fdd;border-color:rgba(148,95,221,0.4);background:rgba(148,95,221,0.06);}
.badge.website{color:#26bbd9;border-color:rgba(38,187,217,0.4);background:rgba(38,187,217,0.06);}
.badge.video{color:#3ea2ea;border-color:rgba(62,162,234,0.4);background:rgba(62,162,234,0.06);}
.badge.thesis{color:#f47434;border-color:rgba(244,116,52,0.4);background:rgba(244,116,52,0.06);}
.badge.medical{color:#e64ca6;border-color:rgba(230,76,166,0.4);background:rgba(230,76,166,0.06);}
.badge.research{color:#9f3fcf;border-color:rgba(159,63,207,0.4);background:rgba(159,63,207,0.06);}
.badge.podcast{color:#ba39c6;border-color:rgba(186,57,198,0.4);background:rgba(186,57,198,0.06);}
.badge.architecture{color:#cb9d4d;border-color:rgba(203,157,77,0.4);background:rgba(203,157,77,0.06);}
.badge.climate{color:#4dd68a;border-color:rgba(77,214,138,0.4);background:rgba(77,214,138,0.06);}
.badge.learning{color:#c945b3;border-color:rgba(201,69,179,0.4);background:rgba(201,69,179,0.06);}
.badge.science{color:#e8c930;border-color:rgba(232,201,48,0.4);background:rgba(232,201,48,0.06);}
.badge.space{color:#515dec;border-color:rgba(81,93,236,0.4);background:rgba(81,93,236,0.06);}
.badge.security{color:#ff5c5c;border-color:rgba(255,92,92,0.4);background:rgba(255,92,92,0.06);}
.badge.business{color:#a6b946;border-color:rgba(166,185,70,0.4);background:rgba(166,185,70,0.06);}
.badge.policy{color:#a1a9ba;border-color:rgba(161,169,186,0.4);background:rgba(161,169,186,0.06);}
.badge.robotics{color:#745fdd;border-color:rgba(116,95,221,0.4);background:rgba(116,95,221,0.06);}

/* Fond de carte teinté par catégorie : --card-accent (fixé par type juste en
   dessous) irrigue à la fois un léger dégradé de fond et la couleur de bordure,
   pour repérer d'un coup d'œil ses centres d'intérêt dans le flux. Mêmes
   teintes que les badges ci-dessus, pour rester cohérent avec eux. Le repli
   sur --border-soft (nul visuellement) couvre les types sans couleur dédiée. */
.card[data-type]{
  --card-accent:transparent;
  background:linear-gradient(160deg, color-mix(in srgb, var(--card-accent) var(--card-tint-bg), var(--bg-panel)), var(--bg-panel) 65%);
  border-color:color-mix(in srgb, var(--card-accent) var(--card-tint-border), var(--border-soft));
}
.card[data-type="essay"],.topic-ring-item[data-type="essay"]{--card-accent:#4c83f0;}
.card[data-type="app"],.topic-ring-item[data-type="app"]{--card-accent:#945fdd;}
.card[data-type="website"],.topic-ring-item[data-type="website"]{--card-accent:#26bbd9;}
.card[data-type="video"],.topic-ring-item[data-type="video"]{--card-accent:#3ea2ea;}
.card[data-type="thesis"],.topic-ring-item[data-type="thesis"]{--card-accent:#f47434;}
.card[data-type="medical"],.topic-ring-item[data-type="medical"]{--card-accent:#e64ca6;}
.card[data-type="research"],.topic-ring-item[data-type="research"]{--card-accent:#9f3fcf;}
.card[data-type="podcast"],.topic-ring-item[data-type="podcast"]{--card-accent:#ba39c6;}
.card[data-type="architecture"],.topic-ring-item[data-type="architecture"]{--card-accent:#cb9d4d;}
.card[data-type="climate"],.topic-ring-item[data-type="climate"]{--card-accent:#4dd68a;}
.card[data-type="learning"],.topic-ring-item[data-type="learning"]{--card-accent:#c945b3;}
.card[data-type="science"],.topic-ring-item[data-type="science"]{--card-accent:#e8c930;}
.card[data-type="space"],.topic-ring-item[data-type="space"]{--card-accent:#515dec;}
.card[data-type="security"],.topic-ring-item[data-type="security"]{--card-accent:#ff5c5c;}
.card[data-type="business"],.topic-ring-item[data-type="business"]{--card-accent:#a6b946;}
.card[data-type="policy"],.topic-ring-item[data-type="policy"]{--card-accent:#a1a9ba;}
.card[data-type="robotics"],.topic-ring-item[data-type="robotics"]{--card-accent:#745fdd;}

/* z-index 2 : la miniature reste au-dessus du lien étiré de la carte, donc un
   clic dessus ouvre bien la vidéo sur YouTube et non l'article. */
.video-thumb{
  position:relative;z-index:2;display:flex;align-items:center;justify-content:center;
  height:150px;border-radius:10px;overflow:hidden;text-decoration:none;
  background:
    radial-gradient(circle at 30% 30%, rgba(47,213,255,0.25), transparent 60%),
    radial-gradient(circle at 75% 70%, rgba(139,123,255,0.25), transparent 55%),
    linear-gradient(135deg, #0d1b33, #0a1526);
  border:1px solid var(--border-soft);
  transition:border-color .2s ease;
}
.video-thumb:hover{border-color:var(--border-glow);}
.video-thumb-img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;
}
.video-thumb:has(.video-thumb-img)::after{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg, rgba(5,8,16,0.15), rgba(5,8,16,0.55));
}
.video-thumb::before{
  content:"";position:absolute;inset:0;z-index:1;
  background-image:repeating-linear-gradient(115deg, rgba(255,255,255,0.03) 0 2px, transparent 2px 6px);
}
.play-btn{
  position:relative;z-index:2;
  width:52px;height:52px;border-radius:50%;
  background:rgba(5,8,16,0.55);border:1.5px solid rgba(47,213,255,0.6);
  display:flex;align-items:center;justify-content:center;
  color:var(--neon-cyan);font-size:1.1rem;
  box-shadow:0 0 22px rgba(47,213,255,0.35);
  transition:transform .2s ease, box-shadow .2s ease;
}
.video-thumb:hover .play-btn{transform:scale(1.08);box-shadow:0 0 30px rgba(47,213,255,0.55);}
.video-duration{
  position:absolute;bottom:9px;right:10px;z-index:2;
  font-family:var(--font-mono);font-size:0.68rem;color:var(--text-primary);
  background:rgba(5,8,16,0.75);border:1px solid var(--border-soft);
  padding:2px 7px;border-radius:5px;
}

/* Cartes vidéo : titre au-dessus, miniature réduite à gauche, texte à droite —
   pour aligner la hauteur des cartes vidéo sur celle des cartes articles classiques. */
.video-row{display:flex;gap:14px;align-items:flex-start;}
.video-row .video-thumb{flex:0 0 175px;width:175px;height:94px;}
.video-row .play-btn{width:38px;height:38px;font-size:0.85rem;box-shadow:0 0 14px rgba(47,213,255,0.35);}
.video-row .video-duration{font-size:0.6rem;padding:1px 6px;bottom:5px;right:6px;}
.video-row .excerpt{flex:1;min-width:0;margin:0;}

/* Source · date, puis le compteur de vues juste en dessous, alignés à droite. */
.card-meta{
  display:flex;flex-direction:column;align-items:flex-end;gap:5px;
  font-family:var(--font-mono);font-size:0.68rem;color:var(--text-dim);
  text-align:right;
  /* `flex:0 1 auto` + `min-width:0` : un nom de source long, combiné à
     `flex:0 0 auto` (repli par défaut des enfants flex), refusait de rétrécir
     sous sa taille de contenu et poussait la carte au-delà de l'écran —
     source du défilement horizontal fantôme sur mobile. */
  flex:0 1 auto;min-width:0;
}
/* Source et date filtrent le flux : ils doivent rester cliquables par-dessus le
   lien étiré de la carte (z-index 1), d'où le passage à 2 comme la miniature. */
.meta-link{
  position:relative;z-index:2;
  color:inherit;text-decoration:none;
  border-bottom:1px dotted transparent;
  transition:color .16s ease, border-color .16s ease;
}
.meta-link:hover{color:var(--neon-cyan);border-bottom-color:currentColor;}
.card-views{
  display:inline-flex;align-items:center;gap:4px;
  font-variant-numeric:tabular-nums;line-height:1;
}
.card-views svg{width:13px;height:13px;flex:0 0 auto;opacity:0.75;}

.card h3{font-family:var(--font-display);font-size:1.12rem;font-weight:700;line-height:1.32;}
.card p.excerpt{color:var(--text-secondary);font-size:0.88rem;}

/* .card-footer et .read-more ont disparu : la carte entière est cliquable et le
   compteur de vues a rejoint la zone de méta, sous la date. */

/* Encart d'espace publicitaire à louer, glissé dans le flux toutes les 24 news.
   Contour tireté et fond neutre : il doit se lire comme un emplacement libre,
   pas comme une actualité de plus — la confusion avec le contenu éditorial
   serait pire que l'absence d'encart. */
.ad-slot{
  /* .card n'apporte que le fond/bordure/radius : le flex + padding qui donnent
     habituellement de l'air aux cartes viennent de .card-inner, absent ici
     (l'encart n'a pas de wrapper) — sans cette ligne, tag/titre/texte/bouton
     collaient directement aux bords tiretés. */
  display:flex;flex-direction:column;
  justify-content:center;align-items:center;text-align:center;gap:12px;
  padding:28px;min-height:200px;
  background:
    repeating-linear-gradient(135deg, rgba(120,170,255,0.045) 0 10px, transparent 10px 20px),
    var(--bg-panel);
  border:1px dashed var(--border-soft);
}
.ad-slot:hover{border-color:var(--border-glow);transform:none;box-shadow:none;}
/* Une vraie campagne payée par un annonceur : bordure pleine plutôt que
   tiretée, elle ne doit plus se lire comme "un emplacement encore libre". */
.ad-slot--campaign{
  border-style:solid;border-color:rgba(139,123,255,0.35);
  background:
    radial-gradient(circle at 15% 0%, rgba(139,123,255,0.10), transparent 50%),
    var(--bg-panel);
}
.ad-slot--campaign:hover{border-color:var(--neon-violet);}
.ad-slot--campaign .ad-tag{color:var(--neon-violet);border-color:rgba(139,123,255,0.4);}
.ad-slot .ad-image{max-width:100%;max-height:180px;object-fit:contain;border-radius:8px;}

/* En dessous de 861px (mobile/tablette étroite), .feed repasse en 1 colonne
   (voir plus bas) : la largeur choisie par l'annonceur ne s'applique qu'en
   desktop, où plusieurs colonnes coexistent réellement. */
@media (min-width:861px){
  .ad-slot{padding:40px;}
  .ad-slot--w1{grid-column:span 1;}
  .ad-slot--w2{grid-column:span 2;}
  /* Le format portrait occupe une colonne et deux rangées réelles de la
     grille. Hors de cette media query, il redevient une carte normale. */
  .ad-slot--tall{grid-column:span 1;grid-row:span 2;}
  .ad-slot--tall .ad-title{max-width:20ch;}
  .ad-slot--tall .ad-text{max-width:32ch;}

  .ad-slot--w3{grid-column:span 3;}
  .ad-slot--wfull{grid-column:1 / -1;}
  /* Sans "dense", un item qui ne tient plus dans la ligne courante (colonne
     restante insuffisante) saute la ligne entière et laisse derrière lui une
     case vide que le placement automatique "sparse" (par défaut) ne rebouche
     jamais — d'où les trous. "dense" fait remonter la carte d'actu suivante
     dans cette case libre plutôt que de la laisser béante. */
  .feed{grid-auto-flow:dense;}

  /* Variation de mise en page : quelques cartes d'actu (pas les encarts pub,
     qui ont déjà leur propre largeur choisie par l'annonceur) occupent
     occasionnellement 2 colonnes de large ou 2 lignes de haut, pour casser la
     monotonie d'une grille toujours identique — assignation aléatoire mais
     stable par article, voir index.php (boucle de rendu du flux). */
  .card.card-wide{grid-column:span 2;}
  .card.card-tall{grid-row:span 2;}
  /* Les cartes agrandies ont plus d'espace à occuper : padding et typographie
     remontés d'un cran, et le contenu (moins haut que l'espace disponible
     côté .card-tall, faute d'image sur les articles non-vidéo) centré
     verticalement plutôt que collé en haut. */
  .card.card-wide .card-inner,
  .card.card-tall .card-inner{padding:30px;}
  .card.card-tall .card-inner{justify-content:center;}
  .card.card-wide h3,
  .card.card-tall h3{font-size:1.38rem;line-height:1.28;}
  .card.card-wide p.excerpt,
  .card.card-tall p.excerpt{font-size:0.96rem;}
  .card.card-tall .video-thumb{height:260px;}
  .card.card-wide .video-row .video-thumb{flex:0 0 260px;width:260px;height:150px;}
}
.ad-tag{
  align-self:center;
  font-family:var(--font-mono);font-size:0.58rem;letter-spacing:0.09em;text-transform:uppercase;
  color:var(--text-dim);border:1px solid var(--border-soft);
  padding:3px 10px;border-radius:20px;
}
.ad-title{font-family:var(--font-display);font-size:1.05rem;font-weight:700;color:var(--text-primary);}
.ad-text{color:var(--text-secondary);font-size:0.85rem;line-height:1.55;}
.ad-cta{
  align-self:center;margin-top:2px;
  font-size:0.8rem;font-weight:600;
  padding:9px 18px;border-radius:20px;
  background:linear-gradient(100deg,var(--neon-cyan),var(--neon-blue));
  color:var(--bg-void);
  transition:transform .18s ease, box-shadow .18s ease, filter .18s ease;
}
.ad-cta:hover{transform:translateY(-1px);box-shadow:0 6px 18px rgba(47,213,255,0.35);filter:brightness(1.08);}

/* Bandeau du filtre actif (date ou source), au-dessus du flux. */
.active-filter{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  margin:0 0 20px;padding:12px 16px;
  background:var(--bg-panel);border:1px solid var(--border-soft);border-radius:var(--radius);
}
.active-filter-label{font-size:0.92rem;font-weight:600;color:var(--text-primary);}
.active-filter-count{
  font-family:var(--font-mono);font-size:0.7rem;color:var(--neon-cyan);
  background:rgba(47,213,255,0.1);border:1px solid rgba(47,213,255,0.28);
  padding:2px 8px;border-radius:20px;font-variant-numeric:tabular-nums;
}
.active-filter-clear{
  display:inline-flex;align-items:center;gap:6px;margin-left:auto;
  font-size:0.8rem;font-weight:600;color:var(--text-secondary);
  padding:6px 12px;border-radius:20px;border:1px solid var(--border-soft);
  transition:color .18s ease, border-color .18s ease;
}
.active-filter-clear:hover{color:var(--neon-cyan);border-color:var(--border-glow);}
.active-filter-clear svg{width:13px;height:13px;}

footer{border-top:1px solid var(--border-soft);padding:44px 0 34px;position:relative;}

.back-to-top{
  position:fixed;bottom:28px;right:28px;z-index:90;
  width:44px;height:44px;border-radius:50%;
  background:var(--bg-panel);border:1px solid var(--border-soft);
  color:var(--neon-cyan);font-size:1rem;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 8px 24px rgba(0,0,0,0.45);
  opacity:0;visibility:hidden;transform:translateY(10px);
  transition:opacity .25s ease, transform .25s ease, visibility .25s, border-color .18s ease, box-shadow .18s ease;
}
.back-to-top.visible{opacity:1;visibility:visible;transform:translateY(0);}
.back-to-top:hover{border-color:var(--border-glow);box-shadow:0 0 18px rgba(47,213,255,0.35);}
@media (max-width:860px){
  .back-to-top{bottom:20px;right:20px;width:40px;height:40px;}
}
.footer-inner{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:24px;}
.footer-inner p{color:var(--text-dim);font-size:0.8rem;max-width:520px;}
.footer-logo{flex:0 0 auto;}
.footer-logo .logo-lockup{font-size:0.95rem;}
/* Discret à dessein : ce lien vers le back-office n'a rien à faire mis en avant
   pour le grand public, mais doit rester atteignable pour l'admin sans avoir à
   taper l'URL de mémoire. */
.footer-admin-link{color:var(--text-dim);font-size:0.72rem;text-decoration:none;opacity:0.6;flex:0 0 auto;}
.footer-admin-link:hover{opacity:1;color:var(--text-secondary);}

@media (max-width:860px){
  /* Tiroir latéral glissant depuis la droite.
     `visibility` (et non `display`) garde l'élément animable tout en le retirant
     de l'ordre de tabulation quand il est fermé — un display:none casserait la
     transition, et un simple translate laisserait les liens focusables. */
  nav.main-nav{
    /* header-h + ticker-h : le bandeau de news est désormais au-dessus du
       header (voir plus bas), le tiroir doit donc démarrer sous les deux. */
    position:fixed;top:calc(var(--header-h) + var(--ticker-h));right:0;bottom:0;
    width:min(78vw,320px);
    display:flex;flex-direction:column;gap:2px;
    background:var(--bg-panel-2);
    border-left:1px solid var(--border-soft);
    box-shadow:-24px 0 60px rgba(0,0,0,0.6);
    padding:18px 14px calc(18px + env(safe-area-inset-bottom));
    z-index:105;
    overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
    /* `display:none` au repos, et non un simple `visibility:hidden` : rangé hors
       écran par translateX(100%), le tiroir élargissait la zone défilable du
       document de sa propre largeur (320px de défilement horizontal parasite en
       affichage mobile, qui empêchait le header de rester collé). `visibility` ne
       retire pas l'élément de ce calcul, `display` si.
       Le glissement est préservé en deux temps, pilotés par app.js : `.mounted`
       met le tiroir dans le rendu, encore hors écran, puis `.open` le fait
       glisser. Deux classes plutôt qu'une seule avec `@starting-style`, qui
       laissait le tiroir bloqué hors écran. */
    display:none;
    transform:translateX(100%);
    transition:transform .34s cubic-bezier(.32,.72,0,1);
  }
  nav.main-nav.mounted{display:flex;}
  nav.main-nav.open{transform:none;}

  /* Sous 860px, le tiroir troque le court menu du bureau (Actualités/Essais/
     Apps/Vidéos) contre la liste complète des catégories, colorées comme les
     onglets .filters — masqués juste en dessous pour libérer la place que ces
     16 onglets prenaient sur la page d'accueil. */
  .nav-desktop-links{display:none;}
  /* Deux colonnes : à raison de 16 catégories, une seule colonne obligeait à
     faire défiler tout le tiroir pour atteindre les dernières. */
  .nav-mobile-links{display:grid;grid-template-columns:1fr 1fr;gap:2px 8px;}

  /* Apparition échelonnée des liens, une fois le tiroir en place. */
  nav.main-nav a{
    padding:13px 14px;border-radius:9px;font-size:0.98rem;
    opacity:0;transform:translateX(16px);
    transition:opacity .28s ease, transform .28s cubic-bezier(.32,.72,0,1),
               background .18s ease, color .18s ease;
  }
  nav.main-nav.open a{opacity:1;transform:none;}
  /* Échelonnement sur les 8 premiers éléments visibles (.nav-mobile-links, la
     liste de catégories, sur mobile) ; au-delà, tout le monde partage le
     dernier délai plutôt que d'énumérer un nth-child par catégorie. */
  nav.main-nav.open .nav-mobile-links a:nth-child(1){transition-delay:.06s;}
  nav.main-nav.open .nav-mobile-links a:nth-child(2){transition-delay:.09s;}
  nav.main-nav.open .nav-mobile-links a:nth-child(3){transition-delay:.12s;}
  nav.main-nav.open .nav-mobile-links a:nth-child(4){transition-delay:.15s;}
  nav.main-nav.open .nav-mobile-links a:nth-child(5){transition-delay:.18s;}
  nav.main-nav.open .nav-mobile-links a:nth-child(6){transition-delay:.21s;}
  nav.main-nav.open .nav-mobile-links a:nth-child(7){transition-delay:.24s;}
  nav.main-nav.open .nav-mobile-links a:nth-child(n+8){transition-delay:.27s;}
  /* Colonnes plus étroites qu'une liste pleine largeur : libellé plus compact
     et retour à la ligne autorisé (les intitulés de catégorie font parfois
     deux mots) plutôt qu'un débordement ou une troncature qui rendrait le nom
     illisible. */
  .nav-mobile-links a{
    padding:10px 10px;font-size:0.86rem;line-height:1.25;
    white-space:normal;word-break:break-word;
    /* Sans ça, un élément de grille garde min-width:auto par défaut : la piste
       1fr ne peut alors pas rétrécir sous la largeur du contenu, et la grille
       déborde du tiroir horizontalement — le tiroir n'affichait de fait que sa
       moitié gauche, le reste nécessitant un défilement horizontal invisible. */
    min-width:0;
  }
  nav.main-nav a.nav-account-link{
    margin-top:10px;padding-top:18px;
    border-top:1px solid var(--border-soft);
    border-radius:0;color:var(--text-dim);font-size:0.88rem;
  }

  /* Bascules archives : deux boutons poussoirs, avec le même style de tiroir
     séparé par un filet que "Mon compte" pour marquer que ce ne sont pas des
     catégories mais des réglages d'affichage. */
  .nav-archives-toggles{
    display:flex;flex-direction:column;gap:2px;
    margin-top:10px;padding-top:14px;
    border-top:1px solid var(--border-soft);
  }
  nav.main-nav a.nav-toggle{
    display:flex;align-items:center;gap:10px;
    padding:10px 14px;color:var(--text-secondary);font-size:0.88rem;
  }
  .nav-toggle-track{
    flex:0 0 auto;position:relative;
    width:34px;height:20px;border-radius:999px;
    background:var(--bg-panel);border:1px solid var(--border-soft);
    transition:background .18s ease, border-color .18s ease;
  }
  .nav-toggle-thumb{
    position:absolute;top:2px;left:2px;
    width:14px;height:14px;border-radius:50%;
    background:var(--text-dim);
    transition:transform .22s cubic-bezier(.32,.72,0,1), background .18s ease;
  }
  nav.main-nav a.nav-toggle.is-on{color:var(--text-primary);}
  nav.main-nav a.nav-toggle.is-on .nav-toggle-track{
    background:rgba(47,213,255,0.18);border-color:var(--neon-cyan);
  }
  nav.main-nav a.nav-toggle.is-on .nav-toggle-thumb{
    transform:translateX(14px);background:var(--neon-cyan);
    box-shadow:0 0 8px rgba(47,213,255,0.6);
  }
  .nav-toggle-label{flex:1;min-width:0;}
  /* Nombre d'articles en archive, sur la bascule "Afficher uniquement les
     archives" — même traitement visuel que .filter-count des onglets. */
  .nav-toggle-count{
    flex:0 0 auto;
    font-family:var(--font-mono);font-size:0.68rem;font-weight:600;
    padding:1px 7px;border-radius:10px;
    background:rgba(120,170,255,0.14);color:var(--text-dim);
  }
  nav.main-nav a.nav-toggle.is-on .nav-toggle-count{
    background:rgba(47,213,255,0.16);color:var(--neon-cyan);
  }

  /* Couleurs par catégorie dans le tiroir mobile, mêmes teintes que les onglets
     .filters (voir plus bas dans ce fichier) — « avec les couleurs
     correspondantes » : la couleur doit identifier la catégorie même quand les
     onglets ne sont plus visibles à l'écran pour comparer. */
  .nav-mobile-links a[data-type="essay"]{color:#4c83f0;}
  .nav-mobile-links a[data-type="app"]{color:#945fdd;}
  .nav-mobile-links a[data-type="website"]{color:#26bbd9;}
  .nav-mobile-links a[data-type="video"]{color:#3ea2ea;}
  .nav-mobile-links a[data-type="thesis"]{color:#f47434;}
  .nav-mobile-links a[data-type="medical"]{color:#e64ca6;}
  .nav-mobile-links a[data-type="architecture"]{color:#cb9d4d;}
  .nav-mobile-links a[data-type="climate"]{color:#4dd68a;}
  .nav-mobile-links a[data-type="learning"]{color:#c945b3;}
  .nav-mobile-links a[data-type="science"]{color:#e8c930;}
  .nav-mobile-links a[data-type="space"]{color:#515dec;}
  .nav-mobile-links a[data-type="security"]{color:#ff5c5c;}
  .nav-mobile-links a[data-type="business"]{color:#a6b946;}
  .nav-mobile-links a[data-type="policy"]{color:#a1a9ba;}
  .nav-mobile-links a[data-type="robotics"]{color:#745fdd;}
  .nav-mobile-links a.active{background:rgba(120,170,255,0.10);}

  /* Onglets de catégories de la page d'accueil : redondants avec le tiroir
     mobile ci-dessus une fois qu'il porte la liste complète, et c'est ce bloc
     qui remplissait l'accueil sur petit écran. */
  .filters{display:none;}
  /* Bascules archives sous la barre de recherche : redondantes avec celles du
     tiroir mobile, qui portent les mêmes liens juste en dessous des catégories. */
  .archives-bar{display:none;}

  /* Bandeau de news figé avec le header (menu, thème, langues) plutôt que
     simplement "sticky" : en `sticky`, le bandeau défile avec la page tant
     qu'on n'a pas remonté jusqu'à lui, et n'apparaît collé qu'ensuite. En
     `fixed`, il reste en place dès le chargement, comme les boutons du
     header. Placé au-dessus du header (et non dessous) : le header, resté
     `sticky`, est décalé de sa hauteur via `top`, ce qui réserve
     naturellement la bande du haut pour le bandeau sans toucher au JS.
     `.hero` compense la hauteur du bandeau, seul élément sorti du flux
     normal (le header garde sa place réservée en restant sticky). */
  .ticker{position:fixed;top:0;left:0;right:0;}
  header.site-header{top:var(--ticker-h);}
  .hero{margin-top:var(--ticker-h);}

  /* Démarre sous le bandeau ET le header, désormais empilés l'un sur
     l'autre en haut d'écran : les deux restent visibles et cliquables
     pendant que le tiroir est ouvert, seul le contenu en dessous s'assombrit. */
  .nav-backdrop{display:block;inset:calc(var(--header-h) + var(--ticker-h)) 0 0 0;}
  /* Colonne "DIRECT" resserrée et calée près du bord gauche : la largeur
     gagnée revient à `.ticker-track-wrap` (flex:1), pour que le bandeau
     défilant ait plus de place. */
  .ticker-label{padding:0 8px 0 6px;gap:5px;}
  .menu-toggle{display:flex;}
  .hero-grid{grid-template-columns:1fr;}
  /* Le bandeau animé reste affiché sur mobile. Il est simplement plus haut :
     à cette largeur le titre passe sur trois lignes, et une bande de 160 px
     le laisserait dépasser hors du champ d'étoiles. */
  .scan-visual{height:240px;}
  .feed{grid-template-columns:1fr;}
  /* `right:0` (aligné sur le bord de l'écran) et une largeur plafonnée à la
     largeur de viewport moins marges : le `right:-40px` précédent décalait
     le panneau hors écran, ne laissant que ses 2/3 gauches visibles — les
     derniers drapeaux de chaque ligne étaient donc coupés. */
  .lang-panel{width:min(300px, calc(100vw - 24px));right:0;}

  /* Cartes vidéo : texte sous la miniature plutôt qu'à côté, en pleine largeur */
  .video-row{flex-direction:column;}
  .video-row .video-thumb{width:100%;flex:0 0 auto;height:180px;}
}

:focus-visible{outline:2px solid var(--neon-cyan);outline-offset:2px;}

/* ============================================================
   FENÊTRE CONNEXION / INSCRIPTION — deux parcours (particulier / pro)
   ============================================================ */
.auth-overlay{
  position:fixed;inset:0;z-index:400;
  display:flex;align-items:center;justify-content:center;
  padding:24px;
  background:radial-gradient(circle at 50% 20%, rgba(76,124,255,0.16), rgba(2,4,10,0.86) 60%);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  opacity:0;pointer-events:none;
  transition:opacity .25s ease;
}
.auth-overlay.is-open{opacity:1;pointer-events:auto;}

.auth-modal{
  position:relative;width:min(920px, 100%);max-height:88vh;overflow-y:auto;
  border-radius:20px;padding:2px;
  background:linear-gradient(135deg, var(--neon-cyan), var(--neon-violet), var(--neon-blue));
  background-size:220% 220%;
  animation:authBorderFlow 8s ease infinite;
  transform:translateY(18px) scale(.98);opacity:0;
  transition:transform .32s cubic-bezier(.2,.8,.2,1), opacity .28s ease;
}
.auth-overlay.is-open .auth-modal{transform:translateY(0) scale(1);opacity:1;}
@keyframes authBorderFlow{
  0%,100%{background-position:0% 50%;}
  50%{background-position:100% 50%;}
}
/* Le dégradé n'habille qu'un liseré de 2px : le fond réel du contenu vit dans
   cette couche interne, opaque, posée par-dessus — d'où le padding:2px ci-dessus
   plutôt qu'une bordure CSS classique (impossible à animer en dégradé). */
.auth-modal::before{
  content:'';position:absolute;inset:2px;border-radius:18px;
  background:
    radial-gradient(circle at 15% 0%, rgba(47,213,255,0.10), transparent 45%),
    radial-gradient(circle at 100% 100%, rgba(139,123,255,0.10), transparent 45%),
    var(--bg-panel);
  z-index:0;
}
.auth-modal > *{position:relative;z-index:1;}

.auth-close{
  position:absolute;top:16px;right:16px;z-index:2;
  width:34px;height:34px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(120,170,255,0.08);border:1px solid var(--border-soft);color:var(--text-secondary);
  cursor:pointer;transition:color .15s ease, border-color .15s ease, transform .15s ease;
}
.auth-close:hover{color:var(--text-primary);border-color:var(--border-glow);transform:rotate(90deg);}

.auth-screen{padding:48px 44px 40px;}

.auth-hero{text-align:center;max-width:520px;margin:0 auto 34px;}
.auth-hero-tag{
  display:inline-block;font-family:var(--font-mono);font-size:0.68rem;letter-spacing:0.14em;text-transform:uppercase;
  color:var(--neon-cyan);border:1px solid var(--border-soft);padding:4px 14px;border-radius:20px;margin-bottom:16px;
}
.auth-hero h2{font-family:var(--font-display);font-size:1.9rem;font-weight:800;margin:0 0 10px;
  background:linear-gradient(100deg, var(--text-primary), var(--neon-cyan) 60%, var(--neon-violet));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.auth-hero p{color:var(--text-secondary);font-size:0.98rem;line-height:1.5;margin:0;}

.auth-tracks{display:grid;grid-template-columns:1fr 1fr;gap:20px;}
.auth-track-card{
  text-align:left;cursor:pointer;
  display:flex;flex-direction:column;gap:12px;
  padding:26px 24px;border-radius:16px;
  background:linear-gradient(160deg, rgba(120,170,255,0.05), transparent 60%), var(--bg-panel-2);
  border:1px solid var(--border-soft);
  color:var(--text-primary);font-family:var(--font-body);
  transition:transform .25s cubic-bezier(.2,.8,.2,1), border-color .25s ease, box-shadow .25s ease;
}
.auth-track-card:hover, .auth-track-card:focus-visible{
  transform:translateY(-4px);
  box-shadow:0 18px 40px rgba(0,0,0,0.35);
}
.auth-track-card--individual:hover{border-color:var(--neon-cyan);}
.auth-track-card--professional:hover{border-color:var(--neon-violet);}
.auth-track-icon{
  width:52px;height:52px;border-radius:14px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(120,170,255,0.08);
}
.auth-track-card--individual .auth-track-icon{color:var(--neon-cyan);}
.auth-track-card--professional .auth-track-icon{color:var(--neon-violet);}
.auth-track-card h3{font-family:var(--font-display);font-size:1.2rem;font-weight:700;margin:0;}
.auth-track-pitch{color:var(--text-secondary);font-size:0.86rem;line-height:1.5;margin:0;}
.auth-track-points{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px;}
.auth-track-points li{
  font-size:0.82rem;color:var(--text-secondary);padding-left:20px;position:relative;
}
.auth-track-points li::before{
  content:'';position:absolute;left:0;top:7px;width:8px;height:8px;border-radius:2px;
  background:linear-gradient(135deg, var(--neon-cyan), var(--neon-violet));
  transform:rotate(45deg);
}
.auth-track-cta{
  margin-top:auto;padding-top:6px;
  font-family:var(--font-display);font-weight:700;font-size:0.9rem;
  background:linear-gradient(100deg,var(--neon-cyan),var(--neon-blue));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}

.auth-login-instead{
  display:block;margin:26px auto 0;background:none;border:none;cursor:pointer;
  color:var(--text-secondary);font-size:0.85rem;text-decoration:underline;text-underline-offset:3px;
}
.auth-login-instead:hover{color:var(--text-primary);}

/* Écran formulaire */
.auth-back{
  background:none;border:none;cursor:pointer;color:var(--text-secondary);font-size:0.82rem;
  margin-bottom:18px;padding:0;
}
.auth-back:hover{color:var(--neon-cyan);}

.auth-form-tabs{display:flex;gap:6px;padding:4px;background:var(--bg-void);border-radius:12px;border:1px solid var(--border-soft);margin-bottom:26px;max-width:320px;}
.auth-form-tab{
  flex:1;padding:9px 12px;border-radius:9px;border:none;cursor:pointer;
  font-family:var(--font-display);font-size:0.85rem;font-weight:600;
  background:transparent;color:var(--text-secondary);transition:background .2s ease, color .2s ease;
}
.auth-form-tab.is-active{background:linear-gradient(100deg,var(--neon-cyan),var(--neon-blue));color:var(--bg-void);}

#authForm{display:flex;flex-direction:column;gap:16px;max-width:480px;}
.auth-field-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
.auth-field-group{display:flex;flex-direction:column;gap:6px;}
.auth-field-group.is-hidden{display:none;}
.auth-field-group label{font-size:0.8rem;font-weight:600;color:var(--text-secondary);}
.auth-field-group input, .auth-field-group textarea{
  background:var(--bg-void);border:1px solid var(--border-soft);border-radius:10px;
  padding:11px 14px;color:var(--text-primary);font-family:var(--font-body);font-size:0.92rem;
  transition:border-color .18s ease, box-shadow .18s ease;
  resize:vertical;
}
.auth-field-group input:focus, .auth-field-group textarea:focus{
  outline:none;border-color:var(--neon-cyan);box-shadow:0 0 0 3px rgba(47,213,255,0.15);
}
.auth-field-group input.is-invalid, .auth-field-group textarea.is-invalid{border-color:#ff5d7a;}
.auth-field-hint{font-size:0.74rem;color:var(--text-dim);}
.auth-field-error{font-size:0.76rem;color:#ff5d7a;}

.auth-form-error{
  font-size:0.85rem;color:#ff5d7a;background:rgba(255,93,122,0.08);border:1px solid rgba(255,93,122,0.3);
  border-radius:10px;padding:10px 14px;margin:0;
}
.auth-form-error[hidden]{display:none;}

.auth-submit{
  margin-top:4px;padding:13px 20px;border:none;border-radius:12px;cursor:pointer;
  font-family:var(--font-display);font-weight:700;font-size:0.95rem;color:var(--bg-void);
  background:linear-gradient(100deg,var(--neon-cyan),var(--neon-blue),var(--neon-violet));
  background-size:200% auto;
  transition:background-position .3s ease, transform .15s ease, box-shadow .2s ease;
  box-shadow:0 10px 26px rgba(47,213,255,0.25);
}
.auth-submit:hover{background-position:100% center;transform:translateY(-1px);box-shadow:0 14px 32px rgba(47,213,255,0.35);}
.auth-submit:disabled{opacity:0.6;cursor:wait;transform:none;}

/* Écran succès */
.auth-screen-success{text-align:center;padding:64px 44px;}
.auth-success-icon{
  width:84px;height:84px;margin:0 auto 22px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(47,213,255,0.1);color:var(--neon-cyan);
  animation:authSuccessPop .4s cubic-bezier(.2,.9,.3,1.3);
}
@keyframes authSuccessPop{from{transform:scale(0.5);opacity:0;}to{transform:scale(1);opacity:1;}}
.auth-screen-success p{color:var(--text-secondary);font-size:0.95rem;line-height:1.6;max-width:420px;margin:0 auto;}

@media (max-width:720px){
  .auth-screen{padding:34px 22px 28px;}
  .auth-tracks{grid-template-columns:1fr;}
  .auth-field-row{grid-template-columns:1fr;}
  .auth-hero h2{font-size:1.5rem;}
}

/* Lien "Mon compte" transformé en déclencheur de la modale + icône compte connecté */
.nav-account-link{cursor:pointer;}

/* Message bref (ex. "connectez-vous pour ajouter aux favoris") : centré en
   bas d'écran, apparition/disparition douce, aucune interaction requise
   (se dissipe tout seul — voir showToast(), auth.js). */
.toast{
  position:fixed;left:50%;bottom:28px;z-index:400;
  max-width:min(88vw, 380px);
  padding:12px 20px;border-radius:999px;
  background:rgba(8,13,26,0.92);border:1px solid var(--border-glow);
  color:var(--text-primary);font-size:0.86rem;text-align:center;line-height:1.4;
  box-shadow:0 10px 30px rgba(0,0,0,0.45);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  opacity:0;pointer-events:none;
  transform:translate(-50%, 10px);
  transition:opacity .22s ease, transform .22s ease;
}
.toast.show{opacity:1;transform:translate(-50%, 0);}
@media (prefers-reduced-motion:reduce){.toast{transition:opacity .15s linear;}}

/* AM-IA identity: geometric vector wordmark, shared by every public header. */
.logo .am-brand{display:block;width:190px;height:auto;color:var(--text-primary);flex-shrink:0;filter:none}
.am-brand-symbol{color:#79ffe1}
:root[data-theme=light] .am-brand-symbol{color:#007f71}
.footer-logo .am-brand{width:165px}
@media(max-width:600px){.logo .am-brand{width:150px}}

/* Selected identity 02: neural lattice, cobalt and periwinkle. */
.am-neural-primary{color:#5271ff}.am-neural-secondary{color:#a49aff}
:root[data-theme=light] .am-neural-primary{color:#304bd4}
:root[data-theme=light] .am-neural-secondary{color:#6553c5}
.logo .am-brand{width:205px}.footer-logo .am-brand{width:180px}
@media(max-width:600px){.logo .am-brand{width:155px}}
