/* =============================================================================
   Atlassian Spacing Tokens — 8px base unit
   Shared conventions with the Penn MEDIATED /about, /home, and /grants repos.
   ============================================================================= */
:root {
  --space-025:   2px;
  --space-050:   4px;
  --space-075:   6px;
  --space-100:   8px;
  --space-150:  12px;
  --space-200:  16px;
  --space-250:  20px;
  --space-300:  24px;
  --space-400:  32px;
  --space-500:  40px;
  --space-600:  48px;
  --space-800:  64px;
  --space-1000: 80px;

  /* ── Brand colour tokens ── */
  --c-dark:       #0d0d0c;
  --c-accent:     #5533ee;   /* brand purple */
  --c-red:        #f03d1f;   /* brand red/orange — the tool's single active/hover accent */
  /* Deeper red-orange — the gradient's closing stop, promoted to a token
     of its own. Link text on a white/light ground uses this: --c-red
     only reaches ~3.9:1 against white, this clears 4.5:1. --c-red stays
     the brand accent for fills, borders, icons, tags and labels. */
  --c-red-dark:   #df3611;
  --c-gray:       #888680;
  --c-gray-dark:  #54534f;   /* ~8:1 contrast on white */
  --c-light-bg:   #f8f7f4;
  --c-white:      #ffffff;
  --c-border:     rgba(13,13,12,0.08);   /* shared hairline, matches every sibling repo */
  --c-pale-red:   #fce4dc;               /* --c-red tinted ~12% onto white, matches /grants' --c-pale-orange */

  /* ── Typography tokens ── */
  /* Two families, no third — and the split is by what the text IS, not by
     heading level. --f-serif: page titles, and titles of works or names of
     people (a post title, a paper title, a person's name), plus pull-quote
     copy. --f-sans: section headings, card and UI labels, running prose,
     metadata, controls and uppercase micro-labels.
     The one that trips people up: a SECTION HEADING IS NOT SERIF. Serif
     marks a thing that has its own name; sans marks the furniture around
     it. See README -> Typography. */
  --f-serif: 'EB Garamond', Georgia, 'Times New Roman', serif;
  --f-sans:  'DM Sans', system-ui, -apple-system, sans-serif;

  /* ── Type scale (sitewide — see README) ──
     The page header and the left column's two scrolling detail boxes
     (#faculty-bio, #paper-detail) use this scale. The rest of the app
     body is a fixed-viewport layout whose dense cards and SVG labels
     are sized independently — see the README's "A note on this page's
     layout". */
  --fs-display:     clamp(36px, 22.7px + 3.70vw, 76px);
  --fs-h1:          clamp(36px, 29.3px + 1.85vw, 56px);
  --fs-h2:          clamp(26px, 21.3px + 1.30vw, 40px);
  --fs-h3:          clamp(20px, 18.7px + 0.37vw, 24px);
  --fs-lede:        clamp(18px, 17.3px + 0.19vw, 20px);
  --fs-body:        16px;
  --fs-small:       14px;
  --fs-small-serif: 15px;
  --fs-micro:       12px;

  --lh-display: 1.05;
  --lh-heading: 1.15;
  --lh-lede:    1.26;
  --lh-title:   1.3;
  --lh-body:    1.55;

  /* ── Categorical colors for the network diagram's actor nodes ──
     Rooted in the brand palette (purple + red) with earthy/teal
     complements added only where a data-vis needs more distinct hues
     than the two-color brand system provides. */
  --actor-gov:    #4b2fc9;   /* Governments — deep brand purple */
  --actor-media:  #1f6f4a;   /* Digital News — forest green */
  --actor-social: #0f7d75;   /* Social Media — teal */
  --actor-tv:     #b3261e;   /* Broadcast TV — muted brick red */
  --actor-llm:    #7c3aed;   /* LLMs — violet */
  --actor-elite:  #6b5b1f;   /* Elites — bronze/olive */
  --actor-public: var(--c-gray);   /* General Public — muted neutral */
  --neutral-line: #c9c6bf;  /* inactive arrow/icon neutral */
}

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

html, body {
  /* No height: 100% and no overflow: hidden here. Inside the iframe this page
     is embedded in, html/body at 100% resolve to the FRAME's height, which is
     itself set from the height this page reports — the same circular loop
     100vh creates (see #page). With overflow: hidden on top of it, the
     reported height could never exceed the frame either, so it froze. #page
     carries the definite height instead and body sizes to it. */
  overflow-x: hidden;
  background: var(--c-light-bg);
  font-family: var(--f-sans);
  color: var(--c-dark);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; height: auto; display: block; }

/* ── PAGE SHELL ─────────────────────────────
   Fixed-height 3-column app — the diagram tool needs a definite height so
   its panes can scroll internally.

   NOT 100vh. This page is embedded in an iframe that reports its own content
   height back to the parent and is resized to match. With 100vh, that loop
   is circular: the frame sets the viewport, the viewport sets 100vh, 100vh
   sets the body, and the body sets the frame — so the height freezes at
   whatever the frame happened to start at instead of settling on the
   content. Measured before this fix: 3000px reported at a 390px-wide
   viewport and 900px at 1440px, neither of which was the real content
   height. A fixed px height gives the resize script something true to
   report. ── */
#page { display: flex; flex-direction: column; height: 900px; }

/* ── HEADER ─────────────────────────────── */
#hdr {
  flex-shrink: 0;
  background: var(--c-white);
  border-bottom: 2px solid var(--c-dark);
  padding: var(--space-300) var(--space-400) var(--space-250);
  display: flex; align-items: flex-start;
  gap: var(--space-400); justify-content: space-between;
}
#hdr-left { min-width: 0; flex: 1; }

#hdr h1 {
  font-family: var(--f-serif);
  font-size: var(--fs-h3); font-weight: 600; color: var(--c-accent);
  line-height: var(--lh-heading); margin-bottom: var(--space-050);
}
#hdr p.hdr-desc {
  font-family: var(--f-sans);
  font-size: var(--fs-small); font-weight: 400;
  color: var(--c-dark); line-height: var(--lh-body);
  max-width: 820px;
}

/* ── MAIN BODY ───────────────────────────── */
#main { flex: 1; min-height: 0; display: flex; overflow: hidden; }

/* ── BOTTOM SPACER ───────────────────────────
   A plain white strip along the very bottom edge so the app's content
   doesn't sit flush against the browser/iframe edge. #main (flex: 1)
   yields this space automatically, so the app still fills exactly the
   #page height with no scrolling introduced. ── */
#page-bottom-spacer { flex-shrink: 0; height: var(--space-300); background: var(--c-white); }

/* ── LEFT COLUMN (faculty bio + paper detail) ─────────── */
#left-col {
  width: 520px; flex-shrink: 0;
  display: flex; flex-direction: column;
  background: var(--c-light-bg);
  border-right: 1px solid var(--c-border);
  min-height: 0; overflow-y: auto;
}

/* ── SVG AREA ────────────────────────────── */
#svg-area {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: var(--space-100) var(--space-075) var(--space-075);
  background: var(--c-light-bg);
}
#svg-wrap { width: 100%; }
/* Direct-child combinator only — the diagram nests small icon <svg>
   elements many levels deep inside <g>s, and a plain descendant
   selector here would stretch every one of those to 100% width too. */
#svg-wrap > svg { display: block; width: 100%; height: auto; }

/* ── RIGHT PANEL ─────────────────────────── */
#panel {
  width: 420px; flex-shrink: 0;
  display: flex; flex-direction: column;
  background: var(--c-white); border-left: 1px solid var(--c-border);
  overflow: hidden;
}

/* actor detail card inside panel */
#actor-card {
  display: none; flex-shrink: 0;
  padding: var(--space-150) var(--space-200) var(--space-150);
  border-bottom: 1px solid var(--c-border);
}
#actor-card.visible { display: block; }
.a-tag {
  font-family: var(--f-sans);
  font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 1.2px; margin-bottom: var(--space-050);
}
.a-title {
  font-family: var(--f-serif);
  font-size: 16px; font-weight: 600; margin-bottom: var(--space-100); line-height: 1.3;
}
.a-desc {
  font-family: var(--f-sans);
  font-size: 13px; font-weight: 400; color: var(--c-gray-dark);
  line-height: 1.65; margin-bottom: var(--space-150);
}
.a-faculty {
  font-family: var(--f-sans);
  font-size: 12px; color: var(--c-gray-dark); line-height: 1.65;
  border-top: 1px solid var(--c-border); padding-top: var(--space-100);
}
.a-faculty-label {
  font-weight: 700; color: var(--c-dark); display: block;
  margin-bottom: var(--space-025); text-transform: uppercase;
  letter-spacing: 0.5px; font-size: 9px;
}

/* hint */
#panel-hint {
  flex-shrink: 0;
  padding: var(--space-150) var(--space-200);
  font-family: var(--f-serif);
  font-size: 13px; font-weight: 400; font-style: italic;
  color: var(--c-gray-dark); line-height: 1.6;
  border-bottom: 1px solid var(--c-border);
}
#panel-hint.hidden { display: none; }

/* paper cards list */
#paper-cards {
  flex: 1; overflow-y: auto; padding: var(--space-100) var(--space-150) var(--space-100);
  display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--space-075);
  align-content: stretch;
}
#paper-cards::-webkit-scrollbar { width: 3px; }
#paper-cards::-webkit-scrollbar-thumb { background: rgba(13,13,12,0.15); }

.arrow-g, .actor-g { cursor: pointer; touch-action: manipulation; }
.paper-card { touch-action: manipulation; }
#culhane-data-icon { touch-action: manipulation; }

.paper-card {
  border: 1.5px solid var(--c-border);
  padding: var(--space-100) var(--space-150); cursor: pointer;
  background: var(--c-white);
  display: flex; flex-direction: column; justify-content: center;
  transition: border-color 0.13s, background 0.13s;
}
.paper-card:hover { background: var(--c-light-bg); border-color: rgba(13,13,12,0.2); }
.paper-card.active {
  border-color: var(--c-red);
  background: var(--c-pale-red);
}
.card-name {
  font-family: var(--f-sans);
  font-weight: 700; font-size: 12.5px; color: var(--c-dark);
  line-height: 1.3; margin-bottom: var(--space-025);
}
.card-school {
  font-family: var(--f-serif);
  font-size: 10.5px; font-weight: 400; color: var(--c-gray);
  font-style: italic; line-height: 1.35;
}
.card-body {
  display: none; margin-top: var(--space-075); padding-top: var(--space-075);
  border-top: 1px solid var(--c-border);
}
.paper-card.active .card-body { display: block; }
.card-desc {
  font-family: var(--f-serif);
  font-size: 10px; font-weight: 400; color: var(--c-dark);
  line-height: 1.7; margin: 0;
}
.card-desc a { color: var(--c-red-dark); font-weight: 500; transition: opacity 0.15s; }
.card-desc a:hover { opacity: 0.7; }

/* card bodies are populated for accessibility but never expand inline —
   detail surfaces in the left-column paper-detail box instead */
.paper-card.active .card-body { display: none; }

/* faculty bio box — top of left column */
#faculty-bio {
  flex-shrink: 0;
  overflow: visible;
  background: var(--c-white);
  border-left: 3px solid var(--c-dark);
  border-bottom: 1.5px solid var(--c-border);
  border-top: none; border-right: none;
  padding: var(--space-200) var(--space-250) var(--space-250);
  box-shadow: 0 6px 22px rgba(13,13,12,0.06);
  display: none;
  flex-direction: column;
}
#faculty-bio.visible { display: flex; }
#fb-header {
  display: flex; align-items: flex-start;
  gap: var(--space-150); margin-bottom: var(--space-150); flex-shrink: 0;
}
#fb-photo {
  width: 72px; height: 72px;
  object-fit: cover; object-position: center top;
  flex-shrink: 0;
  display: none;
  border: 1px solid var(--c-border);
  background: var(--c-light-bg);
}
#fb-photo.visible { display: block; }
#fb-meta { flex: 1; min-width: 0; }
#fb-name-row {
  display: flex; align-items: center; gap: var(--space-150);
  margin-bottom: var(--space-025);
}
/* Box header — stays EB Garamond, on the sitewide scale. */
#fb-name {
  font-family: var(--f-serif);
  font-weight: 600; font-size: var(--fs-lede); color: var(--c-dark);
  line-height: var(--lh-title);
}
#fb-school {
  font-family: var(--f-sans);
  font-size: var(--fs-micro); font-weight: 500; color: var(--c-gray);
  line-height: var(--lh-title);
}
/* Body copy — DM Sans at --fs-small/--lh-body, matching #pd-desc below
   and the rest of the site. (It was EB Garamond at a hand-set 14px/1.75;
   running prose is sans sitewide, serif is for headings.) */
#fb-bio {
  font-family: var(--f-sans);
  font-size: var(--fs-small); font-weight: 400; color: var(--c-dark);
  line-height: var(--lh-body); margin: 0;
}
#fb-bio a { color: var(--c-red-dark); font-weight: 500; transition: opacity 0.15s; }
#fb-bio a:hover { opacity: 0.7; }
#fb-website {
  display: none; flex-shrink: 0;
  font-family: var(--f-sans);
  font-size: var(--fs-micro); font-weight: 600;
  color: var(--c-dark);
  border-bottom: 1px solid rgba(13,13,12,0.35);
  padding-bottom: 1px;
  transition: color 0.15s, border-color 0.15s;
  white-space: nowrap;
}
#fb-website:hover { color: var(--c-red-dark); border-color: var(--c-red-dark); }
#fb-website.visible { display: inline-block; }

/* standalone paper detail box — bottom of left column */
#paper-detail {
  /* 40% of the 900px shell. Same reason as #page: no vh inside a
     self-sizing iframe. */
  height: 360px;
  overflow-y: auto;
  background: var(--c-white);
  border-left: 3px solid var(--c-red);
  border-top: 1.5px solid var(--c-border);
  border-right: none;
  border-bottom: none;
  padding: var(--space-200) var(--space-250) var(--space-300);
  box-shadow: 0 -6px 22px rgba(13,13,12,0.06);
  display: none;
}
#paper-detail.visible { display: block; }
/* Box header — stays EB Garamond, on the sitewide scale, matching
   #fb-name in the bio box above it. */
#pd-title {
  font-family: var(--f-serif);
  font-size: var(--fs-lede); font-weight: 600;
  color: var(--c-dark); line-height: var(--lh-title);
  margin-bottom: var(--space-150);
  transition: margin-bottom 0.3s ease;
}
/* Body copy — DM Sans at --fs-small/--lh-body, matching #fb-bio. */
#pd-desc {
  font-family: var(--f-sans);
  font-size: var(--fs-small); font-weight: 400; color: var(--c-gray-dark);
  line-height: var(--lh-body); margin: 0;
}
#pd-desc a { color: var(--c-red-dark); font-weight: 500; transition: opacity 0.15s; }
#pd-desc a:hover { opacity: 0.7; }
#pd-read-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-075);
  margin-top: var(--space-200);
  font-family: var(--f-sans);
  font-size: var(--fs-small); font-weight: 600;
  color: var(--c-dark);
  border-bottom: 1px solid rgba(13,13,12,0.35);
  padding-bottom: 2px;
  transition: color 0.15s, border-color 0.15s;
}
#pd-read-btn:hover { color: var(--c-red-dark); border-color: var(--c-red-dark); }
#pd-read-btn::after { content: '⟶'; }

/* ── RESPONSIVE ─────────────────────────────── */
@media (max-width: 820px) {
  html, body { height: auto; overflow-x: hidden; overflow-y: auto; }
  /* Content-sized below 820px: the columns have stacked, so there is nothing
     to scroll internally and the page should be exactly as tall as it is.
     min-height: 100vh here was the same circular trap as #page above. */
  #page      { height: auto; }

  #hdr {
    flex-direction: column;
    padding: var(--space-200) var(--space-200) var(--space-150);
    gap: var(--space-150);
  }

  #main { flex-direction: column; overflow: visible; height: auto; }

  #svg-area  { order: 1; width: 100%; flex: none; padding: var(--space-075) var(--space-050) var(--space-050);
               align-items: flex-start; justify-content: flex-start; }
  #panel     { order: 2; width: 100%; flex: none; height: auto;
               border-left: none; border-top: 1px solid var(--c-border);
               overflow: visible; }
  #left-col  { order: 3; width: 100%; flex: none; border-right: none;
               border-top: 1px solid var(--c-border);
               overflow-y: visible; min-height: 0; }

  #paper-cards {
    grid-template-columns: 1fr 1fr;
    flex: none; height: auto; overflow-y: visible;
    padding: var(--space-100);
  }

  #paper-detail { height: auto; min-height: 0; }
}

@media (max-width: 540px) {

  .card-name   { font-size: 12px; }
  /* #fb-bio / #pd-desc had 13px / 14px overrides here; both now sit on
     --fs-small (14px), which is already the narrow-viewport size and
     above the 12px floor, so there is nothing left to step down. */
}

/* ── Trailing-margin guard ─────────────────────────────────────────────────
   These pages are embedded in an iframe that is resized to the height this
   page reports, and that height is measured from document.body.

   A bottom margin on the last element COLLAPSES THROUGH body and out to
   <html>. It never appears in body.scrollHeight, but it does extend
   documentElement.scrollHeight — so the frame gets sized short of the real
   document, the embedded page is left with a few px it can scroll, and it
   swallows the visitor's wheel events: the outer page then only scrolls when
   the cursor is over its scrollbar. It has bitten twice (home, 64px;
   grants-overview, 80px) and it is invisible in the builder.

   display: flow-root makes body a block formatting context, so descendant
   margins can no longer escape it and the measured height is always the whole
   document. Cheap, and it removes a whole class of bug rather than one
   instance. If a page grows here, something was relying on a margin escaping
   — convert that margin to padding rather than removing this.
   ====================================================================== */
body { display: flow-root; }
