/* ============================================================
   styles.css — base + components
   Loaded after tokens.css. Lean by design (target <30KB gz).
   ============================================================ */

/* ---- Reset (minimal) ---- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; hanging-punctuation: first last; }
body { line-height: var(--lh-body); -webkit-font-smoothing: antialiased; }
img, svg, video { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
/* Make [hidden] win against author display: rules (e.g. .tocl li { display: grid }
   would otherwise override the UA stylesheet's [hidden] { display:none }). */
[hidden] { display: none !important; }
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--r-1);
}
::selection { background: var(--selection-bg); color: var(--fg); }

/* ---- Page chrome ---- */
html {
  background: var(--bg);
  color: var(--fg);
}
/* paper grain — single inline SVG noise turbulence layer */
body::before {
  content: "";
  position: fixed; inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: var(--paper-noise-opacity);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.7 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  mix-blend-mode: multiply;
}
[data-theme="dark"] body::before { mix-blend-mode: screen; }

body {
  font-family: var(--font-serif);
  font-size: var(--fs-body);
  font-feature-settings: "onum" 1, "kern" 1, "liga" 1;
  position: relative;
  min-height: 100vh;
}
body > * { position: relative; z-index: 1; }

/* ---- Skip link ---- */
.skip {
  position: absolute;
  left: var(--s-4);
  top: -3rem;
  background: var(--bg);
  color: var(--accent);
  padding: var(--s-2) var(--s-4);
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  border: 1px solid var(--border-strong);
  text-decoration: none;
  z-index: 100;
  transition: top var(--motion) var(--ease);
}
.skip:focus { top: var(--s-3); }

/* ---- Layout primitives ---- */
.shell {
  max-width: var(--col-wide);
  margin-inline: auto;
  padding-inline: var(--s-5);
}
@media (min-width: 64em) {
  .shell { padding-inline: var(--s-7); }
}

.column {
  max-width: var(--col-text);
}

/* Tufte-style article: text column on left, sidenote gutter on right */
.article {
  display: grid;
  grid-template-columns: minmax(0, var(--col-text)) var(--sidenote-w);
  gap: 0 var(--s-7);
  max-width: calc(var(--col-text) + var(--sidenote-w) + var(--s-7));
  margin-inline: auto;
}
.article > * { grid-column: 1; }
.article > aside.sidenote { grid-column: 2; }

@media (max-width: 64em) {
  .article { display: block; max-width: var(--col-text); }
  .article > aside.sidenote { display: none; }
}
/* Articles without any sidenote children fall back to a single column.
   Avoids the "empty gutter" look on index/listing pages that reuse the
   .article scaffold but don't actually have margin annotations.
   :has() shipped in every evergreen browser by mid-2023; in older UAs the
   page falls back to the two-column layout, which is also acceptable. */
@supports selector(:has(*)) {
  .article:not(:has(> aside.sidenote)) {
    display: block;
    max-width: var(--col-text);
  }
}

/* ---- Top bar (nav) ---- */
.topbar {
  border-bottom: var(--bw-hair) solid var(--rule);
  padding-block: var(--s-4);
  font-family: var(--font-sans);
  font-size: var(--fs-small);
}
.topbar-inner {
  max-width: var(--col-wide);
  margin-inline: auto;
  padding-inline: var(--s-5);
  display: flex;
  align-items: baseline;
  gap: var(--s-5);
  flex-wrap: wrap;
}
@media (min-width: 64em) {
  .topbar-inner { padding-inline: var(--s-7); }
}
.brand {
  font-family: var(--font-serif);
  font-size: var(--fs-h4);
  font-weight: 600;
  color: var(--fg);
  text-decoration: none;
  letter-spacing: var(--tracking-tight);
}
.brand:hover { color: var(--accent); }
.brand-callsign {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  font-weight: 400;
  color: var(--fg-muted);
  margin-left: var(--s-2);
  letter-spacing: var(--tracking-loose);
  text-transform: uppercase;
}
/* Uploaded logo (replaces the wordmark when site_settings.logo_path is set). */
.brand-logo {
  display: inline-block;
  height: 1.6rem;        /* matches the wordmark's optical baseline */
  width: auto;
  max-width: 220px;
  vertical-align: middle;
}
.nav {
  display: flex;
  gap: var(--s-5);
  margin-left: auto;
  align-items: baseline;
  flex-wrap: wrap;
}
.nav a {
  color: var(--fg-muted);
  text-decoration: none;
  transition: color var(--motion) var(--ease);
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--fg); }
.nav a[aria-current="page"] { color: var(--accent); }

/* ---- Footer ---- */
.foot {
  margin-top: var(--s-10);
  padding: var(--s-7) 0 var(--s-8);
  border-top: var(--bw-hair) solid var(--rule);
  color: var(--fg-muted);
  font-family: var(--font-sans);
  font-size: var(--fs-small);
}
.foot-inner {
  max-width: var(--col-wide);
  margin-inline: auto;
  padding-inline: var(--s-5);
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
}
@media (min-width: 48em) {
  .foot-inner { grid-template-columns: 1fr auto; align-items: end; padding-inline: var(--s-7); }
}
.foot a { color: var(--fg-muted); }
.foot a:hover { color: var(--accent); }
.foot-meta {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: var(--fg-subtle);
  font-feature-settings: "tnum" 1;
}
.foot-links { display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-5); }

/* ---- Headings ---- */
h1, h2, h3, h4 {
  font-family: var(--font-serif);
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-tight);
  font-weight: 600;
  text-wrap: balance;
}
.display {
  font-size: var(--fs-display);
  line-height: var(--lh-tight);
  letter-spacing: -0.02em;
  font-weight: 400;
  text-wrap: balance;
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); margin-top: var(--s-7); }
h3 { font-size: var(--fs-h3); margin-top: var(--s-6); }
h4 { font-size: var(--fs-h4); margin-top: var(--s-5); }

/* heading anchors */
.h-anchor {
  position: relative;
  scroll-margin-top: var(--s-7);
}
.h-anchor > .anchor-link {
  position: absolute;
  left: -1.2em;
  top: 0;
  color: var(--fg-subtle);
  text-decoration: none;
  font-family: var(--font-sans);
  font-weight: 400;
  opacity: 0;
  transition: opacity var(--motion) var(--ease);
}
.h-anchor:hover > .anchor-link,
.h-anchor:focus-within > .anchor-link { opacity: 1; }
.h-anchor > .anchor-link:hover { color: var(--accent); }

/* ---- Body text ---- */
p, ul, ol, dl, blockquote, figure, table, pre, .callout {
  margin-block: var(--s-4);
}
p { text-wrap: pretty; }
.lede {
  font-size: 1.3125rem;
  line-height: var(--lh-body);
  color: var(--fg);
  letter-spacing: var(--tracking-tight);
  text-wrap: pretty;
}
.muted { color: var(--fg-muted); }
.subtle { color: var(--fg-subtle); }

ul, ol { padding-left: 1.4em; }
li { margin-block: var(--s-1); }
li::marker { color: var(--fg-subtle); }

/* ---- Links ---- */
a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: color-mix(in oklab, var(--accent) 40%, transparent);
  transition: color var(--motion) var(--ease), text-decoration-color var(--motion) var(--ease);
}
a:hover {
  color: var(--accent-hover);
  text-decoration-color: var(--accent-hover);
}
a:visited { color: color-mix(in oklab, var(--accent) 80%, var(--fg-muted)); }
a.plain { color: var(--fg); text-decoration-color: var(--rule); }
a.plain:hover { color: var(--accent); text-decoration-color: var(--accent); }
a[rel~="external"]::after,
a.external::after {
  content: " ↗";
  font-family: var(--font-sans);
  font-size: 0.8em;
  color: var(--fg-subtle);
}

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  font-weight: 500;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--border-strong);
  background: var(--bg);
  color: var(--fg);
  text-decoration: none;
  border-radius: var(--r-1);
  /* Defensive: kill any link-underline inherited from base `a` rules. */
  text-decoration-line: none;
  transition: border-color var(--motion) var(--ease), color var(--motion) var(--ease),
              background var(--motion) var(--ease), transform var(--motion-fast) var(--ease),
              box-shadow var(--motion) var(--ease);
  line-height: 1.2;
  position: relative;
}
/* Only apply hover lift / shadow on devices that actually have a hover
   capability — touch devices would otherwise stay stuck in :hover until
   the user taps somewhere else.
   The selectors are chained as a.btn:hover / button.btn:hover so they
   match the specificity of a.btn:link/:visited below; otherwise visited
   anchors would keep the visited color on hover. */
@media (hover: hover) {
  a.btn:hover, button.btn:hover, .btn:hover {
    border-color: var(--accent);
    color: var(--accent);
    transform: translateY(-1px);
    box-shadow: 0 1px 0 0 var(--rule),
                0 2px 6px -3px color-mix(in oklab, var(--accent) 50%, transparent);
  }
}
.btn:active { transform: translateY(0); box-shadow: none; }

/* `a:visited { color: ... }` (specificity 0,1,1) would otherwise win against
   plain `.btn` / `.btn-primary` (specificity 0,1,0) and re-tint visited
   button-anchors with the visited link color. We pin the link/visited
   colors explicitly at element+class specificity (a.btn = 0,1,1) so the
   colors survive history state. Underline-removal still applies to all
   states. */
a.btn { text-decoration: none; }
a.btn:link, a.btn:visited { color: var(--fg); text-decoration: none; }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}
/* Pin :link + :visited for primary buttons so the visited-link color
   doesn't sneak in. */
a.btn-primary:link, a.btn-primary:visited { color: var(--bg); }
@media (hover: hover) {
  a.btn-primary:hover, button.btn-primary:hover, .btn-primary:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: var(--bg);
    /* Stronger shadow on the primary so the hover feedback is unambiguous. */
    box-shadow: 0 1px 0 0 color-mix(in oklab, var(--accent-hover) 70%, transparent),
                0 4px 10px -3px color-mix(in oklab, var(--accent) 60%, transparent);
  }
}

.btn-ghost { border-color: transparent; padding-inline: var(--s-2); }
@media (hover: hover) {
  a.btn-ghost:hover, button.btn-ghost:hover, .btn-ghost:hover {
    color: var(--accent);
    border-color: transparent;
    background: var(--accent-bg);
    box-shadow: none;       /* keep ghost buttons quiet on hover */
    transform: none;
  }
}

.btn[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); background: var(--accent-bg); }

/* ---- Tag pills ---- */
.tag {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  color: var(--fg-muted);
  background: transparent;
  text-decoration: none;
  letter-spacing: 0.01em;
  transition: color var(--motion) var(--ease), border-color var(--motion) var(--ease), background var(--motion) var(--ease);
}
.tag:hover { color: var(--accent); border-color: var(--accent-muted); }
.tag[aria-pressed="true"], .tag.is-active {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-bg);
}
.tag-row { display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* ---- Inline code ---- */
code, kbd, samp {
  font-family: var(--font-mono);
  font-size: 0.92em;
  font-feature-settings: "calt" 0; /* no ligatures inline */
}
:not(pre) > code {
  background: var(--code-bg);
  padding: 0.05em 0.35em;
  border-radius: var(--r-1);
  color: var(--code-fg);
  border: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
}

/* ---- Code blocks ---- */
.codeblock {
  border: 1px solid var(--border);
  background: var(--code-bg);
  border-radius: var(--r-2);
  overflow: hidden;
  margin-block: var(--s-5);
  font-size: var(--fs-code);
}
.codeblock-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.45rem 0.75rem;
  border-bottom: 1px solid var(--border);
  background: color-mix(in oklab, var(--code-bg) 80%, var(--bg));
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
}
.codeblock-lang {
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  font-size: 0.72rem;
  font-weight: 600;
}
.codeblock-copy {
  font-family: var(--font-sans);
  color: var(--fg-muted);
  padding: 0.15rem 0.45rem;
  border-radius: var(--r-1);
  font-size: var(--fs-caption);
  border: 1px solid transparent;
  transition: color var(--motion) var(--ease), border-color var(--motion) var(--ease);
}
.codeblock-copy:hover { color: var(--accent); border-color: var(--border); }
.codeblock pre {
  margin: 0;
  padding: var(--s-4) var(--s-5);
  overflow-x: auto;
  line-height: 1.6;
  color: var(--code-fg);
  font-family: var(--font-mono);
  tab-size: 2;
}
.codeblock pre code { font-family: inherit; }
/* line numbers */
.codeblock pre.lineno { counter-reset: ln; padding-left: 0; display: grid; grid-template-columns: auto 1fr; }
.codeblock pre.lineno > .ln {
  counter-increment: ln;
  padding: 0 var(--s-4) 0 var(--s-4);
  color: var(--fg-subtle);
  text-align: right;
  user-select: none;
  font-feature-settings: "tnum" 1;
  border-right: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
}
.codeblock pre.lineno > .ln::before { content: counter(ln); }
.codeblock pre.lineno > .ll { padding-left: var(--s-4); padding-right: var(--s-5); white-space: pre; }
.codeblock pre.lineno > .ll.hl,
.codeblock pre.lineno > .ln.hl { background: color-mix(in oklab, var(--accent) 10%, transparent); }

/* simple syntax */
.tk-c  { color: var(--code-comment); font-style: italic; }
.tk-k  { color: var(--code-keyword); }
.tk-s  { color: var(--code-string); }
.tk-n  { color: var(--code-number); }
.tk-f  { color: var(--code-fn); }

/* ---- Pull quote / callouts (notebook-annotation feel) ---- */
.pullquote {
  font-family: var(--font-serif);
  font-size: 1.4rem;
  line-height: var(--lh-snug);
  font-style: italic;
  color: var(--fg);
  border-left: 2px solid var(--accent);
  padding: var(--s-2) 0 var(--s-2) var(--s-5);
  margin: var(--s-6) 0;
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}
.pullquote cite {
  display: block;
  font-style: normal;
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  color: var(--fg-muted);
  margin-top: var(--s-2);
}
.pullquote cite::before { content: "— "; }

.callout {
  font-family: var(--font-serif);
  border-left: 2px solid var(--rule);
  padding: var(--s-3) 0 var(--s-3) var(--s-5);
  color: var(--fg);
}
.callout-label {
  display: block;
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--fg-muted);
  margin-bottom: var(--s-1);
}
.callout--info    { border-left-color: var(--accent-muted); }
.callout--info    .callout-label { color: var(--accent); }
.callout--warn    { border-left-color: #c98a2c; }
.callout--warn    .callout-label { color: #a06917; }
[data-theme="dark"] .callout--warn { border-left-color: #d8a45a; }
[data-theme="dark"] .callout--warn .callout-label { color: #d8a45a; }
.callout--aside   { border-left-style: dashed; color: var(--fg-muted); }

/* ---- Sidenotes ---- */
aside.sidenote {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--fg-muted);
  border-top: 1px solid var(--rule);
  padding-top: var(--s-1);
  margin-top: 0;
  align-self: start;
}
aside.sidenote .sn-num {
  color: var(--accent);
  font-feature-settings: "tnum" 1;
  font-weight: 600;
  margin-right: 0.35em;
}
.sn-ref {
  font-family: var(--font-sans);
  font-feature-settings: "sups" 1;
  color: var(--accent);
  font-size: 0.8em;
  vertical-align: super;
  line-height: 0;
  text-decoration: none;
  margin-left: 0.05em;
}
.sn-ref:hover { color: var(--accent-hover); }

/* Inline expand fallback (mobile) */
.sn-inline {
  display: none;
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  margin: var(--s-3) 0 var(--s-3) var(--s-4);
  border-left: 2px solid var(--rule);
  padding-left: var(--s-3);
}
@media (max-width: 64em) {
  details.sn-inline { display: block; }
  details.sn-inline summary {
    cursor: pointer;
    color: var(--accent);
    list-style: none;
    font-size: var(--fs-caption);
  }
  details.sn-inline summary::-webkit-details-marker { display: none; }
  details.sn-inline > .sn-body { margin-top: var(--s-2); }
}

/* ---- Tables ---- */
table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-small);
  font-feature-settings: "tnum" 1, "onum" 0;
}
table caption {
  text-align: left;
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  margin-bottom: var(--s-2);
}
thead th {
  text-align: left;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg-muted);
  border-bottom: 1px solid var(--fg);
  padding: var(--s-2) var(--s-3) var(--s-2) 0;
}
tbody td {
  padding: var(--s-2) var(--s-3) var(--s-2) 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
tbody tr:last-child td { border-bottom: 1px solid var(--fg); }
tbody td.num { text-align: right; font-feature-settings: "tnum" 1; }

/* ---- Forms ---- */
.field { display: grid; gap: var(--s-2); margin-block: var(--s-4); }
.label {
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--fg);
}
.label .opt { color: var(--fg-subtle); font-weight: 400; margin-left: 0.4em; }
.input, .textarea {
  font-family: var(--font-serif);
  font-size: var(--fs-body);
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-1);
  padding: 0.5rem 0.7rem;
  width: 100%;
  transition: border-color var(--motion) var(--ease);
}
.input:focus, .textarea:focus {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
  border-color: var(--accent);
}
.textarea { font-family: var(--font-serif); min-height: 8rem; line-height: 1.55; resize: vertical; }
.help {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
}
.field.is-error .input, .field.is-error .textarea { border-color: #b03a2a; }
.field.is-error .help { color: #b03a2a; }
[data-theme="dark"] .field.is-error .input, [data-theme="dark"] .field.is-error .textarea { border-color: #d97a5e; }
[data-theme="dark"] .field.is-error .help { color: #d97a5e; }
.field.is-success .help { color: #4f6a2c; }
[data-theme="dark"] .field.is-success .help { color: #b9c096; }

/* ---- Pagination ---- */
.pager {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid var(--rule);
}
.pager a { color: var(--fg-muted); text-decoration: none; }
.pager a:hover { color: var(--accent); }
.pager .label-tiny {
  display: block;
  font-size: var(--fs-caption);
  color: var(--fg-subtle);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  margin-bottom: 2px;
}
.pager .next { text-align: right; }

/* ---- Theme toggle (text label, not icon flip) ---- */
.theme-toggle {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--r-1);
  transition: color var(--motion) var(--ease), border-color var(--motion) var(--ease);
}
.theme-toggle:hover { color: var(--accent); border-color: var(--accent-muted); }
.theme-toggle .tt-label { font-feature-settings: "tnum" 1; }

/* ---- Section divider (typographic ornament) ---- */
.ornament {
  text-align: center;
  font-family: var(--font-serif);
  color: var(--fg-subtle);
  letter-spacing: 0.6em;
  margin: var(--s-7) 0;
  font-size: 1.25rem;
  line-height: 1;
}
.ornament::before { content: "§"; }
[data-ornament="asterism"] .ornament::before { content: "✻"; }
[data-ornament="pilcrow"]  .ornament::before { content: "¶"; }

/* ---- Index list (table-of-contents look) ---- */
.tocl { list-style: none; padding: 0; }
.tocl li {
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
}
.tocl li:first-child { border-top: 1px solid var(--rule); }
.tocl .date {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  font-feature-settings: "tnum" 1;
  letter-spacing: 0.02em;
}
.tocl .title { font-family: var(--font-serif); font-size: var(--fs-body); }
.tocl .title a { color: var(--fg); text-decoration-color: var(--rule); }
.tocl .title a:hover { color: var(--accent); text-decoration-color: var(--accent); }
.tocl .meta {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  margin-top: 2px;
}
.tocl .summary { color: var(--fg-muted); font-size: var(--fs-small); }

/* ---- Currently block (notebook annotation) ---- */
.currently {
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: var(--s-5) 0;
  margin: var(--s-7) 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-4);
}
@media (min-width: 48em) {
  .currently { grid-template-columns: 8rem 1fr; gap: var(--s-5); }
}
.currently h2 {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
}
.currently dl { margin: 0; display: grid; gap: var(--s-3); }
.currently dt {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-subtle);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  margin-bottom: 2px;
}
.currently dd { margin: 0; color: var(--fg); }
.currently dd .note { color: var(--fg-muted); }
.currently-stamp {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: var(--fg-subtle);
  font-feature-settings: "tnum" 1;
}

/* ---- Project meta blocks ---- */
.meta-row {
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  color: var(--fg-muted);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  margin-block: var(--s-4) var(--s-6);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--rule);
}
.meta-row .meta-label {
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  font-size: var(--fs-caption);
  color: var(--fg-subtle);
  margin-right: 0.4em;
}

/* ---- Filter UI (projects index) ---- */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  align-items: baseline;
  margin: var(--s-5) 0;
  padding: var(--s-3) 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.filter-bar .filter-label {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  margin-right: var(--s-2);
}

/* ---- Timeline (about) ---- */
.timeline { list-style: none; padding: 0; margin: 0; }
.timeline li {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-2);
  padding: var(--s-6) 0;
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 48em) {
  .timeline li { grid-template-columns: 11rem 1fr; gap: var(--s-6); }
}
.timeline .when {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  font-feature-settings: "tnum" 1;
  letter-spacing: 0.02em;
  padding-top: 0.4em;
}
.timeline .role {
  font-family: var(--font-serif);
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  margin-bottom: var(--s-2);
}
.timeline .org {
  color: var(--accent);
  font-style: italic;
  font-weight: 400;
}
.timeline .stack {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  margin-top: var(--s-3);
}

/* ---- Microblog stream ---- */
.stream { list-style: none; padding: 0; margin: 0; max-width: var(--col-text); }
.stream li {
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--rule);
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s-3);
}
.stream .body { font-size: 1.0625rem; line-height: 1.6; color: var(--fg); }
.stream .stamp {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: var(--fg-subtle);
  font-feature-settings: "tnum" 1;
  white-space: nowrap;
  align-self: start;
}
.stream .stamp a { color: inherit; text-decoration-color: transparent; }
.stream .stamp a:hover { color: var(--accent); }

/* ---- Component library page utilities ---- */
.cl-section { margin: var(--s-7) 0; }
.cl-section h2 {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--fg-muted);
  font-weight: 500;
  margin-bottom: var(--s-4);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--rule);
}
.cl-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-4);
  align-items: center;
  margin-block: var(--s-3);
}
.cl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--s-4);
}
.swatch {
  border: 1px solid var(--border);
  border-radius: var(--r-1);
  overflow: hidden;
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
}
.swatch .chip { height: 4rem; }
.swatch .meta { padding: var(--s-2) var(--s-3); display: flex; justify-content: space-between; color: var(--fg-muted); }
.swatch .meta b { color: var(--fg); font-weight: 500; }

/* ---- 404 ---- */
.notfound {
  text-align: left;
  max-width: var(--col-text);
  margin: var(--s-9) auto;
}
.notfound .big {
  font-family: var(--font-serif);
  font-size: clamp(5rem, 8vw + 1rem, 9rem);
  line-height: 0.9;
  letter-spacing: -0.04em;
  font-feature-settings: "lnum" 1;
  color: var(--accent);
  margin-bottom: var(--s-5);
}

/* ---- Tweaks panel ---- */
.tweaks {
  position: fixed;
  right: var(--s-4);
  bottom: var(--s-4);
  width: 16rem;
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-2);
  padding: var(--s-4);
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg);
  z-index: 50;
  display: none;
}
.tweaks.is-open { display: block; }
.tweaks h3 {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--fg-muted);
  font-weight: 500;
  margin: 0 0 var(--s-3) 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.tweaks h3 button { color: var(--fg-muted); font-size: 1rem; line-height: 1; }
.tweaks h3 button:hover { color: var(--accent); }
.tweaks .tw-row { display: flex; gap: var(--s-2); align-items: center; margin-block: var(--s-3); }
.tweaks .tw-row > .tw-label { flex: 0 0 4rem; color: var(--fg-muted); }
.tweaks .tw-swatches { display: flex; gap: var(--s-2); }
.tweaks .tw-swatch {
  width: 1.5rem; height: 1.5rem;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  cursor: pointer;
  padding: 0;
  position: relative;
}
.tweaks .tw-swatch[aria-pressed="true"]::after {
  content: "";
  position: absolute;
  inset: -4px;
  border: 1px solid var(--accent);
  border-radius: 50%;
}
.tweaks .tw-seg {
  display: inline-flex;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-1);
  overflow: hidden;
}
.tweaks .tw-seg button {
  padding: 0.25rem 0.6rem;
  font-size: var(--fs-caption);
  font-family: var(--font-sans);
  color: var(--fg-muted);
  border-right: 1px solid var(--border);
}
.tweaks .tw-seg button:last-child { border-right: 0; }
.tweaks .tw-seg button[aria-pressed="true"] { background: var(--accent-bg); color: var(--accent); }

/* ---- Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0ms !important;
    transition-duration: 0ms !important;
  }
  html { scroll-behavior: auto; }
}

html { scroll-behavior: smooth; }

/* ---- Indic script overrides ---- */
:lang(pa), :lang(hi) {
  font-family: "Noto Serif Devanagari", "Noto Serif Gurmukhi", var(--font-serif);
}

/* ---- Misc utility ---- */
.row { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: baseline; }
.spread { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-4); flex-wrap: wrap; }
.smcp { font-variant-caps: all-small-caps; letter-spacing: 0.04em; }
.tnum { font-feature-settings: "tnum" 1, "lnum" 1; }
.sup { font-feature-settings: "sups" 1; }
.dim { color: var(--fg-muted); }
.section-eyebrow {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
}
hr.rule { border: 0; border-top: 1px solid var(--rule); margin: var(--s-7) 0; }
.dot { color: var(--fg-subtle); margin-inline: 0.4em; }

/* Screen-reader-only utility (used by theme toggle's tt-label). */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap;
  border: 0;
}

/* ============================================================
   Section ornament — typographic § divider, per design rationale.
   Renders as <hr class="ornament">; ::before paints the glyph and
   the hr's default rule is hidden. Symmetric padding keeps it on
   the typographic baseline regardless of context.
   ============================================================ */
hr.ornament {
  border: 0;
  height: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: var(--s-8) auto;
  color: var(--fg-subtle);
  font-family: var(--font-serif);
  font-size: 1.25rem;
  letter-spacing: 0.6em;
  position: relative;
  max-width: 8rem;
}
hr.ornament::before { content: "§"; }
[data-ornament="asterism"] hr.ornament::before { content: "✻"; }
[data-ornament="pilcrow"]  hr.ornament::before { content: "¶"; }

/* Footer ornament — § sits just above the foot-inner row, with a hairline
   rule beneath it for typographic chrome. */
.foot-ornament {
  text-align: center;
  font-family: var(--font-serif);
  font-size: 1.05rem;
  color: var(--fg-subtle);
  letter-spacing: 0.6em;
  padding-top: var(--s-6);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--s-5);
}

/* ============================================================
   Topbar icons — search anchor and theme-toggle button.
   ============================================================ */
.nav-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  color: var(--fg-muted);
  border-radius: var(--r-1);
  transition: color var(--motion) var(--ease), background var(--motion) var(--ease);
}
.nav-icon:hover { color: var(--accent); background: var(--accent-bg); }
.nav-icon[aria-current="page"] { color: var(--accent); }

/* Theme toggle now contains two icons; CSS shows whichever matches the
   active theme. The sun is visible in light mode (clicking switches to
   dark), the moon in dark mode (clicking switches to light). */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-1);
  color: var(--fg-muted);
  background: transparent;
  cursor: pointer;
  transition: color var(--motion) var(--ease), border-color var(--motion) var(--ease), background var(--motion) var(--ease), transform var(--motion) var(--ease);
}
.theme-toggle:hover { color: var(--accent); border-color: var(--accent-muted); background: var(--accent-bg); }
.theme-toggle .tt-icon { display: none; }
:root:not([data-theme="dark"]) .theme-toggle .tt-icon-sun  { display: block; }
[data-theme="dark"]            .theme-toggle .tt-icon-moon { display: block; }
.theme-toggle:active .tt-icon { transform: rotate(15deg); }

@media (prefers-reduced-motion: reduce) {
  .theme-toggle, .theme-toggle .tt-icon { transition: none; transform: none; }
}

/* ============================================================
   Mobile menu (≤640px). The hamburger toggles aria-expanded on the
   nav; CSS reveals the panel sliding down underneath the topbar.
   ============================================================ */
.nav-toggle {
  display: none;
  margin-left: auto;
  width: 36px; height: 36px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-1);
  color: var(--fg);
  background: transparent;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  transition: color var(--motion) var(--ease), border-color var(--motion) var(--ease), background var(--motion) var(--ease);
}
.nav-toggle:hover { color: var(--accent); border-color: var(--accent-muted); }

@media (max-width: 40em) {
  .nav-toggle { display: inline-flex; }

  .topbar-inner { gap: var(--s-3); }

  /* Hide nav by default; reveal as a stacked panel when expanded. */
  .nav#primary-nav {
    display: none;
    width: 100%;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin-left: 0;
    margin-top: var(--s-3);
    padding-top: var(--s-3);
    border-top: 1px solid var(--rule);
  }
  .nav#primary-nav[data-open="true"] { display: flex; }

  .nav#primary-nav > a {
    padding: var(--s-3) var(--s-2);
    border-bottom: 1px solid var(--rule);
    font-size: var(--fs-body);
  }
  .nav#primary-nav > a:last-of-type { border-bottom: 0; }

  /* In the panel, the search and theme-toggle icons sit on a single row. */
  .nav#primary-nav > .nav-icon,
  .nav#primary-nav > .theme-toggle {
    display: inline-flex;
    margin-top: var(--s-3);
  }
  .nav#primary-nav > .theme-toggle { margin-left: var(--s-3); }
}

/* ============================================================
   Reading progress — fixed thin bar at the very top of the viewport.
   Width is controlled by --reading-progress (0–1), updated by
   site.js on scroll. CSS handles the easing.
   ============================================================ */
.reading-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 2px;
  z-index: 50;
  pointer-events: none;
  background: transparent;
}
.reading-progress-fill {
  height: 100%;
  width: calc(var(--reading-progress, 0) * 100%);
  background: var(--accent);
  transition: width 80ms linear;
}
@media (prefers-reduced-motion: reduce) {
  .reading-progress-fill { transition: none; }
}

/* ============================================================
   Post TOC — site.js builds an <ol> of anchored h2/h3 inside
   .post-toc and the existing .article grid puts it in column 2
   (the sidenote gutter). Hidden under 64em via the existing
   .article media query.
   ============================================================ */
.post-toc {
  /* Inherits position from .sidenote (article col 2). */
  position: sticky;
  top: var(--s-6);
  align-self: start;
  margin-top: var(--s-6);
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  max-height: calc(100vh - var(--s-7));
  overflow-y: auto;
}
.post-toc[hidden] { display: none; }
.post-toc .post-toc-label {
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--fg-subtle);
  margin-bottom: var(--s-2);
  font-size: 0.72rem;
  font-weight: 600;
}
.post-toc ol {
  list-style: none;
  padding: 0;
  margin: 0;
  border-left: 1px solid var(--rule);
}
.post-toc li { padding: 0; }
.post-toc li.is-h3 { padding-left: var(--s-3); }
.post-toc a {
  display: block;
  padding: 0.25rem var(--s-3);
  color: var(--fg-muted);
  text-decoration: none;
  border-left: 2px solid transparent;
  margin-left: -1px;
  transition: color var(--motion) var(--ease), border-color var(--motion) var(--ease);
  line-height: 1.35;
}
.post-toc a:hover { color: var(--accent); }
.post-toc a.is-active {
  color: var(--accent);
  border-left-color: var(--accent);
  font-weight: 500;
}

/* ============================================================
   Contact form — subtle inset panel so the form reads as a
   separate object on the page rather than floating in the column.
   Light: warm bg-2 with a hairline. Dark: same idea, just darker.
   ============================================================ */
.form-panel {
  background: var(--bg-2);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  padding: var(--s-5) var(--s-5) var(--s-4);
}
@media (min-width: 40em) {
  .form-panel { padding: var(--s-6) var(--s-6) var(--s-5); }
}
.form-panel .field:first-child { margin-top: 0; }
.form-panel .input:focus,
.form-panel .textarea:focus {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
  border-color: var(--accent);
}

/* ============================================================
   Code-block — slightly raised contrast in dark mode (the default
   --code-bg is very close to --bg in dark; nudge it).
   ============================================================ */
[data-theme="dark"] .codeblock {
  background: #1a1612;
  border-color: #322b22;
}
[data-theme="dark"] .codeblock-bar { background: #211c16; border-color: #322b22; }
[data-theme="dark"] :not(pre) > code { background: #1f1a14; border-color: #322b22; }

/* ============================================================
   Link micro-interaction — body links nudge 2px on hover. Skipped
   for nav, headings, code, ToC, pager, anchor links, foot links
   — they have their own hover treatments.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  article a:not(.anchor-link):not(.next):not(.plain) {
    transition: color var(--motion) var(--ease), text-decoration-color var(--motion) var(--ease);
  }
  /* Subtle 1px translate on body anchors. Avoid jitter on long
     wrapping anchors by limiting to inline spans. */
  article p > a:hover,
  article li > a:hover {
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
  }
}

/* ============================================================
   Stronger tag chip — refine the existing aria-pressed / .is-active
   state so the active tag really pops in dark + light.
   ============================================================ */
.tag[aria-pressed="true"], .tag.is-active {
  color: var(--bg);
  background: var(--accent);
  border-color: var(--accent);
  font-weight: 500;
}
[data-theme="dark"] .tag[aria-pressed="true"],
[data-theme="dark"] .tag.is-active {
  color: var(--bg);
  background: var(--accent);
  border-color: var(--accent);
}

/* ============================================================
   Video embed — responsive 16:9 wrapper for the YouTube iframe
   that Markdown::render injects from the @[youtube](URL)
   shortcode. The iframe itself is created server-side; this
   block just keeps it responsive without crowding the article.
   ============================================================ */
figure.video-embed {
  position: relative;
  width: 100%;
  margin: var(--s-6) 0;
  background: var(--bg-sunken);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  overflow: hidden;
  aspect-ratio: 16 / 9;
}
figure.video-embed > iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* ============================================================
   EasyMDE editor — themed to match the notebook palette so the
   admin editor doesn't feel bolted on. Loaded only on edit
   pages (admin/base.twig conditionally includes the vendor
   stylesheet via `needs_editor`).
   ============================================================ */
.EasyMDEContainer {
  background: var(--bg);
  font-family: var(--font-serif);
  font-size: var(--fs-body);
}
.EasyMDEContainer .CodeMirror {
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 0 0 var(--r-2) var(--r-2);
  font-family: var(--font-mono);
  font-size: var(--fs-code);
  line-height: 1.6;
  padding: var(--s-2) var(--s-3);
  min-height: 26rem;
}
.EasyMDEContainer .CodeMirror-cursor { border-left-color: var(--accent); }
.EasyMDEContainer .CodeMirror-selected { background: var(--selection-bg); }
.EasyMDEContainer .editor-toolbar {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-2) var(--r-2) 0 0;
  border-bottom: 0;
}
.EasyMDEContainer .editor-toolbar button {
  color: var(--fg-muted);
  border-radius: var(--r-1);
}
.EasyMDEContainer .editor-toolbar button:hover,
.EasyMDEContainer .editor-toolbar button.active {
  color: var(--accent);
  background: var(--accent-bg);
  border-color: var(--accent-muted);
}
.EasyMDEContainer .editor-toolbar i.separator { border-left-color: var(--rule); }
.EasyMDEContainer .editor-statusbar {
  color: var(--fg-subtle);
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  padding-inline: var(--s-2);
}
.EasyMDEContainer .editor-preview,
.EasyMDEContainer .editor-preview-side {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-serif);
  font-size: var(--fs-body);
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--border);
  border-left: 0;
}
.EasyMDEContainer .editor-preview h1,
.EasyMDEContainer .editor-preview h2,
.EasyMDEContainer .editor-preview h3 {
  font-family: var(--font-serif);
  margin-top: var(--s-5);
}
.EasyMDEContainer .editor-preview pre,
.EasyMDEContainer .editor-preview code {
  font-family: var(--font-mono);
  background: var(--code-bg);
  color: var(--code-fg);
}
.EasyMDEContainer .editor-preview pre { padding: var(--s-3); border-radius: var(--r-2); }
[data-theme="dark"] .EasyMDEContainer .editor-toolbar { background: var(--bg-2); }
[data-theme="dark"] .EasyMDEContainer .CodeMirror,
[data-theme="dark"] .EasyMDEContainer .editor-preview,
[data-theme="dark"] .EasyMDEContainer .editor-preview-side { background: var(--bg); }

/* ============================================================
   /admin/uploads — dropzone with preview, library thumbnails.
   ============================================================ */
.dropzone {
  border: 2px dashed var(--border-strong);
  border-radius: var(--r-2);
  padding: var(--s-6) var(--s-5);
  background: var(--bg-2);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--motion) var(--ease), background var(--motion) var(--ease);
  margin-block: var(--s-4);
}
.dropzone:hover, .dropzone:focus-visible { border-color: var(--accent-muted); }
.dropzone.is-dragover { border-color: var(--accent); background: var(--accent-bg); }
.dropzone-icon { color: var(--fg-subtle); margin-inline: auto; line-height: 1; }
.dropzone-prompt { font-family: var(--font-sans); margin-top: var(--s-3); }
.dropzone-pick {
  appearance: none; background: none; border: 0; padding: 0;
  color: var(--accent); cursor: pointer; font: inherit;
  text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.dropzone-pick:hover { color: var(--accent-hover); }

.dropzone-preview {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--s-4);
  align-items: center;
  text-align: left;
}
.dropzone-thumb {
  width: 80px; height: 80px;
  object-fit: cover;
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--bg);
}
.dropzone-meta { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
.dropzone-meta strong { font-family: var(--font-sans); word-break: break-all; }
.dropzone-meta .muted { font-family: var(--font-mono); font-size: var(--fs-caption); }
.dropzone.has-file { background: var(--bg); border-style: solid; border-color: var(--rule); cursor: default; }

/* Library thumbnail in the uploads table. */
.upload-thumb {
  max-width: 80px; max-height: 60px;
  border: 1px solid var(--border);
  border-radius: var(--r-1);
  background: var(--bg-2);
  display: block;
}

/* ===== Admin nav: unread-messages badge ===== */
.nav-badge {
  display: inline-block;
  min-width: 1.25em;
  padding: 0 0.4em;
  margin-left: 0.35em;
  font-family: var(--font-mono);
  font-size: 0.72em;
  font-weight: 600;
  line-height: 1.5;
  color: #fff;
  background: var(--accent, #c2410c);
  border-radius: 999px;
  text-align: center;
  vertical-align: middle;
}
.nav-badge:empty { display: none; }

