/* =========================================================================
   Blog slice (migration slice 8): /blog/ index + individual post pages.
   Blog pages load base.css + site.css + blog.css only, so hero, prose, and
   card styles that other sections get from programs.css live here.
   Brand tokens come from css/base.css :root. No em dashes in this file.
   ========================================================================= */

/* ---------- Index hero ---------- */
.blog-archive .container { max-width: 1120px; }
/* iprov-agency/eas-easterseals#294: with the intro paragraph gone, the list
   starts 30px under the title block instead of the full section padding. */
.section.blog-archive { padding-top: 30px; }

.archive-hero {
  background: linear-gradient(180deg, #fff 0%, var(--color-light) 100%);
  padding: 64px 0 52px;
}
.archive-hero h1 {
  font-size: clamp(2.1rem, 4.5vw, 3.2rem);
  font-weight: 800;
  color: var(--color-secondary);
  margin-bottom: 16px;
}
.archive-hero-intro {
  max-width: 720px;
  margin: 0 auto;
  font-size: 1.0625rem;
  color: var(--color-text-body);
  line-height: 1.65;
}

/* ---------- Search, topic, year and sort ---------- */
/* The toolbar above the grid, rendered by render_blog_tools in
   scripts/generate_blog.py and driven by js/blog.js. Fields and labels
   follow the careers and people filters (css/careers.css, css/staff.css);
   the chips follow .filter-chip in css/programs.css, which blog pages do not
   load, so the rules are repeated here under blog names. */
.blog-tools {
  margin-bottom: 32px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--color-border);
}
.blog-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px;
  margin-bottom: 20px;
}
.blog-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.blog-field--search { flex: 1 1 320px; }
.blog-field-label {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.4px;
  color: var(--color-text-light);
}
/* The field edge is --color-text-light, not the --color-border the careers
   and people fields use: #5f6773 on white clears the 3:1 WCAG 1.4.11 asks of
   a control's boundary, and #e2e6ec (1.2:1) does not. */
.blog-search,
.blog-select {
  padding: 11px 14px;
  background-color: var(--color-white);
  border: 1px solid var(--color-text-light);
  border-radius: 8px;
  color: var(--color-text);
  font-size: 1rem;
  font-family: var(--font-base);
  transition: border-color 0.2s;
}
.blog-search { width: 100%; }
.blog-search::placeholder { color: var(--color-text-light); }
.blog-select {
  appearance: none;
  -webkit-appearance: none;
  min-width: 170px;
  padding-right: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23004473' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  font-weight: 600;
  cursor: pointer;
}
.blog-search:hover,
.blog-search:focus,
.blog-select:hover,
.blog-select:focus { border-color: var(--color-primary); }

.blog-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.blog-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--font-base);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-secondary);
  background: var(--color-white);
  border: 2px solid var(--color-border);
  border-radius: 50px;
  padding: 8px 16px;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}
.blog-chip:hover { border-color: var(--color-secondary); }
.blog-chip-count {
  font-weight: 600;
  color: var(--color-text-light);
}
/* Pressed is a full fill inversion, as on .filter-chip: navy ground and white
   type (10.1:1) is a change in lightness, not only in hue, so it reads
   without colour perception (WCAG 1.4.1), and aria-pressed carries it to
   assistive technology. */
.blog-chip[aria-pressed="true"] {
  background: var(--color-secondary);
  border-color: var(--color-secondary);
  color: var(--color-white);
}
.blog-chip[aria-pressed="true"] .blog-chip-count { color: var(--color-white); }

.blog-status-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 18px;
  margin-top: 16px;
}
.blog-status {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-secondary);
}
/* A button that reads as a link, like .careers-reset. Orange on white is
   4.53:1, so it is only ever placed on white. */
.blog-clear {
  padding: 4px 2px;
  background: none;
  border: 0;
  font: inherit;
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.blog-clear:hover { color: var(--color-secondary); }

/* The search highlight. Pale yellow is only 1.2:1 against the white card, so
   the navy underline is what marks the hit; the fill is decoration. */
.blog-card mark {
  background: var(--es-yellow-30);
  color: inherit;
  padding: 0 1px;
  border-radius: 2px;
  text-decoration: underline;
  text-decoration-color: var(--color-secondary);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

/* The site's focus ring on every control in the toolbar, the empty state and
   load-more: 3px of --focus-ring-color (navy, 10.1:1 on white) at a 2px
   offset, which keeps it on white around a pressed navy chip. */
.blog-search:focus-visible,
.blog-select:focus-visible,
.blog-chip:focus-visible,
.blog-clear:focus-visible,
.blog-archive .btn:focus-visible {
  outline: 3px solid var(--focus-ring-color);
  outline-offset: 2px;
}

/* .btn sets display:inline-flex, which outranks the [hidden] UA rule, so the
   load-more button never actually hid once every post was showing. This
   covers every node js/blog.js toggles in the archive. */
.blog-archive [hidden] { display: none !important; }

@media (max-width: 680px) {
  .blog-field--search { flex-basis: 100%; }
  .blog-toolbar .blog-field:not(.blog-field--search) { flex: 1 1 0; min-width: 0; }
  .blog-select { width: 100%; min-width: 0; }
  /* One scrolling row on phones. The 5px padding, cancelled by the negative
     margin, keeps the focus ring inside the scroll box, which clips. */
  .blog-chips {
    flex-wrap: nowrap;
    overflow-x: auto;
    margin: 0 -5px;
    padding: 5px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .blog-search,
  .blog-select,
  .blog-chip { transition: none; }
}

/* ---------- Index cards ---------- */
/* .blog-grid and .blog-card base styles come from base.css; these add the
   archive-only pieces of the generated index (the badge and date row, and the
   title and excerpt classes). The card itself is the one-link card every
   .blog-card grid uses (#163). */
.blog-archive .blog-card { text-decoration: none; }
/* base.css sets .blog-card { display:flex }, which outranks the [hidden] UA
   rule, so the load-more / filter JS needs this to actually hide cards. */
.blog-grid .blog-card[hidden] { display: none !important; }
.blog-card-img--placeholder {
  background: linear-gradient(135deg, var(--color-secondary) 0%, #002448 100%);
}
.blog-card-img--placeholder img { width: auto; height: 60px; object-fit: contain; }
.blog-card-date {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.blog-card-title {
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--color-secondary);
  margin-bottom: 10px;
}
.blog-card-excerpt {
  font-size: 1rem;
  color: var(--color-text-body);
  line-height: 1.65;
  margin-bottom: 16px;
  flex-grow: 1;
}

/* ---------- Category badges ---------- */
/* CLIENT REVIEW iprov-agency/eas-easterseals#296, on the archive card pill:
   "Hate the blue type in the yellow pills. Do we need the pills at all?"
   Casey's ruling: the pills STAY, they are the only category cue on the blog
   grid, and they keep the amber ground they have. Only the type moves off navy.
   CONTRAST, measured through the worker 2026-10-22 at 1440 by
   scripts/check-contrast.mjs: the pill is amber #ffa300 with navy #004473 type
   at 5.06:1, which already cleared the 4.5 normal-text requirement. So this is
   a legibility and brand change that RAISES the ratio, not a fix for a failing
   pair. --color-text #1a2733 on #ffa300 measures 7.59:1.
   THE GROUND IS DELIBERATELY NOT MOVED to the cream #ffe3b3. Cream measures
   1.24:1 against the white card the pill sits on, below the 1.5 or so where an
   edge is perceptible at all, which is exactly the "pill DISAPPEARED" failure
   recorded on .post-header .post-badge below. Amber is 2.00:1 on white: weak,
   but the pill holds its shape.
   .post-badge--news is untouched: white on navy, 10.12:1, and never blue on
   yellow. */
.post-badge {
  display: inline-block;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: none;
  padding: 3px 10px;
  border-radius: 50px;
  background: var(--color-accent);
  color: var(--color-text); /* #1a2733 on amber #ffa300 = 7.59:1, was navy 5.06:1 */
}
.post-badge--news {
  background: var(--color-secondary);
  color: #fff;
}

/* ---------- Load more + count ---------- */
.blog-count {
  text-align: center;
  margin-top: 18px;
  font-size: 1rem;
  color: var(--color-text-light);
}
/* The no-results box. White, so the orange .blog-clear buttons inside keep
   4.53:1; on --color-light they would drop to 4.06. */
.blog-empty {
  margin-top: 8px;
  padding: 32px 24px;
  text-align: center;
  font-size: 1.0625rem;
  color: var(--color-text-body);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}
.blog-empty p { margin: 0; }

/* ---------- Post page ----------
   The .post-header band (box and navy title) is shared from site.css. It
   carries no pattern overlay: that was dropped for .post-header on
   2026-10-21, so do not describe this band as textured.
   The back link and byline ride on the band in NAVY, matching the h1.
   CONTRAST (audit 2026-09-15): these three rules were the single largest a11y
   defect on the site -- white/cream on amber measured 2.00 and 1.89 against a
   4.5 requirement, 2,169 failing nodes across 243 blog posts. site.css had
   already moved the h1 to navy for exactly this reason (5.06:1); these
   overrides were simply missed in that pass. Do not put white back on a tint.

   GROUND CHANGED 2026-10-21. site.css repainted .post-header from the amber
   #ffa300 to the light Sky tint #e6f4f9, so every "on amber" figure below is
   restated against the new ground. Navy got BETTER (5.06 -> 9.00) and nothing
   here needed its color changed. The badge did: see the note on it. These are
   the only 247 pages affected; .hero-band and .page-head are still amber, so
   do not copy a figure from here onto one of those. */
.post-header-inner { max-width: 820px; }
.post-back {
  display: inline-block;
  margin-bottom: 16px;
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-secondary); /* navy on the Sky tint = 9.00:1 (was 5.06 on amber) */
}
/* The 0.75 opacity blends navy toward the ground, so the hover is measured on
   the blend, not on the token: #3a7095 on #e6f4f9 = 4.75:1, which clears 4.5
   for normal text. On the amber it was #405c56 on #ffa300 = 3.64:1, short of
   4.5 and only passable as large text. Do not raise the transparency. */
.post-back:hover { color: var(--color-secondary); opacity: 0.75; }
.post-header h1 { margin-bottom: 16px; }
.post-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 1rem;
  color: var(--color-secondary); /* navy on the Sky tint = 9.00:1; was rgba(#fff,.92) = 1.89:1 on amber */
}
/* THE BADGE HAD TO CHANGE, and it is the only color in this file that did.
   A white chip read as a shape on the amber at 2.00:1; on the Sky tint it
   measures 1.12:1 against its own band, which is below the 1.5 or so where an
   edge is perceptible at all, so the pill DISAPPEARED and only its orange text
   survived as floating words. An amber chip is no better here (1.78:1), which
   is why this is navy and not the archive card's treatment.
   Navy fill: 9.00:1 against the band, so the pill holds its shape.
   White text on navy: 10.12:1, already a declared pair in
   scripts/check-contrast.mjs ("site.css donate band"). */
.post-header .post-badge {
  background: var(--color-secondary);
  color: #fff;
}
/* --news is emitted by the archive cards only. scripts/generate_blog.py
   render_post_page writes a bare `post-badge` and has no news branch, so this
   override matches ZERO shipped post pages today (verified 2026-10-21:
   post-badge--news appears in blog/index.html and nowhere under blog/<slug>/).
   It is kept, and kept identical to the rule above, so that if a news post
   ever renders inside a .post-header it cannot land back on a white chip. */
.post-header .post-badge--news {
  background: var(--color-secondary);
  color: #fff;
}
.post-author { font-weight: 600; color: var(--color-secondary); } /* navy on the Sky tint = 9.00:1; was #fff = 2.00:1 on amber */

.post-body { max-width: 800px; padding-top: 40px; padding-bottom: 56px; }
.post-featured { margin: 0 0 36px; }
.post-featured img {
  width: 100%;
  border-radius: var(--radius);
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* ---------- Prose (verbatim WordPress content) ---------- */
.post-content {
  font-size: 1.0625rem;
  line-height: 1.75;
  color: var(--color-text-body);
  /* Imported posts contain bare unbroken URLs (zoom registration links, deep
     PDF paths) that pushed the page 59-162px past a 390 viewport. */
  overflow-wrap: anywhere;
}
.post-content > *:first-child { margin-top: 0; }
.post-content p { margin: 0 0 1.35em; }
/* WP body H2 rhythm: section leads inside post copy are orange (matches the
   live site); H3/H4 stay navy structure headings. */
.post-content h2 {
  font-size: 1.7rem;
  font-weight: 800;
  line-height: 1.25;
  color: var(--color-primary);
  margin: 1.8em 0 0.6em;
}
.post-content h3 {
  font-size: 1.32rem;
  font-weight: 700;
  color: var(--color-secondary);
  margin: 1.6em 0 0.5em;
}
.post-content h4 {
  font-size: 1.12rem;
  font-weight: 700;
  color: var(--color-secondary);
  margin: 1.4em 0 0.5em;
}
.post-content ul,
.post-content ol { margin: 0 0 1.35em 1.4em; }
.post-content li { margin-bottom: 0.5em; }
.post-content a:not(.btn) {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.post-content a:not(.btn):hover { color: var(--color-primary-dark); }
.post-content strong { color: var(--color-text); }
.post-content blockquote {
  margin: 1.6em 0;
  padding: 4px 0 4px 22px;
  border-left: 4px solid var(--color-accent);
  font-size: 1.1em;
  color: var(--color-text);
  font-style: italic;
}
.post-content hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: 2.2em 0;
}
.post-content img { border-radius: var(--radius); }
.post-content figure { margin: 1.8em 0; }
.post-content figure img { width: 100%; }
.post-content figcaption {
  margin-top: 8px;
  font-size: 1rem;
  color: var(--color-text-light);
  text-align: center;
}
.post-content picture { display: block; }
.post-content picture img { width: 100%; }
.post-content .embed-container { margin: 1.8em 0; }
.post-content video,
.post-content .post-video {
  display: block;
  width: 100%;
  margin: 1.8em 0;
  border-radius: var(--radius);
}
.post-content iframe { max-width: 100%; border-radius: var(--radius); }
/* MOBILE OVERFLOW (audit 2026-09-15): imported WP tables carry their own column
   widths and pushed the whole page wider than the viewport on 7 posts (up to
   +110px at 390). `display:block` + `overflow-x:auto` turns each table into its
   own scroll container so it scrolls in place instead of dragging the page.
   Pairs with the .post-content overflow-wrap rule below, which handles the long
   unbroken URLs that caused the other 2 (a Zoom link and a Drexel PDF path). */
.post-content table {
  display: block;
  overflow-x: auto;
  max-width: 100%;
  width: 100%;
  border-collapse: collapse;
  margin: 1.6em 0;
  font-size: 1rem;
}
.post-content th,
.post-content td {
  border: 1px solid var(--color-border);
  padding: 10px 12px;
  text-align: left;
}

/* StoryChief galleries rely on their own JS, which is stripped as a tracking
   script. Reveal the image container, hide the preloader spinner and inert
   nav/controls so the images render as a simple stack. */
.post-content .strchf-gallery-images { display: block !important; }
.post-content .strchf-gallery-preloader,
.post-content .strchf-gallery-nav,
.post-content .strchf-gallery-controls { display: none !important; }
.post-content .strchf-gallery-images picture { margin: 0 0 16px; }
.post-content .strchf-button-wrapper { margin: 1.6em 0; }

.post-footer {
  margin-top: 40px;
  padding-top: 28px;
  border-top: 1px solid var(--color-border);
}

/* ---------- Responsive ---------- */
@media (max-width: 768px) {
  .post-content { font-size: 1rem; }
  .post-content h2 { font-size: 1.45rem; }
  .post-content h3 { font-size: 1.2rem; }
  .archive-hero { padding: 48px 0 38px; }
  .post-header { padding: 32px 0 26px; }
}

/* Heading levels in imported posts are normalised so they never skip a level
   (see normalize_heading_levels in scripts/generate_blog.py). The `hl-N` class
   records the level the author originally used, so a demoted heading keeps the
   size it had before: the document outline is corrected without the page
   looking any different. */
.post-content .hl-4 { font-size: 1.12rem; margin: 1.4em 0 0.5em; }
.post-content .hl-5 { font-size: 1.02rem; margin: 1.3em 0 0.45em; }
.post-content .hl-6 { font-size: 1rem; margin: 1.2em 0 0.4em; }
