:root{
  --paper:#FFFFFF; --ink:#14151A; --soft:#3f4149; --faint:#6a6d78; --whisper:#9aa0ad;
  --hair:#E7E7E4; --rule:#20222A; --blue:#1B4B8F; --blue-soft:#3E6FB8;
  --serif:"Source Serif 4",Georgia,"Times New Roman",serif;
  --display:"Playfair Display",Georgia,"Times New Roman",serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --rail:15rem;
}
@media (prefers-color-scheme:dark){
  :root{--paper:#12131A;--ink:#E9E9F0;--soft:#C0C2CC;--faint:#9195A2;--whisper:#676C7A;
    --hair:#282A34;--rule:#E9E9F0;--blue:#7FA8E6;--blue-soft:#A9C4F0;}
}
*{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;font-size:16px;}
:root{--base:1.5rem;}  /* 24px baseline unit */
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--serif);
  font-size:15.5px;line-height:1.55;-webkit-font-smoothing:antialiased;}
a{color:inherit;text-decoration:none;}
a:focus-visible{outline:1.5px solid var(--blue);outline-offset:3px;}

.shell{display:grid;grid-template-columns:var(--rail) 1fr;}
@media (max-width:760px){.shell{grid-template-columns:1fr;}}

/* left rail */
.rail{border-right:1px solid var(--hair);padding:clamp(1.6rem,3vw,2.4rem) clamp(1.2rem,2vw,1.8rem);
  position:sticky;top:0;align-self:start;height:100vh;display:flex;flex-direction:column;}
.rail-name{font-family:var(--display);font-weight:700;font-size:1.25rem;letter-spacing:-0.01em;margin:0 0 2.2rem;color:var(--blue);}
.rail nav{display:flex;flex-direction:column;gap:0.05rem;}
.rail nav a{font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1;
  font-size:0.92rem;letter-spacing:0.06em;color:var(--blue);padding:0.38rem 0;}
.rail nav a:hover{color:var(--ink);}
.rail nav a.here{color:var(--ink);border-left:2px solid var(--blue);padding-left:0.7rem;margin-left:-0.7rem;}
.rail-foot{margin-top:auto;padding-top:2rem;display:flex;flex-direction:column;gap:0.3rem;
  font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1;
  font-size:0.86rem;letter-spacing:0.06em;color:var(--blue);}
.rail-foot a:hover{color:var(--ink);}
@media (max-width:760px){
  .rail{position:static;height:auto;border-right:none;border-bottom:1px solid var(--hair);
    flex-direction:row;flex-wrap:wrap;align-items:baseline;gap:0.2rem 1.1rem;}
  .rail-name{margin:0 1.2rem 0 0;}
  .rail nav{flex-direction:row;flex-wrap:wrap;gap:0.1rem 1rem;}
  .rail nav a.here{border-left:none;padding-left:0;margin-left:0;border-bottom:2px solid var(--blue);}
  .rail-foot{margin-top:0;padding-top:0;flex-direction:row;flex-wrap:wrap;gap:0.2rem 1rem;
    flex-basis:100%;order:3;}
}

/* body */
.body{padding:clamp(2.2rem,5vw,4rem) clamp(1.4rem,5vw,4.5rem);max-width:44rem;}
.kicker{font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1,"onum" 1;font-size:0.86rem;letter-spacing:0.14em;color:var(--blue-soft);margin:0 0 var(--base);}
.frontmatter{font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1,"onum" 1;
  letter-spacing:0.1em;font-size:0.76rem;color:var(--whisper);
  border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);
  padding:calc(var(--base) * 0.5) 0;margin:0 0 var(--base);
  display:flex;flex-wrap:wrap;gap:0.3rem 1.4rem;}
.frontmatter b{font-weight:400;color:var(--blue-soft);}
h1{font-family:var(--display);font-weight:700;font-size:clamp(1.7rem,3.2vw,2.3rem);letter-spacing:-0.015em;line-height:1.05;margin:0 0 1.1rem;color:var(--blue);}
.lede{font-style:italic;font-size:clamp(0.95rem,1.6vw,1.05rem);line-height:1.4rem;color:var(--soft);
  margin:0 0 var(--base);max-width:29rem;text-wrap:balance;}
.overview{border-top:1px solid var(--hair);padding-top:var(--base);}
.subhead{font-weight:600;font-size:0.92rem;letter-spacing:-0.005em;color:var(--blue);
  margin:var(--base) 0 0;line-height:var(--base);}
.subhead:first-of-type{margin-top:0;}
.overview p{font-size:0.88rem;line-height:1.55;color:var(--soft);margin:0 0 1.05rem;}
/* drop cap: exactly ONE per article, always — never per-column, never per-
   subhead. Case 1: a page with a lede paragraph before .cols (Overview) —
   the drop cap goes there. Case 2: a write-up with no lede, .cols is the
   very first thing in .overview — the drop cap goes on the opening
   paragraph of the first column only, :not(:has(> p)) is what stops case 2
   from also matching on Overview (which does have a direct-child <p>). A
   page like cv.html has neither shape, so it never matches either rule. */
#top .overview > p:first-of-type::first-letter,
.overview:not(:has(> p)) .col:first-child > p:first-of-type::first-letter{
  font-family:var(--display);font-weight:700;font-size:2.6em;line-height:0.72;float:left;margin:0.03em 0.09em 0 0;color:var(--blue);}
.overview ul{margin:0 0 1.05rem;padding-left:1.1rem;}
.overview li{font-size:0.88rem;line-height:1.48;color:var(--soft);margin:0 0 0.45rem;}
.overview code{font-family:var(--mono);font-size:0.87em;background:color-mix(in srgb, var(--ink) 7%, transparent);padding:0.1em 0.4em;border-radius:3px;}

/* two explicit columns for the longer prose pages (Overview, and each
   write-up on projects.html/apps.html) — an author-controlled split, not
   browser auto-balancing, so a short paragraph never gets sliced mid-
   sentence the way `column-count` does */
.cols{display:block;}
@media (min-width:900px){
  .cols{display:grid;grid-template-columns:1fr 1fr;gap:0 3.5rem;}
  .col{max-width:36rem;}
}

/* sheet header (on domain pages, and reused per-entry on projects.html/apps.html) */
.sheet-head{border-bottom:2px solid var(--rule);padding-bottom:1rem;margin-bottom:1.8rem;}
.sheet-head .kicker{margin-bottom:0.7rem;}
.sheet-head h1,.sheet-head h2{font-family:var(--display);font-size:clamp(1.4rem,2.8vw,1.85rem);margin:0 0 0.5rem;font-weight:700;letter-spacing:-0.015em;color:var(--blue);line-height:1.1;}
.sheet-head .tools{font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1;font-size:0.86rem;letter-spacing:0.03em;color:var(--blue-soft);}
.sheet-intro{font-size:0.92rem;line-height:1.55;color:var(--soft);max-width:34rem;margin:0 0 2.2rem;}

/* items */
.item{padding:calc(var(--base) * 0.6) 0;border-top:1px solid var(--hair);display:grid;grid-template-columns:1fr 7rem;gap:1.5rem;}
.item:last-of-type{border-bottom:1px solid var(--hair);}
.item-t{font-weight:600;font-size:0.96rem;letter-spacing:-0.005em;color:var(--ink);}
a.item-t:hover{color:var(--blue);}
a.item-t .go{font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1;font-size:0.82rem;letter-spacing:0.02em;color:var(--blue);margin-left:0.5rem;vertical-align:middle;}
.item-d{font-size:0.82rem;line-height:1.35rem;color:var(--faint);margin:0.25rem 0 0;}
.item-w{font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1;font-size:0.8rem;letter-spacing:0.02em;color:var(--whisper);padding-top:0.25rem;}
@media (max-width:560px){.item{grid-template-columns:1fr;gap:0.15rem;}.item-w{order:-1;}}

/* image slot for the software/apps sheet — the one place screenshots go */
.shots{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1rem;margin:1.4rem 0 0;}
.shot{aspect-ratio:9/16;background:var(--hair);border-radius:10px;position:relative;overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1;font-size:0.8rem;letter-spacing:0.03em;color:var(--whisper);text-align:center;padding:1rem;}
.shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}

/* small inline app mark, used once per app on apps.html */
.app-mark{width:52px;height:52px;border-radius:12px;vertical-align:middle;margin-right:0.7rem;
  box-shadow:0 1px 2px rgba(0,0,0,.15),0 4px 14px rgba(0,0,0,.14);}

.next{margin-top:clamp(3rem,7vw,4.5rem);border-top:1px solid var(--hair);padding-top:1.4rem;
  font-family:var(--serif);font-variant:small-caps;font-feature-settings:"smcp" 1;font-size:0.9rem;letter-spacing:0.02em;}
.next a{color:var(--blue);}
.next a:hover{text-decoration:underline;text-underline-offset:3px;}

/* let the page use the actual width of the screen: once .cols splits into
   two real columns (see above), scale the content well with the viewport
   instead of stopping at a fixed cap, so it doesn't strand a slab of
   white space on a wide monitor */
@media (min-width:900px){
  .body{max-width:min(90vw, 74rem);}
}
