/* =========================================================
   Hamid Mozaffari — personal site
   Minimal academic styling.
   ========================================================= */

:root {
  --bg:           #fdfdfc;
  --bg-soft:      #f5f3ee;
  --rule:         #e6e2d8;
  --ink:          #1a1a1a;
  --ink-soft:     #4a4a4a;
  --ink-mute:     #7a7670;
  --accent:       #8a1538;       /* UMass-inspired deep maroon */
  --accent-soft:  #b8576b;
  --max-width:    980px;
  --serif:        "Source Serif Pro", "Charter", "Iowan Old Style", "Apple Garamond", Georgia, ui-serif, serif;
  --sans:         "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono:         ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #14161a;
    --bg-soft:   #1c1f25;
    --rule:      #2a2e36;
    --ink:       #e9e6df;
    --ink-soft:  #c4bfb4;
    --ink-mute:  #8a8478;
    --accent:    #e88aa0;
    --accent-soft: #c45d76;
  }
}

/* ---- Reset ---- */
*, *::before, *::after { box-sizing: border-box; }
/* The nav is sticky and 56px tall, so an anchor jump (#selected-publications, a post
   linking back to one of its own sections) would land with the heading hidden under it. */
html { -webkit-text-size-adjust: 100%; scroll-padding-top: 72px; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---- Layout ---- */
.wrap {
  max-width: var(--max-width);
  padding: 0 24px;
  margin: 0 auto;
}

/* ---- Top nav ---- */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: saturate(140%) blur(6px);
  border-bottom: 1px solid var(--rule);
}
.site-nav .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
}
.brand {
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink);
  text-decoration: none;
}
.brand em {
  color: var(--ink-mute);
  font-style: normal;
  font-weight: 400;
}
.nav-links {
  display: flex;
  gap: 22px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.nav-links a {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color 0.15s, border-color 0.15s;
}
.nav-links a:hover,
.nav-links a.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.nav-toggle {
  display: none;
  background: none;
  border: 0;
  color: var(--ink);
  font-size: 1.4rem;
  cursor: pointer;
}

/* ---- Hero ---- */
.hero {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 44px;
  align-items: start;
  padding: 64px 0 40px;
}
.hero-side {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.hero-photo {
  width: 220px;
  height: auto;
  border-radius: 4px;
  border: 1px solid var(--rule);
}
.hero-name {
  font-family: var(--serif);
  font-size: 2.4rem;
  line-height: 1.15;
  margin: 0 0 6px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.hero-affil {
  margin: 0 0 18px;
  color: var(--ink-mute);
  font-size: 1.02rem;
}
.hero-affil a { color: inherit; text-decoration: underline; text-decoration-color: var(--rule); }
.hero-affil a:hover { color: var(--accent); text-decoration-color: var(--accent); }

.hero-bio {
  margin: 0 0 22px;
  color: var(--ink-soft);
  font-size: 1.02rem;
}
.hero-bio a { color: var(--accent); text-decoration: none; border-bottom: 1px solid var(--rule); }
.hero-bio a:hover { border-bottom-color: var(--accent); }

.socials {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.socials li {
  line-height: 1.2;
  display: flex;
  align-items: center;
  gap: 9px;
}
.social-ico {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  fill: var(--ink-mute);
  transition: fill 0.15s;
}
.socials li:hover .social-ico { fill: var(--accent); }
.socials a {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.92rem;
  letter-spacing: 0.02em;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1px;
  transition: color 0.15s, border-color 0.15s;
}
.socials a:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* ---- Sections ---- */
.section { padding: 36px 0; border-top: 1px solid var(--rule); }
.section:first-of-type { border-top: 0; }
.section h2 {
  font-family: var(--serif);
  font-size: 1.45rem;
  font-weight: 600;
  margin: 0 0 18px;
  letter-spacing: -0.005em;
}
.section h2 .anchor {
  color: var(--ink-mute);
  text-decoration: none;
  margin-left: 8px;
  font-size: 0.85em;
  opacity: 0;
  transition: opacity 0.15s;
}
.section h2:hover .anchor { opacity: 1; }

.section p, .section li { color: var(--ink-soft); }
.section a { color: var(--accent); text-decoration: none; border-bottom: 1px solid var(--rule); }
.section a:hover { border-bottom-color: var(--accent); }

/* ---- News ---- */
.news {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
}
.news li {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 16px;
  align-items: baseline;
  font-size: 0.98rem;
}
.news .date {
  font-variant-numeric: tabular-nums;
  color: var(--ink-mute);
  font-family: var(--mono);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
}

/* ---- Research interests as chips ---- */
.interests {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.interests li {
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

/* ---- Publications ---- */
.pub-list { list-style: none; margin: 0; padding: 0; }
.pub {
  display: grid;
  grid-template-columns: 88px 1fr;
  gap: 22px;
  padding: 18px 0;
  border-top: 1px dashed var(--rule);
}
.pub:first-child { border-top: 0; }
.pub-year {
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink-mute);
  letter-spacing: 0.04em;
  padding-top: 4px;
}
.pub-title {
  font-family: var(--serif);
  font-size: 1.08rem;
  margin: 0 0 4px;
  line-height: 1.35;
  font-weight: 600;
}
.pub-title a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.pub-title a:hover { color: var(--accent); border-bottom-color: var(--accent); }
.pub-authors { margin: 0 0 4px; color: var(--ink-soft); font-size: 0.97rem; }
.pub-authors strong { color: var(--ink); font-weight: 600; }
.pub-venue {
  margin: 0;
  color: var(--ink-mute);
  font-size: 0.92rem;
  font-style: italic;
}
.pub-links { margin: 6px 0 0; display: flex; gap: 14px; flex-wrap: wrap; }
.pub-links a {
  font-size: 0.85rem;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
}
.pub-links a:hover { border-bottom-color: var(--accent); }

/* ---- Blog ---- */
.blog-intro {
  padding: 56px 0 8px;
  max-width: 680px;
  margin-left: auto;
  margin-right: auto;
}
.blog-intro h1 {
  font-family: var(--serif);
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0 0 16px;
}
.blog-intro p {
  color: var(--ink-soft);
  font-size: 1.05rem;
  margin: 0;
}
.blog-intro p + p { margin-top: 14px; }

.post-list {
  list-style: none;
  max-width: 680px;          /* same column as .blog-intro above it, so the left edges line up */
  margin: 0 auto;
  padding: 28px 0 24px;
}
.post-list li {
  padding: 22px 0;
  border-top: 1px solid var(--rule);
}
.post-list li:first-child { border-top: 0; }
.post-list .date {
  display: block;
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink-mute);
  letter-spacing: 0.02em;
  margin-bottom: 6px;
}
.post-list h2 {
  font-family: var(--serif);
  font-size: 1.3rem;
  font-weight: 600;
  margin: 0 0 6px;
  line-height: 1.3;
}
.post-list h2 a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}
.post-list h2 a:hover { color: var(--accent); border-bottom-color: var(--accent); }
.post-list p {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.98rem;
}

/* ---- Single post / static page ---- */
/* The 680px reading column is narrower than the 980px .wrap, so it needs auto side
   margins to sit on the page's centre line — without them all the slack collects on
   one side and the column reads as off-axis against the full-width nav and footer. */
.post {
  max-width: 680px;
  padding: 48px 0 24px;
  margin-left: auto;
  margin-right: auto;
}
.post .back {
  display: inline-block;
  font-size: 0.88rem;
  color: var(--ink-mute);
  text-decoration: none;
  margin-bottom: 24px;
  border-bottom: 1px solid transparent;
}
.post .back:hover { color: var(--accent); border-bottom-color: var(--accent); }
.post .date {
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink-mute);
  letter-spacing: 0.02em;
}
.post h1 {
  font-family: var(--serif);
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: 8px 0 24px;
}
.post p {
  color: var(--ink-soft);
  font-size: 1.05rem;
  margin: 0 0 20px;
}
/* Sized against the bold body text they outrank: a serif face reads optically smaller
   than Inter at the same px, so 1.3rem sat level with a bold lead-in rather than above it. */
.post h2 {
  font-family: var(--serif);
  font-size: 1.8rem;
  font-weight: 600;
  line-height: 1.25;
  margin: 42px 0 14px;
}
/* Subsection inside a section. Smaller and tighter above than an h2 so the hierarchy
   reads at a glance; the contents list stays h2-only. */
.post h3 {
  font-family: var(--serif);
  font-size: 1.42rem;
  font-weight: 600;
  line-height: 1.3;
  margin: 32px 0 10px;
  color: var(--ink);
}
.post a { color: var(--accent); text-decoration: none; border-bottom: 1px solid var(--rule); }
.post a.back { border-bottom: 1px solid transparent; }
.post a:hover { border-bottom-color: var(--accent); }
.post pre {
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 14px 16px;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--ink);
  margin: 0 0 20px;
}
.post code {
  font-family: var(--mono);
  font-size: 0.88em;
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 1px 5px;
}
.post pre code { background: none; border: 0; padding: 0; font-size: 1em; }
.post ul {
  color: var(--ink-soft);
  font-size: 1.05rem;
  margin: 0 0 20px;
  padding-left: 22px;
}
.post ul li { margin-bottom: 10px; }
.post ul li::marker { color: var(--ink-mute); }
.post strong { color: var(--ink); font-weight: 600; }

/* Figures sit in the 680px reading column, the same measure as the prose — nothing
   extends past the text. The source plots are 2100–2500px wide, so they scale down a
   long way; clicking one opens it fitted to the window in the lightbox, and clicking
   again drops to full resolution, which is where the fine axis labels are read. Height
   is still capped so a very tall plot cannot outrun the window. */
.post figure {
  margin: 34px 0 28px;
}
.post figure img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 82vh;
  height: auto;
  margin: 0 auto;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: #fff;          /* plots carry an alpha channel — keep them readable in dark mode */
  cursor: zoom-in;
}
.post figcaption {
  margin: 10px auto 0;
  color: var(--ink-mute);
  font-size: 0.86rem;
  line-height: 1.5;
  text-align: center;
}

/* Tables */
.post .table-scroll {
  overflow-x: auto;
  margin: 0 0 22px;
}
/* Display equations. Rendered to finished markup by tools/md2post.py, so this styles
   real elements — no JavaScript runs on the page. The GRPO objective is wider than the
   680px column, so the block scrolls on its own rather than letting the page scroll
   sideways; the fade at the right edge is the hint that there is more to see. */
.post .math-display {
  overflow-x: auto;
  overflow-y: hidden;
  margin: 26px 0;
  padding: 6px 2px;
}
.post .math-display .katex-display {
  margin: 0;
}
/* Multi-row equations (\begin{aligned}) are set flush left. Centred, each block sits on
   its own centre line, so the GRPO objective and the PISmith loss below it — same shape,
   different widths — started 67px apart. Single-row equations stay centred. */
.post .math-display--stack .katex-display,
.post .math-display--stack .katex-display > .katex {
  text-align: left;
}
/* KaTeX inherits colour, so both themes come free. Display maths gets a touch more
   size than the body text; inline maths stays level with it so lines do not jump. */
.post .katex {
  font-size: 1.05em;
  color: var(--ink);
}
.post .math-display .katex {
  font-size: 1.12em;
}
.post p .katex {
  font-size: 1em;
}
.post table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.92rem;
  color: var(--ink-soft);
}
.post table th,
.post table td {
  text-align: left;
  padding: 9px 14px 9px 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
.post table thead th {
  color: var(--ink);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.01em;
  border-bottom: 1px solid var(--ink-mute);
  white-space: nowrap;
}
.post table tbody tr:last-child td { border-bottom: 0; }

/* Contents list at the head of a long post. A bare <details>, collapsed until clicked,
   so nothing about it needs JavaScript. */
.post-toc {
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--bg-soft);
  padding: 11px 16px;
  margin: 0 0 28px;
}
.post-toc summary {
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: 9px;
  list-style: none;                /* flex drops the marker anyway — supply our own */
  font-family: var(--sans);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.post-toc summary:hover { color: var(--accent); }
.post-toc summary::-webkit-details-marker { display: none; }
.post-toc summary::before { content: "▸"; font-size: 1.15em; }
.post-toc[open] summary::before { content: "▾"; }
.post-toc[open] summary { margin-bottom: 11px; }
.post-toc ol {
  margin: 0;
  padding-left: 24px;
  color: var(--ink-mute);
  font-size: 0.95rem;
}
.post-toc li { margin: 5px 0; }
/* Subsections, nested under their section and marked with a rule rather than a number —
   the numbering that matters is the section's. */
.post .post-toc ul {
  list-style: none;
  margin: 5px 0 9px;
  padding-left: 0;
  font-size: 0.88rem;
}
.post .post-toc ul li {
  margin: 3px 0;
  padding-left: 15px;
  position: relative;
}
.post .post-toc ul li::before {
  content: "–";
  position: absolute;
  left: 0;
  color: var(--ink-mute);
}
.post .post-toc a { color: var(--ink-soft); border-bottom-color: transparent; }
.post .post-toc a:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* ---- Rollout explorer (post appendix) ----
   Four held-out documents, each attacked by three policies. The comparison only works
   if the three columns are visible at once, so this breaks out of the 680px reading
   column the same way figures do and drops to one column per policy on a phone.
   Everything is in the HTML; the inline script in the post only toggles `hidden`. */
.rollout-explorer {
  width: min(1180px, 94vw);
  margin: 30px 0 28px;
  margin-left: 50%;
  transform: translateX(-50%);
  --ok:     #177a52;
  --ok-bg:  rgba(23, 122, 82, 0.09);
  --no:     #a8383b;
  --no-bg:  rgba(168, 56, 59, 0.09);
  --warn:   #8a6a17;
}
@media (prefers-color-scheme: dark) {
  .rollout-explorer {
    --ok:    #62d39c;
    --ok-bg: rgba(98, 211, 156, 0.13);
    --no:    #ee8f8f;
    --no-bg: rgba(238, 143, 143, 0.13);
    --warn:  #d9b45c;
  }
}

/* The appendix's own intro table is the three policies the explorer compares, so it
   breaks out to the widget's width and lines its columns up with the cards below —
   at prose width its cells wrap to five lines each. The prose around it does not move. */
.rx-intro .table-scroll {
  width: min(1180px, 94vw);
  margin-left: 50%;
  transform: translateX(-50%);
}
.rx-intro table th:first-child,
.rx-intro table td:first-child { width: 22%; }

/* Document picker */
.rx-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}
.rx-tab {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 14px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--bg);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.88rem;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.rx-tab:hover { border-color: var(--accent-soft); color: var(--ink); }
.rx-tab.is-on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
@media (prefers-color-scheme: dark) { .rx-tab.is-on { color: #1a1216; } }
.rx-tab-id {
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  opacity: 0.65;
}

.post .rx-lede {
  font-size: 0.98rem;
  margin: 0 0 16px;
}
.rx-src {
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--ink-mute);
  white-space: nowrap;
}

/* What was asked, and what the attacker wants instead */
.rx-setup {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 14px;
}
.rx-task {
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 12px 14px;
  background: var(--bg-soft);
}
.rx-task--inj { border-left: 3px solid var(--accent); }
/* The card is already a box — the transcript inside it should not be a second one. */
.post .rx-task .rx-pre { background: none; border: 0; padding: 0; }
.rx-stage-label {
  display: block;
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 7px;
}
.rx-doc {
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 10px 14px;
  margin-bottom: 20px;
}
.rx-doc summary {
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--ink-soft);
  display: flex;
  align-items: baseline;
  gap: 10px;
  list-style: none;                /* flex drops the marker anyway — supply our own */
}
.rx-doc summary::-webkit-details-marker { display: none; }
.rx-doc summary::before {
  content: "▸";
  color: var(--ink-mute);
  font-size: 0.8em;
}
.rx-doc[open] summary::before { content: "▾"; }
.rx-doc[open] summary { margin-bottom: 12px; }

/* Three policies, same document */
.rx-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  align-items: stretch;
}
/* Cards stretch to the tallest column and the verdict bar is pushed to the bottom, so
   the three judgements sit on one line and can be compared without hunting for them. */
.rx-policy {
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 14px;
  background: var(--bg);
  border-top: 3px solid var(--ink-mute);
}
.rx-att { display: flex; flex-direction: column; flex: 1; }
/* An author `display` beats the UA sheet's rule for [hidden], and the script hides
   panels with that attribute — without this every rollout shows at once. */
.rollout-explorer [hidden] { display: none; }
.rx-att .rx-verdict { margin-top: auto; }
.rx-policy--vanilla { border-top-color: var(--accent-soft); }
.rx-policy--final   { border-top-color: var(--accent); }
.rx-policy-head h4 {
  font-family: var(--serif);
  font-size: 1rem;
  font-weight: 600;
  margin: 0 0 10px;
  color: var(--ink);
}
.rx-meter {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 14px;
}
.rx-cells { display: flex; gap: 3px; }
.rx-cell {
  width: 9px;
  height: 14px;
  border-radius: 2px;
  background: var(--rule);
}
.rx-cell.is-on { background: var(--ok); }
.rx-meter-n {
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--ink-mute);
  white-space: nowrap;
}

/* Rollout picker */
.rx-picker { display: flex; gap: 8px; margin-bottom: 12px; }
.rx-roll {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 7px 10px;
  border: 1px solid var(--rule);
  border-radius: 7px;
  background: var(--bg-soft);
  color: var(--ink-soft);
  font-family: var(--mono);
  font-size: 0.76rem;
  text-align: left;
  cursor: pointer;
}
.rx-roll em {
  font-style: normal;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.rx-roll--ok em { color: var(--ok); }
.rx-roll--no em { color: var(--no); }
.rx-roll:hover { border-color: var(--ink-mute); }
.rx-roll--ok.is-on { border-color: var(--ok); background: var(--ok-bg); color: var(--ink); }
.rx-roll--no.is-on { border-color: var(--no); background: var(--no-bg); color: var(--ink); }

/* Transcript panes */
.rx-stage { margin-bottom: 8px; }
.rx-stage-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 6px;
}
.rx-stage-head .rx-stage-label { margin: 0; flex: 1; }
.rx-chars {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-mute);
  white-space: nowrap;
}
.rx-expand {
  border: 0;
  background: none;
  padding: 0;
  font-family: var(--sans);
  font-size: 0.72rem;
  color: var(--accent);
  cursor: pointer;
  border-bottom: 1px solid transparent;
}
.rx-expand:hover { border-bottom-color: var(--accent); }
.post .rx-pre {
  margin: 0;
  padding: 11px 12px;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--ink-soft);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 16em;
  overflow-y: auto;
}
.post .rx-pre--short { max-height: none; }
.rx-stage.is-open .rx-pre { max-height: none; }
.rx-flow {
  font-family: var(--sans);
  font-size: 0.72rem;
  color: var(--ink-mute);
  text-align: center;
  margin: 10px 0 12px;
}
.rx-flow::before { content: "↓  "; }
.post .rx-note {
  font-size: 0.76rem;
  line-height: 1.5;
  color: var(--ink-mute);
  margin: 8px 0 0;
}

/* Verbatim echoes: the injected task restated inside the payload, and the exact
   string the target was told to emit turning up in its reply. */
.rollout-explorer mark {
  background: rgba(138, 21, 56, 0.12);
  color: inherit;
  border-radius: 2px;
  padding: 0 1px;
  box-shadow: inset 0 -1px 0 rgba(138, 21, 56, 0.45);
}
.rollout-explorer mark.rx-mark-marker {
  background: var(--ok-bg);
  box-shadow: inset 0 -1px 0 var(--ok);
}
@media (prefers-color-scheme: dark) {
  .rollout-explorer mark {
    background: rgba(232, 138, 160, 0.16);
    box-shadow: inset 0 -1px 0 rgba(232, 138, 160, 0.5);
  }
}

/* Verdict */
.rx-verdict {
  margin-top: 10px;
  padding: 9px 11px;
  border-radius: 7px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.rx-verdict--ok { background: var(--ok-bg); border: 1px solid var(--ok); }
.rx-verdict--no { background: var(--no-bg); border: 1px solid var(--no); }
.rx-outcome {
  font-family: var(--mono);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.08em;
}
.rx-verdict--ok .rx-outcome { color: var(--ok); }
.rx-verdict--no .rx-outcome { color: var(--no); }
.rx-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.rx-chip {
  font-family: var(--sans);
  font-size: 0.7rem;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--bg);
  color: var(--ink-soft);
  white-space: nowrap;
}
.rx-chip--ok   { color: var(--ok); border-color: var(--ok); }
.rx-chip--no   { color: var(--no); border-color: var(--no); }
.rx-chip--warn { color: var(--warn); border-color: var(--warn); }

.post .rx-closing {
  font-size: 0.8rem;
  color: var(--ink-mute);
}

@media (max-width: 900px) {
  .rx-grid { grid-template-columns: 1fr; }
  .rx-setup { grid-template-columns: 1fr; }
  .post .rx-pre { max-height: 22em; }
}

.legal { color: var(--ink-mute); font-size: 0.92rem; }

/* ---- Disclaimer footnote ---- */
.blog-footnote {
  max-width: 680px;
  margin: 40px auto 0;
  padding-top: 16px;
  border-top: 1px solid var(--rule);
}
.blog-footnote p {
  margin: 0;
  color: var(--ink-mute);
  font-size: 0.76rem;
  line-height: 1.55;
}
.blog-footnote sup { font-size: 0.72em; margin-right: 3px; }

/* ---- Bobby photo grid ---- */
.bobby-intro {
  padding: 56px 0 8px;
  max-width: 680px;
}
.bobby-intro h1 {
  font-family: var(--serif);
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0 0 16px;
}
.bobby-intro p {
  color: var(--ink-soft);
  font-size: 1.05rem;
  margin: 0 0 16px;
}
.bobby-intro p:last-child { margin-bottom: 0; }

.photo-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  padding: 28px 0 8px;
}
.photo-grid figure {
  margin: 0;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: 6px;
  border: 1px solid var(--rule);
  background: var(--bg-soft);
  cursor: zoom-in;
}
.photo-grid img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.3s ease;
}
.photo-grid figure:hover img { transform: scale(1.04); }

/* Lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: rgba(0, 0, 0, 0.86);
  cursor: zoom-out;
}
.lightbox.open { display: flex; }
.lightbox img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 4px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
  cursor: zoom-in;
}
/* Second click drops the fit-to-window limit and shows the plot at its own resolution,
   with the overlay scrolling — the source images are up to 2500×3240, so fitting them
   to the window is still a 3× downscale on the densest panels. */
.lightbox.zoomed {
  align-items: flex-start;
  justify-content: flex-start;
  overflow: auto;
}
.lightbox.zoomed img {
  max-width: none;
  max-height: none;
  margin: auto;
  cursor: zoom-out;
}
.lightbox-close {
  position: absolute;
  top: 18px;
  right: 24px;
  background: none;
  border: 0;
  color: #fff;
  font-size: 2rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0.8;
}
.lightbox-close:hover { opacity: 1; }

@media (max-width: 720px) {
  .photo-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
}

/* ---- Footer ---- */
.site-footer {
  border-top: 1px solid var(--rule);
  padding: 28px 0 60px;
  margin-top: 40px;
  color: var(--ink-mute);
  font-size: 0.86rem;
  text-align: center;
}
.site-footer a { color: var(--ink-soft); text-decoration: none; border-bottom: 1px solid var(--rule); }
.site-footer a:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* ---- Responsive ---- */
@media (max-width: 720px) {
  body { font-size: 16px; }
  .hero {
    grid-template-columns: 1fr;
    gap: 22px;
    padding: 36px 0 24px;
    text-align: center;
  }
  .hero-side { align-items: center; }
  .hero-photo { width: 160px; height: auto; margin: 0 auto; }
  .hero-name { font-size: 1.9rem; }
  .socials { align-items: center; }
  .news li { grid-template-columns: 1fr; gap: 2px; }
  .news .date { font-size: 0.78rem; }
  .pub { grid-template-columns: 1fr; gap: 4px; }
  .pub-year { padding-top: 0; }
  .nav-links {
    display: none;
    position: absolute;
    top: 56px; left: 0; right: 0;
    flex-direction: column;
    background: var(--bg);
    border-bottom: 1px solid var(--rule);
    padding: 14px 24px;
    gap: 14px;
  }
  .nav-links.open { display: flex; }
  .nav-toggle { display: inline-block; }
}

@media print {
  .site-nav, .site-footer, .nav-toggle { display: none; }
  body { background: white; color: black; }
  a { color: black; border: 0 !important; }
}
