/* ==========================================================================
  Custom site styles
  Paired with scss/theme-light.scss and scss/theme-dark.scss
  ========================================================================== */


/* ==========================================================================
  1) Design tokens
  ========================================================================== */
  :root {
  /* Layout */
  --content-max: 680px; /* article width */
  --content-pad: clamp(1.25rem, 4vw, 2.25rem);

  /* Type stacks */
  --font-sans: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "Bodoni Moda", Georgia, "Times New Roman", serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;

  /* Radii */
  --radius-lg: 1.25rem;
  --radius-md: 0.75rem;

  /* Common widths */
  --projects-max: 1200px;
}


/* ==========================================================================
    2) Global layout + typography safety
    ========================================================================== */
.page-columns {
  gap: 2rem;
}

.page-columns .content,
.page-columns main.content {
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--content-pad);
  padding-right: var(--content-pad);
}

/* Only pages using page-layout: article */
#quarto-content.page-layout-article .content,
#quarto-content.page-layout-article main.content {
  max-width: var(--content-max);
}

/* Keep long code blocks from breaking layout */
pre {
  overflow: auto;
}


/* ==========================================================================
    3) Global media defaults
    ========================================================================== */
img,
figure img {
  border-radius: var(--radius-lg);
}


/* ==========================================================================
    3b) Typography
    Display sizes use Instrument Serif; section headings stay on Inter so the
    serif reads as a deliberate voice rather than the default for everything.
    ========================================================================== */
/* Bodoni Moda's opsz axis runs 6-96. Above roughly 36 the thin strokes thin out
   to hairlines on screen, so display sizes are held at 20 rather than matched to
   the point size, and small sizes drop to 8 where the face is drawn sturdier. */
h1,
.quarto-title-block .title,
.quarto-title .title {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: "opsz" 20;
  font-size: clamp(2.1rem, 3.4vw, 3.2rem);
  line-height: 1.08;
  letter-spacing: 0;
  text-wrap: balance;
}

h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-sans);
  letter-spacing: -0.015em;
}

h2 {
  font-weight: 700;
  font-size: 1.55rem;
}

h3 {
  font-weight: 650;
  font-size: 1.2rem;
}

/* Bootstrap leaves these at the default heading weight, which on Inter sat close
   enough to body copy that sub-sections stopped reading as headings. */
h4,
h5,
h6 {
  font-weight: 600;
}

/* Small uppercase mono label, used for eyebrows and section markers */
.eyebrow,
.page-tags-label {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.6;
}

/* Figures line up when numbers are tabular */
.kpi .value,
.quarto-listing .card-attribution {
  font-variant-numeric: tabular-nums;
}

/* The home page is being redesigned separately — keep it on the old sans type */
.home-h1,
.home-eyebrow {
  font-family: var(--font-sans);
}


/* ==========================================================================
    3c) KPI strip
    Lived only inside about.qmd's inline <style>, so the block used at the top of
    a case study rendered unstyled. Global now.
    ========================================================================== */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin: 1.75rem 0 2rem;
}

.kpi {
  border: 1px solid rgba(127, 127, 127, 0.25);
  border-radius: 14px;
  padding: 1rem;
  background: rgba(127, 127, 127, 0.06);
}

.kpi .label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.6;
  margin-bottom: 0.35rem;
}

.kpi .value {
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.35;
}

@media (max-width: 900px) {
  .kpi-grid {
    grid-template-columns: 1fr;
  }
}


/* ==========================================================================
    3d) Tag chips (About skills, and the full tag list on a project page)
    ========================================================================== */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
}

.chip {
  border: 1px solid rgba(127, 127, 127, 0.28);
  border-radius: 999px;
  padding: 0.35rem 0.75rem;
  font-size: 0.9rem;
  background: rgba(127, 127, 127, 0.06);
}

.page-tags {
  margin: 3rem 0 1rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(127, 127, 127, 0.22);
}

.page-tags-label {
  margin-bottom: 0.75rem;
}

.page-tags .chip {
  font-size: 0.8rem;
  padding: 0.25rem 0.6rem;
}


/* ==========================================================================
    4) Quarto meta + listing defaults
    ========================================================================== */
.quarto-title-meta,
.quarto-title-meta-contents {
  font-size: 0.92rem;
}

/* Add whitespace above page titles */
.quarto-title-block,
.quarto-title {
  margin-top: 1rem;
  padding-top: 0.75rem;
}

#quarto-content .quarto-title-block {
  margin-top: 1rem;
  padding-top: 0.75rem;
}


/* Default listing cards (general) */
.quarto-listing .card {
  border-radius: var(--radius-lg);
}

.quarto-listing .card .card-body {
  padding: 1.25rem;
}

.quarto-listing .card-title {
  margin-bottom: 0.35rem;
}

.quarto-listing .listing-description {
  margin-top: 0.35rem;
}


/* ==========================================================================
   Resume page
   Single source: resume.qmd renders this view and the downloadable PDF.
   ========================================================================== */

body.resume .quarto-title-block .title {
  margin-bottom: 0.35rem;
}

.resume-contact {
  font-size: 0.9rem;
  line-height: 1.7;
  opacity: 0.8;
  margin-bottom: 1.5rem;
}

.resume-contact a {
  text-decoration: none;
  border-bottom: 1px solid rgba(127, 127, 127, 0.35);
}

.resume-contact a:hover {
  border-bottom-color: currentColor;
}

/* The download sits inside the contact block but reads as an action, so it
   drops to its own line and takes a button treatment rather than a link one. */
a.resume-download {
  display: inline-block;
  margin-top: 0.9rem;
  padding: 0.4rem 0.9rem;
  border: 1px solid rgba(127, 127, 127, 0.4);
  border-radius: 999px;
  border-bottom-width: 1px;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 1;
}

a.resume-download:hover {
  border-color: currentColor;
  background: rgba(127, 127, 127, 0.08);
}

/* Section rules give the long single-column page some structure to scan by. */
body.resume h2 {
  font-size: 0.74rem;
  font-weight: 650;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.6;
  margin: 2.5rem 0 1.1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid rgba(127, 127, 127, 0.22);
}

/* Role and institution. Quarto renders the `**Role** — Org\` line as a
   paragraph whose first child is strong, so the org stays at body weight. */
body.resume h2 + p strong:first-child,
body.resume ul + p strong:first-child {
  font-size: 1.05rem;
  font-weight: 650;
}

body.resume h2 + p,
body.resume ul + p {
  margin-bottom: 0.5rem;
  line-height: 1.5;
}

body.resume h2 + p em,
body.resume ul + p em {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-style: normal;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.6;
}

body.resume ul {
  margin-bottom: 1.6rem;
  padding-left: 1.1rem;
}

body.resume li {
  margin-bottom: 0.4rem;
  line-height: 1.55;
}

body.resume li::marker {
  color: rgba(127, 127, 127, 0.6);
}


/* ==========================================================================
    Pinned site header (replaces the icon rail)
    ========================================================================== */
body {
  --op-soft:  color-mix(in srgb, var(--bs-body-color) 76%, transparent);
  --op-muted: color-mix(in srgb, var(--bs-body-color) 58%, transparent);
  --op-hair:  color-mix(in srgb, var(--bs-body-color) 11%, transparent);
}

.sitehead {
  position: sticky; top: 0; z-index: 1030;
  background: color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(10px);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--op-hair);
}
.sitehead-inner {
  max-width: 1000px; margin: 0 auto; height: 64px;
  padding: 0 clamp(16px, 4vw, 48px);
  display: flex; align-items: center; gap: 28px;
}
.sitehead-name, .sitehead-sections a {
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .09em;
  text-transform: uppercase; text-decoration: none; white-space: nowrap;
}
.sitehead-name { color: var(--bs-body-color); }
.sitehead-sections { display: flex; gap: 28px; margin-left: auto; }
.sitehead-sections a { color: var(--op-muted); }
.sitehead-sections a:hover { color: var(--bs-body-color); }
.sitehead-links {
  display: flex; align-items: center; gap: 2px;
  padding-left: 18px; border-left: 1px solid var(--op-hair);
}
.sitehead-links a, .sitehead-theme {
  width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; border: 0; background: none; cursor: pointer; color: var(--op-soft);
}
.sitehead-links a:hover, .sitehead-theme:hover { background: var(--op-hair); color: var(--bs-body-color); }
.sitehead-links a:focus-visible, .sitehead-theme:focus-visible, .sitehead-sections a:focus-visible {
  outline: 2px solid var(--bs-body-color); outline-offset: 2px;
}
.sitehead .ph { width: 17px; height: 17px; }
@media (max-width: 760px) {
  .sitehead-sections { display: none; }
  .sitehead-links { margin-left: auto; border-left: 0; padding-left: 0; }
}


/* ==========================================================================
    One-page home
    ========================================================================== */
.op {
  max-width: 1000px; margin: 0 auto;
  padding: clamp(40px, 6vw, 88px) clamp(16px, 4vw, 48px) 0;
  display: flex; flex-direction: column; gap: clamp(44px, 5vw, 68px);
}
/* Quarto sets #quarto-content > * { padding-top: 14px }; an ID selector is needed to outrank it. */
#quarto-content > .op { padding-top: clamp(40px, 6vw, 88px); }
.op img { border-radius: 0 !important; }
.op-label {
  font-family: var(--font-mono); font-size: 11px; line-height: 16px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--op-muted);
}

/* hero: a square photo exactly one Work column wide. The headline is sized from the
   width of its own column (cqi), so its three lines fill that width, and with the
   two-line lede the text runs the full height of the photo. */
.op-hero {
  display: grid; grid-template-columns: minmax(0, 1fr) calc((100% - 64px) / 3);
  column-gap: clamp(40px, 5vw, 72px); row-gap: 28px; align-items: stretch;
}
.op-hero-text { display: flex; flex-direction: column; justify-content: space-between; gap: 28px; container-type: inline-size; }
.op-hero-text .op-display { font-size: 12.1cqi; }
.op-hero-text .op-lede { max-width: none; }
.op-hero-text .op-lede { font-size: 15px; }
@media (max-width: 1000px) { .op-hero-text .op-display { font-size: 10.6cqi; } }
@media (max-width: 1100px) { .op-hero-text .op-display { font-size: 10.5cqi; } }
.op-display {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(44px, calc(10vw - 43px), 81px); line-height: 1.02; letter-spacing: -.012em;
  margin: 0; text-wrap: balance;
}
.op-display em { font-style: italic; font-weight: 400; }
.op-lede { font-size: clamp(17px, 1.4vw, 20px); line-height: 1.6; color: var(--op-soft); max-width: 44ch; margin: 0; }
/* Photos are absolutely placed so they take the height of the text beside them
   rather than setting it from their own proportions. */
.op-photo { position: relative; overflow: hidden; min-height: 280px; }
.op-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* the About photo keeps its own proportions (1815 x 2542), uncropped */
.op-about-photo { aspect-ratio: 1815 / 2542; min-height: 0; align-self: start; }
.op-headshot { aspect-ratio: 1 / 1; min-height: 0; align-self: start; }
.op-headshot img { object-position: 50% 50%; }

/* section heads: more air under the rule */
.op-section { scroll-margin-top: 88px; display: flex; flex-direction: column; gap: clamp(28px, 3vw, 40px); }
.op-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  border-top: 1px solid var(--bs-body-color); padding-top: 28px;
}
.op-head h2 {
  font-family: var(--font-display); font-weight: 500; font-size: clamp(30px, 3.4vw, 46px); line-height: 1.05;
  margin: 0; padding: 0; border: 0;
}

/* sub-sections inside About (Values, Experience): mono like the labels, but larger,
   full colour and wider tracked so they read as headings, not as the timeline dates */
#about .op-sub { margin-top: clamp(8px, 1.5vw, 24px); }
#about #experience { margin-top: 0; }  /* the last value row already brings its own padding */
.op-sub { display: flex; flex-direction: column; gap: 28px; scroll-margin-top: 88px; }
.op-subhead {
  font-family: var(--font-mono); font-weight: 500; font-size: 14px; line-height: 18px;
  letter-spacing: .2em; text-transform: uppercase; color: var(--bs-body-color);
  margin: 0; padding: 20px 0 0; border-top: 1px solid var(--bs-body-color);
}

/* work and writing */
.op-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 32px; row-gap: 44px; }
.op-tile { display: flex; flex-direction: column; gap: 14px; text-decoration: none; color: inherit; }
.op-thumb { display: block; overflow: hidden; aspect-ratio: 3 / 2; }
.op-tile img { width: 100%; height: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block; transition: transform .6s cubic-bezier(.2, .7, .2, 1); }
.op-tile:hover img { transform: scale(1.025); }
/* hover: the image zooms and a small arrow slides in after the last word of the title */
.op-ul::after {
  content: "\2192"; display: inline-block; margin-left: .3em; font-family: var(--font-sans); font-weight: 300; font-size: .8em;
  opacity: 0; transform: translateX(-6px); transition: opacity .35s ease, transform .45s cubic-bezier(.2, .7, .2, 1);
}
.op-tile:hover .op-ul::after, .op-tile:focus-visible .op-ul::after { opacity: 1; transform: none; }
.op-tile[target="_blank"] .op-ul::after { content: "\2197"; }  /* the Nature paper opens off-site */
@media (prefers-reduced-motion: reduce) { .op-ul::after { transition: none; } }
.op-meta { display: flex; justify-content: space-between; gap: 12px; }
.op-meta span { font-family: var(--font-mono); font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--op-muted); }
.op-tile h3 { font-family: var(--font-display); font-weight: 500; font-size: 20.5px; line-height: 1.2; margin: 0; }
.op-tile p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--op-soft); }

/* values: one row each (symbol, title, sentence) */
.op-values { display: flex; flex-direction: column; }
.op-value {
  display: grid; grid-template-columns: 56px calc(var(--about-photo-w, 290px) - 56px) minmax(0, 1fr); align-items: center; column-gap: 0;
  padding: 22px 0; border-bottom: 1px solid var(--op-hair);
}
.op-value:last-child { border-bottom: 0; }  /* the Experience rule follows; two lines stacked looked busy */
.op-value svg {
  width: 40px; height: 40px; fill: none; stroke: var(--bs-body-color);
  stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round;
}
.op-value svg .fill { fill: var(--bs-body-color); stroke: none; }
/* sized so the longest name, Challenge Assumptions, runs the full width of the photo above */
.op-value h4 { font-family: var(--font-display); font-weight: 500; font-size: calc((var(--about-photo-w, 290px) - 56px) / 10.62); white-space: nowrap; line-height: 1.2; margin: 0; }
.op-value p { margin: 0 0 0 var(--about-gap); font-size: 15px; line-height: 1.6; color: var(--op-soft); max-width: 60ch; }

/* about: photo and text share one height */
#about { --about-gap: clamp(32px, 5vw, 72px); }
.op-about { display: grid; grid-template-columns: var(--about-photo-w, 290px) minmax(0, 1fr); gap: var(--about-gap); align-items: stretch; }
.op-about-text { display: flex; flex-direction: column; justify-content: space-between; gap: 40px; }
.op-about-bio { display: flex; flex-direction: column; gap: 28px; }
.op-about-bio p:first-child { margin-bottom: 12px; }
.op-about-bio p { margin: 0; font-size: 15.5px; line-height: 1.7; color: var(--op-soft); }
.op-about-bio p:first-child { font-family: var(--font-display); font-size: clamp(21px, 1.9vw, 25px); line-height: 1.3; color: var(--bs-body-color); }
.op-about-bio p:first-child strong { font-weight: 700; }
.op-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.op-facts > div { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--op-hair); padding-top: 14px; }
.op-facts strong { font-family: var(--font-display); font-weight: 500; font-size: 18px; line-height: 1.25; }

/* experience: horizontal timeline */
.op-timeline {
  list-style: none; margin: 0; padding: 0; position: relative;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: 24px;
}
/* the line runs through the centre of each dot, then carries on past the last one and fades out before the edge of the heading rule:
   the career started before 2023 */
.op-timeline::before {
  content: ""; position: absolute; left: 5.5px; right: 0; top: 31.5px; height: 1px;
  background: linear-gradient(90deg, var(--bs-body-color) 79%, transparent 98%);
}
/* each entry spans five shared rows (date, dot, role, org, sentence) so they line up across columns */
.op-timeline li { display: grid; grid-row: span 5; grid-template-rows: subgrid; row-gap: 10px; align-content: start; position: relative; }
.op-dot {
  width: 11px; height: 11px; border-radius: 50%; box-sizing: border-box;
  border: 1.5px solid var(--bs-body-color); background: var(--bs-body-bg);
  position: relative; z-index: 1; margin-bottom: 8px; justify-self: start;
}
.op-timeline li.is-current .op-dot { background: var(--bs-body-color); }
.op-cv {
  align-self: flex-end; font-family: var(--font-mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--op-muted); text-decoration: none; border-bottom: 1px solid var(--op-hair); padding-bottom: 2px; transition: color .2s;
}
.op-cv:hover { color: var(--bs-body-color); }
.op-timeline strong { white-space: nowrap; font-family: var(--font-display); font-weight: 500; font-size: 16.6px; line-height: 1.2; }
.op-org { font-size: 13px; color: var(--op-muted); margin-top: -4px; }
.op-timeline p { width: 0; min-width: 100%; margin: 2px 0 0; font-size: 14px; line-height: 1.55; color: var(--op-soft); max-width: 34ch; }

/* contact: a dark band that closes the page. The box-shadow and clip-path carry the
   colour to the viewport edges and down past the page end without horizontal scroll. */
.op-band {
  --band-bg: #0f1115; --band-ink: #ece9e4; --band-muted: #8a8f97; --band-hair: #2c3038;
  background: var(--band-bg); color: var(--band-ink);
  box-shadow: 0 0 0 100vmax var(--band-bg); clip-path: inset(0 -100vmax -100vmax);
  display: flex; flex-direction: column; gap: 36px; align-items: flex-start;
  padding: clamp(56px, 7vw, 96px) 0 28px; scroll-margin-top: 64px;
}
body.quarto-dark .op-band { --band-bg: #17191e; --band-hair: #30343c; }
.op-band-title { font-family: var(--font-display); font-weight: 500; font-size: clamp(48px, 6.6vw, 84px); line-height: 1; margin: 0; padding: 0; border: 0; color: var(--band-ink); }
.op-band-email {
  font-family: var(--font-display); font-style: italic; font-weight: 400; font-size: clamp(20px, 2.2vw, 28px); line-height: 1.2;
  color: var(--band-ink); text-decoration: none; border-bottom: 1px solid var(--band-muted); padding-bottom: 4px; overflow-wrap: anywhere;
}
.op-band-email:hover { border-bottom-color: var(--band-ink); }
.op-band-icons { display: flex; flex-wrap: wrap; gap: 28px; }
.op-band-icons a { color: var(--band-ink); display: inline-flex; opacity: .85; transition: opacity .2s ease, transform .2s ease; }
.op-band-icons a:hover { opacity: 1; transform: translateY(-2px); }
.op-band-icons .ph { width: 30px; height: 30px; }
.op-band a:focus-visible { outline: 2px solid var(--band-ink); outline-offset: 4px; }
.op-band-foot { align-self: stretch; display: flex; justify-content: space-between; gap: 16px; border-top: 1px solid var(--band-hair); padding-top: 20px; margin-top: 28px; }
.op-band-foot .op-label { color: var(--band-muted); }

/* back to top */
.totop {
  position: fixed; right: clamp(16px, 3vw, 32px); bottom: calc(clamp(16px, 3vw, 32px) + env(safe-area-inset-bottom, 0px));
  z-index: 1030; width: 44px; height: 44px; border-radius: 50%; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--bs-body-color); border: 1px solid var(--op-hair);
  background: color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(10px); backdrop-filter: saturate(1.4) blur(10px);
}
.totop[hidden] { display: none !important; }
.totop:hover { border-color: var(--bs-body-color); }
.totop:focus-visible { outline: 2px solid var(--bs-body-color); outline-offset: 2px; }
.totop .ph { width: 19px; height: 19px; }
.sitehead .ph { width: 19px; height: 19px; }

/* responsive */
/* narrower than four columns allow: the timeline turns vertical, a rail down the left with a dot per role,
   fading out after the last one as it does on desktop */
@media (max-width: 980px) {
  .op-timeline { grid-template-columns: minmax(0, 1fr); row-gap: 36px; padding-left: 28px; }
  .op-timeline::before { left: 5px; right: auto; top: 8px; bottom: -24px; width: 1px; height: auto;
    background: linear-gradient(180deg, var(--bs-body-color) 82%, transparent); }
  .op-timeline li { display: flex; flex-direction: column; gap: 8px; grid-row: auto; }
  .op-timeline .op-dot { position: absolute; left: -28px; top: 2.5px; margin: 0; }
  .op-timeline strong { white-space: normal; font-size: 19px; }
  .op-timeline p { width: auto; max-width: 52ch; }
}
@media (max-width: 900px) {
  .op-hero { grid-template-columns: 1fr; }
  .op-headshot { width: 100%; max-width: calc((100% - 32px) / 2); order: -1; }
  .op-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .op-about { grid-template-columns: 1fr; }
  .op-value { grid-template-columns: 40px minmax(0, 1fr); row-gap: 8px; column-gap: 20px; align-items: start; }
  .op-value p { grid-column: 2; margin-left: 0; }
  .op-value h4 { font-size: clamp(21px, 4vw, 25px); white-space: normal; }
  .op-about-photo { width: 100%; max-width: 420px; }
}
@media (max-width: 600px) {
  .op-band-foot { padding-bottom: 64px; }  /* clear of the back-to-top button */
  .op-hero-text .op-display { font-size: 12.5cqi; }
  .op-headshot { max-width: 100%; }
  .op-grid, .op-facts { grid-template-columns: 1fr; }
  .op-head { flex-wrap: wrap; }
  .op-timeline { grid-template-columns: 1fr; }
  .op-band-foot { flex-direction: column; }
}


/* Quarto's own navbar is replaced by the pinned header */
.navbar, .quarto-navbar, #quarto-header { display: none !important; }

/* Home: the .op wrapper sets its own gutter, so Quarto's content padding goes on phones */
@media (max-width: 900px) {
  body.home #quarto-content .content,
  body.home #quarto-content main.content { padding-left: 0 !important; padding-right: 0 !important; max-width: 100% !important; }
}

/* Header on article pages: keep the contents sidebar and anchors clear of it */
#quarto-margin-sidebar, #quarto-sidebar { top: 80px !important; }
main.content :is(h1, h2, h3, h4)[id], main.content section[id] { scroll-margin-top: 88px; }

/* Phones: fewer icons so the header fits one line (the old rail hid these too) */
@media (max-width: 560px) {
  .sitehead-inner { gap: 12px; }
  .sitehead-name { font-size: 10.5px; }
  .sitehead-links a[aria-label="Medium"], .sitehead-links a[aria-label="Google Scholar"] { display: none; }
  .sitehead-links a, .sitehead-theme { width: 34px; height: 34px; }
}


/* ==========================================================================
    Case study summary: collaborators, the decision, takeaways
    ========================================================================== */
.cs-top { display: flex; flex-direction: column; gap: 18px; margin: 8px 0 44px; }
.cs-with, .cs-label {
  font-family: var(--font-mono); font-size: 11px; line-height: 1.6; letter-spacing: .09em;
  text-transform: uppercase; color: var(--op-muted);
}
.cs-keys {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr); gap: 32px;
  border-top: 1px solid var(--bs-body-color); border-bottom: 1px solid var(--op-hair);
  padding: 20px 0 22px;
}
.cs-key { display: flex; flex-direction: column; gap: 10px; }
.cs-key p { margin: 0; }
.cs-decision {
  display: block; font-family: var(--font-display); font-weight: 500;
  font-size: 18.5px; line-height: 1.3; color: var(--bs-body-color);
}
.cs-key ul { margin: 0; padding-left: 1.1em; display: flex; flex-direction: column; gap: 8px; }
.cs-key li { font-size: 15px; line-height: 1.5; color: var(--op-soft); }
.cs-key li::marker { color: var(--op-muted); }
@media (max-width: 700px) {
  .cs-keys { grid-template-columns: 1fr; gap: 20px; }
}


/* ==========================================================================
    Film grain: a fine noise texture over every page, generated in SVG (no image
    download). Fixed to the viewport so it does not scroll, and click-through.
    ========================================================================== */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 2000; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20width%3D%27240%27%20height%3D%27240%27%3E%3Cfilter%20id%3D%27n%27%3E%3CfeTurbulence%20type%3D%27fractalNoise%27%20baseFrequency%3D%27.85%27%20numOctaves%3D%273%27%20stitchTiles%3D%27stitch%27/%3E%3CfeColorMatrix%20type%3D%27saturate%27%20values%3D%270%27/%3E%3C/filter%3E%3Crect%20width%3D%27100%25%27%20height%3D%27100%25%27%20filter%3D%27url%28%23n%29%27/%3E%3C/svg%3E"); background-size: 240px;
  opacity: .06; mix-blend-mode: multiply;
}
body.quarto-dark::after { opacity: .07; mix-blend-mode: screen; }
@media print { body::after { display: none; } }


/* ==========================================================================
    Premium details (preview branch)
    ========================================================================== */

/* 1: sections fade up once as they enter the viewport. Only applies once the
   script has marked the page, so everything is visible if scripts fail. */
html.js-reveal .reveal { opacity: 0; transform: translateY(12px); transition: opacity .6s ease, transform .6s cubic-bezier(.2, .7, .2, 1); }
html.js-reveal .reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { html.js-reveal .reveal { opacity: 1; transform: none; transition: none; } }

/* 3: underlines that grow from the left */
.sitehead-sections a, .op-band-email, .resume-contact a, main.content p a {
  text-decoration: none; background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  transition: background-size .35s cubic-bezier(.2, .7, .2, 1), color .2s ease;
}
.sitehead-sections a:hover, .op-band-email:hover, .resume-contact a:hover, main.content p a:hover { background-size: 100% 1px; }
main.content p a { background-size: 100% 1px; background-image: linear-gradient(color-mix(in srgb, currentColor 35%, transparent), color-mix(in srgb, currentColor 35%, transparent)); }
main.content p a:hover { background-image: linear-gradient(currentColor, currentColor); }
.op-band-email { border-bottom: 0; background-size: 100% 1px; background-image: linear-gradient(var(--band-muted), var(--band-muted)); }
.op-band-email:hover { background-image: linear-gradient(var(--band-ink), var(--band-ink)); }

/* 4: light/dark cross-fade (driven by the View Transitions API in the header script) */
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .35s; }

/* 6: typographic details */
.op-head h2, .op-display, .op-band-title { letter-spacing: -.015em; }
.op-when, .op-meta, .op-facts, .cs-keys { font-variant-numeric: tabular-nums; }
.cs-top + p::first-letter,
.cs-top + section > h2 + p::first-letter {
  float: left; font-family: var(--font-display); font-weight: 500; font-size: 3.6em; line-height: .82;
  padding: .06em .09em 0 0; color: var(--bs-body-color);
}

/* 10: signature */
.op-sig { display: inline-flex; align-items: baseline; gap: 12px; }
.op-mono-mark { font-family: var(--font-display); font-style: italic; font-size: 22px; line-height: 1; color: var(--band-ink); letter-spacing: -.02em; }

/* 5: case-study pages match the homepage */
body:not(.home):not(.resume) .quarto-title-block .title {
  font-size: clamp(34px, 4.2vw, 52px); line-height: 1.04; letter-spacing: -.015em;
}
body:not(.home):not(.resume) .quarto-title-block .description {
  font-size: clamp(16px, 1.3vw, 18px); line-height: 1.6; color: var(--op-soft); margin-top: 18px;
}
body:not(.home):not(.resume) .quarto-categories { display: flex; flex-wrap: wrap; gap: 4px 0; margin: 0 0 18px; }
body:not(.home):not(.resume) .quarto-category {
  border: 0; padding: 0; border-radius: 0; background: none; opacity: 1;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--op-muted);
}
body:not(.home):not(.resume) .quarto-category:not(:last-child)::after { content: "·"; margin: 0 10px; }
body:not(.home):not(.resume) .quarto-categories { order: -1; }
body:not(.home):not(.resume) .quarto-title { display: flex; flex-direction: column; }
body:not(.home):not(.resume) .quarto-title-meta-heading { font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--op-muted); }
.cs-cover { margin: 8px 0 40px; }
.cs-cover img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block; border-radius: 0; }

/* 8: 404 page */
.op-404 { display: flex; flex-direction: column; gap: 28px; padding-block: clamp(40px, 8vw, 120px) clamp(80px, 12vw, 160px); max-width: 980px; }
.op-404 .op-display { font-size: clamp(40px, 5.4vw, 72px); }
.op-404-links { display: flex; flex-wrap: wrap; gap: 28px; }
.op-404-links a {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--bs-body-color);
  text-decoration: none; background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat; padding-bottom: 4px;
}
.op-404-links a:hover { background-size: 0 1px; background-position: 100% 100%; transition: background-size .35s ease; }

/* Icons are inline Phosphor SVGs (no runtime icon service) */
.ph { display: block; width: 1em; height: 1em; flex: none; }
.sitehead-theme .i-sun { display: none; }
body.quarto-dark .sitehead-theme .i-sun { display: block; }
body.quarto-dark .sitehead-theme .i-moon { display: none; }

/* Phone menu: a quiet "menu" button that opens a full-screen overlay in the display serif */
.sitehead-menu { display: none; background: none; border: 0; padding: 6px; color: var(--bs-body-color); cursor: pointer; }
@media (max-width: 760px) { .sitehead-menu { display: inline-flex; } }
.sitemenu {
  position: fixed; inset: 0; z-index: 1100; display: flex; flex-direction: column; justify-content: center;
  padding: 32px clamp(24px, 8vw, 64px); gap: 24px;
  background: color-mix(in srgb, var(--bs-body-bg) 94%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(14px); backdrop-filter: saturate(1.4) blur(14px);
}
.sitemenu[hidden] { display: none !important; }
.sitemenu nav { display: flex; flex-direction: column; gap: 10px; }
.sitemenu nav a {
  font-family: var(--font-display); font-weight: 500; font-size: clamp(40px, 12vw, 64px); line-height: 1.1;
  color: var(--bs-body-color); text-decoration: none;
}
.sitemenu-close { position: absolute; top: 16px; right: 16px; background: none; border: 0; padding: 10px; color: var(--bs-body-color); cursor: pointer; }
.sitemenu-close .ph { width: 26px; height: 26px; }
html.js-reveal .sitemenu:not([hidden]) nav a { animation: menu-in .5s cubic-bezier(.2, .7, .2, 1) both; }
.sitemenu nav a:nth-child(2) { animation-delay: .05s; } .sitemenu nav a:nth-child(3) { animation-delay: .1s; } .sitemenu nav a:nth-child(4) { animation-delay: .15s; }
@keyframes menu-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
body.menu-open { overflow: hidden; }

/* Copy email */
.op-band-mail { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 20px; }
.op-copy {
  display: inline-flex; align-items: center; gap: 8px; padding: 7px 12px; cursor: pointer;
  background: none; color: var(--band-ink); border: 1px solid var(--band-hair);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  transition: border-color .2s ease;
}
.op-copy:hover { border-color: var(--band-ink); }
.op-copy .ph { width: 15px; height: 15px; }
.op-copy .i-check, .op-copy.is-copied .i-copy { display: none; }
.op-copy.is-copied .i-check { display: block; }

/* Reading progress on case studies: a hairline under the header that fills as you read */
.readbar { position: fixed; left: 0; top: 64px; height: 2px; width: 100%; z-index: 1029; pointer-events: none;
  background: var(--bs-body-color); transform-origin: 0 50%; transform: scaleX(0); }

/* Figures in case studies: mono captions, zoom cursor */
main.content .figure-caption, main.content figcaption {
  font-family: var(--font-mono); font-size: 11.5px; line-height: 1.6; letter-spacing: .02em; color: var(--op-muted);
}
main.content .quarto-figure img, main.content figure img { cursor: zoom-in; }

/* Text selection in the thumbnail slate */
::selection { background: color-mix(in srgb, #7189a6 32%, transparent); }

/* Next case study, at the foot of each article */
.cs-next { margin: 72px 0 24px; border-top: 1px solid var(--bs-body-color); padding-top: 20px; }
.cs-next a { display: grid; grid-template-columns: minmax(0, 1fr) 200px; gap: 28px; align-items: center; color: var(--bs-body-color); text-decoration: none; background: none; }
.cs-next-text { display: flex; flex-direction: column; gap: 8px; }
.cs-next-label { font-family: var(--font-mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--op-muted); }
.cs-next-title { font-family: var(--font-display); font-weight: 500; font-size: clamp(21px, 2.2vw, 27px); line-height: 1.15; }
.cs-next-title::after { content: "\2192"; display: inline-block; margin-left: .3em; font-family: var(--font-sans); font-weight: 300; font-size: .75em; transition: transform .45s cubic-bezier(.2, .7, .2, 1); }
.cs-next a:hover .cs-next-title::after { transform: translateX(6px); }
.cs-next-img { display: block; overflow: hidden; aspect-ratio: 3 / 2; border-radius: 0; }
.cs-next-img img { border-radius: 0 !important; }
.cs-next-img img { width: 100%; height: 100%; object-fit: cover; display: block; margin: 0; transition: transform .6s cubic-bezier(.2, .7, .2, 1); cursor: pointer; }
.cs-next a:hover .cs-next-img img { transform: scale(1.03); }
@media (max-width: 600px) { .cs-next a { grid-template-columns: 1fr; } .cs-next-img { order: -1; } }

/* Article pages share the homepage's 1000px frame (904px inside the gutters):
   contents list on the left, under the header name; a reading column in the middle;
   figure captions and margin notes on the right. Quarto nests grids (the page, main,
   and every section that holds a figure), so each level gets the same named lines. */
@media (min-width: 992px) {
  body:not(.home) #quarto-content.page-columns.page-layout-article {
    grid-template-columns:
      [screen-start] minmax(clamp(16px, 4vw, 48px), 1fr)
      [screen-start-inset page-start page-start-inset] 156px
      [body-start-outset body-start] 32px
      [body-content-start] minmax(0, 532px)
      [body-content-end] 32px
      [body-end body-end-outset] 152px
      [page-end-inset page-end screen-end-inset] minmax(clamp(16px, 4vw, 48px), 1fr)
      [screen-end] !important;
  }
  /* the old centred-reading-column rules (max-width, auto margins, padding) are undone */
  body:not(.home) #quarto-content.page-layout-article > main.content {
    grid-column: body-content-start / page-end !important;
    max-width: none; margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0;
  }
  body:not(.home) #quarto-content.page-layout-article main.content.page-columns,
  body:not(.home) #quarto-content.page-layout-article main.content .page-columns {
    grid-template-columns:
      [screen-start screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0, 532px)
      [body-content-end] 32px
      [body-end body-end-outset] 152px
      [page-end-inset page-end screen-end-inset screen-end] !important;
  }
  /* with the contents on the left, Quarto would pull captions inline; keep them in the right margin */
  body:not(.home) #quarto-content.page-columns.toc-left .margin-caption,
  body:not(.home) #quarto-content.page-columns.toc-left .column-margin,
  body:not(.home) #quarto-content.page-columns.toc-left div.aside,
  body:not(.home) #quarto-content.page-columns.toc-left aside:not(.footnotes):not(.sidebar) {
    grid-column: body-end / page-end !important;
  }
  body:not(.home) #title-block-header { grid-column: body-content-start / body-content-end !important; }
  body:not(.home) #quarto-sidebar.toc-left, body:not(.home) .sidebar.toc-left { grid-column: page-start / body-start !important; padding-right: 24px; }
}
/* breathing room between the article title and its description */
body:not(.home) .quarto-title-block .title { margin-bottom: 28px !important; }
body:not(.home) .quarto-title-block .description { margin-top: 0 !important; }

/* phones: wide tables and equations scroll sideways inside themselves instead of widening the page */
@media (max-width: 767px) {
  main.content table { display: block; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  mjx-container[display="true"] { max-width: 100%; overflow-x: auto; overflow-y: hidden; }
}
