/* Blog index — full redesign reusing the exact split/typography/card
   system already proven on /ai-hub/ (see css/components/ai-hub.css and
   pages/ai-hub.njk), not a new visual language. The design tokens below
   are intentionally byte-identical to ai-hub.css's own --li-* recipe
   (same values, same names) rather than a shared file, matching how this
   codebase already handles this exact situation elsewhere (ai-hub.css's
   own header comment: "lifted directly from .blog-sidebar-card and
   .blog-search in blog.css") — ai-hub.css itself is never touched by this
   file. Scoped to .blog-hero/.blog-feed so nothing here leaks onto any
   other page. */
.blog-hero,
.blog-feed {
  --li-card-bg: rgba(38, 32, 56, 0.55);
  --li-card-blur: blur(24px);
  --li-border: rgba(255, 255, 255, 0.08);
  --li-border-hover: rgba(88, 130, 246, 0.4);
  --li-shadow: 0 4px 24px rgba(0, 0, 0, 0.35);
  --li-shadow-hover: 0 10px 32px rgba(63, 123, 248, 0.16), 0 4px 16px rgba(184, 107, 248, 0.12);
  --li-radius: 16px;
  --li-text: rgba(255, 255, 255, 0.92);
  --li-text-secondary: rgba(255, 255, 255, 0.6);
  --li-media-bg: rgba(10, 8, 16, 0.6);
}

/* Same wide 1560px matrix as /ai-hub/ (not page-split's 1180px default) —
   the whole point of this redesign is that both pages share one matrix,
   so this must equal ai-hub.css's own .ai-hub-hero .section__inner /
   .page-split--ai-hub values exactly, not an approximation. Scoped to
   .page-split--blog / .blog-hero only. */
.blog-hero .section__inner {
  max-width: 1560px;
}

@media (min-width: 1024px) {
  .page-split--blog {
    max-width: 1560px;
    --page-split-intro: 390px;
    --page-split-gap: 56px;
  }

  /* Un seul article publié aujourd'hui -- sans plancher, .blog-hero se
     réduit à la hauteur de ce seul article et le footer apparaît dans le
     premier écran, avant même de scroller ("on voit le footer direct").
     min-height (jamais un max) réserve la hauteur d'un écran typique et
     grandit sans problème le jour où il y a assez d'articles pour la
     dépasser naturellement. */
  .blog-hero {
    min-height: 100vh;
  }
}

.blog-subtitle {
  max-width: 46ch;
}

/* Centered (explicit direction, superseding the left-aligned pass this
   comment used to describe) — same override technique ai-hub.css/
   contact-hero.css/faq.css already use for their own intro columns
   (page-split.css's shared default left-aligns .page-title/.page-subtitle
   at this breakpoint; an ancestor text-align alone isn't specific enough
   to beat that). */
@media (min-width: 1024px) {
  .blog-hero__inner.page-split__intro .page-title,
  .blog-hero__inner.page-split__intro .page-subtitle {
    text-align: center;
    margin-left: auto;
    margin-right: auto;
  }
}

/* Same recipe as .ai-hub-sr-only (ai-hub.css) — not shared as one global
   utility class anywhere on this site (hero.css has its own too), so this
   follows the existing per-component convention rather than reaching
   across to a stylesheet this page never loads. */
.blog-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;
}

/* Restored to the exact pre-redesign recipe (explicit direction: "refais
   exactement comme avant") — the lighter rgba(255,255,255,.1)/.5-border
   glass, not this page's own darker --li-* card tokens. Centered and
   markedly narrower than the content column (explicit direction) rather
   than filling its full width. */
.blog-search {
  position: relative;
  max-width: 640px;
  margin: 0 auto 28px;
}

.blog-search__icon {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  color: rgba(255, 255, 255, 0.6);
  pointer-events: none;
  /* Real bug found and fixed: backdrop-filter on .blog-search__input
     forces that element into the same z-index:0-equivalent stacking
     layer as this absolutely-positioned icon (backdrop-filter/filter
     always creates a stacking context) — with both now in that same
     layer, plain DOM order decided who painted on top, and the input
     comes AFTER the icon in markup, so it silently covered the icon
     completely despite the icon's own opacity/color/position all being
     correct. An explicit z-index (not needed before backdrop-filter
     entered the picture) settles the order for good. */
  z-index: 1;
}

.blog-search__input {
  width: 100%;
  height: 52px;
  min-height: 44px;
  padding: 0 40px 0 48px;
  border: 0.5px solid rgba(255, 255, 255, 0.5);
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border-radius: 8px;
  color: #fff;
  font-family: var(--font-satoshi);
  font-size: 15px;
  appearance: none;
}

.blog-search__input::placeholder {
  color: #666;
}

.blog-search__input:focus-visible {
  outline: 2px solid var(--li-border-hover);
  outline-offset: 2px;
}

/* Native `<input type="search">` clear "x" varies by browser (and is
   sometimes invisible on a dark background) — hidden in favor of this
   explicit, always-legible button, shown only once there's a value to
   clear (see js/blog-filter.js). */
.blog-search__input::-webkit-search-cancel-button {
  display: none;
}

.blog-search__clear {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: var(--li-text-secondary);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
  z-index: 1; /* same backdrop-filter stacking fix as .blog-search__icon */
}

.blog-search__clear[hidden] {
  display: none;
}

.blog-search__clear:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.blog-search__clear:focus-visible {
  outline: 2px solid var(--li-border-hover);
  outline-offset: 2px;
}

/* Newsletter — same premium card recipe as .ai-hub-identity, INCLUDING
   its animated conic-gradient border and hover halo bloom this time
   (explicit direction: "fais le même effet que la carte de mon Hub, la
   couleur au niveau de la bordure, le halo de lumière") — not a generic
   plain card anymore. Own custom property name (--blog-newsletter-
   border-angle, not ai-hub.css's --ai-hub-border-angle) so both pages can
   register the same technique without ever sharing global state. */
.blog-newsletter-card {
  position: relative;
  isolation: isolate;
  margin-top: 32px;
  padding: 26px;
  width: 100%;
  background:
    radial-gradient(120% 100% at 0% 0%, rgba(63, 123, 248, 0.14), transparent 60%),
    radial-gradient(120% 100% at 100% 100%, rgba(184, 107, 248, 0.12), transparent 60%),
    var(--li-card-bg);
  backdrop-filter: var(--li-card-blur);
  -webkit-backdrop-filter: var(--li-card-blur);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 18px;
  box-shadow: 0 16px 36px rgba(0, 0, 0, 0.35);
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}

@property --blog-newsletter-border-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.blog-newsletter-card::after {
  content: "";
  position: absolute;
  inset: -1.5px;
  z-index: -1;
  border-radius: inherit;
  padding: 1.5px;
  background: conic-gradient(
    from var(--blog-newsletter-border-angle),
    transparent 0deg,
    rgba(63, 123, 248, 0.9) 35deg,
    rgba(184, 107, 248, 0.95) 80deg,
    transparent 130deg,
    transparent 360deg
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  animation: blog-newsletter-border-travel 5s linear infinite;
}

@keyframes blog-newsletter-border-travel {
  to {
    --blog-newsletter-border-angle: 360deg;
  }
}

.blog-newsletter-card:hover {
  transform: translateY(-4px);
  border-color: rgba(255, 255, 255, 0.18);
  box-shadow:
    0 26px 52px rgba(0, 0, 0, 0.48),
    0 0 36px rgba(63, 123, 248, 0.28),
    0 0 64px rgba(184, 107, 248, 0.18),
    0 0 0 1px rgba(63, 123, 248, 0.18),
    0 2px 0 rgba(255, 255, 255, 0.04) inset;
}

@media (prefers-reduced-motion: reduce) {
  .blog-newsletter-card::after {
    animation: none;
  }

  .blog-newsletter-card:hover {
    transform: none;
  }
}

/* Phone: a touch narrower than the full column width (explicit
   direction) — same 94% + auto-center pattern used elsewhere on the site
   for a card that shouldn't quite touch the column's own edges. */
@media (max-width: 640px) {
  .blog-newsletter-card {
    width: 94%;
    margin-left: auto;
    margin-right: auto;
  }
}

.blog-newsletter-card__title {
  margin: 0;
  font-family: var(--font-satoshi);
  font-weight: 700;
  font-size: 17px;
  color: #fff;
}

.blog-newsletter-card__desc {
  margin: 10px 0 0;
  font-family: var(--font-satoshi);
  font-size: 14px;
  line-height: 1.6;
  color: var(--li-text-secondary);
}

.blog-newsletter-card form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 20px;
}

.blog-newsletter-card input {
  height: 46px;
  padding: 0 16px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--li-border);
  border-radius: 9px;
  color: #fff;
  font-family: var(--font-satoshi);
  font-size: 14px;
}

.blog-newsletter-card input::placeholder {
  color: var(--li-text-secondary);
}

.blog-newsletter-card input:focus-visible {
  outline: 2px solid var(--li-border-hover);
  outline-offset: 2px;
}

/* Full-width per explicit direction — reuses the site's own IAcine Tech
   gradient (same stops as .btn/button.css), not a one-off color. */
.blog-newsletter-card button {
  width: 100%;
  height: 44px;
  min-height: 44px;
  border-radius: 9999px;
  border: none;
  background: linear-gradient(270.04deg, #3f7bf8 0.04%, #b86bf8 99.96%);
  color: #fff;
  font-family: var(--font-satoshi);
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  transition: opacity 0.2s ease;
}

.blog-newsletter-card button:hover {
  opacity: 0.85;
}

.blog-newsletter-card button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.blog-newsletter-card__status {
  margin: 0;
  font-family: var(--font-satoshi);
  font-size: 12.5px;
  color: var(--li-text-secondary);
  display: none;
}

.blog-newsletter-card__status.is-visible {
  display: block;
}

.blog-newsletter-card__privacy {
  margin: 14px 0 0;
  font-family: var(--font-satoshi);
  font-size: 11px;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.4);
}

.blog-newsletter-card__privacy a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.blog-newsletter-card__privacy a:hover {
  color: #fff;
}

/* Filters — restored per-topic DA (explicit direction: "la même DA comme
   les tags d'avant"): standalone colored-border chips, NOT one shared
   glass toolbar panel. Each topic button carries its own --theme-color
   (set inline from themeMeta.colors, see pages/blogs.njk — same pattern
   the old .blog-theme-tab used). Unselected = colored border only,
   transparent fill; hover = temporarily filled with that color; selected
   = persistently filled. "Tous" carries no --theme-color, so it falls
   back to a neutral white-ish border/fill instead of a topic color.
   Still a real ARIA radiogroup underneath (single selection, roving
   tabindex + arrow-key nav in js/blog-filter.js) — only the coloring
   changed, not the accessible structure. */
.blog-toolbar {
  margin: 0 0 28px;
}

/* Back to flex-wrap, natural button widths — the auto-fit/stretched-grid
   version (each button filling its row edge-to-edge) was tried to
   perfectly balance row widths, but explicit direction reverted it:
   not liked visually. Centered, each chip sized to its own label. */
.blog-filtergroup {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 9px;
}

/* Réduits et arrondis en pilule (explicite : "trop gros", "plus mignons")
   -- même recette de couleur/interaction qu'avant (--theme-color, remplissage
   au survol/sélection), juste une pilule bien plus petite : padding et
   police en baisse, border-radius en 999px plutôt que 10px. min-height
   descend de 44 à 32px -- toujours un vrai bouton, mais qui se lit comme
   un petit tag, pas un CTA. */
.blog-filtergroup__btn {
  appearance: none;
  /* Chaque tag porte déjà sa propre couleur sur la bordure -- au repos,
     un fond transparent teinté de cette même couleur (pas un vrai
     transparent) fait que la pilule se lit colorée dès le départ, pas
     seulement au survol/sélection. */
  background: color-mix(in srgb, var(--theme-color, rgba(255, 255, 255, 0.4)) 16%, transparent);
  border: 1.5px solid var(--theme-color, rgba(255, 255, 255, 0.4));
  font-family: var(--font-satoshi);
  font-size: 12px;
  font-weight: 600;
  color: #fff;
  padding: 6px 14px;
  min-height: 32px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;
}

/* Temporary color fill on hover — reverts on mouse-leave unless also
   selected (the [aria-checked="true"] rule below then keeps it filled). */
.blog-filtergroup__btn:hover {
  background: var(--theme-color, rgba(255, 255, 255, 0.4));
}

.blog-filtergroup__btn[aria-checked="true"] {
  background: var(--theme-color, rgba(255, 255, 255, 0.55));
  box-shadow: 0 4px 16px color-mix(in srgb, var(--theme-color, #fff) 45%, transparent);
}

.blog-filtergroup__btn:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* This used to bump padding/font back UP for mobile (10px 14px / 12.5px)
   from a base that was itself bigger at the time -- now that the base
   pill is already small (6px 14px / 12px, see .blog-filtergroup__btn
   above), that override left mobile chips LARGER than desktop, exactly
   backwards. The small base already reads fine at every width, so this
   rule is gone rather than recomputed. */

/* Discreet — only ever unhidden by JS when a search/filter is active
   (see js/blog-filter.js), never a permanent fixture. */
.blog-results-count {
  margin: 0 0 16px;
  font-family: var(--font-satoshi);
  font-size: 13px;
  color: var(--li-text-secondary);
}

.blog-results-count[hidden] {
  display: none;
}

/* Grid — fluid (auto-fill/minmax), not fixed breakpoint columns like
   .ai-hub-grid: Blog's intro column is wider/heavier (search + newsletter
   card) than Hub IA's fixed 390px identity card, so the content column's
   real available width varies more; a fluid track keeps card width (and
   therefore visual density) matched to Hub IA's own cards at any given
   viewport instead of letting fixed repeat(3,1fr) go uncomfortably narrow
   right at the 1024px split breakpoint. Tuned so the numbers work out
   identical to .ai-hub-grid's real rendered card width at 1440/1920 (the
   comparison points) — 3 columns, ~305-355px cards — while naturally
   dropping to 2 then 1 as real available width shrinks, exactly per the
   brief's "grille fluide fondée sur la largeur réellement disponible". */
.blog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
  transition: opacity 0.18s ease;
}

/* Just the 1024–1439px tier (the split has just kicked in, right where the
   content column is at its narrowest relative to the fixed 390px+56px
   intro) gets a smaller minmax floor — 280px there computes to a single
   fluid column despite the column having real room for two comfortable
   ~260px cards; a smaller floor for exactly this tier fixes that without
   touching the ≥1440px math below, which already lands on the exact same
   card width as .ai-hub-grid at both 1440 and 1920 (the comparison
   points) using the default 280px floor. Still genuinely fluid within
   each tier — auto-fill computes the real column count from the real
   available width either way, this only tunes the floor per tier. */
@media (min-width: 1024px) and (max-width: 1439.98px) {
  .blog-grid {
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  }
}

@media (prefers-reduced-motion: reduce) {
  .blog-grid,
  .blog-card {
    transition: none;
  }
}

/* Card — same dark-glass family/border/radius/hover as .ai-hub-card. The
   whole card is one <a> (full-card click target) with a real heading,
   real paragraph and real link text inside for a genuinely accessible
   structure, not a div-soup wrapped in an anchor. */
.blog-card {
  display: flex;
  flex-direction: column;
  background: var(--li-card-bg);
  backdrop-filter: var(--li-card-blur);
  -webkit-backdrop-filter: var(--li-card-blur);
  border: 1px solid var(--li-border);
  border-radius: var(--li-radius);
  box-shadow: var(--li-shadow);
  overflow: hidden;
  color: inherit;
  text-decoration: none;
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.blog-card:hover {
  transform: translateY(-2px);
  border-color: var(--li-border-hover);
  box-shadow: var(--li-shadow-hover);
}

.blog-card:focus-visible {
  outline: 2px solid var(--li-border-hover);
  outline-offset: 2px;
}

/* [hidden] set directly by js/blog-filter.js on cards that don't match
   the active filter/search, or that are beyond the current "page" —
   author `display: flex` above always wins over the UA [hidden] default
   regardless of specificity, hence this explicit override (same fix
   already applied once for .ai-hub-loadmore/.ai-hub-consent). */
.blog-card[hidden] {
  display: none;
}

/* Same fixed height + object-fit across every card regardless of the
   source image's aspect ratio, matching .ai-hub-card__media's "consistent
   card heights" requirement — cover (not contain) here since these are
   real chosen cover images, not LinkedIn media of unpredictable shape. */
.blog-card__media {
  width: 100%;
  height: 200px;
  overflow: hidden;
  background: var(--li-media-bg);
  flex-shrink: 0;
}

.blog-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.blog-card__media--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, rgba(63, 123, 248, 0.35) 0%, rgba(184, 107, 248, 0.35) 60%, rgba(248, 107, 184, 0.3) 100%);
}

.blog-card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 16px 18px 18px;
}

.blog-card__meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-satoshi);
  font-weight: 500;
  font-size: 12px;
  color: var(--li-text-secondary);
  margin: 0;
}

.blog-card__meta-dot {
  opacity: 0.7;
}

/* Exactly 2 lines — line-clamp is fine here (unlike .ai-hub-card__excerpt,
   whose own comment explains why it avoids the auto-"…"): a blog title is
   authored copy meant to read cleanly truncated, not a raw LinkedIn text
   dump. */
.blog-card__title {
  font-family: var(--font-satoshi);
  font-weight: 700;
  font-size: 17px;
  line-height: 1.35;
  color: #fff;
  margin: 8px 0 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.blog-card__desc {
  font-family: var(--font-satoshi);
  font-weight: 400;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--li-text);
  margin: 8px 0 0;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.blog-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: auto;
  padding-top: 14px;
}

.blog-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}

/* Same per-topic colored-border DA as the filter chips above (--theme-
   color set inline per tag, see pages/blogs.njk) — the old design used
   one consistent .blog-tag recipe for both the filter tabs and each
   card's own tags, so this keeps that same consistency now that the
   filters are colored again. Not interactive, so no hover/selected state
   — border only, matching the old .blog-tag look exactly. */
.blog-card__tag {
  display: inline-flex;
  padding: 3px 10px;
  background: transparent;
  border: 1px solid var(--theme-color, rgba(255, 255, 255, 0.4));
  border-radius: 9999px;
  font-family: var(--font-satoshi);
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
}

.blog-card__tag--more {
  color: rgba(255, 255, 255, 0.4);
}

.blog-card__link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  font-family: var(--font-satoshi);
  font-size: 12.5px;
  font-weight: 600;
  color: #9fb8ff;
  white-space: nowrap;
  transition: color 0.15s ease, transform 0.15s ease;
}

.blog-card:hover .blog-card__link {
  color: #c3d4ff;
}

.blog-card:hover .blog-card__link svg {
  transform: translateX(2px);
}

.blog-card__link svg {
  transition: transform 0.15s ease;
}

/* Load more — identical component to .ai-hub-loadmore (same [hidden]
   fix, same .btn reuse, same width:auto/padding override). */
.blog-loadmore[hidden] {
  display: none;
}

.blog-loadmore {
  display: flex;
  justify-content: center;
  margin-top: 36px;
}

.blog-loadmore button {
  width: auto;
  padding: 0 28px;
}

.blog-empty[hidden] {
  display: none;
}

.blog-empty {
  text-align: center;
  padding: 48px 16px;
}

.blog-empty p {
  font-family: var(--font-satoshi);
  color: var(--color-muted-foreground, #9898a6);
  margin: 0 0 12px;
}

.blog-empty__reset {
  appearance: none;
  border: none;
  background: transparent;
  font-family: var(--font-satoshi);
  font-size: 14px;
  font-weight: 600;
  color: #9fb8ff;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  min-height: 44px;
  padding: 0 8px;
}

.blog-empty__reset:hover {
  color: #c3d4ff;
}

.blog-empty__reset:focus-visible {
  outline: 2px solid var(--li-border-hover);
  outline-offset: 2px;
}
