/* ==========================================================================
   Blog listing page — featured hero card, filter-pill row (markup/behavior
   from filter-pill.css + js/filter.js), a responsive card grid, and a
   "Load more" reveal button. Own near-black shade + small static accent
   spots, following the same per-section background recipe as pitch.css /
   roadmap.css.
   ========================================================================== */

.blog {
  position: relative;
  background-color: #0a0a0d;
  background-image: radial-gradient(circle at 10% 8%, rgba(91, 42, 134, 0.14), transparent 32%),
    radial-gradient(circle at 92% 18%, rgba(255, 122, 26, 0.08), transparent 30%);
  padding-block: var(--space-16);
}

/* WordPress compat: the posts-index page gets <body class="blog">, which
   collides with this section's own `.blog` class and pushed the section's
   padding-block onto <body> — a phantom 64px gap above the sticky header.
   body.blog (0,1,1) outranks .blog (0,1,0), so this neutralises it on the
   body only; the real <section class="blog"> keeps its padding intact. */
body.blog {
  padding-block: 0;
  background-image: none;
}

.blog__inner {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

/* --- Featured hero card: a 3-slide autoplay carousel, same recipe as the
   shop listing's own featured banner (css/shop.css) — image cross-slide,
   dark-glass tag, ring+dot indicators, fade/rise text entrance — adapted
   for a topic/read-time context instead of a price/rating one. See
   js/blog-featured-slider.js for the markup contract and transition
   choreography this CSS hooks into. --- */

.blog__featured {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  align-items: stretch;
  gap: var(--space-8);
  /* Reserves the tallest slide's worst case (3-line title + 3-line excerpt
     + footer) so the row height — and therefore the stretched media panel —
     stays constant across slides even though the title/excerpt no longer
     carry their own min-heights (excerpt now sits directly under the title). */
  min-height: 360px;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.32);
}

/* No aspect-ratio in the 2-column layout — same as .shop__featured-media:
   the media fills its column (stretched to the banner height) and its image
   crops via object-fit. An aspect-ratio here fought that stretch and made
   the picture spill over the text column on narrower screens. The 16:9 crop
   is restored only once the banner stacks into a single column (≤1024,
   image on top). */
.blog__featured-media {
  position: relative;
  overflow: hidden;
}

.blog__featured-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: transform 1000ms ease-in-out;
}

.blog__featured-media img.is-slide-incoming {
  transform: translateX(100%);
}

.blog__featured-media img.is-slide-outgoing {
  transform: translateX(-100%);
}

/* Mirror pair for a backward (swipe-right / prev) transition — incoming
   enters from the LEFT, outgoing exits RIGHT, so the slide follows the
   finger instead of always running right-to-left. See
   js/blog-featured-slider.js. */
.blog__featured-media img.is-slide-incoming-rev {
  transform: translateX(-100%);
}

.blog__featured-media img.is-slide-outgoing-rev {
  transform: translateX(100%);
}

.blog__featured-tag {
  position: absolute;
  z-index: 1;
  top: var(--space-5);
  left: var(--space-5);
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-sm);
  background: rgba(5, 5, 6, 0.72);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: var(--color-text);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  -webkit-user-select: none;
  user-select: none;
}

.blog__featured-dots {
  position: absolute;
  z-index: 2;
  bottom: var(--space-5);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: var(--space-3);
}

.blog__featured-dot {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  width: 10px;
  height: 10px;
  padding: 0;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.6);
  /* Dark translucent fill (all dots) so the white centre dot reads clearly
     against a light banner image behind it. */
  background: rgba(5, 5, 6, 0.45);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-standard);
}

/* Centre dot pinned to the exact middle (50/50 + translate) rather than an
   inset box — inset left it looking slightly off-centre inside the ring. */
.blog__featured-dot::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4px;
  height: 4px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: #fff;
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease-standard);
}

.blog__featured-dot.is-active {
  border-color: #fff;
}

.blog__featured-dot.is-active::before {
  opacity: 1;
}

/* Fixed min-height = the worst case (2-line title + 3-line excerpt) so the
   banner never changes height between slides (no jump), exactly like
   .shop__featured-body. The footer (date + Read-More pill) is pinned to the
   bottom via margin-top:auto, so a shorter title just leaves more room above
   the footer rather than a blank line under the title. */
.blog__featured-body {
  display: flex;
  flex-direction: column;
  min-height: 358px;
  padding: var(--space-8) var(--space-10);
  /* Trim the left padding so gap(32) + padding-left(8) == the 40px on the
     right — otherwise the column gap plus a full space-10 left padding make
     the text sit nearly twice as far from the image as from the right edge.
     Same fix as .shop__featured-body. (Reset to symmetric ≤1024 below.) */
  padding-left: var(--space-2);
}

/* Title+excerpt+date fade + rise together on entrance (transition-delay
   set by js/blog-featured-slider.js); exit (.is-slide-leaving) fades out,
   opacity only, at listing.js's own quicker 300ms leave speed. The CTA
   button deliberately isn't part of this group — like .shop__featured-buy,
   it's a fixed, always-visible control, not per-slide content, so it
   never fades or moves; only its href updates. */
.blog__featured-title,
.blog__featured-excerpt,
.blog__featured-date {
  transition: opacity 1100ms var(--ease-standard), transform 1100ms var(--ease-standard);
}

.blog__featured-title.is-slide-hidden,
.blog__featured-excerpt.is-slide-hidden,
.blog__featured-date.is-slide-hidden {
  opacity: 0;
  transform: translateY(16px);
}

.blog__featured-title.is-slide-leaving,
.blog__featured-excerpt.is-slide-leaving,
.blog__featured-date.is-slide-leaving {
  transition-duration: 300ms;
  opacity: 0;
}

/* No margin-top — title sits at the very top of the body now (no meta
   line above it), same as .shop__featured-title. min-height reserves the
   full 3-line clamp height (3 x line-height, in em so it tracks the
   clamp'd font-size) even when a slide's own title is short enough to fit
   on fewer lines — otherwise a shorter title on one slide leaves the body
   shorter than a 3-line title on another, and since .blog__featured-media
   stretches to match the row (align-items: stretch), the image itself
   would visibly jump height between slides. */
/* Capped at 2 lines ("…" past that), natural height — a 1-line title stays
   one line (excerpt sits directly beneath); the constant banner height is
   held by .blog__featured-body's min-height, same as .shop__featured-title. */
.blog__featured-title {
  font-family: var(--font-heading);
  font-size: 26px;
  line-height: 1.2;
  color: var(--color-text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* No hover reaction here by design — same reasoning as
   .shop__featured-title a: with the banner auto-rotating every 10s, a
   color shift under a cursor just passing through mid-transition would
   read as a glitch rather than an intentional link cue. */
.blog__featured-title a {
  color: inherit;
}

/* min-height reserves the full 3-line clamp height for the same reason as
   .blog__featured-title above — a 1-line excerpt shouldn't leave the row
   shorter than a 3-line one. */
/* Fixed 3-line height (clamped) so a shorter excerpt reserves the same
   space — keeps the body height constant across slides, same as
   .shop__featured-excerpt. */
.blog__featured-excerpt {
  margin-top: var(--space-5);
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--color-text-muted);
  max-width: 46ch;
  height: 8.5em; /* 5 lines — fills the space down to the footer instead of a 3-line gap */
  /* Reserve the space and CLAMP — otherwise a long excerpt overflowed its fixed
     height and ran onto the "Read more" button. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
}

.blog__featured-footer {
  margin-top: auto;
  padding-top: var(--space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.blog__featured-date {
  font-size: var(--fs-small);
  color: var(--color-text-faint);
}

/* The "Next"-pagination-style CTA — same outline + hover-outline-swap
   recipe as .product__related-arrow (css/product.css), just widened into
   a labeled pill instead of an icon-only circle. */
.blog__featured-cta {
  flex-shrink: 0;
  width: fit-content;
  height: 40px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  background: var(--color-bg-elevated);
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  font-weight: 600;
  transition: background var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard);
}

.blog__featured-cta:hover {
  background: var(--color-bg-elevated-hover);
  color: var(--color-text);
  border-color: var(--color-border-strong);
}

/* Tablet/mobile: banner stacks — image on top (restored 16:9), text below.
   Excerpt uses the full block width (no 46ch cap) so it fits in 2 lines
   instead of 3, shrinking the block. Body min-height recomputed for that
   2-line excerpt so slides still don't jump. Same recipe as .shop__featured
   at ≤1024. */
@media (max-width: 1024px) {
  .blog__featured {
    grid-template-columns: 1fr;
    gap: var(--space-4); /* half the desktop gap between image and text when stacked */
  }

  /* iOS Safari collapses `aspect-ratio` on a box whose only children are
     absolutely-positioned (our slide images) → tiny banner. Padding-top ratio
     box is reliable everywhere. */
  .blog__featured-media {
    height: 0;
    padding-top: 56.25%; /* 16:9 */
    align-self: start;
  }

  .blog__featured-excerpt {
    max-width: none;
    -webkit-line-clamp: 2;
    height: 3.4em;
  }

  .blog__featured-body {
    padding: var(--space-4) var(--space-8) var(--space-8);
    padding-left: var(--space-8);
    min-height: 0; /* hug content — no dead space between the excerpt and Read More */
  }
  /* Stacked: date + Read More follow the text directly instead of being pinned
     to the bottom of a tall panel. */
  .blog__featured-footer {
    margin-top: var(--space-5);
  }
}

/* --- Filter row --- */

.blog__filters {
  margin-top: var(--space-16);
}

/* --- Card grid --- */

/* align-items: start — see the identical note on .shop__grid in
   css/shop.css: without it, a filter leaving only a partial row lets
   Grid's default row-stretch inflate these cards (visible background +
   .blog__card-body/-excerpt's own flex: 1 would drag their footer content
   down inside the oversized box) instead of leaving the grid's
   reserved-but-unused space empty below a normal-height card. */
.blog__grid {
  margin-top: var(--space-8);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  align-items: start;
  gap: var(--space-6);
}

/* Mobile: fixed 2x2 grid of compact cards (overrides the 320px min-track,
   which would otherwise drop to a single column on a phone). */
@media (max-width: 767px) {
  .blog__grid {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-5) var(--space-3);
  }
  /* One fixed height for every card (measured worst case: 16:9 image +
     2-line title + 2-line excerpt + reserved gap + Read-More row), so a
     1-line-title card and a 2-line-title card in the same row read as the
     same box. The title/excerpt keep their NATURAL (clamped) height — a
     1-word title lets the excerpt sit directly beneath it with no blank
     second line — and the footer docks to the bottom (margin-top:auto),
     so the leftover of a short card lands as reserved space between the
     excerpt and the button, not as gaps inside the text. body.inner bumps
     specificity so these win over the base rules defined LATER in this file
     (their source order would otherwise beat a plain-class override). */
  body.inner .blog__card {
    min-height: 268px;
  }
  body.inner .blog__card-body {
    padding: var(--space-3);
    gap: var(--space-2);
  }
  body.inner .blog__card-title {
    font-size: 14px;
    line-height: 1.25;
  }
  body.inner .blog__card-excerpt {
    font-size: 12px;
    -webkit-line-clamp: 2;
  }
  /* Drop the date on phones so the title/excerpt get the full card width and
     don't clip; the "Read More" pill stays, pushed to the right edge (with
     the date gone, space-between would otherwise leave it hanging on the
     left). */
  body.inner .blog__card-date {
    display: none;
  }
  body.inner .blog__card-footer {
    padding-top: var(--space-3);
    justify-content: flex-end;
  }
}

/* min-height is the measured worst case: the 16:9 image, a 2-line
   (clamped) title plus a 2-line (clamped) excerpt — see the identical
   note on .works__card in css/works.css for why this beats reserving
   space on the title/excerpt elements themselves. */
.blog__card {
  display: flex;
  flex-direction: column;
  min-height: 383px;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

/* Own 16:9 ratio, isolated from the shared 16:10 in components.css —
   matches the site's product-photography standard (Shop cards, Product
   gallery) rather than the wider, shorter crop the reference card style
   used. */
.blog__card-media {
  aspect-ratio: 16 / 9;
}

/* No transition declared here — see the long comment on .shop__card:hover
   in css/components.css for why: this card is also a [data-filter-item]
   (filter-pill.css) target, which owns `transform`'s transition (opacity
   + transform, staggered) the rest of the time; a competing declaration
   here would silently kill that entrance/exit animation. .blog__card:hover
   and .blog__card-media (+ its hover zoom) are defined once in
   css/components.css, shared with the equivalent Shop/Product/Services
   card recipes. */

.blog__card-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
  padding: var(--space-5);
}

/* The line-clamp (and therefore the truncation "…") lives on the <a>
   itself, not the h3 — the ellipsis is painted by whichever element owns
   -webkit-line-clamp, so putting the clamp AND the color/hover on the same
   directly-hovered <a> is the only way Chromium reliably repaints the "…"
   in the hover color too. The h3 is forced back to a plain block so its
   .clamp-2 utility class doesn't create a second, competing clamp box. */
.blog__card-title {
  font-size: 16px;
  font-weight: 700;
  line-height: 1.3;
  display: block;
}

.blog__card-title a {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  color: var(--color-text);
  transition: color var(--duration-fast) var(--ease-standard);
}

.blog__card-title a:hover {
  color: var(--color-hover-accent);
}

.blog__card-excerpt {
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--color-text-muted);
}

/* margin-top: auto docks the footer (date + Read More) to the bottom of
   the card, consuming whatever space title+excerpt didn't need above it —
   same technique as .shop__card-rating in css/shop.css. */
.blog__card-footer {
  margin-top: auto;
  padding-top: var(--space-1);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.blog__card-date {
  font-size: 12px;
  color: var(--color-text-faint);
}

/* Same outline + hover-outline-swap recipe as .blog__featured-cta /
   .product__related-arrow, just sized down to a card-scale button. */
.blog__card-cta {
  flex-shrink: 0;
  height: 34px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  background: var(--color-bg-elevated);
  color: var(--color-text-muted);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard);
}

.blog__card-cta:hover {
  background: var(--color-bg-elevated-hover);
  color: var(--color-text);
  border-color: var(--color-border-strong);
}


@media (max-width: 860px) {
  .blog__featured {
    grid-template-columns: 1fr;
  }

  .blog__featured-media {
    min-height: 220px;
  }

  .blog__featured-body {
    padding: var(--space-4) var(--space-6) var(--space-6);
  }
}
