/* ============================================================
   Ink & Marigold : design tokens
   marigold = the poet   |   teal = the engineer
   ============================================================ */
:root{
  --paper:#F4F3EE; --raised:#FBFAF7; --ink:#141C33;
  --muted:#525C79; --line:#DEDACE;
  --marigold:#C8781A; --marigold-ink:#9C5B0D;
  --teal:#1D6B66; --teal-ink:#155753;
  /* outcomes: green for sent, red for not sent. Kept desaturated so
     they sit beside marigold and teal rather than shouting over them. */
  --good:#2E7D51; --good-ink:#1F6440;
  --bad:#B23B3B;  --bad-ink:#932F2F;
  --shadow:0 1px 2px rgba(20,28,51,.05), 0 8px 24px -12px rgba(20,28,51,.16);
  --display:"Fraunces",Georgia,"Times New Roman",serif;
  --body:"Archivo",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --wrap:1140px; --r:14px;
}
html[data-theme="dark"]{
  --paper:#10151F; --raised:#171F2E; --ink:#EDEAE2; --muted:#9AA3B8; --line:#28324A;
  --marigold:#E9A23B; --marigold-ink:#F0B662;
  --teal:#54B8B1; --teal-ink:#6FC9C3;
  --good:#4FB07C; --good-ink:#6FC894;
  --bad:#E06A6A;  --bad-ink:#EE8585;
  --shadow:0 1px 2px rgba(0,0,0,.3), 0 8px 24px -12px rgba(0,0,0,.6);
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--body);font-size:17px;line-height:1.65;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{max-width:100%;display:block}
a{color:inherit}
:focus-visible{outline:2.5px solid var(--marigold);outline-offset:3px;border-radius:3px}

.wrap{width:min(100% - 2.5rem,var(--wrap));margin-inline:auto}
@media(max-width:640px){.wrap{width:min(100% - 1.75rem,var(--wrap))}}

/* ---------- type ---------- */
h1,h2,h3,h4{font-family:var(--display);font-weight:600;line-height:1.12;margin:0;
  letter-spacing:-.015em}
h2{font-size:clamp(1.9rem,4.2vw,2.9rem)}
h3{font-size:1.3rem}
p{margin:0 0 1.05em}
.lede{font-size:1.09rem;color:var(--muted)}

.eyebrow{
  font-family:var(--mono);font-size:.7rem;letter-spacing:.19em;text-transform:uppercase;
  color:var(--muted);display:flex;align-items:center;gap:.7rem;margin-bottom:1.1rem;
}
.eyebrow::after{content:"";flex:1;height:1px;background:var(--line)}
.eyebrow{flex-wrap:wrap}
/* The hero eyebrow carries the location and the motto, which is long
   enough that on a small phone the trailing rule collapses to a stub.
   Below this width the rule is dropped rather than shown as a stray dash. */
@media(max-width:460px){
  .hero .eyebrow::after{display:none}
}
.eyebrow b{font-weight:400;color:var(--marigold-ink)}
.eyebrow.eng b{color:var(--teal-ink)}

/* ---------- header ---------- */
header{
  position:sticky;top:0;z-index:50;background:color-mix(in srgb,var(--paper) 86%,transparent);
  backdrop-filter:blur(14px);border-bottom:1px solid transparent;transition:border-color .25s;
}
header.stuck{border-bottom-color:var(--line)}
.bar{display:flex;align-items:center;gap:1.5rem;height:64px}
.mark{font-family:var(--display);font-weight:600;font-size:1.12rem;text-decoration:none;
  letter-spacing:-.02em;white-space:nowrap}
.mark i{color:var(--marigold);font-style:normal}
nav{margin-left:auto;display:flex;gap:.35rem}
nav a{
  text-decoration:none;font-size:.87rem;color:var(--muted);padding:.45rem .7rem;border-radius:8px;
  transition:color .18s,background .18s;
}
nav a:hover{color:var(--ink);background:color-mix(in srgb,var(--line) 45%,transparent)}
nav a.on{color:var(--ink);background:color-mix(in srgb,var(--marigold) 13%,transparent)}
@media(max-width:900px){nav{display:none}}

/* mobile menu */
.burger{display:none}
/* The panel is hidden at every width by default. Only the mobile
   media query below is allowed to reveal it, and only when opened. */
#panel{display:none}
@media(max-width:900px){
  .burger{
    display:grid;place-items:center;background:none;border:1px solid var(--line);color:var(--muted);
    width:38px;height:38px;border-radius:10px;cursor:pointer;flex:none;margin-left:.5rem;
  }
  .burger svg{width:18px;height:18px}
  #panel.open{
    display:block;border-top:1px solid var(--line);background:var(--paper);
    padding:.6rem 0 1rem;
  }
  #panel a{
    display:block;text-decoration:none;color:var(--ink);font-size:1rem;
    padding:.7rem .25rem;border-bottom:1px solid var(--line);
  }
  #panel a:last-child{border-bottom:0}
}
.skip{
  position:absolute;left:-9999px;top:0;background:var(--ink);color:var(--paper);
  padding:.6rem 1rem;border-radius:0 0 8px 0;z-index:100;text-decoration:none;font-size:.9rem;
}
.skip:focus{left:0}
.toggle{
  margin-left:auto;background:none;border:1px solid var(--line);color:var(--muted);
  width:38px;height:38px;border-radius:10px;cursor:pointer;display:grid;place-items:center;
  transition:color .18s,border-color .18s;flex:none;
}
@media(min-width:901px){.toggle{margin-left:.6rem}}
.toggle:hover{color:var(--ink);border-color:var(--muted)}
.toggle svg{width:17px;height:17px}
html[data-theme="dark"] .sun{display:none}
html:not([data-theme="dark"]) .moon{display:none}

/* ---------- hero ---------- */
.hero{padding:clamp(3.5rem,9vw,6.5rem) 0 clamp(2.5rem,6vw,4rem)}
.hero-grid{display:grid;grid-template-columns:1fr 300px;gap:clamp(2rem,5vw,4.5rem);align-items:start}
@media(max-width:860px){.hero-grid{grid-template-columns:1fr;gap:2.25rem}}

.name{
  font-size:clamp(2.5rem,7vw,4.25rem);line-height:1;letter-spacing:-.035em;
  margin:0 0 1.1rem;
}
/* the name he also goes by, bracketed like the About heading */
.alias{
  font-family:var(--mono);font-weight:400;
  font-size:.26em;letter-spacing:.2em;text-transform:uppercase;
  color:var(--muted);white-space:nowrap;vertical-align:.85em;
}
.thesis{
  font-family:var(--display);font-weight:400;
  font-size:clamp(1.35rem,3.1vw,2.05rem);line-height:1.28;letter-spacing:-.018em;
  margin:0 0 1.5rem;max-width:22ch;
}
/* "Words" and "data" carry the whole idea, so they get a soft wash of
   their own colour rather than an underline. Underlines here read as
   hyperlinks and invite a click that goes nowhere. */
.thesis .w,.thesis .d{
  font-weight:600;white-space:nowrap;padding:0 .1em;border-radius:4px;
  background-image:linear-gradient(currentColor 0 100%);
  background-repeat:no-repeat;background-position:0 100%;
  background-size:0% 100%;
  animation:wash .7s cubic-bezier(.2,.8,.3,1) forwards;
}
.thesis .w{color:var(--marigold-ink);animation-delay:.35s}
.thesis .d{color:var(--teal-ink);animation-delay:.55s}
.thesis .w{background-image:linear-gradient(color-mix(in srgb,var(--marigold) 20%,transparent) 0 100%)}
.thesis .d{background-image:linear-gradient(color-mix(in srgb,var(--teal) 22%,transparent) 0 100%)}
@keyframes wash{to{background-size:100% 100%}}

.who{display:flex;flex-wrap:wrap;gap:.55rem;margin-bottom:1.5rem}
.chip{
  font-family:var(--mono);font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;
  border:1px solid var(--line);border-radius:100px;padding:.36rem .8rem;color:var(--muted);
}
.chip.hi{border-color:color-mix(in srgb,var(--teal) 45%,transparent);color:var(--teal-ink)}

.cta{display:flex;flex-wrap:wrap;gap:.7rem;margin-top:1.9rem}
.btn{
  display:inline-flex;align-items:center;gap:.5rem;text-decoration:none;cursor:pointer;
  font-family:var(--body);font-size:.92rem;font-weight:500;
  padding:.72rem 1.3rem;border-radius:10px;border:1px solid transparent;
  transition:transform .16s,box-shadow .16s,background .16s,border-color .16s;
}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--ink);color:var(--paper);box-shadow:var(--shadow)}
.btn-primary:hover{box-shadow:0 6px 20px -6px color-mix(in srgb,var(--ink) 45%,transparent)}
.btn-ghost{border-color:var(--line);color:var(--ink)}
.btn-ghost:hover{border-color:var(--marigold);color:var(--marigold-ink)}
.btn svg{width:15px;height:15px;flex:none}

/* The marigold line is the photo's own border, so the image meets it
   directly with no gap. Ratio lives on <picture> so the border cannot
   distort it. */
.portrait{position:relative}
/* <picture> is inline by default, which leaves a baseline gap under the
   photo and stops height:100% resolving. */
.portrait picture{display:block;width:100%;aspect-ratio:3/5}
.portrait img{
  width:100%;height:100%;object-fit:cover;object-position:center top;
  border-radius:var(--r);
  border:2px solid color-mix(in srgb,var(--marigold) 70%,transparent);
  background:var(--raised);
}
@media(max-width:860px){.portrait{max-width:250px}}

/* ---------- the couplet (signature) ---------- */
.couplet{
  margin-top:clamp(2.5rem,6vw,4rem);border-top:1px solid var(--line);padding-top:2rem;
  display:grid;grid-template-columns:auto 1fr;gap:clamp(1.5rem,4vw,3rem);align-items:start;
  text-decoration:none;color:inherit;
}
@media(max-width:720px){.couplet{grid-template-columns:1fr;gap:1.1rem}}
.couplet .tag{
  font-family:var(--mono);font-size:.7rem;letter-spacing:.19em;text-transform:uppercase;
  color:var(--marigold-ink);white-space:nowrap;padding-top:.4rem;
  transition:transform .2s;display:inline-block;
}
.couplet blockquote{
  margin:0;font-family:var(--display);font-weight:400;
  font-size:clamp(1.02rem,2.1vw,1.28rem);line-height:1.85;
  border-left:2px solid var(--marigold);padding-left:1.35rem;
  transition:padding-left .2s,border-color .2s;
}
a.couplet:hover blockquote{padding-left:1.7rem}
a.couplet:hover .tag{transform:translateX(3px)}
.couplet cite{display:block;margin-top:.9rem;font-family:var(--body);font-style:normal;
  font-size:.82rem;color:var(--muted)}

/* ---------- (verse archive lives on verse.php) ---------- */
.verses{columns:2;column-gap:2.25rem}
@media(max-width:760px){.verses{columns:1}}
.verse{
  break-inside:avoid;margin:0 0 1.15rem;padding:1.5rem 1.6rem;
  background:var(--raised);border:1px solid var(--line);
  border-left:2px solid var(--marigold);border-radius:0 var(--r) var(--r) 0;
  transition:border-color .2s,transform .2s;
}
.verse:hover{transform:translateY(-2px);
  border-color:color-mix(in srgb,var(--marigold) 40%,var(--line));border-left-color:var(--marigold)}
.verse blockquote{
  margin:0;font-family:var(--display);font-weight:400;
  font-size:1.03rem;line-height:1.95;
}
.verse figcaption{
  margin-top:.95rem;font-family:var(--mono);font-size:.66rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted);
}
.verse[hidden]{display:none}
.more{margin-top:1.5rem}

/* the small note under the CV button */
.cv-hint{
  margin:.85rem 0 0;font-family:var(--mono);font-size:.63rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted);
}

/* ---------- publications ----------
   Papers take the teal accent (the engineer half), the book takes
   marigold (the writer half), matching the rest of the site.      */
.pubs{list-style:none;margin:0;padding:0;display:grid;gap:1.25rem;max-width:74ch}
.pub{
  position:relative;padding:1.5rem 1.6rem;
  background:var(--raised);border:1px solid var(--line);
  border-left:2px solid var(--teal);border-radius:0 var(--r) var(--r) 0;
  transition:border-color .2s,transform .2s,box-shadow .2s;
}
.pub:hover{
  transform:translateY(-2px);box-shadow:var(--shadow);
  border-color:color-mix(in srgb,var(--teal) 40%,var(--line));
}
.pub.book{border-left-color:var(--marigold)}
.pub.book:hover{border-color:color-mix(in srgb,var(--marigold) 40%,var(--line))}

.pub .kind{
  display:block;font-family:var(--mono);font-size:.62rem;letter-spacing:.17em;
  text-transform:uppercase;color:var(--teal-ink);
}
.pub.book .kind{color:var(--marigold-ink)}

.pub h3{font-size:1.06rem;line-height:1.4;margin:.7rem 0 .55rem;letter-spacing:-.005em}
.pub h3 a{color:inherit;text-decoration:none}
/* the whole entry is the link; the title anchor just carries it */
.pub h3 a::after{content:"";position:absolute;inset:0;border-radius:inherit}
.pub h3 a:focus-visible::after{outline:2px solid var(--teal-ink);outline-offset:3px}

.pub .where{margin:0;color:var(--muted);font-size:.9rem;line-height:1.6}
.pub .go{
  display:inline-block;margin-top:1rem;font-family:var(--mono);font-size:.64rem;
  letter-spacing:.13em;text-transform:uppercase;color:var(--teal-ink);
}
.pub.book .go{color:var(--marigold-ink)}
.pub .go span{display:inline-block;transition:transform .2s}
.pub:hover .go span{transform:translateX(3px)}

/* ---------- sections ---------- */
section{padding:clamp(3.5rem,8vw,5.75rem) 0;scroll-margin-top:72px}
section + section{border-top:1px solid var(--line)}
.head{max-width:56ch;margin-bottom:clamp(2rem,4.5vw,3rem)}
.head p{margin:.9rem 0 0;color:var(--muted)}
/* the part-of-speech tag after a heading, set like a dictionary entry */
.pos{
  font-family:var(--display);font-style:italic;font-weight:400;
  font-size:.42em;letter-spacing:0;color:var(--muted);
  white-space:nowrap;margin-left:.5em;
}
/* Square brackets drawn by CSS rather than typed, so they can be
   sized and coloured on their own without touching the words. */
.brk::before,.brk::after{
  color:var(--marigold-ink);font-weight:400;font-style:normal;
  font-size:1.12em;line-height:0;vertical-align:-.02em;
}
.brk::before{content:"[";margin-right:.06em}
.brk::after{content:"]";margin-left:.06em}

.prose{max-width:64ch;columns:1}
.prose p{color:var(--muted)}
.prose strong{color:var(--ink);font-weight:600}
.prose a{color:var(--marigold-ink);text-decoration-thickness:1px;text-underline-offset:3px}

.facts{display:grid;gap:1px;background:var(--line);border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;margin-top:2.25rem;
  grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.fact{background:var(--raised);padding:1.15rem 1.3rem}
.fact dt{font-family:var(--mono);font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted);margin-bottom:.45rem}
.fact dd{margin:0;font-size:.95rem}
.fact dd.eq{font-family:var(--mono);color:var(--teal-ink)}
.fact a{color:var(--marigold-ink)}

/* ---------- skills ---------- */
/* Heading with a coloured dot, then pills. A row grid so every heading
   in a row sits on the same line. align-items:start keeps each card its
   own height instead of stretching to fill the row. */
.skills{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:2rem 2.25rem;align-items:start;
}
@media(max-width:1000px){.skills{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:680px){.skills{grid-template-columns:1fr}}
.skillset{margin:0}
.skillset h3{
  font-size:.95rem;font-family:var(--body);font-weight:600;margin-bottom:.9rem;
  display:flex;align-items:center;gap:.55rem;
}
.skillset h3::before{
  content:"";width:7px;height:7px;border-radius:2px;background:var(--teal);flex:none;
}
.skillset.p h3::before{background:var(--marigold)}
.tags{display:flex;flex-wrap:wrap;gap:.45rem;padding:0;margin:0;list-style:none}
.tags li{
  font-size:.85rem;padding:.4rem .8rem;border-radius:8px;
  background:var(--raised);border:1px solid var(--line);color:var(--muted);
  transition:border-color .18s,color .18s;
}
.tags li:hover{border-color:var(--teal);color:var(--ink)}
.skillset.p .tags li:hover{border-color:var(--marigold)}

/* ---------- timeline ---------- */
.time{position:relative;padding-left:1.9rem;margin:0}
.time::before{content:"";position:absolute;left:5px;top:.6rem;bottom:.6rem;width:1px;background:var(--line)}
.job{position:relative;padding-bottom:2.1rem}
.job:last-child{padding-bottom:0}
.job::before{
  content:"";position:absolute;left:-1.9rem;top:.55rem;width:11px;height:11px;border-radius:50%;
  background:var(--paper);border:2px solid var(--line);
}
.job.now::before{border-color:var(--marigold);background:var(--marigold)}
.job time{font-family:var(--mono);font-size:.72rem;letter-spacing:.1em;color:var(--muted);
  text-transform:uppercase}
.job h3{margin:.4rem 0 .3rem;font-size:1.18rem}
.job p{margin:0;color:var(--muted);font-size:.94rem}
.job p b{color:var(--ink);font-weight:600}
.job a{color:var(--marigold-ink)}

/* ---------- services ---------- */
.cards{display:grid;gap:1.15rem;grid-template-columns:repeat(auto-fit,minmax(258px,1fr))}
.card{
  background:var(--raised);border:1px solid var(--line);border-radius:var(--r);padding:1.55rem;
  transition:border-color .2s,transform .2s;
}
.card:hover{border-color:color-mix(in srgb,var(--marigold) 55%,var(--line));transform:translateY(-2px)}
.card h3{font-size:1.06rem;margin-bottom:.55rem}
.card p{margin:0;font-size:.92rem;color:var(--muted)}
.card .n{font-family:var(--mono);font-size:.68rem;letter-spacing:.14em;color:var(--marigold-ink);
  display:block;margin-bottom:.9rem}

/* ---------- projects ---------- */
.filters{display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:2rem}
.filters button{
  font-family:var(--body);font-size:.85rem;cursor:pointer;background:none;
  border:1px solid var(--line);color:var(--muted);padding:.45rem .95rem;border-radius:100px;
  transition:all .18s;
}
.filters button:hover{color:var(--ink);border-color:var(--muted)}
.filters button[aria-pressed="true"]{background:var(--ink);color:var(--paper);border-color:var(--ink)}

.grid{display:grid;gap:1.35rem;grid-template-columns:repeat(auto-fill,minmax(292px,1fr))}
.proj{
  display:flex;flex-direction:column;background:var(--raised);border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;transition:border-color .2s,transform .2s,box-shadow .2s;
}
.proj:hover{border-color:color-mix(in srgb,var(--teal) 50%,var(--line));transform:translateY(-3px);
  box-shadow:var(--shadow)}
.proj .shot{aspect-ratio:16/10;overflow:hidden;background:var(--line);border-bottom:1px solid var(--line)}
.proj .shot img{width:100%;height:100%;object-fit:cover;transition:transform .45s cubic-bezier(.2,.8,.3,1)}
.proj:hover .shot img{transform:scale(1.04)}
.proj .body{padding:1.25rem;display:flex;flex-direction:column;flex:1}
/* a card whose image is not on disk: no empty grey block, just text */
.proj.no-shot{border-left:2px solid var(--teal)}
.proj.no-shot .body{padding-top:1.4rem}
.proj.no-shot.is-writing,.proj.no-shot.is-book{border-left-color:var(--marigold)}
.proj .kind{font-family:var(--mono);font-size:.63rem;letter-spacing:.15em;text-transform:uppercase;
  color:var(--teal-ink);margin-bottom:.6rem}
.proj.is-writing .kind,.proj.is-book .kind{color:var(--marigold-ink)}
.proj h3{font-size:1.07rem;margin-bottom:.5rem}
.proj p{font-size:.89rem;color:var(--muted);margin:0 0 1.15rem}
/* "Read it" / "View repo" links. Defined unscoped so the blog listing,
   the projects grid and anything added later all share them. An inline
   icon with a viewBox but no width will stretch to fill its parent, so
   the size rule below is load-bearing, not decoration. */
.go{
  align-self:flex-start;font-size:.85rem;font-weight:500;text-decoration:none;
  display:inline-flex;align-items:center;gap:.4rem;color:var(--ink);
  border-bottom:1px solid var(--line);padding-bottom:2px;
  transition:border-color .18s,color .18s;
}
.go:hover{border-color:var(--marigold);color:var(--marigold-ink)}
.go svg{width:12px;height:12px;flex:none;transition:transform .18s}
.go:hover svg{transform:translateX(3px)}

.proj .go{margin-top:auto}
.proj .go:hover svg{transform:translate(2px,-2px)}

/* ---------- contact ---------- */
.contact-grid{display:grid;grid-template-columns:1fr 1.1fr;gap:clamp(2rem,5vw,4rem);align-items:start}
@media(max-width:820px){.contact-grid{grid-template-columns:1fr}}
.lines{list-style:none;padding:0;margin:2rem 0 0;display:grid;gap:1rem}
.lines a{text-decoration:none;display:flex;gap:.85rem;align-items:center;color:inherit}
.lines .k{font-family:var(--mono);font-size:.65rem;letter-spacing:.15em;text-transform:uppercase;
  color:var(--muted);display:block;margin-bottom:.15rem}
.lines .v{font-size:.97rem;transition:color .18s}
.lines a:hover .v{color:var(--marigold-ink)}

/* An author rule beats the browser's own [hidden]{display:none},
   so a form or grid told to hide would otherwise stay on screen.
   This has to come first and it has to be !important. */
[hidden]{display:none !important}

form{display:grid;gap:.85rem}
.two{display:grid;grid-template-columns:1fr 1fr;gap:.85rem}
@media(max-width:480px){.two{grid-template-columns:1fr}}
label{font-family:var(--mono);font-size:.65rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);display:block;margin-bottom:.4rem}
input,textarea{
  width:100%;font-family:var(--body);font-size:.95rem;color:var(--ink);
  background:var(--raised);border:1px solid var(--line);border-radius:10px;
  padding:.72rem .9rem;transition:border-color .18s,box-shadow .18s;
}
input:focus,textarea:focus{
  outline:none;border-color:var(--marigold);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--marigold) 16%,transparent);
}
textarea{resize:vertical;min-height:118px}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
/* ---------- contact form outcomes ----------
   Sent replaces the form entirely: one clear result, and nothing
   left on screen to submit a second time. Not sent sits above the
   form, which keeps everything the visitor typed.                */

.sent{
  border:1px solid color-mix(in srgb,var(--good) 38%,var(--line));
  border-left:2px solid var(--good);
  background:color-mix(in srgb,var(--good) 7%,var(--raised));
  border-radius:0 var(--r) var(--r) 0;
  padding:clamp(1.6rem,3vw,2.1rem) clamp(1.5rem,3vw,1.9rem);
  animation:settle .4s cubic-bezier(.2,.8,.3,1) both;
}
.sent-mark{
  display:flex;align-items:center;justify-content:center;
  width:44px;height:44px;border-radius:50%;
  color:var(--good-ink);
  background:color-mix(in srgb,var(--good) 15%,transparent);
  border:1px solid color-mix(in srgb,var(--good) 35%,transparent);
  margin-bottom:1.1rem;
}
.sent-mark svg{animation:draw .5s .15s cubic-bezier(.2,.8,.3,1) both}
.sent h3{font-size:1.24rem;margin:0 0 .55rem;letter-spacing:-.01em}
.sent p{margin:0 0 .9rem;color:var(--muted);font-size:.94rem;line-height:1.65;max-width:46ch}
.sent-alt{font-size:.88rem}
.sent-alt a{color:var(--good-ink);text-decoration:none;border-bottom:1px solid
  color-mix(in srgb,var(--good) 35%,transparent)}
.sent-alt a:hover{border-bottom-color:var(--good)}
/* The ghost button sits on a tinted panel here, where its usual
   border and text colour nearly vanish. */
.sent .btn{
  margin-top:.4rem;
  color:var(--good-ink);
  border-color:color-mix(in srgb,var(--good) 40%,var(--line));
  background:transparent;
}
.sent .btn:hover{
  border-color:var(--good);
  background:color-mix(in srgb,var(--good) 10%,transparent);
}

.alert{
  display:flex;gap:.85rem;align-items:flex-start;
  border:1px solid color-mix(in srgb,var(--bad) 38%,var(--line));
  border-left:2px solid var(--bad);
  background:color-mix(in srgb,var(--bad) 7%,var(--raised));
  border-radius:0 var(--r) var(--r) 0;
  padding:1.05rem 1.2rem;margin-bottom:1.5rem;
  animation:settle .35s cubic-bezier(.2,.8,.3,1) both;
}
.alert-mark{color:var(--bad-ink);flex-shrink:0;margin-top:.1rem;line-height:0}
.alert strong{color:var(--bad-ink);font-family:var(--body);font-weight:600;font-size:.94rem}
.alert strong + span{color:var(--ink);font-size:.94rem}
.alert-alt{margin:.5rem 0 0;font-size:.86rem;color:var(--muted);line-height:1.6}
.alert-alt a{color:var(--bad-ink)}

/* the field that caused it */
input[aria-invalid="true"],textarea[aria-invalid="true"]{
  border-color:var(--bad);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--bad) 14%,transparent);
}

@keyframes settle{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@keyframes draw{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){
  .sent,.alert,.sent-mark svg{animation:none}
}

/* ---------- footer ---------- */
footer{border-top:1px solid var(--line);padding:2.5rem 0 3rem}
.foot{display:flex;flex-wrap:wrap;gap:1.5rem;align-items:center;justify-content:space-between}
.socials{display:flex;gap:.5rem;list-style:none;padding:0;margin:0}
.socials a{
  width:38px;height:38px;border:1px solid var(--line);border-radius:10px;display:grid;
  place-items:center;color:var(--muted);transition:all .18s;
}
.socials a:hover{color:var(--marigold-ink);border-color:var(--marigold);transform:translateY(-2px)}
.socials svg{width:16px;height:16px}
.copy{font-size:.82rem;color:var(--muted)}

/* ---------- scroll reveal ---------- */
.rise{opacity:0;transform:translateY(14px);transition:opacity .6s ease,transform .6s cubic-bezier(.2,.8,.3,1)}
.rise.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.rise{opacity:1;transform:none}}
/* ============================================================
   Verse page : writing showcase
   ============================================================ */
.page-hero{padding:clamp(3rem,7vw,5rem) 0 clamp(2rem,4vw,3rem)}
.page-hero h1{font-size:clamp(2.6rem,7vw,4.5rem);line-height:1;letter-spacing:-.035em;margin:0}
.page-hero .sub{font-size:1.08rem;color:var(--muted);max-width:48ch;margin:1.2rem 0 0}
.back{
  display:inline-flex;align-items:center;gap:.45rem;text-decoration:none;color:var(--muted);
  font-size:.85rem;margin-bottom:1.4rem;transition:color .18s;
}
.back:hover{color:var(--marigold-ink)}
.back svg{width:14px;height:14px}

.page-intro{
  max-width:60ch;margin-top:1.6rem;
}
.page-intro p{
  margin:0 0 1.05em;color:var(--muted);font-size:1rem;line-height:1.75;
}
.page-intro p:last-child{margin-bottom:0}
.page-intro p:first-child{
  border-left:2px solid var(--marigold);padding-left:1.25rem;
}

.tally{display:flex;flex-wrap:wrap;gap:1.75rem;margin-top:2rem;padding-top:1.6rem;
  border-top:1px solid var(--line)}
.tally div{min-width:70px}
.tally dt{font-family:var(--mono);font-size:.63rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted);margin-bottom:.3rem}
.tally dd{margin:0;font-family:var(--display);font-size:1.6rem;line-height:1;color:var(--marigold-ink)}

/* form filters */
.forms{display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:2.25rem}
.forms button{
  font-family:var(--body);font-size:.88rem;cursor:pointer;background:none;
  border:1px solid var(--line);color:var(--muted);padding:.48rem 1.05rem;border-radius:100px;
  transition:all .18s;
}
.forms button:hover{color:var(--ink);border-color:var(--muted)}
.forms button[aria-pressed="true"]{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.forms button span{opacity:.55;font-size:.78em;margin-left:.3rem}

/* ---------- the wall of writing ----------
   A grid rather than masonry columns: every card is the same
   height, so the whole wall shares one baseline. grid-auto-rows:1fr
   makes each row match the tallest card, and because long pieces are
   clipped at five lines that ceiling stays sensible.
   The cards are flex columns so the meta line and the link sit on
   the bottom edge however short the poem is.                       */
.wall{
  display:grid;gap:1.5rem;padding-bottom:2rem;
  grid-template-columns:repeat(3,minmax(0,1fr));
  grid-auto-rows:1fr;align-items:stretch;
}
@media(max-width:1000px){.wall{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* one card per row on a phone, where matching heights would only
   add empty space to the short pieces */
@media(max-width:660px){
  .wall{grid-template-columns:minmax(0,1fr);gap:1.25rem;grid-auto-rows:auto}
}

.piece{
  position:relative;
  display:flex;flex-direction:column;height:100%;
  margin:0;padding:1.7rem 1.75rem;
  background:var(--raised);border:1px solid var(--line);
  border-left:2px solid var(--marigold);border-radius:0 var(--r) var(--r) 0;
  transition:border-color .2s,transform .2s,box-shadow .2s;
}
.piece:hover{transform:translateY(-2px);box-shadow:var(--shadow);
  border-color:color-mix(in srgb,var(--marigold) 40%,var(--line));border-left-color:var(--marigold)}
.piece[hidden]{display:none}

/* each form gets its own accent so the wall is scannable */
.piece.f-haiku{border-left-color:var(--teal)}
.piece.f-haiku:hover{border-color:color-mix(in srgb,var(--teal) 40%,var(--line))}
.piece.f-haiku .form{color:var(--teal-ink)}
.piece.f-ghazal{border-left-color:#8A5CB8}
.piece.f-ghazal .form{color:#7248A6}
html[data-theme="dark"] .piece.f-ghazal{border-left-color:#B08CDB}
html[data-theme="dark"] .piece.f-ghazal .form{color:#C0A2E5}

.piece .form{
  font-family:var(--mono);font-size:.62rem;letter-spacing:.17em;text-transform:uppercase;
  color:var(--marigold-ink);display:block;margin-bottom:.85rem;
}
.piece h2{
  font-size:1.12rem;margin:0 0 .8rem;letter-spacing:-.01em;
}
.piece blockquote{
  margin:0;font-family:var(--display);font-weight:400;
  font-size:1.02rem;line-height:2;
}
.piece figcaption{
  margin:0;
  font-family:var(--mono);font-size:.63rem;letter-spacing:.15em;text-transform:uppercase;
  color:var(--muted);
}

/* the line that says how much of a long piece is still to come */
.piece .cut{
  margin:.9rem 0 0;font-family:var(--mono);font-size:.66rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--muted);
}


/* meta on the left, the way in on the right */
.piece .foot{
  display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  margin-top:auto;padding-top:.85rem;border-top:1px solid var(--line);
}
/* the gap the flex column opens up above the footer */
.piece blockquote,.piece .cut{margin-bottom:1.05rem}
.piece .cut{margin-top:-.15rem}
.piece .open{
  font-family:var(--mono);font-size:.66rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--marigold-ink);text-decoration:none;white-space:nowrap;flex-shrink:0;
}
.piece .open span[aria-hidden]{display:inline-block;transition:transform .2s}
.piece:hover .open span[aria-hidden]{transform:translateX(3px)}
/* the whole card is the link; the anchor just carries the label */
.piece .open::after{content:"";position:absolute;inset:0;border-radius:inherit}
.piece .open:focus-visible::after{outline:2px solid var(--marigold-ink);outline-offset:3px}
.piece.f-haiku .open{color:var(--teal-ink)}
.piece.f-ghazal .open{color:#7248A6}
html[data-theme="dark"] .piece.f-ghazal .open{color:#C0A2E5}
/* a long piece gets a slightly firmer edge, so the wall reads at a glance */
.piece.is-long blockquote{
  -webkit-mask-image:linear-gradient(180deg,#000 72%,color-mix(in srgb,#000 45%,transparent) 100%);
          mask-image:linear-gradient(180deg,#000 72%,color-mix(in srgb,#000 45%,transparent) 100%);
}

/* screen-reader-only label, so "Read more" says what it opens */
.sr{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ---------- one piece, on its own page ---------- */
.poem-page .form{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.19em;text-transform:uppercase;
  color:var(--marigold-ink);margin:1.4rem 0 .4rem;
}
.poem-page.f-haiku .form{color:var(--teal-ink)}
.poem-page.f-ghazal .form{color:#7248A6}
html[data-theme="dark"] .poem-page.f-ghazal .form{color:#C0A2E5}

.poem-body{
  margin:0;font-family:var(--display);font-weight:400;
  font-size:clamp(1.12rem,2.4vw,1.42rem);line-height:2.15;
  border-left:2px solid var(--marigold);padding:.4rem 0 .4rem 1.6rem;
}
.poem-page.f-haiku .poem-body{border-left-color:var(--teal)}
.poem-page.f-ghazal .poem-body{border-left-color:#8A5CB8}
html[data-theme="dark"] .poem-page.f-ghazal .poem-body{border-left-color:#B08CDB}
.poem-sign{
  margin:1.6rem 0 0;font-family:var(--mono);font-size:.68rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted);
}
/* the "more like this" row is a plain grid, not the masonry wall */
.wall-flat{gap:1.25rem;padding-bottom:0;
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.wall-flat .piece{padding:1.4rem 1.45rem}
/* haiku are short, so let them breathe instead of stretching */
.piece.f-haiku blockquote{font-size:1.1rem;line-height:2.1}

.empty{
  border:1px dashed var(--line);border-radius:var(--r);padding:2.5rem;text-align:center;
  color:var(--muted);
}

/* ============================================================
   Blog
   ============================================================ */
.wrap.narrow{width:min(100% - 2.5rem,720px)}
@media(max-width:640px){.wrap.narrow{width:min(100% - 1.75rem,720px)}}

/* ---------- listing ---------- */
.posts{display:grid;gap:1.5rem}
.post{
  display:grid;grid-template-columns:260px 1fr;gap:1.75rem;align-items:start;
  padding-bottom:1.5rem;border-bottom:1px solid var(--line);
}
.post:last-child{border-bottom:0}
@media(max-width:720px){.post{grid-template-columns:1fr;gap:1.1rem}}
.post[hidden]{display:none}

.post-shot{
  display:block;aspect-ratio:16/10;overflow:hidden;border-radius:var(--r);
  border:1px solid var(--line);background:var(--line);
}
.post-shot img{width:100%;height:100%;object-fit:cover;transition:transform .45s cubic-bezier(.2,.8,.3,1)}
.post:hover .post-shot img{transform:scale(1.04)}

.post-meta{
  display:flex;flex-wrap:wrap;gap:.5rem;align-items:center;margin:0 0 .7rem;
  font-family:var(--mono);font-size:.68rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--muted);
}
.post-meta .draft{color:var(--marigold-ink)}
.post-body h2{font-size:1.45rem;margin:0 0 .6rem;letter-spacing:-.018em}
.post-body h2 a{text-decoration:none;transition:color .18s}
.post-body h2 a:hover{color:var(--marigold-ink)}
.post-sum{margin:0 0 1rem;color:var(--muted);font-size:.95rem}

.post-tags{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;padding:0;margin:0 0 1.1rem}
.post-tags li{
  font-family:var(--mono);font-size:.63rem;letter-spacing:.11em;text-transform:uppercase;
  padding:.3rem .65rem;border-radius:100px;border:1px solid var(--line);color:var(--muted);
}

/* ---------- single post ---------- */
.post-title{font-size:clamp(2.1rem,5.2vw,3.1rem);line-height:1.08;letter-spacing:-.03em;margin:.9rem 0 0}
.post-cover{
  width:100%;aspect-ratio:16/8;object-fit:cover;border-radius:var(--r);
  border:1px solid var(--line);margin-bottom:clamp(2rem,4vw,2.75rem);
}

.article{font-size:1.08rem;line-height:1.78;padding-bottom:1rem}
.article > *:first-child{margin-top:0}
.article p{margin:0 0 1.4em;color:var(--ink)}
.article h2{
  font-size:1.62rem;margin:2.6rem 0 .9rem;letter-spacing:-.02em;
  padding-top:.4rem;
}
.article h3{font-size:1.24rem;margin:2rem 0 .7rem}
.article a{color:var(--marigold-ink);text-decoration-thickness:1px;text-underline-offset:3px}
.article strong{font-weight:600}
.article ul,.article ol{margin:0 0 1.4em;padding-left:1.4em}
.article li{margin-bottom:.5em}
.article li::marker{color:var(--marigold)}
.article hr{border:0;border-top:1px solid var(--line);margin:2.5rem 0}
.article img{border-radius:var(--r);border:1px solid var(--line);margin:1.5rem 0}

.article blockquote{
  margin:1.9rem 0;padding:.3rem 0 .3rem 1.5rem;border-left:2px solid var(--marigold);
  font-family:var(--display);font-size:1.16rem;line-height:1.65;color:var(--ink);
}
.article blockquote p:last-child{margin-bottom:0}

.article code{
  font-family:var(--mono);font-size:.86em;padding:.15em .4em;border-radius:5px;
  background:color-mix(in srgb,var(--teal) 11%,transparent);color:var(--teal-ink);
}
.article pre{
  background:var(--raised);border:1px solid var(--line);border-left:2px solid var(--teal);
  border-radius:0 var(--r) var(--r) 0;padding:1.15rem 1.3rem;overflow-x:auto;margin:0 0 1.5em;
}
.article pre code{background:none;padding:0;color:var(--ink);font-size:.86rem;line-height:1.7}

.article table{
  width:100%;border-collapse:collapse;margin:0 0 1.6em;font-size:.94rem;
}
.article th,.article td{
  text-align:left;padding:.65rem .8rem;border-bottom:1px solid var(--line);
}
.article th{
  font-family:var(--mono);font-size:.66rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--muted);font-weight:400;border-bottom-color:var(--muted);
}
.article tbody tr:last-child td{border-bottom:0}

/* ---------- prev / next ---------- */
.post-nav{
  display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-top:clamp(2.5rem,5vw,3.5rem);
  padding-top:2rem;border-top:1px solid var(--line);
}
@media(max-width:600px){.post-nav{grid-template-columns:1fr}}
.post-nav a{
  text-decoration:none;padding:1.1rem 1.25rem;border:1px solid var(--line);border-radius:var(--r);
  background:var(--raised);transition:border-color .2s,transform .2s;display:block;
}
.post-nav a:hover{border-color:var(--marigold);transform:translateY(-2px)}
.post-nav a.r{text-align:right}
.post-nav .k{
  display:block;font-family:var(--mono);font-size:.63rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted);margin-bottom:.4rem;
}
.post-nav .v{display:block;font-family:var(--display);font-size:1rem;line-height:1.35}
