*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* ── FONTS ── */
/* Geist (https://github.com/vercel/geist-font) — variable-font face +
   static Regular/Medium fallbacks for browsers without `font-variation-settings`
   support. Body in blog posts uses this face; site chrome (label, mono meta,
   buttons) stays on IBM Plex Mono below. */

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/geist/Geist-Variable.woff2') format('woff2-variations'),
       url('/fonts/geist/Geist-Variable.woff2') format('woff2');
}

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/geist/Geist-Regular.woff2') format('woff2');
}

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/geist/Geist-Medium.woff2') format('woff2');
}

/* ── THEME ── */

:root,
[data-theme="light"] {
  --bg: #fafafa;
  --fg: #000;
  --accent: #1a3a2a;
  --link: #0a6e7a;
  --inverse-fg: #fafafa;
}

[data-theme="dark"] {
  --bg: #0d0d0d;
  --fg: #ededed;
  --accent: #6fbf94;
  --link: #7ed3d8;
  --inverse-fg: #0d0d0d;
}

html {
  font-size: 20px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: 'IBM Plex Mono', monospace;
  font-weight: 400;
  line-height: 1.6;
  overflow-x: hidden;
  transition: background 0.15s ease, color 0.15s ease;
}

/* ── UTILITY ── */

.label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--fg);
}

.rule {
  border: none;
  border-top: 3.5px solid var(--fg);
  margin: 0;
}

/* ── TOPBAR ── */

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--fg);
}

.topbar-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--fg);
  border-bottom: 1px solid transparent;
}

.topbar-brand:hover {
  border-bottom-color: var(--fg);
}

/* hide the label on the homepage — favicon alone is the brand */
.topbar-brand--home .topbar-label {
  display: none;
}

.topbar-mark {
  width: 1.65rem;
  height: 1.65rem;
  display: block;
  /* gentle continuous animation: subtle rotation + breathing glow */
  animation: scribble-spin 18s linear infinite, scribble-pulse 4.5s ease-in-out infinite;
  transform-origin: 50% 50%;
  flex: 0 0 auto;
}

/* favicon invert for dark mode — the source PNG is black-on-white */
[data-theme="dark"] .topbar-mark,
[data-theme="dark"] img[src$="favicon.png"] {
  filter: invert(1);
}

/* post-body divider image: a wide horizontal rule. The source PNG is 2172x724
   with the actual visible mark at 1918x122 (~15.7:1) inside a transparent
   canvas — but the browser reads the canvas aspect (3:1) and would render
   the divider as a tiny square. Override with `aspect-ratio` so the rendered
   element honors the visible-mark proportions. Sized to sit between 0.55x
   and 1.05x of body line-height: quietly present, never dominant. */
.post-divider {
  display: block;
  width: clamp(220px, 55%, 400px);
  height: auto;
  aspect-ratio: 16 / 1;
  max-width: 100%;
  margin: 2rem auto 2rem 0;
}

[data-theme="dark"] .post-divider {
  filter: invert(1);
}

@keyframes scribble-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@keyframes scribble-pulse {
  0%, 100% { filter: drop-shadow(0 0 0 transparent); }
  50%      { filter: drop-shadow(0 0 4px var(--accent)); }
}

/* on dark, the pulse uses the inverted drop-shadow */
[data-theme="dark"] .topbar-mark {
  animation: scribble-spin 18s linear infinite, scribble-pulse-dark 4.5s ease-in-out infinite;
}
@keyframes scribble-pulse-dark {
  0%, 100% { filter: invert(1) drop-shadow(0 0 0 transparent); }
  50%      { filter: invert(1) drop-shadow(0 0 4px var(--accent)); }
}

@media (prefers-reduced-motion: reduce) {
  .topbar-mark { animation: none; }
}

.topbar a.label {
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.topbar a.label:hover {
  border-bottom-color: var(--fg);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.topbar-clock {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}

.theme-toggle {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  background: transparent;
  color: var(--fg);
  border: 1px solid var(--fg);
  padding: 0.3rem 0.6rem;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.theme-toggle-icon {
  display: block;
  /* inherits color from .theme-toggle so it flips on hover with the bg */
}

.theme-toggle:hover {
  background: var(--fg);
  color: var(--inverse-fg);
}

/* ── HERO ── */

.hero {
  padding: 2.5rem 1.5rem 3.5rem;
}

.hero-title {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  font-size: clamp(64px, 16vw, 200px);
  line-height: 0.85;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  margin-left: -0.04em;
  overflow-wrap: break-word;
}

.hero-tagline {
  margin-top: 1.5rem;
  font-size: 0.9rem;
  max-width: 80ch;
  line-height: 1.65;
}

.hero-interests {
  font-size: 0.8375rem;
  line-height: 1.2;
  max-width: 80ch;
}

.hero-interests p {
  margin-bottom: 0.6em;
}

.hero-interests ul {
  list-style: none;
  margin-bottom: 1.4em;
}

.hero-interests li::before {
  content: "— ";
  opacity: 0.5;
}

.hero-or {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.hero-accent {
  display: block;
  width: 60px;
  height: 2px;
  background: var(--fg);
  margin: 2.5rem 0 2.25rem;
}

/* ── COLUMNS ── */

.columns-section {
  padding: 3.5rem 1.5rem;
}

.columns-section .label {
  margin-bottom: 1.75rem;
}

.columns-body {
  /* 25% bigger than the original 0.8125rem */
  font-size: 1.015rem;
  line-height: 1.75;
  column-count: 2;
  column-gap: 2.5rem;
  column-rule: 1px solid var(--fg);
  max-width: 900px;
}

.columns-body p {
  margin-bottom: 1em;
  break-inside: avoid;
}

/* ── POSTS (was PROJECTS) ── */

.projects {
  padding: 1.25rem 1.5rem;
}

.projects .label {
  margin-bottom: 1.25rem;
}

.project-list {
  list-style: none;
  border-top: 1px solid var(--fg);
}

.project-item {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  gap: 1rem;
  align-items: baseline;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--fg);
  transition: transform 0.2s ease, background 0.15s ease;
}

.project-item a.project-name {
  text-decoration: none;
  color: inherit;
}

.project-item:hover {
  transform: translateX(1.5rem);
  background: var(--fg);
  color: var(--inverse-fg);
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

.project-num {
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
  opacity: 0.5;
}

.project-item:hover .project-num {
  opacity: 1;
}

.project-name {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: -0.01em;
}

.project-meta {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
  opacity: 0.5;
}

.project-item:hover .project-meta {
  opacity: 1;
}

/* ── CONTACT ── */

.contact {
  padding: 4rem 1.5rem;
}

.contact .label {
  margin-bottom: 1.5rem;
}

.contact-email {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  font-size: clamp(1.5rem, 5vw, 3.5rem);
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--fg);
  border-bottom: 3px solid var(--fg);
  padding-bottom: 0.15em;
  transition: border-color 0.2s ease;
}

.contact-email:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* ── FOOTER ── */

.footer {
  padding: 1rem;
  border-top: 3.5px solid var(--fg);
}

.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0.25rem 2rem;
}

.footer-link {
  font-family: 'Newsreader', Georgia, 'Times New Roman', serif;
  font-size: 0.95rem;
  font-weight: 400;
  font-style: italic;
  text-transform: none;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--fg);
  padding: 0.4rem 0;
  display: block;
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s ease, opacity 0.15s ease;
}

.footer-link:hover {
  border-bottom-color: var(--fg);
  opacity: 0.6;
}

/* ── POST PAGE ── */

/* Centered post layout: title + meta are centered;
   body block is centered on the page but its lines stay left-aligned. */
.post {
  padding: 1.5rem 1.5rem 4.5rem;
  text-align: center;
}

.post-header {
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

.post-back {
  display: inline-block;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  font-family: 'Newsreader', Georgia, 'Times New Roman', serif;
  font-size: 0.95rem;
  font-weight: 400;
  font-style: italic;
  text-transform: none;
  letter-spacing: 0;
}

.post-back:hover {
  border-bottom-color: var(--fg);
}

.post-title {
  font-family: 'Newsreader', Georgia, 'Times New Roman', serif;
  font-weight: 400;
  font-style: italic;
  font-size: clamp(1.35rem, 3.4vw, 2.05rem);
  line-height: 1.2;
  letter-spacing: -0.005em;
  margin-top: 1.25rem;
  margin-left: auto;
  margin-right: auto;
  text-wrap: balance;
}

.post-meta {
  margin-top: 1.5rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--fg);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  font-family: 'Newsreader', Georgia, 'Times New Roman', serif;
  font-size: 0.95rem;
  font-weight: 400;
  font-style: italic;
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: var(--fg);
}

.post-meta-sep {
  opacity: 0.4;
}

.post-meta-tag {
  /* visually mark the hashtag without changing the muted feel of the meta line */
  color: var(--accent);
}

.post-body {
  margin-top: 2.75rem;
  max-width: 65ch;
  margin-left: auto;
  margin-right: auto;
  font-family: 'Geist', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 1.015rem;
  line-height: 1.55;
  text-align: left;
}

.post-body p,
.post-body ul,
.post-body ol,
.post-body blockquote {
  margin-bottom: 1.25em;
}

/* keep prose-style blocks left-aligned so lists / quotes don't look awkward */
.post-body ul,
.post-body ol,
.post-body blockquote {
  text-align: left;
}

/* Obsidian-style blockquote: 2px vertical colored bar on the left,
   slight indent so the quoted material reads as borrowed / set apart
   from the author's own prose. Dims the whole block slightly so the
   quote still defers to body text. Italic-heavy quotes still read
   correctly because the existing `.post-body em` italic rule applies
   to nested <em> as well. */
.post-body blockquote {
  border-left: 2px solid var(--accent);
  padding-left: 1.25rem;
  margin-left: 0;
  margin-right: 0;
  opacity: 0.85;
}

.post-body ul,
.post-body ol {
  padding-left: 1.5rem;
}

.post-body li {
  margin-bottom: 0.4em;
}

.post-body strong {
  font-weight: 500;
  background: var(--fg);
  color: var(--inverse-fg);
  padding: 0 0.15em;
}

/* Inside blockquotes, drop the strong weight so the user's emphasis
   reads as a soft pull-quote, not a shouty inverted highlight. */
.post-body blockquote strong {
  font-weight: 300;
}

/* a <strong> wrapping an inline link: drop the inverted highlight, color the link instead */
.post-body strong:has(a),
.post-body strong.post-body-strong--no-bg {
  background: transparent;
  color: inherit;
  padding: 0;
}

.post-body em {
  font-style: italic;
}

/* Per-stanza dimming — opt-in via <em class="faded"> in the post body.
   Used on day-18's "I can choose to end the sentence..." block to set it
   apart from the other italic stanzas in the poem (roulette, Poetry
   definition, etc.) without changing their opacity. Scoped to .post-body
   so the class doesn't bleed elsewhere. */
.post-body em.faded {
  opacity: 0.5;
}

/* Per-post opt-in (originally scoped to day-18's italic-dim override,
   now generalized): posts with disable_italic_dim: true in frontmatter
   get the body class `no-italic-dim`, which (a) bypasses the
   .post-body hr ~ p em { 0.75 } footnote-dim rule for everything except
   .faded ems, and (b) applies the .post-body font-size override below.
   Opt-in via frontmatter so the established dim-after-<hr> contract
   and the 20px site-wide root font-size are preserved on every other
   post (day-16, day-17, etc.). */
body.no-italic-dim .post-body hr ~ p em:not(.faded) {
  opacity: 1;
}

/* Per-post opt-in font-size bump: posts with disable_italic_dim: true
   (day-18, the only one set so far) override the site-wide 20px root
   font-size down to 18px — applies ONLY to that post's .post-body so
   the homepage, index, and other posts stay at the 20px site default.
   18px was the user's '10% bigger' target relative to a 16px interim
   (16px × 1.1 ≈ 17.6, rounded to 18). The override lives here rather
   than mutating `html` so the change stays scoped to this post.
   The disable_italic_dim frontmatter flag is now repurposed as a
   general "day-18 has its own design overrides" opt-in. */
body.no-italic-dim .post-body {
  font-size: 0.9rem;
}

/* Italic inside the disclaimer block (after the in-post <hr>) stays dim —
   these are footnote asides, distinct from body-content italic emphasis.
   The very first paragraph is treated the same way when its <em> wraps a
   day-N challenge disclaimer. */
.post-body hr ~ p em,
.post-body > p:first-child > em {
  opacity: 0.75;
}

/* Disclaimer container: only style the first paragraph when it wraps a
   day-N microblogging-challenge disclaimer (i.e. its direct child is an
   <em>). The :has() selector prevents this from accidentally styling
   regular first paragraphs in posts that don't have a disclaimer (e.g.
   day-3's first paragraph is plain text, not an italic aside).
   Visual: smaller font, subtle left border, reduced opacity, and a tight
   margin to the next paragraph (the "smaller separator" between the
   disclaimer and the actual post content). The em opacity from the rule
   above stacks on top of this, dimming the italic text further. */
.post-body > p:first-child:has(> em) {
  font-size: 0.88rem;
  line-height: 1.5;
  padding: 0.85rem 1rem;
  margin-top: 0;
  margin-bottom: 1.25rem;
  border-left: 2px solid var(--fg);
  opacity: 0.75;
}

/* Strikethrough: inherit color (don't render darker than the text) and
   dim it so the line and text read as quietly removed. */
.post-body del {
  text-decoration: line-through;
  text-decoration-color: currentColor;
  text-decoration-thickness: 1px;
  opacity: 0.5;
}

.post-body a {
  color: var(--link);
  text-decoration: none;
  border-bottom: 1px solid var(--link);
}

.post-body a.post-inline-link {
  font-weight: 500;
  border-bottom: 1px solid var(--link);
}

.post-body a.post-inline-link:hover {
  background: var(--link);
  color: var(--inverse-fg);
}

.post-body h2,
.post-body h3 {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  margin: 2em 0 0.75em;
}

/* Scoped h3 variant: small italic sub-headings inside a post. Drops the
   uppercase transform (UPPERCASE ITALIC reads shouty) and adds italic.
   Used inline via `### Title` + a `.post-body-h3--italic` class on the
   rendered <h3>. Other posts with vanilla h3 (day-3's "The challenge",
   etc.) keep their existing uppercase Space Grotesk look. */
.post-body h3.post-body-h3--italic {
  font-family: 'Newsreader', Georgia, 'Times New Roman', serif;
  font-weight: 500;
  font-style: italic;
  text-transform: none;
  letter-spacing: -0.005em;
  font-size: 1.4rem;
  margin: 2em 0 0.6em;
}

/* The `---` rule inside a post separates the body from the italic
   disclaimer block. Give it breathing room underneath so the footnote
   doesn't feel pinned to the last sentence. */
.post-body hr {
  border: none;
  border-top: 1px solid var(--fg);
  margin: 2.5rem 0 2.25rem;
  opacity: 0.4;
}

/* Everything below the in-post <hr> reads as a footnote / disclaimer.
   Slightly smaller type so the appendix stays out of the way of the
   main text. Color stays at full --fg so the body reads at the same
   brightness as the intro paragraph before the <hr>. Italic inside
   this block (the asides, wrapped in <em>) is dimmed by the
   `.post-body hr ~ p em` rule above so footnote text reads quieter
   than body text. The <hr> is the only rule inside .post-body that
   should trigger this scope. */
.post-body hr ~ p,
.post-body hr ~ ul,
.post-body hr ~ ol,
.post-body hr ~ blockquote {
  color: var(--fg);
  font-size: 0.95em;
}

/* Footnote paragraph treatment: visually distinct from body content
   via a subtle tinted background that flips lightness per theme.
   Light mode gets a slightly darker (gray) bg; dark mode gets a
   slightly lighter bg. The hr + post-footnote selector targets ONLY
   paragraphs with the class that immediately follow an <hr>, so other
   post-hr content isn't affected. */
.post-body hr + p.post-footnote {
  margin-top: 0;
  margin-bottom: 1.25em;
  padding: 1rem 1.25rem;
  border-left: 2px solid var(--fg);
  opacity: 0.85;
}
:root,
[data-theme="light"] {
  --post-footnote-bg: rgba(0, 0, 0, 0.04);
}
[data-theme="dark"] {
  --post-footnote-bg: rgba(255, 255, 255, 0.05);
}
.post-body hr + p.post-footnote {
  background: var(--post-footnote-bg);
}

.post-nav {
  margin-top: 3.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--fg);
}

.post-nav a:not(.post-back) {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
  color: var(--fg);
  border-bottom: 1px solid var(--fg);
}

/* Speaker tinting: very subtle per-speaker color on debate/multi-voice posts.
   Applies an ~10% speaker-color tint blended with 90% of the base text color
   (--fg), so the effect reads as a "barely warmer / cooler" version of the
   surrounding text rather than a full-saturation accent. Designed for posts
   like day-17 where Z and D alternate lines and you want to scan who said
   what without losing the prose feel.

   Why not `opacity`? Opacity multiplies the foreground alpha and leaves the
   color fully saturated — the text looks like a faded full-color highlight,
   not a subtle tint. A 10% color blend keeps the text appearing as "almost
   the same color as the surrounding body" with a hint of warmth/coolness.

   Light mode base: --fg = #000 (true black). Dark mode base: --fg = #ededed
   (off-white). The tinted hex values below are pre-blended for those bases
   so the same visual cue lands in both themes. */
:root .post-body p.speaker-z { color: #030a11; }  /* 10% #2563a8 on #000 */
:root .post-body p.speaker-d { color: #120609; }  /* 10% #b3405a on #000 */
[data-theme="dark"] .post-body p.speaker-z { color: #dee3e8; }  /* 10% #7eb0e8 on #ededed */
[data-theme="dark"] .post-body p.speaker-d { color: #e8e1e2; }  /* 10% #e89aab on #ededed */

/* ── RESPONSIVE ── */

@media (max-width: 640px) {
  html { font-size: 18px; }

  .hero {
    padding: 1.25rem 1rem 2.5rem;
  }

  .hero-title {
    font-size: clamp(44px, 13vw, 80px);
    margin-left: -0.02em;
    letter-spacing: -0.03em;
  }

  .topbar,
  .projects,
  .columns-section,
  .footer {
    padding-left: 1rem;
    padding-right: 1rem;
  }

  /* post page on mobile: tighten the gaps */
  .post {
    padding: 1rem 1rem 1rem;
  }

  .post-title {
    margin-top: 0.75rem;
  }

  .post-meta {
    margin-top: 0.85rem;
    padding-top: 0.55rem;
  }

  .post-body {
    margin-top: 1.5rem;
  }

  .post-nav {
    margin-top: 1.5rem;
    padding-top: 0.75rem;
  }

  .columns-body {
    column-count: 1;
    column-rule: none;
  }

  .project-item {
    grid-template-columns: 2rem 1fr;
    gap: 0.2rem 0.75rem;
    padding: 0.75rem 0;
  }

  .project-meta {
    grid-column: 2;
    margin-top: 0;
  }

  .project-item:hover {
    transform: translateX(0.75rem);
  }

  .footer {
    padding-top: 1rem;
    padding-bottom: 1rem;
  }

  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: 0 1.5rem;
  }

  .footer-link {
    padding: 0.25rem 0;
  }
}

/* Local-only alt preview: triggered by ?wide=1 in the URL. Sets the body
   paragraph column to match the .post-header column (720px) so the post
   can be screenshotted at "full title size" without resizing the window.
   The class is added by the inline script in layouts/_default/baseof.html
   reading the query param; visiting without ?wide=1 leaves it inert. */
body.body-wide .post-body {
  max-width: 720px;
}
