/* knuples.com — layout D3-b (golden ratio)
   Reference bundle: the four stylesheets of the prototype, in cascade order,
   with the review-only overlay rules removed. Order matters: later sections
   override earlier ones. */

/* ==========================================================================
   Tokens, fonts, base  (shared/golden.css)
   ========================================================================== */

/* ==========================================================================
   Golden tokens shared by all three variants.
   Every size, gap and ratio below is a power of φ (or a √φ half-step).
   ========================================================================== */

@font-face { font-family: "TeX Gyre Heros"; src: url("fonts/texgyreheros-regular.otf") format("opentype"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "TeX Gyre Heros"; src: url("fonts/texgyreheros-italic.otf") format("opentype"); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "TeX Gyre Heros"; src: url("fonts/texgyreheros-bold.otf") format("opentype"); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "TeX Gyre Heros"; src: url("fonts/texgyreheros-bolditalic.otf") format("opentype"); font-weight: 700; font-style: italic; font-display: swap; }

:root {
  --phi: 1.618;

  /* space: φ^-3 … φ^4 */
  --s-3: 0.236rem;
  --s-2: 0.382rem;
  --s-1: 0.618rem;
  --s0: 1rem;
  --s1: 1.618rem;
  --s2: 2.618rem;
  --s3: 4.236rem;
  --s4: 6.854rem;

  /* type: φ^n with √φ (1.272) half-steps */
  --t-1: 0.786rem;
  --t0: 1rem;
  --t05: 1.272rem;
  --t1: 1.618rem;
  --t15: 2.058rem;
  --t2: 2.618rem;
  --t3: 4.236rem;

  --sans: "TeX Gyre Heros", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* palette carried over from knuples.com */
  --bg: #fdfcfa;
  --surface: #f3f1ec;
  --ink: #111111;
  --ink-2: #404040;
  --ink-3: #6b6b6b;
  --rule: #d8d4cc;
  --accent: #0d9488;
  --accent-ink: #0a6f66;
  --guide: rgba(220, 38, 38, 0.55);
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #1f1f1f;
    --surface: #282828;
    --ink: #eeeeee;
    --ink-2: #c8c8c8;
    --ink-3: #9a9a9a;
    --rule: #3c3c3c;
    --accent: #2dd4bf;
    --accent-ink: #5eead4;
    --guide: rgba(251, 113, 133, 0.6);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --bg: #1f1f1f;
  --surface: #282828;
  --ink: #eeeeee;
  --ink-2: #c8c8c8;
  --ink-3: #9a9a9a;
  --rule: #3c3c3c;
  --accent: #2dd4bf;
  --accent-ink: #5eead4;
  --guide: rgba(251, 113, 133, 0.6);
  color-scheme: dark;
}

/* base 17px on desktop; GRT measure (17·φ)² ≈ 757px */
html { font-size: 15px; -webkit-text-size-adjust: 100%; }
@media (min-width: 40em) { html { font-size: 16px; } }
@media (min-width: 64em) { html { font-size: 17px; } }

*, *::before, *::after { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  line-height: var(--phi);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 0.18em; text-decoration-color: color-mix(in srgb, currentColor 35%, transparent); }
a:hover { color: var(--accent-ink); text-decoration-color: currentColor; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: absolute; left: var(--s0); top: -4rem; background: var(--ink); color: var(--bg); padding: var(--s-2) var(--s-1); z-index: 10; }
.skip:focus { top: var(--s0); }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* venue mark: a golden rectangle, s2 × s1 = 44.5 × 27.5 (ratio φ), border-box */
.pub-year[data-venue]::after {
  content: attr(data-venue);
  display: inline-grid;
  place-items: center;
  box-sizing: border-box;
  width: var(--s2);
  height: var(--s1);
  border: 1px solid var(--rule);
  font: 700 0.618rem/1 var(--sans);
  letter-spacing: 0.04em;
  color: var(--ink-2);
  vertical-align: middle;
  visibility: visible;  /* stays visible when a repeated year is hidden */
}

/* ==========================================================================
   D · centred column  (d/style.css)
   ========================================================================== */

/* Variant D · Golden Circle
   The original single centred column, rebuilt on φ:
   column = (17px · φ)² ≈ 44.5rem, circle = column / φ³, rules = column / φ. */

.col {
  --col: min(100vw - 2 * var(--s1), 44.5rem);
  width: var(--col);
  margin-inline: auto;
  padding-block: var(--s3) var(--s2);
  position: relative;
}

/* ---- masthead ---- */
.masthead { text-align: center; }
.avatar {
  width: calc(var(--col) * 0.236);
  aspect-ratio: 1;
  margin-inline: auto;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 18%;
  box-shadow: 0 0 0 var(--s-3) var(--bg), 0 0 0 calc(var(--s-3) + 1px) var(--rule);
}
.name {
  margin-top: var(--s1);
  font-size: var(--t1);
  line-height: 1.272;
  font-weight: 700;
}
.pronoun { margin-left: var(--s-2); }
.ipa { color: var(--ink-3); font-size: var(--t-1); }
.role { margin-top: var(--s-1); color: var(--ink); }
.email { margin-top: var(--s-3); font-size: var(--t-1); color: var(--ink-3); }

/* rules are always the major part (61.8 %) of the column, centred */
.intro::before, .section::before {
  content: ""; display: block;
  width: 61.8%; height: 1px; margin: 0 auto var(--s2);
  background: var(--rule);
}

/* ---- intro ---- */
.intro { margin-top: var(--s2); display: grid; gap: var(--s0); }
.lede { font-size: var(--t05); line-height: 1.5; }
.intro p:not(.lede) { color: var(--ink-2); }

/* ---- sections ---- */
.section { margin-top: var(--s2); }
/* section titles one √φ step below the name, so the name stays the top of the hierarchy */
.section-title { text-align: center; font-size: var(--t05); line-height: 1.272; margin-bottom: var(--s1); }

.pubs { display: grid; gap: var(--s1); }
.pub-year { font-weight: 700; color: var(--ink-3); font-size: var(--t0); margin-bottom: var(--s-2); font-variant-numeric: tabular-nums; }
.pub.same-year .pub-year { font-size: 0; } /* keep the venue mark, drop the repeated year */
/* type levels, one √φ step apart: name t1 › section t05 › paper t0 › authors t-1 */
.pub-title { font-size: var(--t0); line-height: 1.382; font-weight: 400; }
.pub-authors { margin-top: var(--s-3); font-size: var(--t-1); color: var(--ink-2); }
.pub-venue { font-style: italic; font-size: var(--t-1); color: var(--ink-2); }
.pub-links { display: flex; gap: var(--s0); margin-top: var(--s-2); font-size: var(--t-1); text-transform: uppercase; letter-spacing: 0.08em; }

/* the original's stacked dates, kept: column width 1 : φ³ */
.vita { display: grid; gap: var(--s1); }
.vita-item { display: grid; grid-template-columns: 1fr 6.854fr; column-gap: var(--s1); align-items: center; } /* 1 : φ⁴ */
.dates { display: flex; flex-direction: column; align-items: flex-start; font-variant-numeric: tabular-nums; color: var(--ink-2); line-height: 1.272; font-size: var(--t-1); }
.bar { width: 2px; height: var(--s-1); margin: var(--s-3) 0 var(--s-3) var(--s0); background: var(--rule); }

/* ---- footer ---- */
.foot { margin-top: var(--s3); text-align: center; font-size: var(--t-1); color: var(--ink-3); display: grid; gap: var(--s-1); }
.foot::before { content: ""; display: block; width: 23.6%; height: 1px; margin: 0 auto var(--s0); background: var(--rule); }
.social { display: flex; justify-content: center; gap: var(--s1); font-size: var(--t0); }

@media (max-width: 40em) {
  .col { --col: calc(100vw - 2 * var(--s1)); padding-top: var(--s2); }
  .avatar { width: calc(var(--col) * 0.382); }
}

/* ---- title page (D only): the header is centred on the upper golden line
   (38.2 % of the window height) and the first rule falls exactly on the
   lower one (61.8 %). The header box is 2 × 38.2 % tall so its centre is
   the 38.2 % line; a negative margin of 14.6 % (= 76.4 − 61.8) brings the
   rule back up to 61.8 %. Only on screens tall enough to hold it. ---- */

/* the rule is a grid item of .intro, so the grid gap would add to its
   margin; take it back so rule → text is exactly one φ step (s2) */
.intro::before { margin-bottom: calc(var(--s2) - var(--s0)); }

/* venue mark sits on the year line, one s-1 after the year */
.pub-year[data-venue]::after { margin-left: var(--s-1); }
.pub.same-year .pub-year[data-venue]::after { margin-left: 0; }

/* ==========================================================================
   D3 · axis  (d3/style.css)
   ========================================================================== */

/* Variant D3 · Circle, Hanging Years
   D, with years and dates hanging outside the measure.
   - hang = column / φ³ (the same width as the circle)
   - the block (hang + gutter + column) is centred in the window
   - the circle hangs too (its diameter is the hang), so circle, years and
     dates sit right of one axis and all text starts on it
   - margin items share the first baseline of their entry (grid baseline)
   - every margin item is right-aligned to one axis: the gutter */

@media (min-width: 64em) {
  .col {
    --hang: calc(var(--col) * 0.236);
    --reach: calc(var(--hang) + var(--s1));
    box-sizing: content-box;
    padding-left: var(--reach);
    /* centre hang + column together */
    margin-inline: auto;
    width: var(--col);
    /* the lede starts on the window's 38.2 % line */
    --pt: max(var(--s2), 38.2vh - var(--hang) - 2 * var(--s2) - 1px);
    padding-top: var(--pt);
  }

  /* one row = margin | text, pulled out over the padding */
  .pub,
  .vita-item {
    display: grid;
    grid-template-columns: var(--hang) var(--col);
    column-gap: var(--s1);
    margin-left: calc(-1 * var(--reach));
    align-items: baseline;
  }
  .pub > * { grid-column: 2; }

  /* the circle is column / φ³ wide — exactly the hang — so it hangs too,
     and the header reads from the same axis as everything below */
  .masthead {
    display: grid;
    /* lockup: square (circle) + golden rectangle (text, hang·φ × hang) */
    grid-template-columns: var(--hang) calc(var(--hang) * 1.618);
    column-gap: var(--s1);
    margin-left: calc(-1 * var(--reach));
    align-content: center;
    text-align: left;
  }
  .avatar { grid-column: 1; grid-row: 1 / 5; width: 100%; align-self: center; margin: 0; }
  .masthead > :not(.avatar) { grid-column: 2; }
  .name { margin-top: 0; align-self: end; }
  .email { align-self: start; }

  /* titles, rules and footer start on the axis instead of centring */
  .section-title, .foot { text-align: left; }
  .intro::before, .section::before, .foot::before { margin-left: 0; }
  .social { justify-content: flex-start; }

  .pub-year {
    grid-column: 1;
    grid-row: 1;
    margin: 0;
    text-align: right;
    font-weight: 400;
    color: var(--ink-3);
  }
  .pub-title { grid-row: 1; }
  .pub.same-year .pub-year { display: block; visibility: hidden; }

  /* dates, stacked end over start like the original site, so the margin
     stays one narrow column: the end on the entry's baseline, flush to the
     axis like the publication years; "– start" one √φ step smaller beneath */
  .dates {
    grid-column: 1;
    display: grid;
    grid-template-columns: max-content max-content;
    justify-content: end;
    align-items: baseline;
    column-gap: var(--s-2);
    font-size: var(--t0);
    color: var(--ink-3);
    line-height: inherit;
  }
  .dates span:first-child { grid-column: 2; grid-row: 1; justify-self: end; }
  .dates .bar { grid-column: 1; grid-row: 2; width: var(--s-1); height: 1px; margin: 0; align-self: center; background: currentColor; }
  .dates span:last-child { grid-column: 2; grid-row: 2; justify-self: end; font-size: var(--t-1); line-height: 1.272; }
  .vita-event { grid-column: 2; }
}

/* venue mark hangs under the year, right-aligned to the axis */
@media (min-width: 64em) {
  .pub-year[data-venue]::after { display: grid; margin: var(--s-2) 0 0 auto; }
  .pub.same-year .pub-year { font-size: inherit; }
}

/* ==========================================================================
   D3-b · margin labels, final tweaks  (d3-b/style.css)
   ========================================================================== */

/* Variant D3-b · Axis, margin labels
   D3, with the section titles moved into the margin too: set small and
   right-aligned to the axis, on the line of the section rule. Now every
   label sits left of the axis and every piece of content right of it. */

@media (min-width: 64em) {
  .section { position: relative; }
  .section-title {
    position: absolute;
    top: 0.5px;                       /* the rule's centre line */
    left: calc(-1 * var(--reach));
    width: var(--hang);
    transform: translateY(-50%);
    margin: 0;
    text-align: right;
    font-size: var(--t0);             /* one √φ step up from the other margin labels */
    line-height: 1;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--ink);
  }

  /* the stacked dates read clearly without a dash between them */
  .dates .bar { display: none; }
  .dates { column-gap: 0; }
}

/* pronunciation and email one √φ step up (13.4 → 17 px), still quieter than
   the name through colour; both must fit the header's golden text block */
.ipa, .email { font-size: var(--t0); }

/* show the photo from its very top, for room above the head */
.avatar { object-position: 50% 0%; }

/* footer links: a line icon before each label — icon = 1em (the label's
   size), gap = s-2, stroke φ px on a 24-unit grid; colour follows the link */
.social a { display: inline-flex; align-items: center; gap: var(--s-2); }
.icon {
  width: 1em; height: 1em; flex-shrink: 0;
  fill: none; stroke: currentColor; stroke-width: 1.618;
  stroke-linecap: round; stroke-linejoin: round;
}
