
/* ============================================================
   TOKENS. Black, white, one red.
   ============================================================ */
:root{
  --paper:#FFFFFF;
  --ink:#000000;
  --ink-2:#3A3A3A;
  --mute:#6E6E6E;
  --rule:#000000;
  --hair:#D6D6D6;
  --red:#CE2F19;
  --dot:#111111;
  --wash:#F5F5F4;

  /* One scale for the whole page. Before this there were eight different body
     sizes between .90 and .99rem and eight mono sizes between .62 and .78rem,
     which is why nothing looked deliberate. Two mono sizes only: eyebrow is for
     uppercase letterspaced labels, mono is for everything else. */
  /* One family. Computer Modern is the LaTeX face, and no amount of restraint
     stops a reader who has met a thousand papers from feeling it. Distinction
     now comes from weight and scale instead: the display sizes are heavy and
     tightly tracked, the body is plain. Nothing is downloaded at all. */
  --font-display:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-body:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;

  --fs-lead:.98rem;
  --fs-title:1.02rem;
  --fs-body:.88rem;
  --fs-note:.8rem;
  --fs-mono:.74rem;
  --fs-eyebrow:.66rem;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --paper:#0A0A0A;
    --ink:#F2F2F0;
    --ink-2:#C2C2BE;
    --mute:#8A8A86;
    --rule:#F2F2F0;
    --hair:#2E2E2C;
    --red:#FF5A3C;
    --dot:#E4E4E0;
    --wash:#131312;
  }
}
:root[data-theme="dark"]{
  --paper:#0A0A0A;
  --ink:#F2F2F0;
  --ink-2:#C2C2BE;
  --mute:#8A8A86;
  --rule:#F2F2F0;
  --hair:#2E2E2C;
  --red:#FF5A3C;
  --dot:#E4E4E0;
  --wash:#131312;
}

/* ============================================================
   BASE
   ============================================================ */
*{box-sizing:border-box;}
/* anchors roll instead of jumping. the reduced motion rule below turns it off. */
html{scroll-behavior:smooth;}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto;}}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:17px;
  line-height:1.58;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3{margin:0;font-family:var(--font-display);font-weight:800;line-height:1.06;letter-spacing:-.028em;}
p{margin:0;}
a{color:inherit;}
a:focus-visible{outline:2px solid var(--red);outline-offset:3px;}
::selection{background:var(--red);color:var(--paper);}
img{max-width:100%;display:block;}

/* ---- the grid. every block lines up on it. ---- */
/* width:100% is load bearing. Sections are column flexboxes, and margin-inline:auto
   on a flex item cancels the default stretch, so each container shrank to fit its
   own content and every section sat at a different width. Measured before the fix:
   eight sections, five different left edges, 174px apart at 1214px. */
.container{
  width:100%;
  max-width:1320px;margin-inline:auto;
  padding-inline:clamp(20px,4vw,52px);
}
/* minmax(0,1fr), never plain 1fr. Each section carries its own grid, and a plain
   1fr track is allowed to grow past its share when its content asks for it. So a
   long word or a wide figure widened that section's columns and moved the column
   boundary, and the whole page drifted left and right as you scrolled. Measured
   before the fix: eight sections, five different left edges, 112px apart. */
.grid{
  display:grid;
  grid-template-columns:repeat(12,minmax(0,1fr));
  column-gap:clamp(16px,2vw,28px);
}
.col-label{grid-column:1 / 4;}
.col-main{grid-column:4 / 13;}
@media (max-width:900px){
  .col-label,.col-main,.col-half-a,.col-half-b{grid-column:1 / -1;}
  .col-label{margin-bottom:18px;}
}

/* Not sticky. It used to follow you down the section, which left the number as much
   as 1200px away from the heading it belongs to. The rail is short now and the
   sections are not tall enough to need it. */
.lab{display:block;}
.lab .num{
  display:block;font-family:var(--font-display);font-weight:800;
  font-size:clamp(1.9rem,3.2vw,2.7rem);line-height:1;color:var(--red);
  letter-spacing:-.045em;
}
.lab .rule{display:block;width:38px;height:1px;background:var(--rule);margin:14px 0 12px;}
.lab .txt{
  display:block;font-family:var(--font-body);
  font-size:var(--fs-eyebrow);letter-spacing:.11em;text-transform:uppercase;
  color:var(--ink-2);line-height:1.7;max-width:15ch;
}
@media (max-width:900px){
  .lab{display:flex;align-items:baseline;gap:14px;}
  .lab .num{font-size:1.6rem;}
  .lab .rule{width:20px;margin:0;align-self:center;}
  .lab .txt{max-width:none;}
}

/* thin persistent bar so people always know where they are */
.topbar{
  position:fixed;top:0;left:0;right:0;z-index:50;
  background:var(--paper);border-bottom:1px solid var(--hair);
  /* Visible from the first screen. Hiding it until you scrolled meant the first
     thing a visitor saw offered no way anywhere, and no sense of how long the
     page was. */
  transition:box-shadow .3s ease;
}
.topbar.show{box-shadow:0 1px 0 rgba(0,0,0,.04);}
.topbar-in{display:flex;align-items:center;justify-content:space-between;gap:20px;padding-block:11px;}
.tb-name{font-weight:700;font-size:.95rem;white-space:nowrap;}
.tb-links{display:flex;gap:clamp(12px,1.8vw,26px);}
.tb-links a{
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.09em;text-transform:uppercase;
  color:var(--mute);text-decoration:none;white-space:nowrap;
  padding-bottom:2px;border-bottom:2px solid transparent;
}
.tb-links a:hover{color:var(--red);}
/* where you are now, marked with the same red rule the headings use */
.tb-links a.on{color:var(--ink);border-bottom-color:var(--red);}

/* Narrow screens used to delete the last three or four links outright, which put
   Papers, Talks and the CV out of reach on a phone. Scroll them instead. */
@media (max-width:760px){
  .topbar-in{gap:14px;}
  .tb-name{font-size:.85rem;}
  .tb-links{
    overflow-x:auto;scrollbar-width:none;
    -webkit-overflow-scrolling:touch;
    gap:16px;margin-inline-start:auto;
  }
  .tb-links::-webkit-scrollbar{display:none;}
}
@media (max-width:420px){.tb-name{display:none;}}

/* anchor jumps used to land headings flush under the bar */
:where(section,header,div)[id]{scroll-margin-top:76px;}
/* the bar is always there now, so the first screen starts below it */
.masthead{padding-top:clamp(72px,9vw,120px)!important;}

/* full bleed rules between sections */
.band{border-top:1px solid var(--rule);}
.band.hair{border-top:1px solid var(--hair);}
/* A full screen floor left the short sections, talks and contact especially,
   more than half empty, which reads as unfinished rather than as breathing room.
   The long sections set their own height anyway. */
.sec{
  min-height:76svh;
  display:flex;flex-direction:column;justify-content:center;
  padding-block:clamp(40px,5vh,66px);
}
@media (max-width:900px){
  .sec{min-height:0;display:block;padding-block:clamp(46px,7vw,66px);}
}

h2.head{
  font-size:clamp(1.62rem,3vw,2.2rem);
  margin-bottom:clamp(20px,2.6vw,30px);
  max-width:22ch;
}

/* ============================================================
   MASTHEAD
   ============================================================ */
.masthead{
  padding-block:clamp(34px,4.6vw,64px) clamp(20px,2.4vw,32px);
  min-height:100svh;display:flex;flex-direction:column;justify-content:center;
}
@media (max-width:900px){.masthead{min-height:0;padding-block:clamp(34px,7vw,56px);}}
.masthead .grid{row-gap:clamp(22px,2.8vw,36px);}
.mast-side{
  display:flex;flex-direction:column;gap:18px;align-items:flex-start;
}
/* masthead grid: claim on the left, face on the right, hint below */
.mast-name{grid-column:1 / 9;grid-row:1;}
.mast-side{grid-column:9 / 13;grid-row:1;align-self:center;}
@media (max-width:1000px){
  .mast-name{grid-column:1 / 8;}
  .mast-side{grid-column:8 / 13;}
}
@media (max-width:820px){
  .mast-name,.mast-side{grid-column:1 / -1;grid-row:auto;}
  /* no order swap here on purpose. it used to put the photo and the links above
     the name, so the first thing a stranger met was an unlabelled face. */
  .mast-side{flex-direction:row;align-items:center;gap:20px;}
  .mast-side .portrait{max-width:108px;}
}
#rwd{width:100%;height:auto;display:block;overflow:visible;}
.role{
  margin-top:14px;font-size:clamp(1rem,1.7vw,1.15rem);color:var(--ink-2);
}
.intro .r{color:var(--red);}
/* justified like a printed paper. hyphens stop it opening rivers. */
.said,.track p,.track li,.row .rd,.pub .n,.tl li,.split p,.contact p,.sec-head .sub{
  text-wrap:pretty;
}
.portrait{
  /* height:auto is load bearing. The img carries width="230" height="288" so the
     browser can reserve space before it loads, but a specified height makes both
     dimensions definite and aspect-ratio is ignored. At full size 230x288 is 4:5
     anyway, so it looked fine; at max-width:108px on a phone the height stayed
     288, the box became 108x288, and object-fit:cover sliced the sides off. */
  width:100%;max-width:230px;height:auto;aspect-ratio:4/5;object-fit:cover;
  border:1px solid var(--hair);
  /* In colour on purpose. It was grayscale, which matched the palette but made the
     one human element on eight screens as austere as everything else. The warm
     tone is close to the red accent, and the OHDSI Europe shirt is a credential.
     Add filter:grayscale(1) here to put it back. */
}
.meta{font-family:var(--font-body);font-size:var(--fs-mono);line-height:1.9;color:var(--mute);}
.meta a{text-decoration:none;border-bottom:1px solid var(--hair);}
.meta a:hover{color:var(--red);border-bottom-color:var(--red);}

/* ============================================================
   THE ANIMATION. full bleed.
   ============================================================ */
/* The figure now lives inside the section it explains, on the same canvas as the
   claim, instead of in a full bleed band underneath it. */
.figbox{
  background:var(--wash);
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
  padding:clamp(14px,1.8vw,20px) clamp(14px,1.8vw,20px);
  margin-bottom:clamp(16px,2vw,22px);
}
.figbox.split{
  display:grid;grid-template-columns:minmax(0,420px) minmax(0,1fr);
  gap:clamp(20px,3vw,44px);align-items:center;
}
.figbox .side p{
  color:var(--ink-2);font-size:var(--fs-body);max-width:46ch;
}
.figbox .side p + p{margin-top:10px;}
@media (max-width:820px){
  .figbox.split{grid-template-columns:1fr;}
}
#viz{width:100%;height:auto;display:block;overflow:visible;}
.viz-cap{
  display:flex;flex-wrap:wrap;gap:8px 30px;
  padding-top:12px;
  font-family:var(--font-body);font-size:var(--fs-mono);letter-spacing:.05em;color:var(--mute);
}
.viz-cap b{color:var(--ink);font-weight:400;}
.viz-cap .k{display:inline-flex;align-items:center;gap:9px;}
.viz-cap .k i{width:9px;height:9px;border-radius:50%;background:var(--dot);flex:none;}
.viz-cap .k.m i{background:var(--red);}


/* ============================================================
   LISTS
   ============================================================ */
.rows{display:flex;flex-direction:column;}
/* Name and role stack on the left, description on the right. The role used to sit
   in a third column, right aligned and set in the palest type on the page, which
   buried the one line a hiring reader looks for first. */
.row{
  display:grid;grid-template-columns:230px minmax(0,1fr);
  column-gap:clamp(16px,2vw,28px);row-gap:4px;
  padding:20px 0;border-top:1px solid var(--hair);
  text-decoration:none;
}
.rows .row:first-child{border-top:1px solid var(--rule);}
.rows .row:last-child{border-bottom:1px solid var(--rule);}
.row .rn{grid-column:1;grid-row:1;font-size:var(--fs-title);font-weight:700;}
.row .rn a{
  /* these are links. they should look like links before you touch them. */
  text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:3px;text-decoration-color:var(--mute);
}
.row .rn a:hover{color:var(--red);text-decoration-color:var(--red);}
.row .rr{
  grid-column:1;grid-row:2;align-self:start;
  font-family:var(--font-body);font-size:var(--fs-mono);color:var(--ink-2);letter-spacing:.04em;
}
/* The description spans both rows so the role can sit directly under the name.
   Placed in its own row, the role sank to the bottom of a cell as tall as the
   description, which put it a long way from the thing it describes. */
.row .rd{grid-column:2;grid-row:1 / 3;color:var(--ink-2);font-size:var(--fs-body);}
/* the paper sits under the thing it is evidence for, not in a list of its own */
.row .rp{
  grid-column:2;grid-row:3;margin-top:7px;
  font-family:var(--font-body);font-size:var(--fs-mono);line-height:1.6;
  letter-spacing:.03em;color:var(--mute);
}
.row .rp a{color:var(--ink-2);text-decoration:none;border-bottom:1px solid var(--hair);}
.row .rp a:hover{color:var(--red);border-bottom-color:var(--red);}
@media (max-width:860px){
  .row{grid-template-columns:1fr;row-gap:6px;}
  .row .rn,.row .rr,.row .rd,.row .rp{grid-column:1;grid-row:auto;}
  /* keep the role directly under the name once it all stacks */
  .row .rn{order:1;} .row .rr{order:2;} .row .rd{order:3;} .row .rp{order:4;}
}

/* ============================================================
   THE RESULT. The one screen a visitor should still be able to
   repeat to a colleague afterwards. Real axis, stated range, exact
   numbers next to every bar.
   ============================================================ */
.result{margin-top:clamp(22px,3vw,32px);}
/* Same track template as the bars, so 0.50 and 1.00 sit exactly above the ends
   of the bars rather than above the number column. An axis that does not line up
   with what it measures is worse than no axis. */
.rax{
  display:grid;grid-template-columns:minmax(0,1fr) 84px;
  column-gap:clamp(14px,2vw,24px);
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.1em;
  text-transform:uppercase;color:var(--mute);
  padding-bottom:7px;border-bottom:1px solid var(--rule);
}
.rax span{grid-column:1;grid-row:1;}
.rax span:last-child{justify-self:end;}
.rbar{
  display:grid;grid-template-columns:minmax(0,1fr) 84px;
  align-items:center;column-gap:clamp(14px,2vw,24px);
  padding:13px 0;border-bottom:1px solid var(--hair);
}
.rbar .rlab{
  grid-column:1;grid-row:1;font-size:var(--fs-body);color:var(--ink-2);
  padding-bottom:7px;
}
.rbar .rtrack{
  grid-column:1;grid-row:2;display:block;height:9px;
  background:var(--wash);border:1px solid var(--hair);
}
.rbar .rtrack i{display:block;height:100%;background:var(--ink-2);}
.rbar .rval{
  grid-column:2;grid-row:1 / 3;
  font-family:var(--font-display);font-size:1.28rem;font-weight:700;text-align:right;line-height:1;
  font-variant-numeric:tabular-nums;
}
/* the one that reverses the reader's expectation */
.rbar.win .rlab{color:var(--ink);}
.rbar.win .rtrack i{background:var(--red);}
.rbar.win .rval{color:var(--red);}
.rnote{
  margin-top:12px;font-size:var(--fs-note);color:var(--mute);
  font-style:italic;max-width:62ch;
}
@media (max-width:560px){
  .rbar,.rax{grid-template-columns:minmax(0,1fr) 68px;}
  .rbar .rval{font-size:1.08rem;}
}

/* the scale it was measured at */
.counts{
  display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  gap:0;margin-top:clamp(26px,3.4vw,36px);
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
}
.counts div{padding:15px 14px 15px 0;}
.counts div + div{border-left:1px solid var(--hair);padding-left:14px;}
.counts .cn{
  display:block;font-family:var(--font-display);font-size:clamp(1.2rem,2.3vw,1.7rem);font-weight:700;line-height:1;
  font-variant-numeric:tabular-nums;letter-spacing:-.02em;
}
.counts .cl{
  display:block;margin-top:6px;font-family:var(--font-body);font-size:var(--fs-eyebrow);
  letter-spacing:.1em;text-transform:uppercase;color:var(--mute);line-height:1.4;
}
.counts .zero .cn{color:var(--red);}
@media (max-width:900px){
  .counts{grid-template-columns:repeat(3,minmax(0,1fr));}
  .counts div:nth-child(3n+1){border-left:none;padding-left:0;}
  .counts div{border-top:1px solid var(--hair);}
  .counts div:nth-child(-n+3){border-top:none;}
}
@media (max-width:520px){
  .counts{grid-template-columns:repeat(2,minmax(0,1fr));}
  .counts div{border-left:1px solid var(--hair);padding-left:14px;border-top:1px solid var(--hair);}
  .counts div:nth-child(2n+1){border-left:none;padding-left:0;}
  .counts div:nth-child(-n+2){border-top:none;}
}

.rsrc{
  margin-top:clamp(20px,2.6vw,28px);font-size:var(--fs-body);color:var(--ink-2);
  max-width:74ch;
}
.rsrc a{color:var(--red);text-decoration:none;border-bottom:1px solid var(--hair);}
.rsrc a:hover{border-bottom-color:var(--red);}

/* ============================================================
   NETWORKS. Who takes part, and under what rules. The question an
   industry reader has that a publication list cannot answer.
   ============================================================ */
.who{margin:0;padding:0;border-top:1px solid var(--rule);}
.who > div{
  display:grid;grid-template-columns:minmax(0,190px) minmax(0,1fr);
  column-gap:clamp(18px,3vw,40px);row-gap:5px;
  padding:16px 0;border-bottom:1px solid var(--hair);
}
.who dt{
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.09em;
  text-transform:uppercase;color:var(--red);padding-top:3px;
}
.who dd{
  margin:0;font-size:var(--fs-body);color:var(--ink-2);line-height:1.55;
}
@media (max-width:760px){
  .who > div{grid-template-columns:1fr;row-gap:4px;}
}

/* what it is actually made of */
.stack{
  margin-top:clamp(24px,3vw,32px);padding-top:16px;
  border-top:1px solid var(--rule);
  display:grid;grid-template-columns:150px minmax(0,1fr);
  column-gap:clamp(16px,2vw,28px);
}
.stack .sh{
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.11em;
  text-transform:uppercase;color:var(--red);padding-top:3px;
}
.stack .sl{font-size:var(--fs-body);color:var(--ink-2);max-width:64ch;}
@media (max-width:640px){.stack{grid-template-columns:1fr;row-gap:8px;}}

/* what I am open to, said once, without a banner */
.avail{
  border-left:3px solid var(--red);padding:2px 0 2px 18px;
  margin-bottom:clamp(24px,3vw,32px);max-width:60ch;
}
.avail .a1{font-size:var(--fs-lead);line-height:1.5;}
.avail .a1 .r{color:var(--red);}

.pub{
  display:grid;grid-template-columns:70px minmax(0,1fr);
  column-gap:clamp(16px,2vw,28px);
  padding:20px 0;border-top:1px solid var(--hair);text-decoration:none;
}
.pubs .pub:first-child{border-top:1px solid var(--rule);}
.pubs .pub:last-child{border-bottom:1px solid var(--rule);}
.pub .y{font-family:var(--font-body);font-size:var(--fs-mono);color:var(--mute);padding-top:4px;}
.pub .t{display:block;overflow-wrap:anywhere;font-size:var(--fs-title);font-weight:700;line-height:1.38;margin-bottom:5px;}
.pub:hover .t{color:var(--red);}
.pub .s{display:block;overflow-wrap:anywhere;font-size:var(--fs-body);color:var(--mute);}
.pub .s i{color:var(--ink-2);}
.pub .n{display:block;margin-top:9px;font-size:var(--fs-body);color:var(--ink-2);border-left:2px solid var(--red);padding-left:12px;}
.after{margin-top:18px;font-size:var(--fs-body);}
.after a{color:var(--red);}

.ev{
  display:grid;grid-template-columns:130px 1fr;
  column-gap:clamp(16px,2vw,28px);
  padding:15px 0;border-top:1px solid var(--hair);
}
.evs .ev:first-child{border-top:1px solid var(--rule);}
.evs .ev:last-child{border-bottom:1px solid var(--rule);}
.ev .d{
  font-family:var(--font-body);font-size:var(--fs-mono);color:var(--ink-2);
  padding-top:3px;font-variant-numeric:tabular-nums;white-space:nowrap;
}
.ev .h{font-size:var(--fs-title);font-weight:700;}
.ev .x{font-size:var(--fs-body);color:var(--mute);margin-top:2px;}
@media (max-width:620px){.ev{grid-template-columns:1fr;row-gap:3px;}}

/* Fixed track counts, never auto-fit. auto-fit used to land on three tracks at
   some widths, leaving one orphan cell carrying a left border with nothing beside
   it, which read as a rendering fault. */
.links{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:0;border-top:1px solid var(--rule);}
.links a{
  padding:20px 18px 20px 0;text-decoration:none;
  display:flex;flex-direction:column;gap:4px;
  border-bottom:1px solid var(--rule);
}
.links a + a{border-left:1px solid var(--hair);padding-left:20px;}
@media (max-width:820px){
  .links{grid-template-columns:repeat(2,minmax(0,1fr));}
  .links a:nth-child(2n+1){border-left:none;padding-left:0;}
}
@media (max-width:520px){
  .links{grid-template-columns:1fr;}
  .links a + a{border-left:none;padding-left:0;}
}
.links .w{font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.1em;text-transform:uppercase;color:var(--mute);}
/* an email address is longer than any other value here, and used to run straight
   through the divider into the next cell */
.links .v{font-size:clamp(.84rem,1vw,1.02rem);font-weight:700;overflow-wrap:anywhere;}
.links a:hover .v{color:var(--red);}

footer{padding-block:24px 40px;}
.foot{display:flex;flex-wrap:wrap;gap:8px 28px;justify-content:space-between;color:var(--mute);font-size:var(--fs-note);}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important;}
}

/* ============================================================
   THE HOOK. First screen: who, the claim, the proof. No figure.
   ============================================================ */
.hook-head{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 16px;
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.11em;
  text-transform:uppercase;color:var(--mute);
}
.hook-head b{color:var(--ink);font-weight:400;}
.hook{
  margin-top:clamp(22px,3.4vw,38px);
  font-size:clamp(2.1rem,5.6vw,4.3rem);
  line-height:1.02;letter-spacing:-.042em;font-weight:800;
  max-width:19ch;text-wrap:balance;
}
.hook .r{color:var(--red);}
.hook-sub{
  margin-top:clamp(20px,2.6vw,30px);
  font-size:clamp(1.08rem,1.75vw,1.32rem);
  line-height:1.45;max-width:34ch;color:var(--ink);
}
.hook-say{margin-top:16px;color:var(--ink-2);font-size:var(--fs-lead);max-width:54ch;}


/* one plain line out of the hero, into the thing that proves it */
.hook-cta{margin-top:clamp(26px,3.4vw,36px);font-size:var(--fs-lead);}
.hook-cta a{
  color:var(--red);text-decoration:none;
  border-bottom:1px solid var(--red);padding-bottom:2px;
}
.hook-cta a::after{content:" \2193";}

/* ============================================================
   THE FOUR FACTS. Inside the first screen, not in a band under it.
   Label, fact, year: three lines, so they scan as four separate
   things instead of one run on sentence.
   ============================================================ */
.creds{
  grid-column:1 / -1;grid-row:2;
  list-style:none;margin:clamp(30px,4vw,52px) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:0;border-top:1px solid var(--rule);
}
.creds li{
  display:flex;flex-direction:column;gap:5px;
  padding:15px 20px 4px 0;
}
.creds li + li{border-left:1px solid var(--hair);padding-left:20px;}
.creds .ck{
  font-size:var(--fs-eyebrow);letter-spacing:.13em;text-transform:uppercase;
  color:var(--red);
}
.creds .cv{font-size:var(--fs-body);color:var(--mute);line-height:1.45;}
.creds .cv b{color:var(--ink);font-weight:700;}
.creds .cv .r{color:var(--red);font-weight:700;}
.creds .cy{
  margin-top:auto;padding-top:8px;
  font-size:var(--fs-eyebrow);letter-spacing:.1em;color:var(--mute);
  font-variant-numeric:tabular-nums;
}
@media (max-width:900px){
  .creds{grid-template-columns:repeat(2,minmax(0,1fr));}
  .creds li:nth-child(2n+1){border-left:none;padding-left:0;}
  .creds li:nth-child(n+3){border-top:1px solid var(--hair);}
}
@media (max-width:560px){
  .creds{grid-template-columns:1fr;}
  .creds li + li{border-left:none;padding-left:0;border-top:1px solid var(--hair);}
}

/* ============================================================
   PRINCIPLES. What "thinks differently" actually looks like.
   ============================================================ */
/* Two by two. The number sits above the heading rather than in a narrow gutter
   beside it, so every cell starts on the same left edge and the ragged alignment
   between cells goes away. */
.prin{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:clamp(28px,4vw,60px);counter-reset:belief;
  border-top:1px solid var(--rule);
}
.prin > div{
  padding:clamp(18px,2.4vh,26px) 0;
  border-bottom:1px solid var(--hair);
}
.prin > div:nth-child(n+3){border-top:1px solid var(--hair);}
.prin > div::before{
  counter-increment:belief;content:counter(belief,decimal-leading-zero);
  display:block;margin-bottom:10px;
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.13em;
  color:var(--red);
}
.prin h3{
  font-size:clamp(1.08rem,1.7vw,1.3rem);line-height:1.28;font-weight:700;
  max-width:26ch;text-wrap:balance;margin-bottom:9px;
}
.prin p{
  color:var(--ink-2);font-size:var(--fs-body);max-width:44ch;
}
@media (max-width:760px){
  .prin{grid-template-columns:1fr;}
  .prin > div:nth-child(n+2){border-top:1px solid var(--hair);}
}

/* ============================================================
   CV + FULL PUBLICATIONS PAGES
   ============================================================ */
.page-head{padding-block:clamp(70px,8vw,104px) clamp(26px,3vw,40px);}
.page-head h1{font-size:clamp(2.1rem,5vw,3.4rem);letter-spacing:-.022em;}
.page-head p{margin-top:14px;color:var(--ink-2);max-width:56ch;}
.back{
  display:inline-block;margin-bottom:20px;font-family:var(--font-body);
  font-size:var(--fs-eyebrow);letter-spacing:.11em;text-transform:uppercase;
  color:var(--mute);text-decoration:none;
}
.back:hover{color:var(--red);}

.cvblock{display:flex;flex-direction:column;}
.cvrow{
  display:grid;grid-template-columns:150px 1fr;
  column-gap:clamp(16px,2.4vw,32px);row-gap:6px;
  padding:20px 0;border-top:1px solid var(--hair);
}
.cvblock .cvrow:first-child{border-top:1px solid var(--rule);}
.cvblock .cvrow:last-child{border-bottom:1px solid var(--rule);}
.cvrow .when{font-family:var(--font-body);font-size:var(--fs-mono);color:var(--mute);padding-top:4px;}
.cvrow .what{font-size:var(--fs-title);font-weight:700;line-height:1.35;}
.cvrow .where{font-size:var(--fs-body);color:var(--mute);margin-top:2px;}
.cvrow ul{margin:9px 0 0;padding:0;list-style:none;}
.cvrow li{
  font-size:var(--fs-body);color:var(--ink-2);padding-left:16px;position:relative;
  line-height:1.5;margin-top:5px;
}
.cvrow li::before{content:"";position:absolute;left:0;top:.62em;width:8px;height:1px;background:var(--red);}
@media (max-width:640px){.cvrow{grid-template-columns:1fr;}}

.yearmark{
  font-family:var(--font-display);font-weight:700;font-size:clamp(1.5rem,3vw,2.1rem);
  color:var(--red);line-height:1;padding-top:2px;
}
.bibnote{
  display:inline-block;margin-left:8px;font-family:var(--font-body);
  font-size:var(--fs-eyebrow);letter-spacing:.09em;text-transform:uppercase;
  color:var(--mute);border:1px solid var(--hair);padding:2px 7px;
  vertical-align:middle;white-space:nowrap;
}
/* a long tag like "Multiple Sclerosis Data Alliance" cannot fit on a phone,
   and nowrap made it push the whole page sideways */
@media (max-width:560px){.bibnote{white-space:normal;display:inline;margin-left:0;}}
.bibnote.sel{color:var(--red);border-color:var(--red);}

/* ============================================================
   MORE RED. Signature stripe, section rules, principle heads.
   ============================================================ */
body::before{
  content:"";position:fixed;top:0;left:0;right:0;height:3px;
  background:var(--red);z-index:60;
}
.topbar{top:3px;}

h2.head{position:relative;padding-bottom:15px;}
h2.head::after{
  content:"";position:absolute;left:0;bottom:0;width:46px;height:2px;background:var(--red);
}
.page-head h1{position:relative;padding-bottom:16px;}
.page-head h1::after{
  content:"";position:absolute;left:0;bottom:0;width:52px;height:2px;background:var(--red);
}

.prin h3{color:var(--red);}
.tb-name a:hover{color:var(--red);}

/* events get a red tick on the left */
.ev{position:relative;padding-left:16px;}
/* one dash width for every row. two sizes made the date column look ragged. */
.ev::before{
  content:"";position:absolute;left:0;top:1.05em;width:10px;height:2px;background:var(--red);
}

.mast-side{align-self:center;}
.hero-viz{max-width:460px;}
.figbox .hero-viz{max-width:100%;}

/* ============================================================
   DEFINITION + PROBLEM/RESPONSE PAIRS
   Sections 02 and 03 name the term, then show the difficulty
   on the left and what I do about it on the right.
   ============================================================ */
.define{
  border-left:3px solid var(--red);
  padding:2px 0 2px 18px;
  margin-bottom:clamp(26px,3.4vw,38px);
  font-size:var(--fs-lead);
  line-height:1.5;max-width:56ch;
}
.define b{font-weight:700;}
.define span{color:var(--ink-2);}

.pair{margin:0;padding:0;border-top:1px solid var(--rule);}
.pair > div{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);
  column-gap:clamp(18px,3vw,40px);row-gap:6px;
  padding:14px 0;border-bottom:1px solid var(--hair);
}
.pair dt{
  font-size:var(--fs-body);color:var(--ink);font-weight:700;line-height:1.45;
  position:relative;padding-left:18px;
}
.pair dt::before{
  content:"";position:absolute;left:0;top:.62em;width:10px;height:2px;background:var(--red);
}
.pair dd{
  margin:0;font-size:var(--fs-body);color:var(--ink-2);line-height:1.55;
}
.pair .cap{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);
  column-gap:clamp(18px,3vw,40px);padding-bottom:9px;
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.11em;
  text-transform:uppercase;color:var(--mute);border-bottom:none;
}
@media (max-width:760px){
  .pair > div,.pair .cap{grid-template-columns:1fr;}
  .pair .cap span:last-child{display:none;}
  .pair dd{padding-left:18px;}
}

/* keep the four highlight cells the same visual weight */

.mast-side picture{display:block;width:100%;}

/* ============================================================
   The definition moved into the label column, which was empty.
   Smaller here, and the label stops sticking so the two travel together.
   ============================================================ */
/* The statement is the first paragraph of the section now, not a slab of display
   type sitting above it. It reads as someone talking, which is the point. */
.lede{
  margin:0 0 clamp(18px,2.4vw,26px);
  max-width:70ch;
  font-size:var(--fs-lead);line-height:1.55;color:var(--ink-2);
}
.lede b{color:var(--ink);}

/* ============================================================
   RESULT LEAD INS. Say what the numbers are before showing them.
   ============================================================ */
.rlead{
  font-size:var(--fs-body);color:var(--ink-2);max-width:74ch;
  margin-bottom:clamp(18px,2.4vw,26px);
}
.rlead b{color:var(--ink);}
.clead{
  margin-top:clamp(22px,3vw,30px);margin-bottom:9px;
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.11em;
  text-transform:uppercase;color:var(--red);
}
.counts{margin-top:0;}

/* The email is the longest value on the page and used to run out of its cell.
   Its own full width row, at a size that says this is the way to reach me. */
.mailrow{
  display:flex;flex-direction:column;gap:5px;
  padding:18px 0;text-decoration:none;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--hair);
}
.mailrow .w{
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.1em;
  text-transform:uppercase;color:var(--mute);
}
.mailrow .v{
  font-family:var(--font-display);font-size:clamp(1.12rem,2.1vw,1.55rem);font-weight:700;
  overflow-wrap:anywhere;line-height:1.2;
}
.mailrow:hover .v{color:var(--red);}
.links.three{grid-template-columns:repeat(3,minmax(0,1fr));border-top:none;}
@media (max-width:640px){
  .links.three{grid-template-columns:1fr;}
  .links.three a + a{border-left:none;padding-left:0;}
}

/* talk type. the list is newest first, so the tag carries the "which of these is
   industry" question that the ordering used to carry badly. */
.ev .t{
  display:inline-block;margin-right:10px;vertical-align:1px;
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.09em;
  text-transform:uppercase;color:var(--mute);
  border:1px solid var(--hair);padding:1px 6px;
}
.ev .t.ind{color:var(--red);border-color:var(--red);}

/* the caveat I make about my own result, set apart from the argument for it */
.rsrc.caveat{
  border-left:2px solid var(--red);padding-left:16px;margin-top:16px;
}
.rsrc.caveat b{color:var(--ink);}

/* the one line on the page that is not about work */
.avail .a2{
  margin-top:12px;font-size:var(--fs-body);color:var(--mute);
}

/* ============================================================
   THE THREE THINGS YOU CAN OPERATE.
   Panels, not cards: a rule at the top, no box, no shadow, no
   rounding. They read as parts of the page rather than widgets
   dropped onto it.
   ============================================================ */
.demo{
  border-top:1px solid var(--rule);
  padding-block:clamp(22px,3vw,32px);
}
.demo-head{
  display:flex;align-items:baseline;
  gap:8px 18px;flex-wrap:wrap;margin-bottom:10px;
}
.demo-head .dn{font-family:var(--font-display);font-size:1.32rem;font-weight:700;}
.demo-head .dn a{
  text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:3px;text-decoration-color:var(--mute);
}
.demo-head .dn a:hover{color:var(--red);text-decoration-color:var(--red);}
.demo-head .dr{
  font-family:var(--font-body);font-size:var(--fs-mono);
  letter-spacing:.04em;color:var(--ink-2);
}
.dlead{
  font-size:var(--fs-lead);color:var(--ink-2);max-width:70ch;line-height:1.5;
  margin-bottom:clamp(16px,2vw,22px);
}
.dlead b{color:var(--ink);}

.dstage{
  background:var(--wash);
  border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);
  padding:clamp(12px,1.6vw,18px) clamp(10px,1.4vw,16px);
}
.dstage svg{width:100%;height:auto;display:block;overflow:visible;}

/* the control itself */
.dctl{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;gap:0 clamp(12px,2vw,20px);
  padding:16px 0 4px;
}
.dcl,.dcv{
  font-family:var(--font-body);font-size:var(--fs-eyebrow);letter-spacing:.1em;
  text-transform:uppercase;color:var(--mute);white-space:nowrap;
}
.dcv{color:var(--red);text-align:right;font-variant-numeric:tabular-nums;}
.dctl input[type=range]{
  -webkit-appearance:none;appearance:none;
  width:100%;height:26px;background:transparent;cursor:pointer;
}
.dctl input[type=range]::-webkit-slider-runnable-track{
  height:2px;background:var(--rule);
}
.dctl input[type=range]::-moz-range-track{height:2px;background:var(--rule);}
.dctl input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;
  width:17px;height:17px;border-radius:50%;background:var(--red);
  border:2px solid var(--paper);margin-top:-8px;
}
.dctl input[type=range]::-moz-range-thumb{
  width:17px;height:17px;border-radius:50%;background:var(--red);
  border:2px solid var(--paper);
}
.dctl input[type=range]:focus-visible{outline:2px solid var(--red);outline-offset:4px;}
@media (max-width:620px){
  .dctl{grid-template-columns:1fr auto;}
  .dctl input[type=range]{grid-column:1 / -1;grid-row:2;}
}

/* the readout */
.dout{
  display:grid;grid-template-columns:minmax(0,190px) minmax(0,1fr) auto;
  align-items:center;gap:0 clamp(12px,2vw,20px);
  padding:12px 0;border-bottom:1px solid var(--hair);
}
.dok{
  font-family:var(--font-body);font-size:var(--fs-mono);
  letter-spacing:.04em;color:var(--ink);
}
.dobar{display:block;height:9px;background:var(--paper);border:1px solid var(--hair);}
.dobar i{display:block;height:100%;background:var(--red);transition:width .22s ease;}
.dov{
  font-family:var(--font-display);font-size:1.32rem;font-weight:700;
  color:var(--red);font-variant-numeric:tabular-nums;text-align:right;
}
@media (max-width:620px){
  .dout{grid-template-columns:1fr auto;}
  .dobar{grid-column:1 / -1;grid-row:2;margin-top:8px;}
}

/* the toggles on the three streams figure */
.dtoggles{display:flex;flex-wrap:wrap;gap:10px;padding:16px 0 4px;}
.dtog{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--font-body);font-size:var(--fs-mono);letter-spacing:.03em;
  color:var(--mute);background:none;cursor:pointer;
  border:1px solid var(--hair);padding:7px 13px;
}
.dtog .tg{
  width:9px;height:9px;background:var(--hair);flex:none;
  transition:background .18s ease;
}
.dtog.on{color:var(--ink);border-color:var(--rule);}
.dtog.on .tg{background:var(--ink-2);}
.dtog.key.on{border-color:var(--red);color:var(--red);}
.dtog.key.on .tg{background:var(--red);}
.dtog:hover{border-color:var(--red);}
.dtog:focus-visible{outline:2px solid var(--red);outline-offset:3px;}

.dsay{
  margin-top:14px;font-size:var(--fs-body);color:var(--ink-2);
  max-width:72ch;line-height:1.55;min-height:3.1em;
}
.dsay b{color:var(--ink);}
.dnote{
  margin-top:10px;font-size:var(--fs-note);color:var(--mute);
  font-style:italic;max-width:72ch;
}
.dnote a{color:var(--mute);}
.dnote a:hover{color:var(--red);}

/* the list of everything else sits below the three, quieter */
.demo + .rows{margin-top:clamp(26px,3.4vw,38px);}

/* ============================================================
   THE DIAL. The control for a degree should look like a degree,
   not like a form input and not like three buttons.
   ============================================================ */
.dial{padding:14px 0 2px;display:flex;justify-content:center;}
.dial svg{
  width:100%;max-width:420px;height:auto;display:block;
  cursor:grab;touch-action:none;
}
.dial svg:active{cursor:grabbing;}
.dial svg:focus-visible{outline:2px solid var(--red);outline-offset:6px;}

/* ============================================================
   HINT. Nobody should have to guess that a figure does something.
   ============================================================ */
.demo{position:relative;}
.hint{
  display:inline-flex;align-items:center;gap:7px;margin-right:auto;
  font-size:var(--fs-eyebrow);letter-spacing:.09em;text-transform:uppercase;
  color:var(--red);
}
.hint::before{
  content:"";width:9px;height:9px;border-radius:50%;
  background:var(--red);
  animation:pulse 2.6s ease-in-out infinite;
}
@keyframes pulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.5);opacity:.35}}
@media (prefers-reduced-motion:reduce){.hint::before{animation:none;}}
@media (max-width:760px){
  .hint{order:3;flex-basis:100%;margin-top:2px;}
}

/* ============================================================
   NETWORKS. Two across, three down. Wider cells even out the
   copy lengths, which a three column layout could not.
   ============================================================ */
.whogrid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0;border-top:1px solid var(--rule);
}
.wc{
  padding:clamp(22px,2.6vw,30px) clamp(20px,2.4vw,30px) clamp(24px,2.8vw,32px) 0;
  border-bottom:1px solid var(--hair);
}
.wc:nth-child(even){
  border-left:1px solid var(--hair);
  padding-left:clamp(20px,2.4vw,30px);
}
.wmark{display:block;width:64px;height:64px;margin-bottom:16px;overflow:visible;}
.wc h3{
  font-size:1.14rem;font-weight:700;margin-bottom:9px;letter-spacing:-.016em;
}
.wc p{font-size:var(--fs-body);color:var(--ink-2);line-height:1.55;max-width:46ch;}
.wc .r{color:var(--red);}
@media (max-width:700px){
  .whogrid{grid-template-columns:1fr;}
  .wc,.wc:nth-child(even){border-left:none;padding-left:0;}
}

/* the roles in the FLkit figure are pressable text */
.flkit-role:hover{fill:var(--red);}

/* last updated, and the counter when it is switched on */
.hits{font-variant-numeric:tabular-nums;}

/* ============================================================
   BENCHMARK TAG. This widget reports 0.846 on 740 records from a
   public benchmark. Section 01 reports 0.8398 on 26,246 patients.
   Same red, same bars, very different evidence, so say which.
   ============================================================ */
.tagbench{
  display:inline-block;
  font-size:var(--fs-eyebrow);letter-spacing:.1em;text-transform:uppercase;
  color:var(--mute);border:1px solid var(--hair);padding:2px 8px;
}
#d-dof .dobar i,#d-dof .dov{color:var(--ink-2);}
#d-dof .dobar i{background:var(--ink-2);}

/* the plain reading of the maths, above the maths */
.dsay-plain{
  margin-top:12px;font-size:var(--fs-body);color:var(--ink);
  max-width:70ch;line-height:1.55;
}

/* the performance trace: a plateau, then a step, then a settle */
.perf{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;gap:0 clamp(14px,2vw,22px);
  padding:16px 0 10px;border-top:1px solid var(--hair);margin-top:14px;
}
.perf .pl{
  font-size:var(--fs-eyebrow);letter-spacing:.1em;text-transform:uppercase;
  color:var(--mute);line-height:1.5;
}
.perf svg{width:100%;height:auto;display:block;overflow:visible;}
.perf .pv{
  font-size:1.6rem;font-weight:800;letter-spacing:-.03em;color:var(--red);
  font-variant-numeric:tabular-nums;text-align:right;
}
@media (max-width:620px){
  .perf{grid-template-columns:1fr auto;}
  .perf svg{grid-column:1 / -1;grid-row:2;margin-top:10px;}
}

/* what kind of talk it was, so one list can hold all of them */
.ttag{
  display:inline-block;margin-right:10px;vertical-align:1px;
  font-size:var(--fs-eyebrow);letter-spacing:.09em;text-transform:uppercase;
  color:var(--mute);border:1px solid var(--hair);padding:1px 6px;font-weight:400;
}
.ttag.ind{color:var(--red);border-color:var(--red);}

/* ============================================================
   THE THREE LINKS. Marks drawn here rather than borrowed, and the
   word stays next to each one so nothing depends on recognising a
   glyph.
   ============================================================ */
.meta{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px;}
.meta a{
  display:inline-flex;align-items:center;gap:9px;
  font-size:var(--fs-mono);color:var(--mute);text-decoration:none;
  border-bottom:1px solid transparent;padding-bottom:1px;
}
.meta svg{
  width:16px;height:16px;flex:none;
  fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round;
}
.meta svg .k{fill:currentColor;stroke:none;}
.meta a:hover{color:var(--red);border-bottom-color:var(--red);}

/* the two column list on the CV. its old rules went with markup that no
   longer exists, and this one still uses them. */
.tracks{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(24px,3vw,48px);
}
.track h3{font-size:var(--fs-title);margin-bottom:10px;}
.track ul{margin:0;padding:0;list-style:none;}
.track li{
  font-size:var(--fs-body);color:var(--ink-2);
  padding:8px 0;border-top:1px solid var(--hair);
}
@media (max-width:700px){.tracks{grid-template-columns:1fr;}}

/* ============================================================
   THE TWO RULES. A claim, not a caption, so it is allowed to
   take up room and hold the eye.
   ============================================================ */
.rules{
  margin:0 0 clamp(26px,3.2vw,36px);
  padding:clamp(16px,2vw,22px) 0 clamp(16px,2vw,22px) clamp(18px,2vw,24px);
  border-left:3px solid var(--red);
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
  font-size:clamp(1.02rem,1.5vw,1.2rem);line-height:1.45;
  max-width:62ch;color:var(--ink);
}
.rules b{display:block;color:var(--red);margin-bottom:6px;}

/* the project names carry the section, so let them be seen */
.demo-head .dn{font-size:1.62rem;letter-spacing:-.03em;}
@media (max-width:620px){.demo-head .dn{font-size:1.36rem;}}

/* ============================================================
   THE HERO ON A PHONE. These two have to live at the end of the
   file: the rules they override are declared after the masthead
   media query, so putting them up there loses on source order.
   ============================================================ */
@media (max-width:820px){
  /* The credentials are pinned to row 2 for the desktop grid. Left pinned, auto
     placement pushed the portrait into row 3 and it landed below them. */
  .creds{grid-row:auto;}
  /* The picture is width:100% for the desktop column. In a row it ate the whole
     line and shoved the links off the right edge of the screen. */
  .mast-side picture{width:auto;flex:none;}
  .mast-side .portrait{max-width:108px;}
}

/* ============================================================
   THE NUMBER AND THE HEADING SHARE A BASELINE.
   Matching the box tops is not the same thing. The number is
   43px and the heading 35px, so equal tops put their baselines
   about six pixels apart and the number hangs below the line of
   the title. Grid baseline alignment does it properly, and it
   keeps working when either size changes.
   ============================================================ */
@media (min-width:901px){
  .sec > .container.grid{align-items:baseline;}
}
