/* ============================================
   BLOG
   Posts index, single post, category and tag archives.

   Loaded ONLY by the ppcsherpa_is_blog_view() block in functions.php. The
   template-slug auto-loader cannot reach a hierarchy template, so this file
   has exactly one enqueue path -- see the comment on that block.

   Every value here comes from an existing token in style.css. No new color
   and no new spacing value is introduced anywhere in this file.

   THE CARD TREATMENT IS COPIED FROM .fx-crosslink IN feature-pages.css, NOT
   REUSED FROM IT. That stylesheet is enqueued only against
   $feature_page_templates, so a blog view carries none of its rules and an
   fx- class used here would render as unstyled markup. The copy is
   deliberate and matches this theme's per-page duplication default.
   ============================================ */


/* ============================================
   PAGE HEADING BLOCK (index and both archives)
   ============================================ */

.blog-head {
  /* Pulls the heading up toward the nav; the list section below supplies the
     separation. Without this the two stacked .section paddings put 160px
     between the nav and the first card. */
  padding-bottom: 0;
}

.blog-head__eyebrow {
  display: inline-block;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-primary);
  background: var(--color-primary-light);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  margin-bottom: var(--space-4);
}

.blog-head__title {
  margin-bottom: var(--space-4);
}

.blog-head__sub {
  font-size: var(--text-lg);
  color: var(--color-text-muted);
  max-width: var(--container-narrow);
  margin-bottom: 0;
}

/* Term description on a category or tag archive. Editor-authored, so it can
   contain paragraphs and links and both need to inherit this treatment. */
.blog-head__desc {
  font-size: var(--text-lg);
  color: var(--color-text-muted);
  max-width: var(--container-narrow);
}

.blog-head__desc p {
  margin-bottom: var(--space-3);
}

.blog-head__desc p:last-child {
  margin-bottom: 0;
}


/* ============================================
   CARD GRID
   ============================================ */

.blog-grid {
  display: grid;
  /* Single column by default, two above the tablet breakpoint. Written
     mobile-first so the min-width query below is the only override -- the
     inverse would put the one-column rule in a max-width block and leave it
     vulnerable to any later rule at equal specificity, the source-order trap
     documented in docs/05-traps.md. */
  grid-template-columns: 1fr;
  gap: var(--space-8);
}

@media (min-width: 769px) {
  .blog-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.blog-card {
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.blog-card:hover {
  border-color: var(--color-primary);
  box-shadow: var(--shadow-md);
}

/* THE WHOLE CARD IS ONE ANCHOR (see template-parts/post-card.php). This element
   wraps every other part of the card, so the pointer cursor, the click target
   and the focus ring all cover the card including its empty space.

   IT MUST BE THE SAME FLEX COLUMN .blog-card IS. The anchor was inserted
   BETWEEN .blog-card and its former children, so without this it would be a
   plain block box in the middle of the column and .blog-card__body's `flex: 1`
   would have no flex parent to grow against -- the body would collapse to its
   content height and the run of dates along a row would stop lining up. Making
   the anchor an identical flex column, and giving it `flex: 1` so it fills the
   card, hands the body back exactly the parent it had. Geometry is unchanged.

   No padding, margin, background or border of its own: every one of those still
   lives on .blog-card and .blog-card__body, so the card's box is untouched.

   color: inherit stops the global `a { color: var(--color-primary) }` from
   turning the whole card blue. Each descendant keeps the color it already had. */
.blog-card__link {
  display: flex;
  flex-direction: column;
  flex: 1;
  color: inherit;
}

/* The card's own hover already supplies the border and shadow change, and it
   still fires because the anchor fills the card. This only restores the title
   color shift that .blog-card__title a used to own. */
.blog-card__link:hover .blog-card__title {
  color: var(--color-primary);
}

/* FOCUS RING, AND WHY IT IS INSET RATHER THAN OFFSET.

   The theme's global rule is `:focus-visible { outline: 2px solid
   var(--color-primary); outline-offset: 2px; }`. A positive offset draws the
   ring OUTSIDE the element's border box -- and .blog-card sets
   `overflow: hidden` (needed to clip the image to the card's rounded corners),
   which clips exactly that. The ring would be invisible or shaved off on the
   image edge.

   .fx-crosslink does not hit this because it has no image and therefore no
   overflow clip. So the offset is inverted here: a negative offset draws the
   ring just inside the anchor's own edge, where nothing clips it, and the
   radius matches the card so it follows the rounded corners. Same 2px width
   and same token color as the global ring.

   :focus-visible, not :focus, so a mouse click does not leave a ring behind. */
.blog-card__link:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
  border-radius: var(--radius-xl);
}

/* The thumb is omitted from the markup entirely when a post has no featured
   image (see template-parts/post-card.php), so there is no empty-state rule
   to write here -- the body simply becomes the whole card. Now a <div> rather
   than its own <a>, which would have nested inside the card anchor. */
.blog-card__thumb {
  display: block;
  aspect-ratio: 16 / 9;
  background: var(--color-bg);
  overflow: hidden;
}

.blog-card__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.blog-card__body {
  /* flex: 1 makes every card in a row the same height regardless of title or
     excerpt length, which is what keeps the grid even. */
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: var(--space-6);
}

.blog-card__cat {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-primary);
  margin-bottom: var(--space-2);
}

/* The title is now bare text inside the <h2>, not its own anchor -- the card
   anchor is the link. So the color lives here directly, and the hover shift
   that .blog-card__title a:hover used to own is driven from
   .blog-card__link:hover above. Identical values, identical result, one fewer
   anchor. The transition is declared here because the color now changes on
   this element rather than on a nested <a>. */
.blog-card__title {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-dark);
  line-height: 1.3;
  margin-bottom: var(--space-2);
  transition: color var(--transition-fast);
}

.blog-card__excerpt {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: 1.6;
  margin-bottom: var(--space-4);
}

.blog-card__meta {
  /* margin-top: auto pins the date to the bottom of the card body, so dates
     line up across a row even when excerpts differ in length. */
  margin-top: auto;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.blog-empty {
  color: var(--color-text-muted);
}


/* ============================================
   PAGINATION

   Styles the markup paginate_links( 'type' => 'list' ) emits: a <ul> of
   <li>, each holding either an <a class="page-numbers"> or a
   <span class="page-numbers current">. Real anchors, so these are crawlable
   and keyboard-operable with nothing scripted.

   The global reset zeroes list padding and removes markers, so the <ul>
   needs no list-style reset of its own here.
   ============================================ */

.blog-pagination {
  margin-top: var(--space-12);
}

.blog-pagination ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
}

.blog-pagination .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.blog-pagination a.page-numbers:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.blog-pagination .page-numbers.current {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-surface);
}

/* The gap ellipsis WordPress inserts between distant page numbers. Not a
   control, so it gets no border or hover. */
.blog-pagination .page-numbers.dots {
  border-color: transparent;
  background: transparent;
  color: var(--color-text-muted);
}


/* ============================================
   BREADCRUMB (single posts, category and tag archives)
   ============================================
   Markup comes from template-parts/blog-breadcrumb.php, which calls Yoast's
   own yoast_breadcrumb(). Only the .blog-breadcrumb wrapper is ours; the
   inner <span> nesting and the <span class="breadcrumb_last"> on the current
   item are Yoast's, which is why the rules below select those rather than a
   class of our own naming.

   VALUES MATCH .app-breadcrumb IN style.css DELIBERATELY, but the block is
   NOT shared with it. Two reasons. That component is scoped to /app/ and
   carries interactive account and feature switcher dropdowns, so it is a
   different thing that happens to look similar -- the theme's stated test for
   sharing is that a component must BEHAVE identically, not merely look alike.
   And blog-only styling belongs in this stylesheet per the same rule that put
   everything else here. The one intentional difference is the weight: regular
   rather than semibold, since this trail sits above an article title and
   should recede.

   Every value is an existing token. No new color and no new spacing value. */

/* EVERY DECLARATION BELOW IS COPIED FROM .app-breadcrumb IN style.css SO THE
   TWO COMPUTE IDENTICALLY. Same font-size, same font-weight, same colors,
   same gap, same margin-bottom, same separator character. A blog trail and an
   app trail should be distinguishable only by their content.

   Not shared with that block, per the theme's duplication default: this is
   blog-only styling and belongs in this stylesheet, and .app-breadcrumb is
   scoped to /app/ where its middle segments are interactive switcher
   dropdowns. Same look, different behavior.

   ***** IF EITHER BLOCK CHANGES, CHANGE BOTH. Nothing enforces the pairing
   except this comment and its twin on .app-breadcrumb's own values. ***** */

.blog-breadcrumb {
  /* Matches .app-breadcrumb's font and spacing. The flex/gap lives on the
     inner span, not here -- see below. */
  margin-bottom: var(--space-8);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
}

/* THE FLEX CONTAINER IS YOAST'S OUTER SPAN, NOT .blog-breadcrumb ITSELF.
   Yoast wraps the whole trail in one <span>, so .blog-breadcrumb has exactly
   ONE element child. display:flex here would lay out that single wrapper and
   the gap would never fall between crumbs. Applying it one level down makes
   the per-crumb spans the flex items, which is what .app-breadcrumb's own
   children are, so the same --space-2 gap produces the same rhythm.

   The separator is a bare text node between those spans; as a flex item it
   becomes an anonymous flex item and the gap applies to it too. */
.blog-breadcrumb > span {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* Links: muted at rest, primary on hover. Identical to
   .app-breadcrumb__link and its hover. */
.blog-breadcrumb a {
  color: var(--color-text-muted);
}

.blog-breadcrumb a:hover {
  color: var(--color-primary);
}

/* The current item. Yoast renders it as bare text in this span, never as a
   link. --color-dark and the inherited semibold match
   .app-breadcrumb__item--current exactly. */
.blog-breadcrumb .breadcrumb_last {
  color: var(--color-dark);
}

/* THE SEPARATOR CANNOT BE COLORED, AND THAT IS A YOAST CONSTRAINT, NOT AN
   OVERSIGHT. Yoast emits its configured character as a BARE TEXT NODE between
   the crumb spans, so no selector can reach it -- CSS cannot target a text
   node. It therefore inherits .blog-breadcrumb's color rather than taking
   .app-breadcrumb__sep's --color-border.

   The character itself now matches: Yoast's breadcrumbs-sep setting was
   changed from the default to "/", the same character .app-breadcrumb uses.

   The fallback branch in template-parts/blog-breadcrumb.php (used only if
   Yoast is deactivated) DOES wrap its separator in this class, so there it
   gets the exact border tone. */
.blog-breadcrumb__sep {
  color: var(--color-border);
}


/* ============================================
   SINGLE POST HEADER
   ============================================ */

.blog-single__head {
  margin-bottom: var(--space-8);
}

.blog-single__cat {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-primary);
  margin-bottom: var(--space-3);
}

.blog-single__title {
  /* Below the global h1 (--text-5xl / 48px), which is sized for a marketing
     hero and overpowers an 800px reading column. clamp keeps it proportional
     down to a phone. */
  font-size: clamp(2rem, 4vw, var(--text-4xl));
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin-bottom: var(--space-4);
}

.blog-single__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.blog-single__hero {
  margin-bottom: var(--space-10);
}

.blog-single__hero img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
}


/* ============================================
   ARTICLE BODY TYPOGRAPHY

   ***** EVERY RULE IN THIS BLOCK IS SCOPED TO .blog-content. *****

   This theme has no article typography at all, so all of it is written here.
   The scoping follows page-legal.css, whose own comment states the reason:
   these are opinionated resets and they must not bleed onto other pages.

   One difference from that file, and it is deliberate. page-legal.css opens
   with an UNSCOPED `.section h1 { margin-bottom: var(--space-8); }`, which
   matches any h1 inside any .section anywhere. It is contained today only
   because that stylesheet loads on one template. It is NOT copied here.

   THE GLOBAL RESET IS THE THING TO REMEMBER. style.css sets
   `ul, ol { list-style: none; }` and zeroes every margin and padding through
   the universal selector, so a list inside post content arrives flush and
   marker-less. Markers and indentation are restored explicitly below. Any
   element an author can insert from the editor that is not handled here will
   likewise arrive with no margins at all.

   Inline <code> and <pre> already have full global styling in style.css and
   are deliberately not touched.
   ============================================ */

.blog-content {
  font-size: var(--text-lg);
  line-height: 1.8;
  color: var(--color-text);
}

.blog-content > *:last-child {
  margin-bottom: 0;
}


/* Paragraphs ------------------------------------------------ */

.blog-content p {
  margin-bottom: var(--space-6);
}


/* Headings within the article ------------------------------- */
/* The post title is the page's only h1, so author headings start at h2. */

.blog-content h2,
.blog-content h3,
.blog-content h4 {
  color: var(--color-dark);
  line-height: 1.25;
}

.blog-content h2 {
  font-size: var(--text-3xl);
  margin-top: var(--space-12);
  margin-bottom: var(--space-4);
}

.blog-content h3 {
  font-size: var(--text-2xl);
  margin-top: var(--space-10);
  margin-bottom: var(--space-3);
}

.blog-content h4 {
  font-size: var(--text-xl);
  margin-top: var(--space-8);
  margin-bottom: var(--space-3);
}

/* A heading opening the article, or opening the second half after the inline
   CTA, must not carry its top margin -- the container already provides that
   space and the doubled gap reads as a break in the article. */
.blog-content > h2:first-child,
.blog-content > h3:first-child,
.blog-content > h4:first-child {
  margin-top: 0;
}


/* Lists ------------------------------------------------------ */
/* Markers and indentation restored against the global reset. */

.blog-content ul,
.blog-content ol {
  padding-left: var(--space-8);
  margin-bottom: var(--space-6);
}

.blog-content ul {
  list-style-type: disc;
}

.blog-content ol {
  list-style-type: decimal;
}

.blog-content li {
  margin-bottom: var(--space-3);
}

.blog-content li:last-child {
  margin-bottom: 0;
}

/* Nested lists: a second level takes a distinct marker, sits tighter, and
   must not repeat its parent's bottom margin. */
.blog-content li > ul,
.blog-content li > ol {
  margin-top: var(--space-3);
  margin-bottom: 0;
}

.blog-content li > ul {
  list-style-type: circle;
}


/* Links ------------------------------------------------------ */
/* Underlined in body copy: color alone is not a sufficient affordance in a
   long passage. Matches page-legal.css's treatment. */

.blog-content a {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.blog-content a:hover {
  color: var(--color-primary-hover);
}


/* Blockquotes ------------------------------------------------ */
/* No blockquote rule exists anywhere else in this theme. */

.blog-content blockquote {
  margin-bottom: var(--space-6);
  padding: var(--space-2) 0 var(--space-2) var(--space-6);
  border-left: 3px solid var(--color-primary);
  color: var(--color-text-muted);
  font-size: var(--text-xl);
  line-height: 1.6;
}

.blog-content blockquote p {
  margin-bottom: var(--space-4);
}

.blog-content blockquote p:last-child {
  margin-bottom: 0;
}

.blog-content blockquote cite {
  display: block;
  font-size: var(--text-sm);
  font-style: normal;
  color: var(--color-text-muted);
}


/* Images and figures ----------------------------------------- */
/* style.css already sets img { display: block; max-width: 100% }, so this
   block covers only the article-specific flow, rounding and caption. */

.blog-content img {
  height: auto;
  border-radius: var(--radius-md);
}

.blog-content figure {
  margin-bottom: var(--space-8);
}

.blog-content figcaption {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: 1.5;
}

/* WordPress's own alignment classes, emitted by both the classic editor and
   the block editor. Without these, an aligned image renders inline-flow. */
.blog-content .aligncenter {
  margin-inline: auto;
}

.blog-content .alignleft,
.blog-content .alignright {
  display: block;
  margin-inline: auto;
}

@media (min-width: 769px) {
  .blog-content .alignleft {
    float: left;
    margin: 0 var(--space-6) var(--space-4) 0;
  }

  .blog-content .alignright {
    float: right;
    margin: 0 0 var(--space-4) var(--space-6);
  }
}

/* Stops a float from escaping the article and overlapping the CTA or the
   back link beneath it. */
.blog-content::after {
  content: '';
  display: table;
  clear: both;
}


/* Tables inside content --------------------------------------- */
/* .table in style.css is the model, but it cannot be used directly: an
   author writing a table in the editor produces a bare <table> with no
   class and no scrolling wrapper. These rules give that bare element the
   same treatment, and the horizontal scroll is put on the table's own block
   container so a wide table cannot widen the page on a phone. */

.blog-content table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  margin-bottom: var(--space-8);
  display: block;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.blog-content th,
.blog-content td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border-bottom: 1px solid var(--color-border);
}

.blog-content th {
  font-weight: var(--weight-semibold);
  color: var(--color-dark);
  background: var(--color-bg);
  white-space: nowrap;
}


/* Horizontal rule --------------------------------------------- */

.blog-content hr {
  border: none;
  border-top: 1px solid var(--color-border);
  margin-block: var(--space-12);
}


/* ============================================
   INLINE CTA (inside the article body)
   ============================================
   Built on the shared .card class, so only the inner type and the spacing
   are declared here. Sits inside .container--narrow, which is why it is a
   card and not a full-bleed band. */

.blog-inline-cta {
  margin-block: var(--space-10);
  border-color: var(--color-primary);
  background: var(--color-primary-light);
  text-align: center;
}

.blog-inline-cta__title {
  font-size: var(--text-2xl);
  margin-bottom: var(--space-3);
}

.blog-inline-cta__body {
  color: var(--color-text-muted);
  margin-bottom: var(--space-6);
}


/* ============================================
   BACK LINK
   ============================================ */

.blog-back {
  margin-top: var(--space-12);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}


/* ============================================
   CLOSING CTA BAND

   Matches .hp-final-cta / .fx-final-cta exactly in structure and treatment:
   a full-bleed primary band with an inverted .btn--primary. Copied rather
   than shared for the same reason as the card -- those rules live in page
   stylesheets that never load on a blog view.
   ============================================ */

.blog-cta-band {
  background: var(--color-primary);
  padding-block: var(--space-20);
}

.blog-cta-band__inner {
  text-align: center;
  max-width: 620px;
}

.blog-cta-band h2 {
  color: var(--color-surface);
  font-size: var(--text-4xl);
  margin-bottom: var(--space-4);
}

.blog-cta-band p {
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--text-lg);
  margin-bottom: var(--space-8);
}

.blog-cta-band .btn--primary {
  background: var(--color-surface);
  color: var(--color-primary);
}

.blog-cta-band .btn--primary:hover {
  background: var(--color-primary-light);
  color: var(--color-primary-hover);
}


/* ============================================
   RESPONSIVE
   ============================================ */

@media (max-width: 768px) {
  .blog-content {
    font-size: var(--text-base);
  }

  .blog-content h2 {
    font-size: var(--text-2xl);
  }

  .blog-content h3 {
    font-size: var(--text-xl);
  }

  .blog-content blockquote {
    font-size: var(--text-lg);
  }

  .blog-cta-band h2 {
    font-size: var(--text-3xl);
  }
}
