/* =========================================================================
   Portfolio — "Lamplit engineering journal"
   Warm dark theme (default) + warm light theme via html.light
   Bricolage Grotesque (display) · Source Serif 4 (body)
   · Space Mono (labels) · single amber accent · inverted amber close
   ========================================================================= */

/* =========================================================================
   Self-hosted fonts
   Served from this origin instead of fonts.googleapis.com: one fewer
   third-party on the critical render path, two fewer DNS+TLS handshakes
   before first paint, and no visitor IP handed to Google on every page view
   — which sat oddly next to the deliberate /24-and-/48 IP masking in
   core/models.py. It also lets the CSP say font-src 'self' (ADR 0010).

   url() paths are RELATIVE on purpose: collectstatic's
   ManifestStaticFilesStorage rewrites url() references to the content-hashed
   filenames, and it can only do that for relative URLs it can resolve.

   Subsetted to Latin + Latin-Ext — exactly the ranges Google served, so no
   visitor loses coverage — and the variable faces are clamped to the weight
   range this stylesheet actually uses. Regenerate with fonttools; see
   readme.md §4.6.

   font-display: swap so text paints immediately in the fallback face and
   reflows, rather than being invisible while the font downloads.
   ========================================================================= */

/* Display — headings. CSS uses 600/700/800; the width axis is unused and was
   pinned away. */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("../fonts/bricolage-grotesque-var.f3891c98de61.woff2") format("woff2");
  font-weight: 600 800;
  font-style: normal;
  font-display: swap;
}

/* Body serif — 400 running text, 600 in-prose headings, 700 for <strong>. */
@font-face {
  font-family: "Source Serif 4";
  src: url("../fonts/source-serif-4-var.81b6c43f8fcc.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* Real italic, not a synthetic slant — .prose blockquote depends on it. */
@font-face {
  font-family: "Source Serif 4";
  src: url("../fonts/source-serif-4-italic-var.cf811d6ec3dc.woff2") format("woff2");
  font-weight: 400 700;
  font-style: italic;
  font-display: swap;
}

/* Mono — labels, kickers, code. Static faces: Space Mono has no variable cut.
   No italic face is shipped, matching what Google served, so the italic
   comment tokens in .prose .highlight stay synthetically obliqued exactly as
   they are today. Add space-mono-400-italic.woff2 and a matching @font-face
   if that should become a real italic. */
@font-face {
  font-family: "Space Mono";
  src: url("../fonts/space-mono-400.7f69ed338bc4.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Space Mono";
  src: url("../fonts/space-mono-700.dc06c820d87a.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: dark;

  --bg: #141519;
  --bg-1: #1a1c22;
  --bg-2: #22252e;
  --text: #ece6da;
  --text-strong: #fff;
  --text-soft: #a39e92;
  --text-dim: #726e66;
  --line: rgba(236, 230, 218, 0.10);
  --line-2: rgba(236, 230, 218, 0.20);
  --accent: #e7a44b;
  --accent-bright: #f1b566;
  --accent-soft: rgba(231, 164, 75, 0.14);
  --accent-ink: #19120a;
  --danger: #d9564a;
  --danger-bright: #e56d61;
  --danger-ink: #1f0a08;
  --code-fn: #7ec4e0;
  --code-string: #9fd88f;
  --code-number: #f1b566;
  --hero-glow-1: rgba(231, 164, 75, 0.16);
  --hero-glow-2: rgba(231, 164, 75, 0.06);
  --pulse: rgba(231, 164, 75, 0.5);

  --display: "Bricolage Grotesque", system-ui, sans-serif;
  --serif: "Source Serif 4", Georgia, serif;
  --mono: "Space Mono", ui-monospace, monospace;

  --wrap: 1120px;
  --gut: clamp(1.25rem, 4.5vw, 3rem);
  --r: 9px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* --- Light theme — "daylit journal": warm paper, deepened amber ----------
   Same structure, inverted values. The accent is darkened so mono labels
   and links keep AA contrast on the paper background; hover goes *darker*
   (ink saturates on paper, where the dark theme brightened toward light). */
html.light {
  color-scheme: light;

  --bg: #f7f2e7;
  --bg-1: #efe8d8;
  --bg-2: #e6dcc7;
  --text: #26231d;
  --text-strong: #141109;
  --text-soft: #5c564a;
  --text-dim: #8b8474;
  --line: rgba(38, 35, 29, 0.12);
  --line-2: rgba(38, 35, 29, 0.24);
  --accent: #9a5d15;
  --accent-bright: #7e4b0f;
  --accent-soft: rgba(154, 93, 21, 0.12);
  --accent-ink: #fffaf0;
  --danger: #b23a2c;
  --danger-bright: #8f2e22;
  --danger-ink: #fff5f2;
  --code-fn: #1f6e8c;
  --code-string: #3f7a34;
  --code-number: #7e4b0f;
  --hero-glow-1: rgba(196, 128, 43, 0.14);
  --hero-glow-2: rgba(196, 128, 43, 0.05);
  --pulse: rgba(154, 93, 21, 0.4);
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--serif);
  font-size: 1.075rem;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background .3s var(--ease), color .3s var(--ease);
}

::selection {
  background: var(--accent);
  color: var(--accent-ink);
}

h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.02em;
  margin: 0;
}

a {
  color: inherit;
}

img {
  max-width: 100%;
  display: block;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.wrap--narrow {
  max-width: 720px;
}

/* Repository entries carry code blocks and tables that need more breathing
   room than the 720px reading width used by forms and error pages. */
.entry .wrap--narrow {
  max-width: 880px;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  z-index: 100;
  background: var(--accent);
  color: var(--accent-ink);
  padding: .7rem 1.1rem;
  font-family: var(--mono);
  font-size: .85rem;
  border-radius: 0 0 var(--r) 0;
}

.skip-link:focus {
  left: 0;
}

/* --- Eyebrow / mono labels ---------------------------------------------- */
.kicker {
  font-family: var(--mono);
  font-size: .73rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: .7rem;
}

.kicker::before {
  content: "";
  width: 22px;
  height: 2px;
  background: var(--accent);
  display: inline-block;
}

/* --- Header -------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  padding-block: 1.05rem;
  border-bottom: 1px solid transparent;
  transition: background .3s var(--ease), border-color .3s var(--ease), padding .3s var(--ease);
}

.site-header.is-scrolled {
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(12px) saturate(1.2);
  border-bottom-color: var(--line);
  padding-block: .75rem;
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.brand {
  font-family: var(--mono);
  font-weight: 700;
  font-size: .95rem;
  text-decoration: none;
  letter-spacing: -.01em;
  color: var(--text);
}

.brand-mark {
  color: var(--accent);
  margin-right: .1rem;
}

.nav-menu {
  display: flex;
  align-items: center;
  gap: 2rem;
}

.nav-menu a {
  font-family: var(--mono);
  font-size: .82rem;
  letter-spacing: .02em;
  text-decoration: none;
  color: var(--text-soft);
  position: relative;
  transition: color .2s var(--ease);
}

.nav-menu a:not(.nav-cta)::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -5px;
  height: 1.5px;
  width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .28s var(--ease);
}

.nav-menu a:not(.nav-cta):hover {
  color: var(--text);
}

.nav-menu a:not(.nav-cta):hover::after {
  transform: scaleX(1);
}

.nav-menu .nav-cta {
  color: var(--accent);
  border: 1px solid var(--line-2);
  padding: .5rem 1rem;
  border-radius: var(--r);
  transition: border-color .2s var(--ease), background .2s var(--ease);
}

.nav-menu .nav-cta:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.nav-toggle {
  display: none;
  background: none;
  border: 0;
  cursor: pointer;
  width: 2.6rem;
  height: 2.6rem;
  padding: .6rem;
  gap: .4rem;
  flex-direction: column;
  justify-content: center;
}

.nav-toggle span {
  height: 1.5px;
  background: var(--text);
  transition: transform .25s var(--ease), opacity .25s var(--ease);
}

.nav-toggle[aria-expanded="true"] span:first-child {
  transform: translateY(5px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span:last-child {
  transform: translateY(-4.5px) rotate(-45deg);
}

/* --- Theme toggle ---------------------------------------------------------
   Groups the menu + toggle(s) on the right; on mobile the menu drops out of
   flow (position:absolute), leaving theme + hamburger side by side. */
.nav-cluster {
  display: flex;
  align-items: center;
  gap: 1.4rem;
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.3rem;
  height: 2.3rem;
  padding: 0;
  background: none;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  color: var(--text-soft);
  cursor: pointer;
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}

.theme-toggle:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
}

.theme-toggle svg {
  width: 15px;
  height: 15px;
}

/* Dark (default) offers the sun; light offers the moon. */
.theme-toggle .icon-moon,
html.light .theme-toggle .icon-sun {
  display: none;
}

html.light .theme-toggle .icon-moon {
  display: block;
}

/* --- Buttons ------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--mono);
  font-size: .85rem;
  letter-spacing: .01em;
  padding: .85rem 1.5rem;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--r);
  cursor: pointer;
  transition: background .22s var(--ease), color .22s var(--ease), border-color .22s var(--ease), transform .22s var(--ease);
}

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
}

.btn-primary:hover {
  background: var(--accent-bright);
  transform: translateY(-2px);
}

.btn-ghost {
  border-color: var(--line-2);
  color: var(--text);
}

.btn-ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
  transform: translateY(-2px);
}

/* --- Hero ---------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-height: 86vh;
  padding-block: clamp(4rem, 9vw, 7rem);
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(60% 55% at 18% 8%, var(--hero-glow-1), transparent 60%),
    radial-gradient(50% 50% at 92% 100%, var(--hero-glow-2), transparent 70%);
}

.hero .wrap {
  position: relative;
  z-index: 1;
  width: 100%;
}

.hero-kicker {
  flex-wrap: wrap;
  gap: .6rem 1rem;
  color: var(--text-soft);
}

.hero-kicker::before {
  content: none;
}

.hero-kicker .dot {
  color: var(--text-dim);
}

.hero-kicker>span {
  font-family: var(--mono);
  font-size: .8rem;
  letter-spacing: .04em;
}

.hero-kicker .status {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 999px;
  padding: .25rem .8rem;
  letter-spacing: .04em;
}

.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 var(--accent);
  animation: pulse 2.6s infinite;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 var(--pulse);
  }

  70% {
    box-shadow: 0 0 0 7px transparent;
  }

  100% {
    box-shadow: 0 0 0 0 transparent;
  }
}

.hero-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2.6rem, 6.4vw, 5rem);
  letter-spacing: -0.03em;
  max-width: 16ch;
  margin-top: 1.6rem;
  text-wrap: balance;
}

.hero-subtitle {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.3rem, 2.6vw, 1.9rem);
  color: var(--text-soft);
  letter-spacing: -0.01em;
  max-width: 32ch;
  margin-top: .8rem;
  text-wrap: balance;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .9rem;
  margin-top: 2.4rem;
}

.hero-aside {
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--text-soft);
  margin-top: 1.3rem;
}

.hero-aside a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color .2s var(--ease);
}

.hero-aside a:hover {
  border-bottom-color: var(--accent);
}

.focus {
  list-style: none;
  margin: 3rem 0 0;
  padding: 1.5rem 0 0;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: .6rem 1.4rem;
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--text-soft);
  letter-spacing: .02em;
}

.focus li {
  display: inline-flex;
  align-items: center;
}

.focus li::before {
  content: "→";
  color: var(--accent);
  margin-right: .55rem;
}

/* --- Sections (single-column editorial) --------------------------------- */
.section {
  padding-block: clamp(4rem, 9vw, 7rem);
  border-top: 1px solid var(--line);
}

.section--flush {
  border-top: 0;
}

.section-grid {
  display: block;
}

.section-head {
  margin-bottom: 2.8rem;
}

.section-sub {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.5rem, 3.4vw, 2.2rem);
  letter-spacing: -.02em;
  color: var(--text);
  margin-top: 1.1rem;
}

.section-body {
  max-width: 100%;
}

.section-lede {
  font-family: var(--serif);
  color: var(--text-soft);
  font-size: 1.02rem;
  margin-top: 1.1rem;
}

/* --- Prose --------------------------------------------------------------- */
.prose {
  max-width: 100%;
}

.prose p {
  margin: 0 0 1.3rem;
  color: var(--text);
}

/* .prose p:first-child {
  font-size: 1.28rem;
  line-height: 1.6;
  color: #f3eee4;
} */

.prose p:last-child {
  margin-bottom: 0;
}

.prose strong {
  font-weight: 600;
  color: var(--text-strong);
}

.prose a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color .2s var(--ease);
}

.prose a:hover {
  border-bottom-color: var(--accent);
}

.prose blockquote {
  margin: 0 0 1.6rem;
  padding: .2rem 1.3rem;
  border-left: 3px solid var(--accent);
  color: var(--text-dim);
  font-style: italic;
}

/* --- Prose: code blocks (VSCode-preview-style panel) ---------------------
   Inline `code` renders as a small pill; fenced blocks (wrapped by
   markdown's codehilite extension in a div.highlight) get the full panel
   treatment. Syntax-highlight token colors are scoped under .highlight so
   they never bleed into inline code or the rest of the page. */
.prose code {
  font-family: var(--mono);
  font-size: .85em;
  color: var(--accent);
  background: var(--bg-1);
  border: 1px solid var(--line);
  padding: .15em .45em;
  border-radius: 5px;
  word-break: break-word;
}

.prose .highlight {
  margin: 0 0 1.6rem;
}

.prose pre {
  margin: 0 0 1.6rem;
  padding: 1.15rem 1.35rem;
  border-radius: 10px;
  border: 1px solid var(--line-2);
  background: var(--bg-1);
  overflow-x: auto;
  font-family: var(--mono);
  font-size: .85rem;
  line-height: 1.65;
  color: var(--text);
}

.prose .highlight pre {
  margin: 0;
}

.prose pre code {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  border-radius: 0;
  word-break: normal;
}

.prose .highlight .k,
.prose .highlight .kc,
.prose .highlight .kd,
.prose .highlight .kn,
.prose .highlight .kp,
.prose .highlight .kr,
.prose .highlight .kt {
  color: var(--accent);
  font-weight: 600;
}

.prose .highlight .nf,
.prose .highlight .nc,
.prose .highlight .nd,
.prose .highlight .fm,
.prose .highlight .nt,
.prose .highlight .ne {
  color: var(--code-fn);
}

.prose .highlight .nb,
.prose .highlight .bp,
.prose .highlight .nn {
  color: var(--code-fn);
  opacity: .8;
}

.prose .highlight .s,
.prose .highlight .s1,
.prose .highlight .s2,
.prose .highlight .sa,
.prose .highlight .sb,
.prose .highlight .sc,
.prose .highlight .dl,
.prose .highlight .sd,
.prose .highlight .se,
.prose .highlight .sh,
.prose .highlight .si,
.prose .highlight .sx,
.prose .highlight .sr,
.prose .highlight .ss {
  color: var(--code-string);
}

.prose .highlight .m,
.prose .highlight .mb,
.prose .highlight .mf,
.prose .highlight .mh,
.prose .highlight .mi,
.prose .highlight .mo,
.prose .highlight .il {
  color: var(--code-number);
}

.prose .highlight .c,
.prose .highlight .c1,
.prose .highlight .cm,
.prose .highlight .cp,
.prose .highlight .cpf,
.prose .highlight .ch,
.prose .highlight .cs {
  color: var(--text-dim);
  font-style: italic;
}

.prose .highlight .o,
.prose .highlight .ow,
.prose .highlight .p,
.prose .highlight .na {
  color: var(--text-soft);
}

.prose .highlight .err {
  color: var(--danger);
}

/* --- Prose: tables ---------------------------------------------------
   python-markdown's "tables" extension emits a bare <table> with no
   wrapper, so the horizontal-scroll fallback lives on the table itself:
   display:block keeps overflow-x working while tr/td keep their normal
   table layout. */
.prose table {
  display: block;
  width: 100%;
  margin: 0 0 1.6rem;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: .92rem;
  line-height: 1.55;
}

.prose th,
.prose td {
  padding: .65rem .9rem;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}

.prose thead th {
  font-family: var(--mono);
  font-size: .73rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--bg-1);
  border-bottom: 1px solid var(--line-2);
  white-space: nowrap;
}

.prose tbody tr:nth-child(even) {
  background: var(--bg-1);
}

.prose tbody tr:last-child td {
  border-bottom: 0;
}

/* --- Prose: lists (flush on small screens) --------------------------------
   Markdown ul/ol inherit the browser's ~40px default indent. On narrow
   viewports that eats a big share of the content width, so below 760px it's
   cut to just enough room for the marker. list-style-position stays outside
   (not inside) because nested lists make python-markdown wrap li content in
   <p> tags ("loose" lists) — with inside positioning the marker then lands
   on its own line above the paragraph instead of beside it. Desktop keeps
   the native indent. */
@media (max-width: 760px) {
  .prose ul,
  .prose ol {
    padding-left: 1.2rem;
  }
}

/* --- Certifications ------------------------------------------------------ */
.cert-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.cert {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.4rem;
  padding: 1.4rem 0;
  border-top: 1px solid var(--line);
}

.cert:first-child {
  border-top: 0;
  padding-top: 0;
}

.cert-title {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.2rem;
  letter-spacing: -.01em;
}

.cert-meta {
  margin: .4rem 0 0;
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--text-soft);
  letter-spacing: .02em;
}

.cert-link {
  font-family: var(--mono);
  font-size: .78rem;
  text-decoration: none;
  color: var(--accent);
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: border-color .2s var(--ease);
}

.cert-link:hover {
  border-bottom-color: var(--accent);
}

/* --- Engagement types (Work with me page) --------------------------------- */
.engagement-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.engagement {
  padding: 1.6rem 0;
  border-top: 1px solid var(--line);
}

.engagement:first-child {
  border-top: 0;
  padding-top: 0;
}

.engagement-title {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.2rem;
  letter-spacing: -.01em;
}

.engagement-desc {
  margin: .5rem 0 0;
  color: var(--text-soft);
}

.engagement-list + .btn {
  margin-top: 2rem;
}

/* --- Skills -------------------------------------------------------------- */
.skills {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

.skills-heading {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.5rem, 3.4vw, 2.2rem);
  letter-spacing: -.02em;
  color: var(--text);
  margin-bottom: 1.5rem;
}

.skill-group {
  margin-bottom: 1.7rem;
}

.skill-group:last-child {
  margin-bottom: 0;
}

.skill-category {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 .8rem;
}

.skill-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .55rem;
}

.skill-tag {
  font-family: var(--mono);
  font-size: .8rem;
  letter-spacing: .01em;
  border: 1px solid var(--line-2);
  padding: .4rem .85rem;
  border-radius: 999px;
  color: var(--text);
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}

.skill-tag:hover {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}

/* --- Repository entries -------------------------------------------------- */
.entry-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: .7rem;
}

/* Scoped to the kicker pairing (series_detail.html) rather than adding
   margin-top to .entry-row itself — other pages (details.html) open
   straight with .entry-row, no kicker above it to space away from. */
.kicker + .entry-row {
  margin-top: 1rem;
}

.entry-kind {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid var(--line-2);
  padding: .25rem .7rem;
  border-radius: 999px;
}

/* Muted vs. .entry-kind — track is secondary metadata (which exam this
   touches), category stays the primary/accent badge. */
.entry-track {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-soft);
  border: 1px solid var(--line);
  padding: .25rem .7rem;
  border-radius: 999px;
}

.entry-date {
  font-family: var(--mono);
  font-size: .75rem;
  color: var(--text-dim);
  letter-spacing: .04em;
  font-weight: 700;
}

.entry-views {
  font-family: var(--mono);
  font-size: .75rem;
  color: var(--text-dim);
  letter-spacing: .04em;
}

.entry-summary {
  color: var(--text-soft);
  margin: .7rem 0 0;
}

.tags {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: 1.1rem 0 0;
  padding: 0;
}

.tags li {
  font-family: var(--mono);
  font-size: .72rem;
  color: var(--text-soft);
  background: var(--bg-1);
  border: 1px solid var(--line);
  padding: .25rem .65rem;
  border-radius: 999px;
}

/* --- Repository: compact masthead --------------------------------------- */
/* Quiet header — the entry feed below is the main event, not a hero. */
.repo-head {
  padding-block: clamp(2.4rem, 5vw, 3.5rem) 1.5rem;
}

.repo-title {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -.02em;
  font-size: clamp(1.45rem, 2.8vw, 2.05rem);
  margin-top: .9rem;
  text-wrap: balance;
}

.repo-sub {
  color: var(--text-soft);
  margin-top: .55rem;
  font-size: 1.02rem;
}

/* --- Repository: filter / category bar ---------------------------------- */
.repo-bar {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.repo-bar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8rem 1.4rem;
  padding-block: .85rem;
  flex-wrap: wrap;
}

.repo-count {
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .08em;
  color: var(--text-dim);
  margin: 0;
  white-space: nowrap;
}

/* --- Repository: tag search --------------------------------------------- */
.repo-search {
  display: flex;
  align-items: center;
  gap: .5rem;
}

.repo-search-field {
  display: flex;
  align-items: center;
  gap: .5rem;
  background: var(--bg-1);
  border: 1px solid var(--line-2);
  border-radius: 999px;
  padding: .35rem .85rem;
  transition: border-color .2s var(--ease);
}

.repo-search-field:focus-within {
  border-color: var(--accent);
}

.repo-search-field svg {
  color: var(--text-dim);
  flex: none;
}

.repo-search-field:focus-within svg {
  color: var(--accent);
}

.repo-search input {
  background: none;
  border: 0;
  outline: none;
  color: var(--text);
  font-family: var(--mono);
  font-size: .8rem;
  width: clamp(8rem, 22vw, 13rem);
}

.repo-search input::placeholder {
  color: var(--text-dim);
}

.repo-search input::-webkit-search-cancel-button {
  -webkit-appearance: none;
}

.repo-search-btn {
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--accent-ink);
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  padding: .5rem 1rem;
  cursor: pointer;
  transition: background .2s var(--ease);
}

.repo-search-btn:hover {
  background: var(--accent-bright);
}

.repo-bar-controls {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
}

/* --- Repository: active filter chips ------------------------------------ */
.repo-chips {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: .9rem;
}

.repo-chips .tags {
  margin-top: 0;
}

/* --- Repository: results status line ------------------------------------ */
.repo-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: .2rem;
}

.repo-clear {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono);
  font-size: .76rem;
  color: var(--danger-ink);
  background: var(--danger);
  text-decoration: none;
  white-space: nowrap;
  border: 0;
  border-radius: 999px;
  padding: .4rem .9rem;
  transition: background .2s var(--ease);
}

.repo-clear:hover {
  background: var(--danger-bright);
}

/* --- Pagination ---------------------------------------------------------- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
}

.page-link {
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--text);
  text-decoration: none;
  padding: .55rem .9rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  transition: border-color .2s var(--ease), background .2s var(--ease), color .2s var(--ease);
}

.page-link:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
}

.page-link.is-disabled {
  color: var(--text-dim);
  border-color: var(--line);
  background: transparent;
  pointer-events: none;
}

.page-numbers {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
}

.page-link.is-current {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
  pointer-events: none;
}

@media (max-width: 600px) {
  .repo-bar-inner {
    flex-direction: column;
    align-items: stretch;
  }

  .repo-bar-controls {
    flex-direction: column;
    align-items: stretch;
  }

  .tag-picker-panel {
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
  }

  .repo-search {
    justify-content: space-between;
  }

  .repo-search input {
    width: 100%;
  }

  .repo-search-field {
    flex: 1;
  }
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: .55rem;
  margin: 0;
}

.filter {
  font-family: var(--mono);
  font-size: .78rem;
  text-decoration: none;
  color: var(--text-soft);
  border: 1px solid var(--line-2);
  padding: .4rem .9rem;
  border-radius: 999px;
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}

.filter:hover {
  color: var(--text);
  border-color: var(--text-soft);
}

.filter.is-active {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}

/* --- Repository: tag picklist (dropdown, multi-select) ------------------ */
.tag-picker {
  position: relative;
}

.tag-picker-toggle {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  cursor: pointer;
  user-select: none;
  list-style: none;
}

.tag-picker-toggle::-webkit-details-marker {
  display: none;
}

.tag-picker[open] .tag-picker-toggle {
  color: var(--text);
  border-color: var(--accent);
}

.tag-picker-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 .3rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: .68rem;
}

.tag-picker-chevron {
  transition: transform .2s var(--ease);
}

.tag-picker[open] .tag-picker-chevron {
  transform: rotate(180deg);
}

.tag-picker-panel {
  position: absolute;
  z-index: 60;
  top: calc(100% + .5rem);
  left: 0;
  width: max(15rem, 100%);
  max-width: 20rem;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: 14px;
  padding: .6rem;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.28);
}

.tag-picker-filter {
  display: block;
  width: 100%;
  margin-bottom: .4rem;
  padding: .4rem .55rem;
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--text);
  background: var(--bg-1);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  outline: none;
}

.tag-picker-filter:focus {
  border-color: var(--accent);
}

.tag-picker-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 15rem;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: .1rem;
}

.tag-picker-list li[hidden] {
  display: none;
}

.tag-picker-option {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .4rem .5rem;
  border-radius: 8px;
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--text-soft);
  text-decoration: none;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease);
}

.tag-picker-option:hover {
  background: var(--line);
  color: var(--text);
}

.tag-picker-option.is-active {
  background: var(--accent);
  color: var(--accent-ink);
}

.tag-picker-option input {
  accent-color: var(--accent);
  width: 14px;
  height: 14px;
  flex: none;
}

.tag-picker-empty {
  padding: .4rem .5rem;
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--text-dim);
}

.tag-picker-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .6rem;
  margin-top: .55rem;
  padding-top: .55rem;
  border-top: 1px solid var(--line);
}

/* --- Repository: blog-archive feed -------------------------------------- */
.repo-feed {
  padding-block: clamp(1.25rem, 3vw, 2rem) clamp(4rem, 8vw, 6rem);
}

.post-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.post:first-child {
  border-top: 1px solid var(--line);
}

/* Border (and break-inside) live on .post, not .feed-row, so the row and
   its sibling .part-of chip (see below) are enclosed as one card and can't
   be pulled apart by a print/PDF page break. */
.post {
  border-bottom: 1px solid var(--line);
  break-inside: avoid;
}

/* --- Feed row: shared shell for Post and Series list items ---------------
   One quiet, divider-separated row for both entry types — icon + meta +
   title + summary, identical typography and hover behaviour. The only
   difference between them is the icon glyph and the "Series" corner tag,
   added by _series_card.html. --compact is the same component at the
   smaller scale used in the homepage's two-column module. Named .feed-row
   (not .entry-row) to avoid colliding with the unrelated .entry-row meta
   strip used on the entry/series detail pages. */
.feed-row {
  position: relative;
  display: block;
  padding: clamp(1.5rem, 3vw, 2.1rem) 1.2rem;
  text-decoration: none;
  color: inherit;
  transition: background .2s var(--ease);
}

.feed-row:hover {
  background: var(--bg-1);
}

/* Icon + body live in their own wrapper so the hover nudge is a transform
   (paint-time, after text has already wrapped) rather than growing
   padding-left, which shrinks the available width just enough to tip a
   title that's already brushing the edge onto a second line mid-hover. */
.feed-row-inner {
  display: flex;
  gap: .9rem;
  transition: transform .25s var(--ease);
}

.feed-row:hover .feed-row-inner {
  transform: translateX(.5rem);
}

.feed-row-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-top: .3rem;
  color: var(--text-dim);
  transition: color .2s var(--ease);
}

.feed-row:hover .feed-row-icon {
  color: var(--accent);
}

.feed-row-body {
  min-width: 0;
}

.feed-row-meta {
  display: block;
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.feed-row-title {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -.02em;
  font-size: clamp(1.35rem, 2.3vw, 1.85rem);
  margin: .5rem 0 0;
  color: var(--text);
  transition: color .2s var(--ease);
}

.feed-row-title::after {
  content: "→";
  display: inline-block;
  margin-left: .5rem;
  color: var(--accent);
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity .25s var(--ease), transform .25s var(--ease);
}

.feed-row:hover .feed-row-title {
  color: var(--accent);
}

.feed-row:hover .feed-row-title::after {
  opacity: 1;
  transform: translateX(0);
}

.feed-row-body .entry-summary {
  margin-top: .65rem;
}

.feed-row-body .tags {
  margin-top: .95rem;
}

/* Series-only marker — a plain type label, not a fact, so it sits apart
   from .feed-row-meta rather than inside it. */
.feed-row-tag {
  position: absolute;
  top: clamp(1.5rem, 3vw, 2.1rem);
  right: 1.2rem;
  font-family: var(--mono);
  font-size: .64rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: .22rem .6rem;
}

/* The tag is absolutely positioned (out of flow) and sits at the same
   vertical position as .feed-row-meta's first line, so on narrow rows
   nothing stops long, piped meta text from running underneath it. Reserve
   space equal to the tag's own footprint so the meta text wraps clear of
   it instead. */
.feed-row-tag ~ .feed-row-inner .feed-row-meta {
  padding-right: 4rem;
}

/* --- Feed row: compact (homepage two-column module) ----------------------- */
.feed-row--compact {
  padding: 1rem 0;
}

.feed-row--compact .feed-row-icon {
  width: 17px;
  height: 17px;
}

.feed-row--compact .feed-row-title {
  font-size: 1.05rem;
  letter-spacing: -.01em;
}

.feed-row--compact .feed-row-body .entry-summary {
  font-size: .88rem;
  margin-top: .45rem;
}

.feed-row--compact .feed-row-tag {
  top: 1rem;
  right: 0;
}

/* Clickable tags (detail page) — link to the filtered repository list. */
.tags--links li {
  padding: 0;
  border: 0;
  background: none;
}

.tags--links a {
  display: inline-block;
  text-decoration: none;
  font-family: var(--mono);
  font-size: .72rem;
  color: var(--text-soft);
  background: var(--bg-1);
  border: 1px solid var(--line);
  padding: .25rem .65rem;
  border-radius: 999px;
  transition: color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease);
}

.tags--links a:hover {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

@media (max-width: 640px) {
  .feed-row {
    padding-left: 1rem;
  }
}

/* --- Entry detail -------------------------------------------------------- */
.entry {
  padding-block: clamp(3rem, 7vw, 5rem) clamp(4rem, 9vw, 7rem);
}

/* --- Breadcrumbs ----------------------------------------------------------
   Replaces the old .back "← Repository" link everywhere it appeared —
   gives the same "step back" affordance plus the full path, in the same
   space. Prev/next series nav (.series-inline, .series-continue) and the
   .entry-footer buttons are a different job (sequential flow / end-of-
   content actions) and stay separate from this. */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4em;
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--text-dim);
  margin: 0 0 2.4rem;
}

.crumbs a {
  color: var(--text-soft);
  text-decoration: none;
  transition: color .2s var(--ease);
}

.crumbs a:hover {
  color: var(--accent);
}

.crumbs .sep {
  color: var(--text-dim);
  opacity: .6;
}

.crumbs .current {
  color: var(--text);
}

.entry-header {
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 2.8rem;
}

.entry-headline {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -.03em;
  font-size: clamp(2rem, 5vw, 3.1rem);
  margin-top: 1.1rem;
  text-wrap: balance;
}

/* Series detail's track row sits after the headline (unlike Post detail's,
   which sits before it) — the adjacent-sibling combinator scopes this
   top margin to only that placement. */
.entry-headline + .entry-row {
  margin-top: 1.1rem;
}

.entry-lede {
  font-size: 1.3rem;
  color: var(--text-soft);
  margin: 1.2rem 0 0;
  line-height: 1.55;
}

.entry-body p {
  font-size: 1.13rem;
  line-height: 1.8;
}

.entry-body p:first-child {
  font-size: 1.13rem;
  color: var(--text);
}

.entry-footer {
  margin-top: 3.5rem;
  padding-top: 2rem;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem;
  flex-wrap: wrap;
}

.entry-footer .kicker {
  color: var(--text-dim);
}

.entry-footer .kicker::before {
  background: var(--text-dim);
}

/* --- Repository: related entries (detail page) --------------------------- */
.related-entries {
  margin-top: 3.5rem;
}

.related-entries .kicker {
  margin-bottom: 1.2rem;
}

.related-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.1rem;
}

.related-card a {
  display: flex;
  flex-direction: column;
  height: 100%;
  text-decoration: none;
  color: inherit;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 1.2rem;
  transition: border-color .2s var(--ease), transform .2s var(--ease);
}

.related-card a:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
}

.related-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
}

.related-title {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -.01em;
  font-size: 1.05rem;
  margin: .7rem 0 0;
  color: var(--text);
}

.related-card .entry-summary {
  font-size: .88rem;
  margin-top: .5rem;
  flex: 1;
}

.related-meta {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin-top: 1rem;
}

@media (max-width: 720px) {
  .related-grid {
    grid-template-columns: 1fr;
  }
}

/* --- Series hub: track filter -------------------------------------------
   A flat, always-visible pill row, not the repository list's <details>
   dropdown — one facet doesn't need that machinery. */
.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: 1.6rem;
}

.filter-row .pill {
  font-family: var(--mono);
  font-size: .74rem;
  color: var(--text-soft);
  background: var(--bg-1);
  border: 1px solid var(--line);
  padding: .4rem .9rem;
  border-radius: 999px;
  text-decoration: none;
  transition: color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease);
}

.filter-row .pill:hover {
  border-color: var(--accent);
  color: var(--text);
}

.filter-row .pill.active {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: transparent;
  font-weight: 700;
}

.tags li.tags-more {
  color: var(--text-dim);
  background: none;
  border-color: transparent;
}

/* --- Homepage: Recent posts / Series two-column module ------------------- */
.home-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.2rem;
}

@media (max-width: 760px) {
  .home-cols {
    grid-template-columns: 1fr;
    gap: 2.6rem;
  }
}

.home-col-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.1rem;
}

.home-col-head h3 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1rem;
  color: var(--text-strong);
  margin: 0;
}

.home-col-head a {
  font-family: var(--mono);
  font-size: .76rem;
  color: var(--accent);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: border-color .2s var(--ease);
}

.home-col-head a:hover {
  border-bottom-color: var(--accent);
}

.home-col-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.home-col-list li:first-child .feed-row--compact {
  border-top: 1px solid var(--line);
}

/* "Part of <series>" chip on a post row in the flat list. A sibling of
   .feed-row, not nested inside it — the whole row is already one <a>,
   and a link inside a link is invalid HTML. The enclosing .post carries
   the card border instead of .feed-row, so this still reads as part of
   the same card. Accent-tinted rather than the muted .entry-track pill,
   so it reads as structural, not a facet. */
.part-of {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  font-family: var(--mono);
  font-size: .72rem;
  color: var(--accent-bright);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  padding: .3em .8em;
  border-radius: 999px;
  text-decoration: none;
  margin: .9rem 0 1.3rem 1.2rem;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}

.part-of:hover {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}

/* --- Series detail: table of contents ------------------------------------ */
.series-toc {
  margin-top: 3.5rem;
}

.series-toc .kicker {
  margin-bottom: 1.2rem;
}

.series-toc-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}

.series-toc-item a {
  display: grid;
  grid-template-columns: 2.6rem 1fr;
  gap: 1rem;
  align-items: baseline;
  text-decoration: none;
  color: inherit;
  padding: 1.2rem 0;
  border-bottom: 1px solid var(--line);
  transition: transform .25s var(--ease), color .2s var(--ease);
}

.series-toc-item a:hover {
  transform: translateX(.6rem);
  color: var(--accent);
}

.series-toc-index {
  font-family: var(--mono);
  font-size: .85rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.series-toc-body {
  display: flex;
  flex-direction: column;
  gap: .4rem;
}

.series-toc-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--text);
}

.series-toc-item a:hover .series-toc-title {
  color: var(--accent);
}

.series-toc-item .entry-summary {
  font-size: .9rem;
  margin: 0;
}

/* series-toc-body is already a flex column with its own gap, so the tag
   list's default top margin would double up the spacing. */
.series-toc-item .tags {
  margin-top: 0;
}

.series-toc-item.is-locked .series-toc-title {
  color: var(--text-soft);
}

.lock-badge {
  font-size: .8em;
  margin-left: .3em;
  opacity: .8;
}

@media (max-width: 640px) {
  .series-toc-item a {
    grid-template-columns: 1.8rem 1fr;
  }
}

/* --- Post detail: series inline nav (top) + continue block (bottom) -----
   One quiet mono line above the body, folded into the same breadcrumb/
   kicker vocabulary rather than a boxed banner. .series-continue is its
   counterpart just before .entry-footer, so a reader who finishes the
   post has somewhere to go without scrolling back up. */
.series-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .5rem;
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--text-dim);
  padding-bottom: 1rem;
  margin-bottom: 2rem;
  border-bottom: 1px solid var(--line);
}

.series-inline-link {
  color: var(--accent);
  text-decoration: none;
}

.series-inline-link:hover {
  text-decoration: underline;
}

.series-inline-sep {
  color: var(--text-dim);
}

.series-inline-arrows {
  margin-left: auto;
  display: flex;
  gap: .9rem;
}

.series-inline-arrows a {
  color: var(--text-soft);
  text-decoration: none;
  transition: color .2s var(--ease);
}

.series-inline-arrows a:hover {
  color: var(--accent);
}

.series-continue {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  margin-top: 2.6rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--line);
  font-size: .92rem;
}

.series-continue a {
  text-decoration: none;
  color: var(--text-soft);
  transition: color .2s var(--ease);
}

.series-continue a:hover {
  color: var(--accent);
}

.series-continue-next {
  margin-left: auto;
  text-align: right;
  color: var(--text);
  font-weight: 600;
  font-family: var(--display);
}

.series-continue-prev {
  font-family: var(--display);
  font-weight: 600;
  color: var(--text-soft);
}

.series-continue-label {
  display: block;
  font-family: var(--mono);
  font-weight: 400;
  font-size: .64rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: .3rem;
}

/* --- Locked teaser (GATED post) ------------------------------------------- */
.entry-body--locked {
  padding: 1.6rem;
  background: var(--bg-1);
  border: 1px dashed var(--line-2);
  border-radius: var(--r);
}

.locked-cta {
  display: flex;
  align-items: center;
  gap: .8rem;
  margin-top: 1.2rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--line);
  color: var(--text-soft);
  font-size: .92rem;
}

.locked-cta p {
  margin: 0;
}

.locked-cta .lock-badge {
  font-size: 1.3rem;
  opacity: 1;
}

/* --- Contact (inverted amber panel — the signature close) ---------------- */
.contact {
  background: var(--accent);
  color: var(--accent-ink);
  border-top: 0;
  position: relative;
  overflow: hidden;
}

.contact::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(45% 70% at 88% 110%, rgba(0, 0, 0, 0.10), transparent 60%);
}

.contact .wrap {
  position: relative;
  z-index: 1;
}

.contact .kicker {
  color: var(--accent-ink);
  opacity: .7;
}

.contact .kicker::before {
  background: var(--accent-ink);
}

.contact-title {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -.03em;
  font-size: clamp(2rem, 5.2vw, 3.4rem);
  max-width: 17ch;
  margin-top: 1.3rem;
  text-wrap: balance;
}

.contact-sub {
  color: var(--accent-ink);
  opacity: .82;
  max-width: 52ch;
  margin-top: 1.1rem;
  font-size: 1.15rem;
}

.contact-sub a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: .2em;
  opacity: 1;
}

.contact-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.4rem 2rem;
  margin-top: 2.6rem;
}

.contact .btn-primary {
  background: var(--bg);
  color: var(--text);
}

.contact .btn-primary:hover {
  background: var(--bg-2);
  transform: translateY(-2px);
}

/* --- Socials ------------------------------------------------------------- */
.socials {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem;
  margin: 0;
  padding: 0;
}

.socials a {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  text-decoration: none;
  font-family: var(--mono);
  font-size: .82rem;
  color: inherit;
  opacity: .85;
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}

.socials a:hover {
  opacity: 1;
  transform: translateY(-1px);
}

.contact .socials a {
  color: var(--accent-ink);
}

/* --- Error pages (404 / 403 / 400) ---------------------------------------- */
.error-page {
  display: flex;
  align-items: center;
  min-height: 60vh;
  padding-block: clamp(4rem, 9vw, 7rem);
}

.error-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  letter-spacing: -0.03em;
  margin-top: 1.2rem;
}

.error-text {
  font-family: var(--serif);
  color: var(--text-soft);
  font-size: 1.05rem;
  margin-top: .9rem;
}

.error-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .9rem;
  margin-top: 2rem;
}

/* --- Contact page (standalone form, distinct from the homepage's inverted
   amber .contact panel) ----------------------------------------------------- */
.contact-page {
  padding-block: clamp(4rem, 9vw, 7rem);
}

.contact-page-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  letter-spacing: -0.03em;
  margin-top: 1.2rem;
}

.contact-page-sub {
  font-family: var(--serif);
  color: var(--text-soft);
  font-size: 1.05rem;
  margin-top: .9rem;
}

.contact-page-sub a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color .2s var(--ease);
}

.contact-page-sub a:hover {
  border-bottom-color: var(--accent);
}

/* --- Standalone page header (Work with me, and any future narrow page) --- */
.page-header {
  padding-block: clamp(4rem, 9vw, 7rem);
}

.page-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  letter-spacing: -0.03em;
  margin-top: 1.2rem;
}

.page-sub {
  font-family: var(--serif);
  color: var(--text-soft);
  font-size: 1.05rem;
  margin-top: .9rem;
}

/* --- Alerts (Django messages) ---------------------------------------------- */
.alert {
  font-family: var(--mono);
  font-size: .85rem;
  padding: .85rem 1.1rem;
  border-radius: var(--r);
  border: 1px solid var(--line-2);
  margin-top: 2rem;
}

.alert-success {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-bright);
}

.alert-error {
  background: rgba(217, 86, 74, 0.12);
  border-color: var(--danger);
  color: var(--danger-bright);
}

/* --- Form -------------------------------------------------------------- */
.form {
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
  margin-top: 2.4rem;
}

.field label {
  display: block;
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-soft);
  margin-bottom: .5rem;
}

.field input[type="text"],
.field input[type="email"],
.field textarea {
  width: 100%;
  background: var(--bg-1);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  color: var(--text);
  font-family: var(--serif);
  font-size: 1rem;
  padding: .8rem 1rem;
  transition: border-color .2s var(--ease);
}

.field input[type="text"]:focus,
.field input[type="email"]:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
}

.field textarea {
  resize: vertical;
  min-height: 8rem;
}

.field-error {
  color: var(--danger-bright);
  font-family: var(--mono);
  font-size: .78rem;
  margin-top: .5rem;
}

.field-actions {
  margin-top: .6rem;
}

.hp-wrap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- Footer -------------------------------------------------------------- */
.site-footer {
  padding-block: 3.5rem;
  border-top: 1px solid var(--line);
}

.footer-grid {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.footer-id .kicker {
  color: var(--text);
}

.footer-id .kicker::before {
  background: var(--accent);
}

.footer-id p {
  margin: .6rem 0 0;
  color: var(--text-soft);
  font-size: .92rem;
}

.footer-note {
  width: 100%;
  margin: 1.4rem 0 0;
  padding-top: 1.6rem;
  border-top: 1px solid var(--line);
  font-family: var(--mono);
  font-size: .74rem;
  color: var(--text-dim);
  letter-spacing: .03em;
}

.empty {
  color: var(--text-soft);
}

.empty code {
  font-family: var(--mono);
  font-size: .85em;
  background: var(--bg-1);
  border: 1px solid var(--line);
  padding: .12rem .45rem;
  border-radius: 5px;
}

/* --- Focus visibility ---------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --- Motion: load + scroll reveal --------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .hero .wrap>* {
    opacity: 0;
    animation: rise .8s var(--ease) forwards;
  }

  .hero-kicker {
    animation-delay: .05s;
  }

  .hero-title {
    animation-delay: .15s;
  }

  .hero-subtitle {
    animation-delay: .21s;
  }

  .hero-actions {
    animation-delay: .28s;
  }

  .focus {
    animation-delay: .4s;
  }

  @keyframes rise {
    from {
      opacity: 0;
      transform: translateY(18px);
    }

    to {
      opacity: 1;
      transform: none;
    }
  }

  .js .reveal {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity .7s var(--ease), transform .7s var(--ease);
  }

  .js .reveal.is-in {
    opacity: 1;
    transform: none;
  }
}

/* --- Responsive ---------------------------------------------------------- */
@media (max-width: 760px) {
  .nav-toggle {
    display: flex;
  }

  .nav-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: var(--bg-1);
    border-bottom: 1px solid var(--line);
    padding: .5rem var(--gut) 1.4rem;
    max-height: 0;
    overflow: hidden;
    visibility: hidden;
    pointer-events: none;
    transition: max-height .3s var(--ease), visibility 0s linear .3s;
  }

  .nav-menu.is-open {
    max-height: 24rem;
    visibility: visible;
    pointer-events: auto;
    transition: max-height .3s var(--ease), visibility 0s linear;
  }

  .nav-menu a {
    width: 100%;
    padding: .8rem 0;
  }

  .nav-menu a:not(.nav-cta)::after {
    content: none;
  }

  .nav-menu .nav-cta {
    margin-top: .6rem;
  }

  .cert {
    flex-direction: column;
    gap: .3rem;
  }

  .entry-footer {
    flex-direction: column;
    align-items: flex-start;
  }

  .entry-row {
    flex-wrap: wrap;
    row-gap: .5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  * {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}