/* From the Lab: blog index and article (homepage-v2). Loaded by
 * templates/blog/*.html after tokens.css and site.css. Post bodies come
 * from the database as HTML, so .post-content styles plain elements. */

/* ---------- Index ---------- */
.blog-filter { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s5); padding: 0; list-style: none; }
.blog-filter a {
  display: inline-flex; align-items: center; min-height: 36px; padding: 6px 14px;
  border: 1px solid rgba(255, 255, 255, 0.35); border-radius: var(--r-pill);
  color: var(--on-navy); font-size: var(--fs-small); font-weight: 600; text-decoration: none;
}
.blog-filter a:hover { border-color: var(--white); color: var(--white); }
.blog-filter a[aria-current="true"] { background: var(--white); border-color: var(--white); color: var(--navy); }
.blog-grid { display: grid; gap: var(--s5); grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); padding: 0; list-style: none; }
.blog-card { display: flex; flex-direction: column; height: 100%; background: var(--white); border: 1px solid var(--line); border-radius: var(--r-card); overflow: hidden; }
.blog-card:hover { border-color: var(--line-strong); }
.blog-card__img { aspect-ratio: 16 / 9; background: var(--mist); }
.blog-card__img img { width: 100%; height: 100%; object-fit: cover; }
.blog-card__body { display: flex; flex-direction: column; gap: var(--s2); flex: 1; padding: var(--s5); }
.blog-card__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); font-size: var(--fs-tiny); color: var(--muted); }
.blog-card h2 { font-size: 1.25rem; line-height: 1.3; }
.blog-card h2 a { color: var(--ink); text-decoration: none; }
.blog-card h2 a::after { content: ""; position: absolute; inset: 0; }
.blog-card { position: relative; }
.blog-card h2 a:hover { color: var(--teal-text); }
.blog-card p { font-size: 0.9375rem; color: var(--body); flex: 1; }
.blog-card__more { font-size: var(--fs-small); font-weight: 600; color: var(--teal-text); }
.blog-empty { text-align: center; padding-block: var(--s16); }
/* Newer and Older links under the grid. Older sits on the right even when it
   is the only link (page 1). Both fit on one row at 320px; if they ever do
   not, they wrap onto two rows. */
.blog-pages { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s10); }
.blog-pages__older { margin-left: auto; }
.blog-pages__archive { align-self: center; }

/* Blog archive (templates/blog/archive.html): one section per year, plain links. */
.archive-year + .archive-year { margin-top: var(--s10); }
.archive-year h2 { font-size: clamp(1.5rem, 1.35rem + 0.6vw, 1.875rem); margin: 0 0 var(--s3); }
.archive-list { display: grid; gap: var(--s1); margin: 0; padding: 0; list-style: none; max-width: 70ch; }
.archive-list a { display: flex; align-items: center; min-height: var(--tap); color: var(--teal-text); text-decoration: underline; text-underline-offset: 0.18em; }
.archive-list a:hover { color: var(--navy); }
.archive-back { margin-top: var(--s10); }

/* ---------- Article opening ---------- */
/* Article title: wide enough for two or three deliberate lines on desktop.
   text-wrap: balance evens the line lengths so the last line isn't a stub. */
.post-open h1 {
  max-width: 34ch;
  font-size: clamp(2rem, 1.6rem + 1.9vw, 3.125rem);
  text-wrap: balance;
}
.post-open .pill { margin-bottom: var(--s3); }
.post-meta-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s4); }
.post-meta { font-size: var(--fs-small); color: var(--on-navy-muted); }

/* Featured image: sits entirely below the navy header, inside the article
   column, matching the body's 70ch measure. The font-size makes ch resolve
   the same way it does for .post-content, so the edges line up exactly. */
.post-figure {
  font-size: var(--fs-article);
  max-width: 70ch;
  margin: 0 0 var(--s8);
}
.post-figure img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--r-card);
  background: var(--mist);
}
.post-featured-img-wrap { display: block; cursor: zoom-in; }

/* Share */
.share-wrap { display: inline-flex; align-items: center; }
.share-toggle, .share-btn, .share-close {
  display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px;
  border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.3); background: var(--navy-raised);
  color: var(--white); cursor: pointer;
}
.share-toggle:hover, .share-btn:hover, .share-close:hover { border-color: var(--white); }
.share-sheet { display: flex; align-items: center; gap: 4px; overflow: hidden; max-width: 0; opacity: 0; pointer-events: none; }
.share-sheet.open { max-width: 320px; opacity: 1; pointer-events: auto; margin-left: 8px; }
.share-copied { font-size: var(--fs-tiny); font-weight: 600; color: var(--teal-on-navy); white-space: nowrap; padding: 0 4px; }
@media (prefers-reduced-motion: no-preference) {
  .share-sheet { transition: max-width 0.25s ease, opacity 0.2s ease; }
}

/* Lightbox */
.lb-overlay { display: none; position: fixed; inset: 0; z-index: 9999; background: rgba(14, 36, 56, 0.92); align-items: center; justify-content: center; cursor: zoom-out; }
.lb-overlay.active { display: flex; }
.lb-overlay img { max-width: 92vw; max-height: 90vh; border-radius: var(--r-control); object-fit: contain; cursor: default; }
.lb-close { position: absolute; top: 16px; right: 16px; width: var(--tap); height: var(--tap); border: 0; background: none; color: var(--white); font-size: 32px; line-height: 1; cursor: pointer; }

/* ---------- Article layout ---------- */
.post-layout { max-width: var(--wrap-max); margin: 0 auto; padding: var(--s10) var(--gutter) var(--s16); display: grid; gap: var(--s10); align-items: start; }
.post-layout > article { min-width: 0; }
@media (min-width: 1024px) {
  .post-layout { grid-template-columns: minmax(0, 1fr) 320px; gap: var(--s16); }
  .post-sidebar { position: sticky; top: 100px; }
}

/* ---------- Article body (HTML from the database) ---------- */
.post-content { font-size: var(--fs-article); line-height: 1.65; color: var(--body); max-width: 70ch; min-width: 0; }
.post-content > * + * { margin-top: 1em; }
.post-content h2 { font-size: clamp(1.5rem, 1.35rem + 0.6vw, 1.875rem); margin-top: 1.9em; }
.post-content h3 { font-size: clamp(1.25rem, 1.18rem + 0.3vw, 1.4375rem); margin-top: 1.6em; }
.post-content h2 + *, .post-content h3 + * { margin-top: 0.6em; }
.post-content p { margin-bottom: 0; }
.post-content a { color: var(--teal-text); text-decoration: underline; text-underline-offset: 0.18em; }
.post-content a:hover { color: var(--navy); }
.post-content > ul, .post-content > ol { padding-left: 1.4em; }
.post-content > ul > li + li, .post-content > ol > li + li { margin-top: 0.45em; }
.post-content > ul > li::marker { color: var(--teal); }
.post-content > ol > li::marker { color: var(--teal-text); font-weight: 700; }
.post-content > blockquote { border-left: 3px solid var(--teal); padding: var(--s4) var(--s5); background: var(--mist); border-radius: 0 var(--r-control) var(--r-control) 0; color: var(--ink); }
.post-content img { height: auto; border-radius: var(--r-control); }
.post-content svg { max-width: 100%; height: auto; }
.post-content figure { margin-inline: 0; }
.post-content figcaption { font-size: var(--fs-small); color: var(--muted); margin-top: var(--s2); }
.post-content hr { border: 0; border-top: 1px solid var(--line); margin-block: 2em; }
.post-content pre, .post-content code { font-size: 0.875em; }
.post-content pre { overflow-x: auto; background: var(--mist); padding: var(--s4); border-radius: var(--r-control); }

/* Tables: horizontal scroll by default; under 640px the enhancement script
   adds .stack and data-label so each row becomes a labeled card. */
.post-content table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; line-height: 1.5; }
.post-content th, .post-content td { text-align: left; vertical-align: top; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.post-content th { background: var(--mist); color: var(--ink); font-weight: 700; }
.post-content .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.post-content table:not(.stack) { display: block; overflow-x: auto; }
@media (max-width: 640px) {
  .post-content table.stack, .post-content table.stack tbody, .post-content table.stack tr, .post-content table.stack td, .post-content table.stack th[scope="row"] { display: block; width: 100%; }
  .post-content table.stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
  .post-content table.stack tr { background: var(--white); border: 1px solid var(--line); border-radius: var(--r-control); padding: var(--s2) var(--s4); margin-bottom: var(--s3); }
  .post-content table.stack td { border: 0; padding: 6px 0; }
  .post-content table.stack td[data-label]::before { content: attr(data-label); display: block; font-size: var(--fs-tiny); font-weight: 700; color: var(--muted); }
}

/* Small labels that are H3s (Sept 29 audit heading-order fix). In two posts
   (20, 21) the label above a bear/bull column and above a chart was an H4
   directly under an H2; scripts/apply_sept29_blog_content.py made each an H3.
   The posts' own inline CSS styles these as '.tcal-col h4' and '.tcal-figure h4',
   which an H3 does not match, so an H3 would take the post's '.tcal-article h3'
   and this file's '.post-content h3' rules instead. These rules give the H3s in
   those two containers, and only those, the H4 look again, value for value from
   the posts' rules (mono, .74rem, uppercase, 0.12em, bold, the post's colors and
   margins). line-height and text-wrap are reset because the H3 rules of the site
   set them (the H4 inherited the article's line-height and wrapped normally).
   Each selector names .tcal-article and a container class as well as the tag,
   so it beats '.tcal-article h3' and '.post-content h3' whatever order the
   styles load in. */
.tcal-article .tcal-col h3, .tcal-article .tcal-figure h3 { font-size: 0.74rem; font-weight: 700; line-height: inherit; letter-spacing: 0.12em; text-transform: uppercase; text-wrap: wrap; }
.tcal-article .tcal-col h3 { font-family: 'Space Mono', monospace; margin: 0 0 0.6rem; }
.tcal-article .tcal-col.bear h3 { color: var(--tcal-bear, #c2543a); }
.tcal-article .tcal-col.bull h3 { color: #1f7a6e; }
.tcal-article .tcal-figure h3 { font-family: var(--mono, 'Space Mono', 'SFMono-Regular', Menlo, monospace); margin: 0 0 2px; color: var(--teal-deep, #0E7490); }

/* Mid-article newsletter: desktop Beehiiv embed, mobile Subscribe Free card.
   The swap at 640px is the long-standing behavior and is kept exactly. */
.post-newsletter { margin-block: 2em; padding: var(--s4) var(--s5) 0; background: var(--navy); border-radius: var(--r-card); overflow: hidden; }
@media (max-width: 640px) { .post-newsletter { display: none; } }
.post-newsletter-mobile { display: none; margin-block: 2em; padding: var(--s5); background: var(--navy); border-radius: var(--r-card); text-align: center; }
@media (max-width: 640px) { .post-newsletter-mobile { display: block; } }
.post-newsletter-label { font-size: var(--fs-tiny); font-weight: 600; color: var(--on-navy-muted); margin-bottom: 4px; }
.post-newsletter-copy h3, .post-newsletter-mobile h3 { color: var(--white); font-size: 1.25rem; margin: 0 0 4px; }
/* Some post bodies carry their own inline style, '.tcal-article h3 { color: navy; font-family: Georgia }'
   (posts 17, 20, 21, 29, 32). It beat the rule above and left these headings navy on navy.
   The extra class wins on specificity whatever order the styles load in. */
.tcal-article .post-newsletter-copy h3, .tcal-article .post-newsletter-mobile h3 { color: var(--white); font-family: var(--font-serif); }
.post-newsletter-copy p, .post-newsletter-mobile p { font-size: var(--fs-small); color: var(--on-navy); line-height: 1.45; }
.post-newsletter-mobile p { margin-bottom: var(--s4); }
.post-newsletter [data-beehiiv-form] { margin-top: -28px; display: block; }
/* Beehiiv facade (static/js/beehiiv-facade.js). The loader is injected into the
   slot when the card nears the viewport, so the slot holds the embed's place:
   the form is an iframe 262px tall at every card width, and the -28px is the
   pull-up the loader script itself had before. Card height is the same before
   and after the form appears, so nothing below it moves. Without script, or
   when the loader is blocked, the card is just its text with the usual bottom
   padding (the old loader tag's -28px margin used to clip that text). */
.post-newsletter-slot { margin-top: -28px; min-height: 262px; }
.post-newsletter-slot [data-beehiiv-form] { margin-top: 0; }
.post-newsletter-slot[data-state="failed"] { margin-top: 0; min-height: var(--s4); }
@media (scripting: none) { .post-newsletter-slot { margin-top: 0; min-height: var(--s4); } }

/* "Related service: <name>." line before the newsletter card */
.post-content .post-service-line { font-size: 0.9375rem; color: var(--body); }

/* Related service box (partials/related_service.html) */
.related-service { margin-top: 2.5em; padding: var(--s5); background: var(--mist); border-radius: var(--r-card); }
.post-content .related-service p { margin: 0 0 var(--s2); }
.related-service-label { font-size: var(--fs-tiny); font-weight: 700; color: var(--teal-text); margin-bottom: var(--s2); }
.post-content .related-service .related-service-h1 { font-family: var(--font-serif); font-weight: 600; font-size: 1.375rem; line-height: 1.3; color: var(--ink); }
.post-content .related-service .related-service-desc { font-size: 0.9375rem; color: var(--body); }
.post-content .related-service-link { font-size: 0.9375rem; font-weight: 600; color: var(--navy); }

/* Related reading: three more posts, after the article and before the closing call to action */
.related-reading { max-width: 70ch; margin-top: var(--s12); }
.related-reading h2 { font-size: 1.375rem; margin: 0 0 var(--s4); }
.related-reading__list { display: grid; gap: var(--s4); margin: 0; padding: 0; list-style: none; }
.related-reading__list a { display: block; font-family: var(--font-serif); font-weight: 600; font-size: 1.0625rem; line-height: 1.35; color: var(--ink); text-decoration: none; }
.related-reading__list a:hover { color: var(--teal-text); text-decoration: underline; }
.related-reading__meta { display: block; margin-top: 2px; font-size: var(--fs-tiny); color: var(--muted); }

/* End of article */
.post-end { margin-top: var(--s12); display: grid; gap: var(--s4); max-width: 70ch; }
.post-end .card h2 { font-size: 1.375rem; }

/* ---------- Sidebar ---------- */
.sb-section { padding-bottom: var(--s8); margin-bottom: var(--s8); border-bottom: 1px solid var(--line); }
.sb-section:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
.sb-heading { font-family: var(--font-sans); font-size: var(--fs-small); font-weight: 700; color: var(--teal-text); margin: 0 0 var(--s3); }
.sb-section p { font-size: 0.9375rem; color: var(--body); margin: 0 0 var(--s3); }
.sb-link { font-size: var(--fs-small); font-weight: 600; color: var(--teal-text); }
.sb-about-top { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s3); }
.sb-about-top picture { flex: 0 0 52px; }
.sb-avatar { width: 52px; height: 52px; max-width: none; border-radius: 50%; object-fit: cover; }
.sb-cta { background: var(--navy); border-radius: var(--r-card); padding: var(--s6); border-bottom: 0; }
.sb-cta .sb-heading { color: var(--on-navy-muted); }
.sb-cta p { color: var(--on-navy); }
.sb-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.sb-list a, .sb-list .sb-current { display: block; font-family: var(--font-serif); font-weight: 600; font-size: 1rem; line-height: 1.35; color: var(--ink); text-decoration: none; }
.sb-list a:hover { color: var(--teal-text); text-decoration: underline; }
.sb-list .sb-current { color: var(--muted); }
.sb-field-note { border-top: 2px solid var(--teal); padding-top: var(--s4); }
.sb-field-note .sb-eyebrow { font-size: var(--fs-tiny); font-weight: 700; color: var(--teal-text); margin-bottom: var(--s2); }
.sb-field-note blockquote { font-family: var(--font-serif); font-weight: 600; font-size: 1.0625rem; line-height: 1.5; color: var(--ink); margin: 0 0 var(--s3); }
