/* Blog post styles (article pages only). Moved out of each post's <head> in 2.15.0: it was 20 KB inlined into
   every post, downloaded again on every visit. Edit here; bump ARTICLE_CSS_V in admin/app/generator.php after. */
/* Reading progress — thin fixed line under the nav, width driven by
   the inline script at the bottom of the page. Fixed rather than
   sticky so it tracks scroll position precisely regardless of what's
   above it in the document. */
.reading-progress { position:fixed; top:var(--nav-h); left:0; width:0%; height:3px; background:var(--red); z-index:999; pointer-events:none; }
@media (prefers-reduced-motion:no-preference) { .reading-progress { transition:width .12s linear; } }

.article-breadcrumbs { display:flex; align-items:center; flex-wrap:wrap; gap:8px; font-size:13px; margin-bottom:24px; }
.article-breadcrumbs a { color:var(--paper); opacity:0.6; text-decoration:none; }
.article-breadcrumbs a:hover { opacity:1; color:var(--red-bright); }
.article-breadcrumbs span[aria-hidden] { color:var(--paper); opacity:0.3; }
.article-breadcrumbs span[aria-current] { color:var(--paper); opacity:0.85; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:640px; }
@media (max-width:640px) { .article-breadcrumbs span[aria-current] { max-width:60vw; } }

/* ── Appearance control — reader-adjustable text size / column width,
   a la Wikipedia's own version of this. Lives at the top of the CTA
   rail now (moved out of the hero — the hero must never be affected
   by either setting, see the comment on .article-hero above), so the
   trigger button matches the light page it now sits on, and the panel
   itself stays a dark onyx block, same treatment as the CTA/newsletter
   cards it sits directly above. Values are read from localStorage and
   applied via data-article-text/-width attributes on <html> (set
   pre-paint in <head>, see gen_post_page()), and every change applies
   live via a plain 'change' listener — nothing here needs an Apply
   button or a reload for the reader to see the effect. */
.article-appearance { position:relative; }
.article-appearance-btn { display:flex; align-items:center; justify-content:center; gap:8px; width:100%; background:transparent; border:1.5px solid var(--border-light); border-radius:6px; color:var(--ink); font-family:var(--font-head); font-weight:700; font-size:13.5px; padding:11px 14px; cursor:pointer; transition:border-color .15s, color .15s; }
.article-appearance-btn:hover, .article-appearance-btn[aria-expanded="true"] { border-color:var(--red); color:var(--red-text); }
.article-appearance-btn svg { width:15px; height:15px; flex-shrink:0; }
.article-appearance-panel { position:absolute; top:calc(100% + 8px); left:0; right:0; z-index:50; background:var(--onyx); border-radius:8px; padding:18px; box-shadow:0 16px 40px rgba(0,0,0,0.35); }
.article-appearance-panel[hidden] { display:none; }
.article-appearance-label { font-family:var(--font-head); font-size:11px; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--paper); opacity:0.55; margin:14px 0 10px; }
.article-appearance-label:first-child { margin-top:0; }
.article-appearance-row { display:flex; flex-direction:column; gap:2px; }
.article-appearance-option { display:flex; align-items:center; gap:10px; padding:7px 4px; border-radius:5px; cursor:pointer; }
.article-appearance-option:hover { background:rgba(236,234,224,0.07); }
.article-appearance-option input { accent-color:var(--red-bright); width:15px; height:15px; flex-shrink:0; }
.article-appearance-option span { font-size:14px; color:var(--paper); }
.article-appearance-divider { border:none; border-top:1px solid rgba(236,234,224,0.14); margin:14px 0 0; }
/* Width only matters once there's a rail either side to spread out —
   below the 1024px collapse (see the article-layout query further
   down) TOC/CTA already drop to normal single-column flow, so "Wide"
   has nothing left to do. Text size still works fine at any width, so
   only the Width half of the panel is hidden here, not the button. */
@media (max-width:1024px) { .article-appearance-width-group { display:none; } }

/* Hero deliberately stays at the sitewide 1240px .container — it was
   widened to match the body grid below at one point, but the hero's
   image sits at a fixed 420px in its own 2-column grid, so stretching
   the container just dragged the image away from the text with a huge
   dead gap between them. The breadcrumb truncation was actually the
   span[aria-current] max-width above, not the container, so that fix
   holds on its own without this. */
.article-hero { padding: 40px 0 56px; }
.article-hero-grid { display:grid; grid-template-columns:1fr 420px; gap:52px; align-items:center; }
.article-hero-grid--no-media { grid-template-columns:1fr; }
.article-hero .article-cat { display:inline-block; font-family:var(--font-head); font-size:12px; font-weight:700; letter-spacing:0.14em; text-transform:uppercase; color:var(--red-bright); margin-bottom:18px; }
.article-hero h1 { font-size:clamp(30px,3.6vw,46px); line-height:1.14; }

/* Byline — Team SWD's own mark, name and date/read-time stacked next to it. */
.article-byline { display:flex; align-items:center; gap:14px; margin-top:26px; }
.article-byline-avatar { flex-shrink:0; width:42px; height:42px; border-radius:50%; object-fit:cover; }
.article-byline-text { display:flex; flex-direction:column; gap:2px; }
.article-byline-name { font-family:var(--font-head); font-size:14.5px; font-weight:700; color:var(--paper); }
.article-byline-meta { font-size:13.5px; color:var(--paper); opacity:0.58; }

/* Featured image sits beside the title on desktop, fully contained —
   no more overlap into the section below. */
.article-hero-media .article-featured-img { margin:0; }
.article-featured-img { width:100%; height:auto; display:block; border-radius:8px; box-shadow:0 22px 54px rgba(0,0,0,0.38); }
[data-theme="dark"] .article-featured-img { box-shadow:0 22px 54px rgba(0,0,0,0.6); }

/* ── Body + sidebar layout ── */
/* The wrapping .container here is the sitewide one, capped at 1240px —
   that was quietly overriding every max-width tried on .article-layout
   below it, since a child can never actually render wider than its own
   parent allows. .article-outer raises that cap specifically for this
   section so .article-layout's own max-width (1560/1760 below) is the
   thing that actually decides the width, not an invisible ceiling one
   level up. 1760 is the largest either state needs. */
.article-outer { max-width:1760px; }
/* Three tracks: TOC rail, article, CTA rail. This width is now what the
   Appearance panel's "Width" setting actually controls — Standard here
   is a normal reading layout, and [data-article-width="wide"] below
   pushes the gap and max-width out further so the TOC/CTA rails
   visibly separate toward the edges. Only this grid changes — the hero
   above has its own separate .container and is never touched by either
   Appearance setting, on purpose (see the comment on .article-hero
   below for why that coupling was a mistake the first time). */
.article-layout { display:grid; grid-template-columns:240px 1fr 280px; gap:120px; align-items:start; max-width:1760px; margin:0 auto; }
/* Wide is the default; reader-set "Small" pulls the rails back in. */
html[data-article-width="small"] .article-layout { gap:64px; max-width:1560px; }
.article-content { max-width:none; }
/* Now sits in the dark hero under the byline, not the light body section
   below — --red-bright is the dark-surface counterpart of --red-text,
   same red-on-small-text contrast rule the rest of the site follows. */
.article-back { display:inline-flex; align-items:center; gap:8px; font-family:var(--font-head); font-weight:700; font-size:14px; color:var(--red-bright); margin-top:20px; }
.article-back:hover { color:var(--paper); }

/* Centered, not left-hung, within the (wider) content column — at
   Standard width the reading column is narrower than the grid track
   that holds it, so without this the text sits flush left with a big
   dead gap on the right. margin:0 auto keeps that gap even on both
   sides instead. */
.article-body { font-size:19px; line-height:1.65; max-width:54em; margin-left:auto; margin-right:auto; }
/* Reader-set overrides from the Appearance panel — see the comment
   above .article-appearance for how these attributes get here. */
html[data-article-text="small"] .article-body { font-size:17px; }
html[data-article-text="large"] .article-body { font-size:21px; }
html[data-article-width="small"] .article-body { max-width:34em; }
.article-body p { margin:0 0 1.25em; }
.article-body h2 { font-size:clamp(26px,3.2vw,32px); margin:1.7em 0 0.6em; line-height:1.2; scroll-margin-top:calc(var(--nav-h) + 20px); }
.article-body h3 { font-size:clamp(21px,2.4vw,24px); margin:1.5em 0 0.55em; line-height:1.3; }
.article-body h4 { font-size:18px; margin:1.4em 0 0.5em; }
.article-body ul, .article-body ol { margin:0 0 1.25em 1.5em; }
.article-body ul { list-style:disc; }
.article-body ol { list-style:decimal; }
.article-body li { margin-bottom:0.45em; }
.article-body a { color:var(--red-text); text-decoration:underline; text-underline-offset:3px; }
.article-body img { border-radius:6px; margin:1.6em 0; max-width:100%; height:auto; }
.article-body figure { margin:1.6em 0; }
.article-body figure img { margin:0; }
.article-body figcaption { font-size:13.5px; color:var(--ink-3); margin-top:8px; text-align:center; }
.article-body .align-left { float:left; margin:0.3em 1.6em 1em 0; max-width:50%; }
.article-body .align-right { float:right; margin:0.3em 0 1em 1.6em; max-width:50%; }
.article-body .align-center { margin-left:auto; margin-right:auto; }
.article-body .align-left figcaption, .article-body .align-right figcaption { text-align:left; }
.article-body blockquote { border-left:3px solid var(--red); padding:4px 0 4px 22px; margin:1.6em 0; font-style:italic; color:var(--ink-2); font-size:19px; }
.article-body pre { background:var(--onyx); color:var(--paper); border-radius:6px; padding:18px 20px; overflow-x:auto; font-size:14.5px; margin:1.6em 0; }
.article-body code { font-family:ui-monospace,'Cascadia Code',Consolas,monospace; font-size:0.9em; background:var(--surface-sunk); padding:2px 6px; border-radius:4px; }
.article-body pre code { background:none; padding:0; }
.article-body hr { border:none; border-top:1.5px solid var(--hairline); margin:2.2em 0; }
.article-body table { width:100%; border-collapse:collapse; margin:1.8em 0; font-size:15px; }
.article-body th, .article-body td { padding:12px 16px; text-align:left; border-bottom:1px solid var(--border-light); vertical-align:top; }
.article-body thead th { font-family:var(--font-head); font-weight:700; font-size:13px; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-2); border-bottom:2px solid var(--red); }
.article-body td:first-child, .article-body th:first-child { font-family:var(--font-head); font-weight:600; color:var(--text); }
.article-body tbody tr:last-child td { border-bottom:0; }
@media (max-width:640px) { .article-body table { display:block; overflow-x:auto; white-space:nowrap; } }

/* ── Table of contents — its own sticky rail on the left, CTAs in a
   separate rail on the right. order:-1/1 place them either side of the
   article in the grid while keeping both after the article in the DOM,
   so reading order and screen readers still hit the article first.
   Both reset to normal flow when the layout collapses to one column
   below (see the 1024px query). ── */
/* No top margin here — the section's own padding-top now gives every
   column in the grid the same starting offset, so the rails line up
   with the first line of the article instead of sitting lower than it. */
.article-toc-rail { position:sticky; top:calc(var(--nav-h) + 24px); order:-1; }
.article-cta-rail { position:sticky; top:calc(var(--nav-h) + 24px); display:flex; flex-direction:column; gap:20px; order:1; }
.article-toc { border-top:2px solid var(--red); padding-top:20px; max-height:calc(100vh - var(--nav-h) - 64px); overflow-y:auto; }
.article-toc h2 { font-family:var(--font-head); font-size:13px; font-weight:700; text-transform:uppercase; letter-spacing:0.1em; margin-bottom:14px; }
.article-toc ol { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:10px; }
.article-toc a { display:block; font-size:13.5px; line-height:1.4; color:var(--ink-2); text-decoration:none; border-left:2px solid var(--border-light); padding-left:12px; transition:color .2s, border-color .2s; }
.article-toc a:hover { color:var(--red-text); border-color:var(--red); }
.article-toc a.is-active { color:var(--red-text); border-color:var(--red); font-weight:600; }

.article-sidebar-cta { background:var(--onyx); border-radius:8px; padding:22px; text-align:center; }
.article-sidebar-cta p { color:var(--paper); font-size:13.5px; opacity:0.72; margin-bottom:14px; line-height:1.5; }
.article-sidebar-cta .btn-primary { width:100%; text-align:center; justify-content:center; }

/* Newsletter signup box styles now live in styles.css (.newsletter-block),
   shared with the /newsletter archive. */

/* Mobile/tablet table of contents — a collapsible details block instead
   of a sticky rail (no room for a permanent column below 1024px), only
   rendered when a desktop TOC also exists. */
.article-toc-mobile { display:none; }
.article-toc-mobile summary { cursor:pointer; list-style:none; display:flex; align-items:center; justify-content:space-between; font-family:var(--font-head); font-weight:700; font-size:14px; padding:16px 18px; border:1px solid var(--border-light); border-radius:6px; }
.article-toc-mobile summary::-webkit-details-marker { display:none; }
.article-toc-mobile summary::after { content:'+'; font-size:20px; color:var(--red-text); transition:transform .2s; }
.article-toc-mobile[open] summary::after { transform:rotate(45deg); }
.article-toc-mobile ol { list-style:none; margin:0; padding:14px 18px; border:1px solid var(--border-light); border-top:none; border-radius:0 0 6px 6px; display:flex; flex-direction:column; gap:10px; }
.article-toc-mobile a { font-size:14px; color:var(--ink-2); text-decoration:none; }
.article-toc-mobile a:hover { color:var(--red-text); }

/* ── CTA — a hairline of red on top, text and button as a row on
   desktop so it reads as one deliberate unit. ── */
.article-cta { background:var(--onyx); border-top:3px solid var(--red); border-radius:8px; padding:40px 44px; margin-top:64px; display:flex; align-items:center; justify-content:space-between; gap:32px; }
.article-cta-eyebrow { display:block; font-family:var(--font-head); font-size:11px; font-weight:700; letter-spacing:0.12em; text-transform:uppercase; color:var(--red-bright); margin-bottom:10px; }
.article-cta h3 { color:var(--paper); font-size:23px; margin-bottom:8px; }
.article-cta p { color:var(--paper); opacity:0.68; font-size:15.5px; margin:0; max-width:38em; }
.article-cta .btn-primary { flex-shrink:0; }

/* ── Related posts — always 3 across on desktop, not the listing
   page's 2-column .blog-grid (that's 2-up because it shares the row
   with a sidebar; this section has the full width to itself). ── */
.article-related { max-width:1080px; margin:72px auto 0; padding-top:48px; border-top:1px solid var(--border-light); }
.article-related h2 { font-size:24px; margin-bottom:28px; }
.article-related .blog-grid { grid-template-columns:repeat(3, 1fr); }

@media (max-width:1024px){
  .article-hero-grid { grid-template-columns:1fr; gap:32px; }
  .article-hero-media { order:-1; }
  .article-layout { grid-template-columns:1fr; max-width:760px; }
  .article-content { max-width:none; }
  .article-toc-rail { display:none; }
  .article-cta-rail { position:static; order:0; margin-top:0; }
  .article-cta-rail > .article-sidebar-cta { display:none; }
  /* Below this point a script moves .article-appearance to sit right
     here, as the first thing in the layout — see the JS near the other
     article behaviour IIFEs. Grid row/column spanning couldn't do this
     cleanly (spanning the content column across two rows to make room
     for the button dragged the CTA rail hundreds of pixels down the
     page), so this is a plain DOM move gated on the same breakpoint
     the rails already collapse at. */
  .article-appearance-mobile-anchor + .article-appearance { margin-bottom:24px; }
  .article-toc-mobile { display:block; margin-bottom:40px; }
  .article-related .blog-grid { grid-template-columns:1fr 1fr; }
}
@media (max-width:640px){
  .article-hero { padding:32px 0 40px; }
  .article-body{ font-size:17px; }
  .article-body .align-left, .article-body .align-right { float:none; max-width:100%; margin:1.6em 0; }
  .article-cta{ flex-direction:column; align-items:flex-start; padding:28px 24px; }
  .article-cta .btn-primary{ width:100%; text-align:center; }
  .article-related { margin-top:56px; padding-top:36px; }
  .article-related .blog-grid { grid-template-columns:1fr; }
}

/* A featured image whose size is unknown still reserves a 16:9 box, so the title below it does not jump (2.15.0). */
.article-featured-img--no-dims { aspect-ratio: 16 / 9; object-fit: cover; }
