/* ==========================================================================
   ARTICLE — styles specific to article.html only
   (hero reuses .orbit-hero — same wash/dots/blob background as home —
   but as a taller "extended" variant: the wash + dots keep going below the
   heading so the article header (image/title/meta) can sit on top of it.
   It does NOT fill the viewport like the home hero; it just gives enough
   room for the header block before the page settles into plain --bg.)
   ========================================================================== */

/* ---- Extended hero -------------------------------------------------------- */
.orbit-hero--article{
  padding-block: clamp(6.5rem, 13vw, 9.5rem) 0;
}
.orbit-hero--article .orbit-hero__inner{
  min-height: auto;
  display: block;
  place-items: unset;
}
/* The dot mask on the base hero is centered/short (fades by ~72% down) —
   stretch it so dots keep going the extra length of this taller hero. */
.orbit-hero--article .orbit-hero__dots{
  -webkit-mask-image: radial-gradient(65% 90% at 50% 30%, #000 0%, transparent 80%);
  mask-image: radial-gradient(65% 90% at 50% 30%, #000 0%, transparent 80%);
}

/* ---- Article header: image left, title/meta right, sits on the hero ---- */
.article-header{
  display: grid;
  grid-template-columns: minmax(0, 460px) 1fr;
  align-items: center;
  gap: clamp(2rem, 5vw, 3.5rem);
}
.article-header[hidden]{
  display: none;
}
.article-header__media{
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 4/3;
  box-shadow: var(--card-shadow);
}
.article-header__media img{
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.article-header__badge{
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--accent-ink);
  background: var(--accent);
  padding: 0.35rem 0.9rem;
  border-radius: var(--radius-pill);
  margin-bottom: 1rem;
}
.article-header__title{
  font-size: var(--step-3);
  font-weight: 600;
  line-height: 1.1;
  max-width: 20ch;
}
.article-header__desc{
  color: var(--ink-soft);
  font-size: var(--step-1);
  max-width: 46ch;
  margin-top: 1rem;
}
.article-header__author{
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.5rem;
}
.article-header__author .avatar{
  width: 40px;
  height: 40px;
}
.avatar__letter{
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--step--1);
  color: var(--accent-ink);
  background: var(--accent);
}
.article-header__author-name{
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--step-0);
  display: block;
}
.article-header__author-role{
  font-size: var(--step--1);
  color: var(--ink-mute);
}
.article-header .meta-row{
  margin-top: 1.1rem;
}

/* Space below the header before the plain-bg body content starts —
   this is the part that "extends the hero below" without going full page. */
.article-header-wrap{
  padding-bottom: clamp(3rem, 7vw, 4.5rem);
}

@media (max-width: 780px){
  .article-header{
    grid-template-columns: 1fr;
  }
  .article-header__media{
    max-width: 420px;
  }
}

/* ---- Body layout: sticky TOC sidebar (left) + centered article column
   (middle) + sticky "Popular" widget (right) — three columns on wide
   screens so the empty space to the right of the content column isn't
   just left blank.

   The old gap — clamp(2.5rem, 6vw, 4.5rem) — hit its 4.5rem (72px) per
   side ceiling at just a ~1200px viewport and then stayed pinned there
   for every wider screen after that, while the 720px content column had
   nowhere further to grow. That fixed 144px of total gap (72px on each
   side) sitting next to a column that had already stopped growing is
   what was making the space next to the TOC and next to Popular posts
   feel oversized on typical wide desktop screens — not the column being
   too narrow. Widening the column further doesn't fit: at this page's
   1240px content ceiling (--content-max), 220px (TOC) + 240px minimum
   (Popular) already leaves well under 720px once any real gap is added,
   so 720px was already close to this layout's real ceiling.

   Fix is the gap itself: a lower ceiling (3rem instead of 4.5rem) and a
   gentler vw-scaling rate, so it grows more slowly and stops sooner —
   comfortable breathing room at every width, without the wasted-space
   feeling on large screens. ------------------------------------------- */
.article-body-grid{
  display: grid;
  grid-template-columns: 220px minmax(0, 720px) minmax(240px, 1fr);
  gap: clamp(1.75rem, 3vw, 3rem);
  align-items: start;
}
/* Pin each region to its named column explicitly. Without this, hiding
   the TOC (display:none while its list is empty, e.g. during the
   skeleton-loading state) removes it from grid auto-placement entirely —
   the remaining two visible items then auto-place starting from column 1,
   shoving the article body into the TOC's 220px track and Popular posts
   into the body's wide track. Explicit placement keeps every region in
   its own column regardless of which siblings are hidden. */
.article-toc{ grid-column: 1; }
.article-content{ grid-column: 2; }
.article-popular{ grid-column: 3; }

/* Table of contents — generated by article.js from the article's own
   headings, so it always mirrors what's actually in the body. */
.article-toc{
  position: sticky;
  top: 100px;
}
.article-toc__label{
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 1rem;
}
.article-toc__list{
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  border-left: 2px solid var(--hairline);
}
.article-toc__list a{
  display: block;
  padding: 0.5rem 0 0.5rem 1rem;
  margin-left: -2px;
  border-left: 2px solid transparent;
  font-size: var(--step--1);
  color: var(--ink-soft);
  line-height: 1.35;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.article-toc__list a:hover{
  color: var(--ink-text);
}
.article-toc__list a[aria-current="true"]{
  color: var(--ink-text);
  border-left-color: var(--accent);
  font-weight: 600;
}
/* Level 1 (h1) sits at the base indent; each level below steps in one
   notch further and shrinks slightly, mirroring the admin editor's TOC. */
.article-toc__list a[data-level="2"]{
  padding-left: 1.75rem;
  font-size: 0.8125rem;
}
.article-toc__list a[data-level="3"]{
  padding-left: 2.5rem;
  font-size: 0.78125rem;
}
.article-toc__list a[data-level="4"]{
  padding-left: 3.25rem;
  font-size: 0.75rem;
}

@media (max-width: 960px){
  .article-body-grid{
    grid-template-columns: 1fr;
  }
  .article-toc,
  .article-content,
  .article-popular{
    grid-column: 1;
  }
  .article-toc{
    position: static;
    order: -1;
    padding: 1.25rem;
    background: var(--bg-raised);
    border-radius: var(--radius-md);
  }
  .article-toc__label{ margin-bottom: 0.75rem; }
  .article-popular{
    position: static;
  }
}

/* ---- Popular posts widget (sticky, right rail) — compact list, not the
   full .post-card, since the column is too narrow for that treatment ---- */
.article-popular{
  position: sticky;
  top: 100px;
}
.article-popular__label{
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 1.1rem;
}
.article-popular__list{
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}
.article-popular__item{
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 0.75rem;
  align-items: start;
}
.article-popular__num{
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 700;
  color: var(--hairline-strong);
  line-height: 1.3;
  transition: color var(--dur) var(--ease);
}
.article-popular__item:hover .article-popular__num{ color: var(--accent); }
.article-popular__title{
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--ink-text);
  transition: color var(--dur) var(--ease);
}
.article-popular__item:hover .article-popular__title{ color: #B98600; }
[data-theme="dark"] .article-popular__item:hover .article-popular__title{ color: var(--accent); }
.article-popular__meta{
  display: block;
  margin-top: 0.35rem;
  font-size: var(--step--1);
  color: var(--ink-mute);
}

/* ---- Article content typography ------------------------------------------ */
.article-content{
  max-width: 720px;
}
.article-content > * + *{
  margin-top: 1.4rem;
}
/* Fixed rem sizes here previously didn't scale down at all on mobile —
   at a 720px max-width column squeezed to ~320-375px, a 36px h1 felt
   oversized relative to the line length. Clamp keeps the same desktop
   size while easing down on small screens. */
.article-content h1{
  font-size: clamp(1.6rem, 1.35rem + 1.1vw, 2.25rem);
  font-weight: 700;
  margin-top: 3rem;
  scroll-margin-top: 100px;
}
.article-content h2{
  font-size: clamp(1.35rem, 1.15rem + 0.85vw, 1.75rem);
  font-weight: 600;
  margin-top: 2.75rem;
  scroll-margin-top: 100px;
}
.article-content h3{
  font-size: clamp(1.15rem, 1.02rem + 0.55vw, 1.375rem);
  font-weight: 600;
  margin-top: 2rem;
  scroll-margin-top: 100px;
}
.article-content h4{
  font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.125rem);
  font-weight: 600;
  margin-top: 1.5rem;
  scroll-margin-top: 100px;
}
.article-content p{
  color: var(--ink-soft);
  line-height: 1.75;
}
/* execCommand('bold') (used by the article editor's Bold tool) outputs
   <b>, not <strong>, in Chrome/Edge — Firefox does the same. Both tags
   need the same "make bold text read as full ink, not the paragraph's
   soft gray" treatment, or content saved from the editor renders bold
   text in the paragraph's dim color instead of standing out. */
.article-content strong,
.article-content b{
  color: var(--ink-text);
}
.article-content ul,
.article-content ol{
  color: var(--ink-soft);
  line-height: 1.75;
  padding-left: 1.4rem;
}
.article-content ul{ list-style: disc; }
.article-content ol{ list-style: decimal; }
.article-content li + li{ margin-top: 0.5rem; }
.article-content blockquote{
  border-left: 3px solid var(--accent);
  padding: 0.25rem 0 0.25rem 1.4rem;
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 500;
  color: var(--ink-text);
}
.article-content figure{
  margin: 0;
}
.article-content figure img{
  width: 100%;
  border-radius: var(--radius-md);
}
.article-content figcaption{
  margin-top: 0.6rem;
  font-size: var(--step--1);
  color: var(--ink-mute);
  text-align: center;
}

/* On mobile the content column shrinks to roughly 300–335px, so the same
   1.4rem (22.4px) left inset that reads as tasteful on the 720px desktop
   column instead eats a disproportionate chunk of the line and reads as
   "pushed in". Tightened together here (not just on the blockquote
   alone) so lists and quotes keep starting at the same x-position as
   each other at the new width — just less indented overall than desktop.

   The two values below aren't identical on purpose: blockquote also has
   a 3px left border baked into its padding-left, so its total inset
   (border + padding) needs to be 3px less padding than the list's to
   land its actual text at the same start position as the list's
   marker/text. .quote-attributed (article-blocks.css) shares this exact
   padding/border combination and gets the identical blockquote value at
   the same breakpoint. */
@media (max-width: 620px){
  .article-content ul,
  .article-content ol{
    padding-left: 1.15rem;
  }
  .article-content blockquote{
    padding-left: calc(1.15rem - 3px);
  }
}

/* ---- Share row — sits at the end of the article content, no divider
   above it (the article simply ends and this follows). Same specificity
   as .article-content > * + *, but declared later so it wins the extra
   breathing room without needing !important. ----------------------------- */
.article-share{
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 2.75rem;
}
.article-share__label{
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--ink-mute);
}
.article-share__icons{
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.article-share__icon{
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1.5px solid var(--hairline-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-text);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.article-share__icon svg{ width: 18px; height: 18px; }
.article-share__icon:hover{
  color: #B98600;
  border-color: #B98600;
}
[data-theme="dark"] .article-share__icon:hover{
  color: var(--accent);
  border-color: var(--accent);
}

/* ---- Related articles — no top divider; the share row above already
   separates it from the article body ------------------------------------- */
.article-related{
  padding-top: clamp(2.5rem, 5vw, 3.5rem);
}
