/* Blog (/blog and /blog/:slug) in the jcode.sh idiom: mono, monochrome, minimal.
   One JetBrains Mono face for everything, an 860px centred column, light paper inside the
   site's dark chrome, solid hairline rules, and links underlined by a border that darkens
   on hover.

   Loaded after landing.css and chrome.css (via yield :head), so equal-specificity rules
   here win. The page goes light via body.blog-mono, set by the blog views. */

/* landing.css zooms body.lp to 1.1; the blog is set at jcode's true 16px, and the zoom
   would also skew the fixed rail's overlap math against the media queries (which measure
   real viewport px). */
body.lp.blog-mono{ background:#fff; zoom:1; }

main.blog{
  --ink:#111;
  --muted:#666;
  --faint:#999;
  --rule:#ccc;
  --wash:#f4f4f4;
  --bg:#fff;
  --radius:8px;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  /* The column spans exactly the nav's inner box: .sc-nav-in's 975px max-width times the
     chrome's 1.1 zoom. Both centre with matching gutters, so the edges line up. */
  --menu-w:calc(975px * 1.1);

  font-family:var(--mono); color:var(--ink); background:var(--bg);
  font-size:16px; line-height:1.65; -webkit-font-smoothing:antialiased;
  padding:0 1.5rem 6rem;
}
.blog .wrap{ max-width:var(--menu-w); margin:0 auto; }

/* Every link is ink with a rule underline that sharpens to ink on hover; components that
   want no underline (cards, the contents menu) opt out below. */
.blog a,
.blog a:visited{ color:var(--ink); text-decoration:none; background:none; border-bottom:1px solid var(--rule); }
.blog a:hover{ color:var(--ink); background:none; border-bottom-color:var(--ink); }

.blog ::selection{ background:var(--ink); color:var(--bg); }

/* The nav and footer must look exactly as they do on the landing. The landing gets its
   10% scale-up from body.lp's zoom, which blog-mono resets for the article's sake — so
   the chrome alone gets the same zoom back here. */
body.blog-mono .sc{ zoom:1.1; }

/* The black/white switch, blog pages only (see shared/_site_nav). It lives in the dark
   nav, so it wears the chrome's tokens in both themes. */
body.blog-mono .sc-theme{
  width:30px; height:30px; display:grid; place-items:center; padding:0;
  font:inherit; font-size:15px; line-height:1;
  color:var(--sc-faint); background:none; border:1px solid var(--sc-rule); cursor:pointer;
}
body.blog-mono .sc-theme:hover{ color:#fff; border-color:#fff; }

/* ---------- the black design ---------- */
/* The same monochrome system with the poles swapped: near-black paper, light ink, and
   every component follows because everything below reads these tokens. Applied before
   paint by the inline script in the blog views; persisted by blog.js. */
html[data-theme="dark"] body.lp.blog-mono{ background:#0d0d0d; }
html[data-theme="dark"] main.blog{
  --ink:#e6e6e6;
  --muted:#9a9a9a;
  --faint:#6f6f6f;
  --rule:#333;
  --wash:#161616;
  --bg:#0d0d0d;
}

/* ---------- index ---------- */
.blog-head{ padding:5rem 0 1rem; }
.blog-head h1{ font-size:2.5rem; font-weight:700; line-height:1.2; letter-spacing:-.02em; margin:0; }
.blog-head p{ color:var(--muted); margin:1rem 0 0; max-width:760px; }

.blog-list{ margin-top:3rem; }

/* A post is a rule-topped row: title, then the byline beneath it, then the muted excerpt. */
.blog .blog-card,
.blog .blog-card:visited{ display:block; padding:1.75rem 0; border-top:1px solid var(--rule); border-bottom:none; }
.blog .blog-card:hover{ border-bottom:none; }

.blog-card h2{ font-size:1.75rem; font-weight:700; line-height:1.25; letter-spacing:-.02em; margin:0; text-wrap:pretty; }
.blog .blog-card:hover h2{ text-decoration:underline; text-decoration-color:var(--rule); text-underline-offset:6px; }
.blog-card .blog-meta{ margin-top:.75rem; }

.blog-card-excerpt{ color:var(--muted); font-size:.9rem; margin:.65rem 0 0; max-width:760px; text-wrap:pretty; }
.blog-card-more{ display:inline-block; margin-top:1rem; font-size:.8rem; color:var(--faint); }
.blog .blog-card:hover .blog-card-more{ color:var(--ink); }

.blog-meta{ display:flex; align-items:baseline; gap:.5rem; color:var(--muted); font-size:.85rem; }
.blog-dot{ color:var(--faint); }
.blog-author{ color:var(--muted); }

.blog-empty{
  margin-top:3rem; padding:3.5rem 1.5rem; text-align:center;
  border:1px solid var(--rule); border-radius:var(--radius); background:var(--wash);
  color:var(--muted); font-size:.9rem;
}

/* ---------- post ---------- */
/* The article keeps the index's measure; on desktop the contents menu rides a sticky
   column to its right (grid, below), and on narrow screens everything stacks. */
.blog-post .post-wrap{ display:flex; flex-direction:column; max-width:var(--menu-w); margin:0 auto; }
.blog-post .post-col{ min-width:0; padding-top:5rem; }

.blog .post-back,
.blog .post-back:visited{ display:inline-block; font-size:.85rem; color:var(--muted); }
.blog .post-back:hover{ color:var(--ink); }

.post-head{ margin:0 0 2.5rem; }
.post-head h1{ font-size:2.5rem; font-weight:700; line-height:1.2; letter-spacing:-.02em; margin:1.5rem 0 1rem; text-wrap:pretty; }
.post-head .blog-meta{ margin-top:0; }

.post-foot{ margin-top:3.5rem; padding-top:1.5rem; border-top:1px solid var(--rule); }

@media(max-width:640px){
  main.blog{ font-size:15px; }
  .blog-head{ padding-top:3.5rem; }
  .blog-post .post-col{ padding-top:3.5rem; }
  .blog-head h1, .post-head h1{ font-size:2rem; }
  .blog-card h2{ font-size:1.35rem; }
}

/* ---------- post body ---------- */
.post-body{ font-size:1rem; line-height:1.65; }
.post-body > *:first-child{ margin-top:0; }
.post-body p{ margin:0 0 1rem; text-wrap:pretty; }

.post-body h1,
.post-body h2{
  font-size:1.5rem; font-weight:700; letter-spacing:-.01em; line-height:1.35;
  margin:2.75rem 0 1rem; scroll-margin-top:88px; position:relative; text-wrap:pretty;
}
.post-body h3{ font-size:1.05rem; font-weight:700; margin:2.5rem 0 .5rem; scroll-margin-top:88px; position:relative; }
@media(max-width:640px){
  .post-body h1, .post-body h2{ font-size:1.25rem; }
}

.post-body .anchor{ position:absolute; left:-.9em; width:.9em; border-bottom:none; opacity:0; }
.post-body .anchor::before{ content:"#"; color:var(--faint); font-weight:400; }
.post-body .anchor:hover::before{ color:var(--ink); }
.post-body h1:hover .anchor,
.post-body h2:hover .anchor,
.post-body h3:hover .anchor{ opacity:1; }
@media(max-width:900px){ .post-body .anchor{ display:none; } }

.post-body strong{ font-weight:700; }
.post-body ul,
.post-body ol{ margin:0 0 1rem; padding-left:1.25rem; }
.post-body li{ margin:.35rem 0; text-wrap:pretty; }
.post-body hr{ border:none; border-top:1px solid var(--rule); margin:2.5rem 0; }
.post-body img{ display:block; max-width:100%; height:auto; border:1px solid var(--rule); }
.post-body blockquote{ margin:0 0 1rem; padding:.25rem 0 .25rem 1.25rem; border-left:2px solid var(--rule); color:var(--muted); }
.post-body blockquote p:last-child{ margin-bottom:0; }

.post-body table{ width:100%; border-collapse:collapse; font-size:.85rem; margin:1rem 0 1.5rem; display:block; overflow-x:auto; }
.post-body thead th,
.post-body th{
  text-align:left; font-weight:400; color:var(--muted);
  text-transform:uppercase; letter-spacing:.08em; font-size:.7rem;
  padding:0 1rem .5rem 0; border-bottom:1px solid var(--ink);
}
.post-body td{ padding:.55rem 1rem .55rem 0; border-bottom:1px solid var(--rule); vertical-align:top; }

/* inline code + fenced blocks */
.post-body code{
  background:var(--wash); border:1px solid var(--rule); padding:0 .3em; font-size:.9em; color:inherit;
}
.post-body pre.highlight{
  background:var(--wash); border:1px solid var(--rule); border-radius:var(--radius);
  padding:.75rem 1.25rem; overflow-x:auto; margin:0 0 1.25rem;
}
.post-body pre.highlight code{ background:none; border:none; padding:0; font-size:.85rem; line-height:1.65; color:var(--ink); }

/* Rouge tokens stay monochrome: weight and shade carry the structure, never hue. */
.post-body .highlight .c,.post-body .highlight .c1,.post-body .highlight .cm,.post-body .highlight .cs{ color:var(--faint); font-style:italic; }
.post-body .highlight .k,.post-body .highlight .kd,.post-body .highlight .kn,.post-body .highlight .kr,.post-body .highlight .kc,.post-body .highlight .kp,.post-body .highlight .kt,.post-body .highlight .nt{ font-weight:700; }
.post-body .highlight .s,.post-body .highlight .s1,.post-body .highlight .s2,.post-body .highlight .sb,.post-body .highlight .sc,.post-body .highlight .sd,.post-body .highlight .se,.post-body .highlight .sh,.post-body .highlight .si,.post-body .highlight .sx,.post-body .highlight .sr,
.post-body .highlight .m,.post-body .highlight .mi,.post-body .highlight .mf,.post-body .highlight .mh,.post-body .highlight .mo,.post-body .highlight .il{ color:var(--muted); }

/* inline animation + tweet embed */
.post-body .post-video{ margin:0 0 1.5rem; }
.post-body .post-video video{
  display:block; width:100%; height:auto; aspect-ratio:16/9;
  border:1px solid var(--rule); background:var(--wash);
}
.tweet-embed{ margin:0 0 1.5rem; min-height:260px; }
.tweet-embed .twitter-tweet{ margin:0 !important; }
.tweet-embed blockquote:not(.twitter-tweet-rendered){ border-left:2px solid var(--rule); padding:.75rem 0 .75rem 1.25rem; margin:0; color:var(--muted); }
.tweet-embed blockquote:not(.twitter-tweet-rendered) a{ font-size:.8rem; word-break:break-all; }

/* ---------- sidebar: contents + promo ---------- */
/* Desktop: the menu is a sticky column on the article's right — jcode's section map as a
   true sidebar: small, faint, a hairline on its left, the active section in ink. The whole
   grid holds the nav's width, and the article yields measure first (minmax(0,1fr)) as the
   viewport tightens. */
@media(min-width:1100px){
  .blog-post .post-wrap{
    display:grid; grid-template-columns:minmax(0,1fr) 14rem; column-gap:3rem;
    align-items:start;
  }
  .post-side{
    position:sticky; top:6rem; margin-top:5.5rem;
    max-height:calc(100vh - 8rem); overflow-y:auto;
  }
  .post-toc{ border-left:1px solid var(--rule); padding-left:1rem; }
}

.post-toc summary{
  display:flex; align-items:center; gap:.45rem; cursor:pointer; list-style:none;
  font-size:.7rem; text-transform:uppercase; letter-spacing:.1em; font-weight:700; color:var(--faint);
  padding-bottom:.75rem;
}
.post-toc summary::-webkit-details-marker{ display:none; }
.post-toc summary:hover{ color:var(--ink); }
.post-toc summary::before{
  content:""; width:0; height:0; border-left:4px solid currentColor;
  border-top:3.5px solid transparent; border-bottom:3.5px solid transparent; transition:transform .2s;
}
.post-toc details[open] > summary::before{ transform:rotate(90deg); }
@media (prefers-reduced-motion: reduce){ .post-toc summary::before{ transition:none; } }

.post-toc ol{ list-style:none; margin:0; padding:0; }
.post-toc li{ margin:.15rem 0; }
.blog .post-toc li a,
.blog .post-toc li a:visited{
  display:block; padding:.1rem 0; border-bottom:none;
  font-size:.72rem; line-height:1.5; color:var(--faint);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.blog .post-toc li a:hover{ color:var(--ink); border-bottom:none; }
.blog .post-toc li.is-active > a{ color:var(--ink); }
.post-toc li.toc-h3 a{ padding-left:1rem; }

.post-promo{
  margin-top:1.5rem; padding:1rem 1.1rem;
  border:1px solid var(--rule); border-radius:var(--radius); background:var(--wash);
}
.post-promo-text{ margin:0; color:var(--muted); font-size:.8rem; line-height:1.6; }
.post-promo-text strong{ color:var(--ink); font-weight:700; }
.blog .post-promo-cta,
.blog .post-promo-cta:visited{ display:inline-block; margin-top:.75rem; font-size:.8rem; color:var(--ink); border-bottom:1px solid var(--rule); }
.blog .post-promo-cta:hover{ border-bottom-color:var(--ink); }

/* Below the sidebar's breakpoint the menu moves above the article as a collapsible panel
   and the promo drops below the post. */
@media(max-width:1099px){
  /* The column's air moves from the article to the wrap so the menu panel shares it. */
  .blog-post .post-wrap{ padding-top:2.5rem; }
  .blog-post .post-col{ padding-top:0; }
  .post-side{ display:contents; }
  .post-toc{
    order:-1; margin-bottom:2.5rem; padding:1rem 1.25rem;
    border:1px solid var(--rule); border-radius:var(--radius); background:var(--wash);
  }
  .post-toc summary{ padding-bottom:0; }
  .post-toc details[open] > summary{ padding-bottom:.75rem; }
  .blog .post-toc li a{ white-space:normal; }
  .post-promo{ order:1; margin-top:3rem; }
}
