:root {
  --bg: #eeeee8;
  --bg-1: #f8f8f2;
  --bg-2: #e5e7df;
  --bg-3: #dce1d4;
  --line: #c8cbc3;
  --line-2: #90998d;
  --fg: #171b1b;
  --fg-dim: #535b55;
  --fg-faint: #626b60;
  --accent: #2044ee;
  --accent-2: #2044ee;

  --t-foundations: #6d3fa3;
  --t-perception:  #2044ee;
  --t-planning:    #176953;
  --t-control:     #996019;
  --t-manipulation:#a13b58;
  --t-learning:    #4e681d;
  --t-systems:     #626b60;

  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: Arial, Helvetica, sans-serif;
  --serif: Georgia, "Times New Roman", serif;
  --maxw: 1180px;

  /* Sticky offsets, as variables rather than magic numbers repeated down the file.
     Every sticky layer below the header has to know how tall the layers above it are;
     when those were hardcoded (53px / 190px) the header wrapping to two rows on a phone
     silently slid the era bar underneath it. */
  --h-top: 53px;    /* header.top */
  --h-bar: 57px;    /* .era-bar, the slim sticky era indicator */
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font-family: var(--sans); font-size: 15px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent-2); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3, h4 { line-height: 1.25; margin: 0; font-weight: 600; }
code, .mono { font-family: var(--mono); }

/* ---------- chrome ---------- */
header.top {
  position: sticky; top: 0; z-index: 50;
  background: rgba(238,238,232,.96); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.top-in {
  max-width: var(--maxw); margin: 0 auto; padding: 10px 20px;
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
}
.brand { font-weight: 700; letter-spacing: -.01em; font-size: 15px; white-space: nowrap; }
.brand span { color: var(--accent); }
nav.tabs { display: flex; gap: 2px; }
nav.tabs button {
  background: none; border: 0; color: var(--fg-dim); font: inherit; font-size: 14px;
  padding: 6px 12px; border-radius: 7px; cursor: pointer;
  /* "Reading paths" wrapping onto a second line makes the whole tab row two lines tall,
     which pushed the sticky header to 142px on a phone — a sixth of the screen, permanently. */
  white-space: nowrap;
}
nav.tabs button:hover { background: var(--bg-2); color: var(--fg); }
nav.tabs button.on { background: var(--bg-3); color: var(--fg); }
.grow { flex: 1; }
#q {
  background: var(--bg-2); border: 1px solid var(--line); color: var(--fg);
  border-radius: 7px; padding: 7px 11px; font: inherit; font-size: 14px; width: 230px;
  /* At its natural 230px the search field could not fit beside the tabs between ~790px and
     ~1080px, so it wrapped and doubled the sticky header to 116px across that whole band.
     Note that shrinking alone does not fix it: flexbox breaks lines using each item's flex
     *base* size, before any shrinking is applied, so a 230px basis wraps no matter how
     shrinkable it is. Declare the small size as the basis and grow back up to 230px. */
  flex: 1 1 150px; min-width: 150px; max-width: 230px;
}
#q:focus { outline: none; border-color: var(--line-2); background: var(--bg-3); }

main { max-width: var(--maxw); margin: 0 auto; padding: 0 20px 140px; }

/* ---------- hero ---------- */
.hero { padding: 56px 0 30px; border-bottom: 1px solid var(--line); margin-bottom: 34px; }
.hero h1 { font-size: 40px; letter-spacing: -.025em; margin-bottom: 14px; }
.hero p { color: var(--fg-dim); max-width: 74ch; font-size: 16px; margin: 0 0 10px; }
.stats { display: flex; gap: 26px; margin-top: 22px; flex-wrap: wrap; }
.stat b { display: block; font-size: 25px; font-family: var(--mono); color: var(--accent); line-height: 1.2; }
.stat span { font-size: 11.5px; color: var(--fg-faint); text-transform: uppercase; letter-spacing: .09em; }

/* ---------- filter bar ---------- */
.filters {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  padding: 12px 0 18px; border-bottom: 1px solid var(--line); margin-bottom: 26px;
}
.chip {
  background: var(--bg-2); border: 1px solid var(--line); color: var(--fg-dim);
  border-radius: 999px; padding: 4px 12px; font-size: 12.5px; cursor: pointer; font: inherit;
  font-size: 12.5px; display: inline-flex; align-items: center; gap: 6px;
}
.chip:hover { border-color: var(--line-2); color: var(--fg); }
.chip.on { background: var(--fg); color: var(--bg); border-color: var(--fg); font-weight: 600; }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.filters .sep { width: 1px; height: 20px; background: var(--line); margin: 0 4px; }
.filters label { font-size: 11.5px; color: var(--fg-faint); text-transform: uppercase; letter-spacing: .08em; }

/* ---------- timeline ---------- */
.era { margin: 0 0 10px; }

/* Only this slim bar is sticky. It is a direct child of section.era so it stays pinned
   for the whole era, and it holds nothing but the years, the title and the paper count —
   about one line. The era blurb and the ~310-word essay used to live inside the sticky
   element, which pinned 750-800px to the top of the viewport: on a laptop that left a
   sliver of content visible, and on a phone the pinned header was taller than the screen,
   so scrolling an era showed the essay and never reached the papers. */
.era-bar {
  position: sticky; top: var(--h-top); z-index: 20; background: var(--bg);
  display: flex; align-items: baseline; gap: 13px; flex-wrap: wrap;
  padding: 17px 0 11px; border-bottom: 1px solid var(--line-2); margin-bottom: 18px;
}
.era-bar h2 { font-size: 22px; letter-spacing: -.02em; }
.era-bar .yrs {
  font-family: var(--mono); font-size: 12px; color: var(--accent); letter-spacing: .06em;
}
.era-bar .n {
  margin-left: auto; font-family: var(--mono); font-size: 12px; color: var(--fg-faint);
}
.era-head { padding: 0; margin-bottom: 22px; }
.era-head p { color: var(--fg-dim); margin: 0; max-width: 78ch; font-size: 14.5px; }
.era-essay {
  margin: 16px 0 0; padding: 15px 18px; background: var(--bg-1);
  border-left: 2px solid var(--line-2); border-radius: 0 8px 8px 0;
  font-family: var(--serif); font-size: 15.5px; line-height: 1.68; color: var(--fg); max-width: 82ch;
}
.era-essay p { margin: 0 0 10px; } .era-essay p:last-child { margin: 0; }
/* A ~310-word essay held to an 82ch measure is a 640px-wide, 650px-tall box sitting in a
   1140px column — half the width empty, and six screens of scrolling before the papers.
   Once there is room for two measures, set it in two columns: same line length, half the
   height, and the era's argument fits on one screen above its own reading list. */
@media (min-width: 1080px) {
  .era-essay { max-width: none; column-count: 2; column-gap: 38px; column-rule: 1px solid var(--line); }
}

.year-row { display: grid; grid-template-columns: 62px 1fr; gap: 18px; margin-bottom: 12px; }
.year-tick {
  font-family: var(--mono); font-size: 13px; color: var(--fg-faint);
  padding-top: 10px; text-align: right; height: fit-content;
  position: sticky; top: calc(var(--h-top) + var(--h-bar) + 10px);
}
.year-cards { display: flex; flex-direction: column; gap: 8px; min-width: 0; }

.card {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: 9px;
  padding: 11px 14px; cursor: pointer; position: relative;
  border-left: 3px solid var(--thread, var(--line-2));
  transition: background .12s, border-color .12s, transform .12s;
}
.card:hover { background: var(--bg-2); border-color: var(--line-2); border-left-color: var(--thread); transform: translateX(2px); }
.card.t1 { background: linear-gradient(90deg, rgba(255,180,84,.07), transparent 60%), var(--bg-1); }
.card-t { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.card-t h3 { font-size: 15px; font-weight: 600; letter-spacing: -.005em; }
.card .meta { font-size: 12.5px; color: var(--fg-faint); font-family: var(--mono); }
.card .why { color: var(--fg-dim); font-size: 13.5px; margin-top: 5px; max-width: 92ch; }
.badges { display: flex; gap: 5px; align-items: center; margin-left: auto; padding-left: 8px; }
.b {
  font-size: 10px; text-transform: uppercase; letter-spacing: .07em; font-weight: 700;
  padding: 2px 7px; border-radius: 5px; white-space: nowrap;
}
.b.tier1 { background: var(--accent); color: #23180a; }
.b.tier2 { background: var(--bg-3); color: var(--fg-dim); }
.b.ann   { background: rgba(163,224,90,.16); color: var(--t-learning); }
.b.low   { background: rgba(255,143,163,.14); color: var(--t-manipulation); }
/* Louder than .b.low on purpose: weak notes are a quality caveat, an unconfirmed
   citation is a claim we could not stand behind at all. */
.b.unver { background: rgba(255,171,64,.18); color: #ffc266; border: 1px solid rgba(255,171,64,.35); }

/* ---------- topics ---------- */
.topic-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); gap: 12px; }
.topic-card {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: 11px;
  padding: 16px 17px; cursor: pointer; border-top: 3px solid var(--thread, var(--line-2));
}
.topic-card:hover { background: var(--bg-2); border-color: var(--line-2); }
.topic-card h3 { font-size: 15.5px; margin-bottom: 6px; }
.topic-card .n { font-family: var(--mono); font-size: 11.5px; color: var(--fg-faint); }
.topic-card p { color: var(--fg-dim); font-size: 13.5px; margin: 8px 0 0; }

.prose { max-width: 76ch; }
/* About is nothing but prose, so the 1180px page frame made the h1 and its rule run to
   1220px while the text stopped at 660px — the page read as half-failed-to-load rather than
   as a measured column. Pull the whole view in to the measure so the frame agrees with the
   text. Left-aligned, not centred: every other view starts at the same gutter. */
#view.v-about { max-width: 690px; }
/* Debates and a single subfield are also prose end to end. Slightly wider than About because
   both carry a full-width row above the text — the debate chips, the subfield's paper list —
   that needs the room. */
#view.v-debates, #view.v-topic { max-width: 940px; }
.prose h2 { font-size: 22px; margin: 34px 0 12px; letter-spacing: -.015em; }
.prose h3 { font-size: 16px; margin: 26px 0 8px; color: var(--fg-dim); text-transform: uppercase; letter-spacing: .08em; font-size: 12px; }
.prose p, .prose li { font-family: var(--serif); font-size: 16px; line-height: 1.72; color: var(--fg); }
.prose ol, .prose ul { padding-left: 22px; }
.prose li { margin-bottom: 7px; }
.prose a { border-bottom: 1px solid rgba(124,196,255,.3); }

/* ---------- detail panel ---------- */
.scrim {
  position: fixed; inset: 0; background: rgba(6,8,11,.62); z-index: 90;
  opacity: 0; pointer-events: none; transition: opacity .16s;
}
.scrim.on { opacity: 1; pointer-events: auto; }
aside.detail {
  position: fixed; top: 0; right: 0; height: 100vh; width: min(680px, 94vw);
  background: var(--bg-1); border-left: 1px solid var(--line-2); z-index: 100;
  transform: translateX(100%); transition: transform .2s cubic-bezier(.4,0,.2,1);
  overflow-y: auto; overscroll-behavior: contain;
}
aside.detail.on { transform: none; }
.detail-in { padding: 26px 30px 90px; }
.detail-close {
  position: sticky; top: 0; float: right; background: var(--bg-3); border: 1px solid var(--line);
  color: var(--fg-dim); border-radius: 7px; width: 30px; height: 30px; cursor: pointer;
  font-size: 17px; line-height: 1; z-index: 2;
}
.detail-close:hover { color: var(--fg); border-color: var(--line-2); }
.detail h2 { font-size: 22px; letter-spacing: -.02em; margin: 4px 44px 10px 0; }
.detail .dmeta { font-family: var(--mono); font-size: 12.5px; color: var(--fg-faint); margin-bottom: 4px; }
.detail .dlinks { display: flex; gap: 8px; flex-wrap: wrap; margin: 14px 0 22px; }
.btn {
  background: var(--bg-3); border: 1px solid var(--line); color: var(--fg);
  padding: 6px 13px; border-radius: 7px; font-size: 13px; cursor: pointer; font: inherit; font-size: 13px;
}
.btn:hover { border-color: var(--line-2); background: var(--bg-2); }
.btn.primary { background: var(--accent); color: #23180a; border-color: var(--accent); font-weight: 600; }
.btn.primary:hover { background: #ffc271; }
/* The "353 pp, 17 MB" hint inside a PDF button. Opacity rather than a colour: this sits on the
   amber primary button on most cards and on the plain dark one elsewhere, and any fixed grey
   that reads well on one is unreadable on the other. */
.btn .heft { opacity: .68; font-weight: 500; }

.sec { margin-bottom: 20px; }
.sec > h4 {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .11em;
  color: var(--fg-faint); margin-bottom: 6px; font-weight: 700;
}
.sec > p { margin: 0; font-size: 14.7px; line-height: 1.68; color: var(--fg); }
.sec.hl > p {
  background: var(--bg-2); border-left: 2px solid var(--thread, var(--accent));
  padding: 11px 14px; border-radius: 0 7px 7px 0;
}
.lineage { display: grid; gap: 6px; }
.lin-item {
  font-size: 13.5px; color: var(--fg-dim); padding: 7px 11px; background: var(--bg-2);
  border-radius: 7px; border: 1px solid transparent;
}
.lin-item.click { cursor: pointer; }
.lin-item.click:hover { border-color: var(--line-2); color: var(--fg); }
.lin-item .arrow { color: var(--fg-faint); font-family: var(--mono); margin-right: 7px; }
.warn {
  background: rgba(255,143,163,.09); border: 1px solid rgba(255,143,163,.24);
  color: #ffc2cd; padding: 9px 13px; border-radius: 8px; font-size: 13px; margin-bottom: 18px;
}
.warn.unver {
  background: rgba(255,171,64,.10); border-color: rgba(255,171,64,.30); color: #ffd39b;
}
/* Provenance for the one PDF route where a search engine, not a trusted identifier, chose the
   URL. It is a caption and not a warning: the link still had to match the paper's own first
   page, so styling it like the unverified-citation banner would overstate the doubt. */
.prov { color: var(--fg-faint); font-size: 12px; margin: -6px 0 16px; }
.taglist { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 6px; }
.tag { font-family: var(--mono); font-size: 11px; color: var(--fg-faint); background: var(--bg-2); padding: 2px 7px; border-radius: 5px; }

/* ---------- paths ---------- */
.path {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: 12px;
  padding: 22px 24px; margin-bottom: 16px;
}
.path h3 { font-size: 19px; letter-spacing: -.015em; }
.path > p { color: var(--fg-dim); margin: 8px 0 16px; max-width: 78ch; font-size: 14.5px; }
.path .for { font-size: 12px; color: var(--accent); font-family: var(--mono); margin-bottom: 4px; }
.step { display: grid; grid-template-columns: 30px 1fr; gap: 12px; padding: 9px 0; border-top: 1px solid var(--line); }
.step .num { font-family: var(--mono); color: var(--fg-faint); font-size: 13px; padding-top: 2px; }
.step .st { cursor: pointer; }
.step .st:hover h4 { color: var(--accent-2); }
.step h4 { font-size: 14.5px; font-weight: 600; }
.step .note { color: var(--fg-dim); font-size: 13.5px; margin-top: 2px; }
.step .miss { color: var(--fg-faint); font-style: italic; }

.empty { color: var(--fg-faint); padding: 50px 0; text-align: center; font-size: 15px; }
.back { font-size: 13px; color: var(--fg-dim); cursor: pointer; display: inline-block; margin-bottom: 16px; }
.back:hover { color: var(--fg); }
footer { border-top: 1px solid var(--line); margin-top: 60px; padding: 24px 0; color: var(--fg-faint); font-size: 12.5px; }
footer code { color: var(--fg-dim); }

@media (max-width: 720px) {
  .hero h1 { font-size: 29px; }
  .year-row { grid-template-columns: 44px 1fr; gap: 11px; }
  .year-tick { position: static; text-align: left; }
  /* flex-basis beats width in a flex container, so the desktop `flex: 0 1 230px` has to be
     restated here or the field silently stays 230px wide instead of filling its own row. */
  .top-in { gap: 12px; } #q { width: 100%; flex: 1 0 100%; max-width: none; order: 3; }
  .detail-in { padding: 20px 18px 80px; }
  /* The header wraps to two rows here (the search field takes its own line), so the sticky
     stack is ~95px before the era bar even starts. syncSticky() measures the real height, but
     between two sticky layers and a ~700px viewport the bar is no longer worth its space —
     the era is obvious from the prose right under it. Keep the header, drop the second layer. */
  .era-bar { position: static; padding: 20px 0 10px; }
  .era-bar h2 { font-size: 20px; }
  .era-essay { font-size: 15px; padding: 13px 15px; }
  /* The tabs no longer wrap, so on a narrow screen they have to go somewhere: scroll them
     sideways as one row rather than letting the row grow taller than the content it labels.
     Negative margin + matching padding keeps the first and last tab flush with the page
     gutter while still letting them scroll past it. */
  nav.tabs {
    overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
    margin: 0 -20px; padding: 0 20px; max-width: 100vw;
    /* The scrollbar is hidden, so the last tab being half-cut is the only cue that the row
       scrolls — and a half-cut word reads as a clipping bug, not an invitation. Fade the
       trailing edge instead: same information, and it looks deliberate. */
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
  }
  nav.tabs::-webkit-scrollbar { display: none; }
  /* Vertical bars between chip groups land wherever the flex happens to wrap — usually
     dangling alone at the right edge, reading as a rendering artefact. The uppercase
     TIER / THREAD labels already separate the groups. */
  .filters .sep { display: none; }
  /* 30px is under every touch-target guideline; these are the primary controls on mobile. */
  .chip { padding: 7px 13px; }
}

/* Editorial treatments shared with the Roost front page. */
.top-in{padding-block:14px}.brand{font-weight:500}.brand span{font:italic 19px var(--serif)}
.hero{padding:64px 0 38px}.hero h1{font-size:clamp(38px,5.8vw,72px);font-weight:500;line-height:1.02;letter-spacing:-.055em;max-width:950px}.hero p{font-size:17px;line-height:1.65}
.stats{gap:32px;margin-top:30px}.stat b{font:italic 36px/1.1 var(--serif)}
nav.tabs button,#q,.chip,.card,.topic-card,.btn,.path,.b,.tag,.warn,.lin-item,.sec.hl>p,.era-essay{border-radius:0}
nav.tabs button{min-height:40px}nav.tabs button.on{background:var(--accent);color:#fff}
#q:focus{outline:2px solid var(--accent);outline-offset:2px}
.chip{min-height:36px}.chip.on{background:#d5f36c;border-color:var(--fg);color:var(--fg)}
.card{padding:17px 20px}.card:hover{transform:none}.card.t1{background:var(--bg-1)}
.card-t h3{font-size:17px}.card .why{font-size:14px}.b.tier1{background:#d5f36c;color:var(--fg)}
.era-bar h2{font:400 28px/1.1 var(--serif)}.era-essay{padding:22px;font-size:17px;border-left:1px solid var(--line-2)}
.topic-card{padding:24px}.topic-card h3{font-size:21px;font-weight:500}.topic-card p{font-size:15px}
.prose p,.prose li{font-size:18px}.path{padding:28px}.path h3{font:400 29px/1.1 var(--serif)}
.btn.primary{color:white}.btn.primary:hover{background:var(--fg);border-color:var(--fg)}
.warn{color:#8c2942;background:#f9e6e8;border-color:#d8acb4}.warn.unver,.b.unver{color:#78420d;background:#f6ead4;border-color:#c6a674}
.detail h2{font:400 32px/1.12 var(--serif)}.detail-close{width:40px;height:40px;border-radius:0}
:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
@media(max-width:720px){.top-in>.brand{display:none}.top-in{gap:8px;padding-block:10px}.hero{padding-top:38px}.topic-grid{grid-template-columns:1fr}.card{padding:14px}.era-essay{font-size:16px}.detail h2{font-size:28px}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{transition:none!important}}
