/* ============================================================================
   Dissensus / Farzulla shared design system  —  research-grade serif + sans
   One source of truth. Single light theme: the dark path was removed in Aug
   2026 after the toggle came out of the nav, so there is exactly one palette
   and no [data-theme] selectors anywhere. Signature: Source Serif 4 display,
   Inter prose, IBM Plex Mono labels, mono section indices, thin burgundy rule.
   Fonts are self-hosted woff2 (latin subsets) in assets/fonts — no CDN.
   ============================================================================ */

/* ---- self-hosted fonts ----------------------------------------------------- */
@font-face { font-family: "Source Serif 4"; font-style: normal; font-weight: 400; font-display: swap; src: url("../assets/fonts/source-serif-4-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "Source Serif 4"; font-style: italic; font-weight: 400; font-display: swap; src: url("../assets/fonts/source-serif-4-latin-400-italic.woff2") format("woff2"); }
@font-face { font-family: "Source Serif 4"; font-style: normal; font-weight: 600; font-display: swap; src: url("../assets/fonts/source-serif-4-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "Source Serif 4"; font-style: normal; font-weight: 700; font-display: swap; src: url("../assets/fonts/source-serif-4-latin-700-normal.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap; src: url("../assets/fonts/inter-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: italic; font-weight: 400; font-display: swap; src: url("../assets/fonts/inter-latin-400-italic.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap; src: url("../assets/fonts/inter-latin-500-normal.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap; src: url("../assets/fonts/inter-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap; src: url("../assets/fonts/inter-latin-700-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap; src: url("../assets/fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: italic; font-weight: 400; font-display: swap; src: url("../assets/fonts/ibm-plex-mono-latin-400-italic.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url("../assets/fonts/ibm-plex-mono-latin-500-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap; src: url("../assets/fonts/ibm-plex-mono-latin-600-normal.woff2") format("woff2"); }

/* Greek + latin-ext for Inter, declared after the latin faces so they win for the
   ranges they claim. The latin subsets stop at 230 codepoints, so without these the
   friction notation (α σ ε τ ρ φ ψ Δ Σ) and the ħ in the temporal-bitmap post drop
   to a system sans mid-sentence. unicode-range keeps them off pages that don't use
   them — the greek file is ~8 KB, latin-ext ~35 KB and only the news post pulls it.
   Adding a new Inter weight means adding its greek subset too.

   Deliberately NOT here: Source Serif 4 (no Greek reaches a serif element — checked
   every text node) and IBM Plex Mono. Plex Mono has no Greek at any weight, from any
   source, so mono Greek is an unavoidable fallback. Its latin-ext exists but carries
   ə without ɛ or ɪ, which would split "/dɪˈsɛnsəs/" on the homepage across two fonts
   — a uniform fallback is the better of the two bad options there. */
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap; src: url("../assets/fonts/inter-greek-400-normal.woff2") format("woff2"); unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap; src: url("../assets/fonts/inter-greek-500-normal.woff2") format("woff2"); unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap; src: url("../assets/fonts/inter-greek-600-normal.woff2") format("woff2"); unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap; src: url("../assets/fonts/inter-greek-700-normal.woff2") format("woff2"); unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap; src: url("../assets/fonts/inter-latin-ext-400-normal.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

/* ---- tokens ---------------------------------------------------------------- */
:root {
  /* warm cream, true burgundy carries the brand — the only palette */
  --bg:        #faf8f5;
  --surface:   #ffffff;
  --surface-2: #f4f1ec;
  --line:      #e6e0d7;
  --text:      #1c1917;
  --text-dim:  #57504a;
  --burgundy:  #800020;   /* brand constant */
  --accent:    #800020;
  --accent-dim: rgba(128, 0, 32, 0.07);
  --shadow:    0 1px 0 rgba(0,0,0,0.02), 0 10px 30px rgba(60,40,45,0.08);

  /* type */
  --font-serif: "Source Serif 4", Georgia, "Times New Roman", serif;
  --font-sans: "Inter", system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --fs-hero: clamp(2.4rem, 6vw, 4.25rem);
  --fs-h1:   clamp(1.9rem, 4vw, 2.75rem);
  --fs-h2:   clamp(1.4rem, 2.6vw, 1.9rem);
  --fs-h3:   1.15rem;
  --fs-body: 1.02rem;
  --fs-sm:   0.9rem;
  --fs-mono: 0.8rem;
  --lh:      1.6;
  --measure: 68ch;

  /* space + shape */
  --sp-1: 0.25rem; --sp-2: 0.5rem; --sp-3: 0.75rem; --sp-4: 1rem;
  --sp-6: 1.5rem;  --sp-8: 2rem;   --sp-12: 3rem;   --sp-16: 4rem; --sp-24: 6rem;
  --radius: 5px;
  --container: 1080px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* A fixed 1080px container reads as a narrow, compact column on a full-screen desktop
   — everything squeezed into the middle third with the footer worst hit. The container
   and the section rhythm both open up with the viewport instead. Prose stays readable
   because it is capped by --measure regardless of how wide the container gets. */
@media (min-width: 1280px) {
  :root { --container: 1160px; --sp-24: 7rem; }
}
@media (min-width: 1600px) {
  :root { --container: 1280px; --sp-24: 8rem; --fs-body: 1.06rem; }
}

/* ---- reset / base --------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; overflow-x: clip; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { font-family: var(--font-serif); line-height: 1.15; font-weight: 600; letter-spacing: -0.01em; }
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); font-weight: 600; }
p { color: var(--text-dim); max-width: var(--measure); }
a { color: var(--accent); text-decoration: none; transition: color 0.15s var(--ease); }
a:hover { color: var(--text); }
img, svg { max-width: 100%; display: block; }
::selection { background: var(--accent-dim); }

/* ---- layout --------------------------------------------------------------- */
.container { max-width: var(--container); margin-inline: auto; padding-inline: var(--sp-6); }
.section { padding-block: var(--sp-24); border-top: 1px solid var(--line); }
.section:first-of-type { border-top: 0; }
/* A .section directly after the hero stacked its own 6-8rem top padding onto the hero's
   bottom padding, leaving ~14rem of dead space that read as a rendering fault at large
   widths. The hero already provides the separation. */
.hero + .section { padding-top: var(--sp-12); }

/* mono kicker / section index — the unifying signature */
.kicker {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  text-transform: uppercase;
  letter-spacing: 0.28em;
  color: var(--accent);
  display: inline-block;
  margin-bottom: var(--sp-4);
}
.index {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  color: var(--text-dim);
  letter-spacing: 0.15em;
}
.rule { width: 56px; height: 3px; background: var(--burgundy); border: 0; margin: var(--sp-6) 0; }

/* ---- nav ------------------------------------------------------------------ */
.nav {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-4) var(--sp-6);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.nav__brand { font-family: var(--font-mono); font-weight: 600; letter-spacing: 0.12em; color: var(--text); text-transform: uppercase; flex: none; }
.nav__links { display: flex; gap: var(--sp-6); align-items: center; }
.nav__links a { font-family: var(--font-mono); font-size: var(--fs-mono); text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-dim); white-space: nowrap; }
.nav__links a:hover { color: var(--accent); }

/* hamburger — hidden on wide screens, becomes the menu control below 880px */
.nav__burger {
  display: none; flex-direction: column; justify-content: center; gap: 4px;
  width: 38px; height: 34px; padding: 0 8px; background: transparent;
  border: 1px solid var(--line); border-radius: var(--radius); cursor: pointer;
}
.nav__burger span { display: block; height: 2px; width: 100%; background: var(--text); transition: transform 0.2s var(--ease), opacity 0.2s var(--ease); }
.nav__burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav__burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* below 880px the row would compress into the brand — collapse to a dropdown */
@media (max-width: 880px) {
  .nav { flex-wrap: wrap; }
  .nav__burger { display: flex; }
  .nav__links {
    display: none; flex-direction: column; align-items: flex-start;
    width: 100%; gap: var(--sp-4); padding: var(--sp-4) 0 var(--sp-2);
    border-top: 1px solid var(--line); margin-top: var(--sp-4);
  }
  .nav__links.is-open { display: flex; }
}

/* ---- hero ----------------------------------------------------------------- */
.hero { padding-block: clamp(4rem, 12vw, 9rem); }
.hero h1 { font-size: var(--fs-hero); max-width: 20ch; }
.hero p { font-size: 1.2rem; margin-top: var(--sp-6); }

/* ---- cards ---------------------------------------------------------------- */
/* min() floor: a hard 300px track exceeds the container at 320px viewports, so cards
   were clipped by the html overflow-x:clip rather than fitting. */
.grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
/* Grid items default to min-width:auto, so a long unbreakable token (a DOI in a
   button label) holds the track open past the container. Let them shrink, and let
   the tokens themselves break. */
.grid > *, .grid--wide > * { min-width: 0; }
/* The .grid--wide two-column variant is gone: tools.html was retired, and the projects
   and join pages went linear in Aug 2026, so nothing used it. */
.card { display: flex; flex-direction: column; }
.grid--wide > .card > .btn-row { margin-top: auto; padding-top: var(--sp-4); }
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-6);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.card:hover { border-color: var(--accent); transform: translateY(-2px); }
.card__meta { font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--text-dim); letter-spacing: 0.08em; text-transform: uppercase; }
.card h3 { margin: var(--sp-3) 0; color: var(--text); }
.card p { font-size: var(--fs-sm); }

/* status pills */
.pill { display: inline-block; font-family: var(--font-mono); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.1em;
  padding: 2px var(--sp-2); border-radius: 100px; border: 1px solid var(--line); color: var(--text-dim); }
.pill--review { color: var(--accent); border-color: var(--accent); }
.pill--preprint { color: var(--text-dim); }

/* ---- buttons -------------------------------------------------------------- */
.btn { display: inline-flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-mono); font-size: var(--fs-sm); letter-spacing: 0.06em;
  padding: var(--sp-3) var(--sp-6); border-radius: var(--radius); cursor: pointer;
  border: 1px solid var(--burgundy); background: var(--burgundy); color: #fff;
  transition: opacity 0.15s var(--ease); }
.btn:hover { opacity: 0.88; color: #fff; }
.btn--ghost { background: transparent; color: var(--text); border-color: var(--line); }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }

/* ---- footer --------------------------------------------------------------- */
/* Rebuilt Aug 2026. It had been two flex blocks with inline styles, and at full-screen
   width the link list and the legal block collided into a cramped strip. Three columns
   with real vertical rhythm, then a base row for socials and the small print. */
.footer { border-top: 1px solid var(--line); padding-block: var(--sp-16) var(--sp-8); margin-top: var(--sp-8); }
.footer, .footer a { font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--text-dim); letter-spacing: 0.06em; }
.footer a:hover { color: var(--accent); }

.footer__grid { display: grid; gap: var(--sp-12); }
@media (min-width: 62rem) {
  .footer__grid { grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-16); }
}
.footer__col { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.footer__col p { max-width: 44ch; line-height: 1.75; }
.footer__brand {
  font-family: var(--font-mono); font-size: 0.82rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--text); margin-bottom: var(--sp-1);
}
.footer__legal { margin-top: var(--sp-4); line-height: 1.8; opacity: 0.85; }
.footer__k {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text); margin-bottom: var(--sp-3);
}
.footer__col--nav a, .footer__col--contact a { padding-block: 0.18rem; }

.footer__base {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-4) var(--sp-8); margin-top: var(--sp-16);
  padding-top: var(--sp-6); border-top: 1px solid var(--line);
}
.footer__social { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-6); margin: 0; }
.footer__social a { display: inline-flex; align-items: center; gap: 0.45rem; text-transform: uppercase; }
.footer__social svg { width: 14px; height: 14px; fill: currentColor; flex: none; }
.footer__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.footer__meta .sep { color: var(--line); }

/* ---- responsive ----------------------------------------------------------- */
@media (max-width: 720px) {
  .section { padding-block: var(--sp-16); }
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }
