/* ==========================================================================
   evanuster.com — shared styles
   Palette: near-black ground, off-white paper sections, one blue accent.
   Two easing curves only. Spacing on a 4px grid.
   ========================================================================== */
:root{
  --black:#0E0E0F;
  --ink:#08090C;
  --off-white:#F0EFEB;
  --white:#fff;
  --accent:#2F6FED;
  --accent-bright:#5C90FF;
  --accent-deep:#12379C;
  --mid:#8A8A8F;
  --dim:#6C6C70;
  --line-dark:rgba(255,255,255,.12);
  --line-light:rgba(0,0,0,.14);
  --font:'Space Grotesk',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --mono:'DM Mono',ui-monospace,SFMono-Regular,monospace;
  --ease:cubic-bezier(.16,1,.3,1);
  --snap:cubic-bezier(.2,.8,.2,1);
  --s1:8px; --s2:16px; --s3:24px; --s4:40px; --s5:64px; --s6:96px;
  --gutter:20px;
  color-scheme:dark;
}
@media (min-width:900px){:root{--gutter:40px}}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}
body{margin:0;background:var(--black);color:var(--off-white);font-family:var(--font);font-size:16px;line-height:1.55;
  -webkit-font-smoothing:antialiased;overflow-x:hidden}
a{color:inherit;text-decoration:none}
img{display:block;max-width:100%}
::selection{background:var(--accent);color:#fff}
:focus-visible{outline:2px solid var(--accent-bright);outline-offset:3px;border-radius:2px}
.paper :focus-visible{outline-color:var(--accent)}
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--accent);color:#fff;padding:12px 16px;font:500 14px var(--font)}
.skip:focus{left:12px;top:12px}

.wrap{width:100%;max-width:1320px;margin-inline:auto;padding-inline:var(--gutter)}
.narrow{max-width:760px}
.label{font:500 11px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--mid)}
.label b{color:var(--accent-bright);font-weight:500}
.grain{position:fixed;inset:0;z-index:3;pointer-events:none;opacity:.03;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E")}

/* ---------- cross-document page transitions (native, no library) ---------- */
@view-transition{navigation:auto}
@media (prefers-reduced-motion:no-preference){
  ::view-transition-old(root){animation:vtOut .22s var(--snap) both}
  ::view-transition-new(root){animation:vtIn .34s var(--ease) both}
  @keyframes vtOut{to{opacity:0}}
  @keyframes vtIn{from{opacity:0;transform:translateY(8px)}}
}
#nav{view-transition-name:nav}

/* ---------- nav ---------- */
#nav{position:fixed;left:50%;top:14px;transform:translateX(-50%);z-index:60;display:flex;align-items:center;gap:6px;
  padding:6px;border-radius:999px;background:rgba(14,14,15,.74);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  box-shadow:inset 0 0 0 1px var(--line-dark),0 12px 40px rgba(0,0,0,.45);max-width:calc(100vw - 24px)}
/* The nav pill is dark on every page, so its text colour cannot inherit from
   the page: on the light pages that made the brand black on near-black. */
#nav{color:var(--off-white)}
#nav .brand{display:flex;align-items:center;min-height:44px;padding:0 12px;font-weight:700;font-size:15px;letter-spacing:-.01em;white-space:nowrap;color:var(--off-white)}
#nav .brand i{color:var(--accent-bright);font-style:normal}
#nav .links{position:relative;display:none;align-items:center;gap:2px;padding-left:10px;margin-left:4px;border-left:1px solid var(--line-dark)}
#nav .links a{position:relative;z-index:1;display:flex;align-items:center;min-height:40px;padding:0 13px;font-size:14px;color:var(--mid);
  border-radius:999px;transition:color .18s var(--snap)}
#nav .links a:hover{color:var(--off-white)}
#nav .links a[aria-current]{color:var(--white)}
#nav .ind{position:absolute;top:0;bottom:0;left:0;width:0;border-radius:999px;background:rgba(255,255,255,.09);z-index:0;opacity:0;
  transition:transform .42s var(--ease),width .42s var(--ease),opacity .25s}
#nav .ind.on{opacity:1}
#nav .cta{display:inline-flex;align-items:center;min-height:44px;margin-left:4px;padding:0 17px;border-radius:999px;background:var(--accent);color:#fff;
  font:500 11px var(--mono);letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;
  transition:background-color .18s var(--snap),transform .12s var(--snap)}
#nav .cta:hover{background:var(--accent-bright)}
#nav .cta:active{transform:scale(.97)}
#nav .burger{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border:0;background:transparent;color:inherit;cursor:pointer;border-radius:999px}
#nav .burger span{position:relative;display:block;width:16px;height:1.5px;background:currentColor;transition:transform .3s var(--ease)}
#nav .burger span::after{content:"";position:absolute;left:0;top:5px;width:16px;height:1.5px;background:currentColor;transition:transform .3s var(--ease),top .3s var(--ease)}
#nav .burger span{transform:translateY(-2.5px)}
body.menu-open #nav .burger span{transform:rotate(45deg)}
body.menu-open #nav .burger span::after{top:0;transform:rotate(-90deg)}
@media (min-width:1000px){#nav .links{display:flex}#nav .burger{display:none}}

/* ---------- mobile menu ---------- */
#menu{position:fixed;inset:0;z-index:55;background:var(--ink);display:flex;flex-direction:column;justify-content:space-between;
  padding:calc(78px + env(safe-area-inset-top,0px)) var(--gutter) calc(28px + env(safe-area-inset-bottom,0px));
  clip-path:inset(0 0 100% 0);visibility:hidden;transition:clip-path .55s var(--ease),visibility 0s .55s}
body.menu-open #menu{clip-path:inset(0 0 0 0);visibility:visible;transition:clip-path .55s var(--ease)}
#menu ol{list-style:none;margin:0;padding:0}
#menu li{overflow:hidden;border-bottom:1px solid var(--line-dark)}
#menu li a{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding:14px 0;
  font-weight:700;font-size:clamp(34px,10vw,54px);line-height:1.05;letter-spacing:-.035em;
  transform:translateY(105%);transition:transform .6s var(--ease),color .2s var(--snap)}
#menu li a small{font:400 12px var(--mono);color:var(--mid);letter-spacing:0}
#menu li a[aria-current]{color:var(--accent-bright)}
body.menu-open #menu li a{transform:none;transition-delay:calc(var(--i) * 42ms + 110ms)}
#menu .foot{display:flex;flex-wrap:wrap;gap:18px;font:400 13px var(--mono);color:var(--mid)}
#menu .foot a:hover{color:var(--accent-bright)}

/* ---------- page header (interior pages) ---------- */
.page-head{padding:calc(96px + env(safe-area-inset-top,0px)) 0 var(--s4)}
.page-head .label{display:block;margin-bottom:var(--s2)}
.page-head h1{margin:0;font-weight:700;font-size:clamp(40px,8.4vw,86px);line-height:.96;letter-spacing:-.04em;text-wrap:balance}
.page-head h1 i{color:var(--accent-bright);font-style:normal}
.page-head .lede{margin:var(--s3) 0 0;max-width:48ch;font-size:clamp(17px,2.1vw,20px);color:#C6C8CF}
.rule{height:1px;background:var(--line-dark);margin:0}
.paper .rule{background:var(--line-light)}

/* ---------- sections ---------- */
section{padding-block:clamp(56px,9vw,112px)}
.paper{background:var(--off-white);color:var(--black)}
.paper .label{color:var(--dim)}
.paper .label b{color:var(--accent-deep)}
h2{font-weight:700;letter-spacing:-.035em;line-height:1.02;text-wrap:balance;margin:var(--s2) 0 var(--s3);font-size:clamp(28px,5vw,52px)}
h3{font-weight:600;letter-spacing:-.02em;margin:0}
.prose p{margin:0 0 var(--s2);max-width:62ch;font-size:17px;color:#C6C8CF}
.paper .prose p{color:#2B2B2E}
.prose p:last-child{margin-bottom:0}
.prose strong{color:var(--white);font-weight:600}
.paper .prose strong{color:var(--black)}
.prose a{color:var(--accent-bright);border-bottom:1px solid rgba(92,144,255,.35);transition:border-color .18s var(--snap)}
.prose a:hover{border-color:var(--accent-bright)}
.paper .prose a{color:var(--accent-deep);border-bottom-color:rgba(18,55,156,.35)}

/* ---------- buttons ---------- */
/* border:0 matters on <button>: without it the browser draws its own outset
   frame, which showed up as a pale box around Send message. */
.btn{display:inline-flex;align-items:center;gap:10px;min-height:48px;padding:0 20px;border:0;background:var(--accent);color:#fff;
  font:500 11px var(--mono);letter-spacing:.14em;text-transform:uppercase;
  transition:background-color .18s var(--snap),transform .12s var(--snap)}
.btn:hover{background:var(--accent-bright)}
.btn:active{transform:translateY(1px) scale(.99)}
.btn.ghost{background:transparent;color:inherit;box-shadow:inset 0 0 0 1px var(--line-dark)}
.btn.ghost:hover{background:rgba(255,255,255,.06)}
.paper .btn.ghost{box-shadow:inset 0 0 0 1px var(--line-light)}
.paper .btn.ghost:hover{background:rgba(0,0,0,.05)}
.btn svg{transition:transform .3s var(--ease)}
.btn:hover svg{transform:translateX(3px)}

/* ---------- project rows (home + projects index) ---------- */
.rows-work{border-top:1px solid var(--line-dark)}
.work-row{display:grid;gap:var(--s2);padding-block:var(--s3);border-bottom:1px solid var(--line-dark);position:relative;
  transition:transform .42s var(--ease)}
.work-row .meta{display:flex;gap:14px;align-items:baseline;font:400 12px var(--mono);color:var(--mid)}
.work-row .meta .live{color:var(--accent-bright)}
.work-row h3{font-size:clamp(34px,8vw,64px);font-weight:700;letter-spacing:-.04em;line-height:.98}
.work-row p{margin:0;max-width:52ch;color:#B9BCC5}
.work-row .go{display:inline-flex;align-items:center;gap:8px;font:500 11px var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--accent-bright)}
.work-row .go svg{transition:transform .32s var(--ease)}
@media (hover:hover){
  .work-row:hover{transform:translateX(10px)}
  .work-row:hover h3{color:var(--accent-bright)}
  .work-row:hover .go svg{transform:translate(3px,-3px)}
}
.work-row:active{transform:translateX(10px)}
.work-row h3{transition:color .2s var(--snap)}
@media (min-width:900px){
  .work-row{grid-template-columns:minmax(0,7fr) minmax(0,5fr);align-items:end;column-gap:var(--s5);padding-block:var(--s4)}
  .work-row .side{display:flex;flex-direction:column;gap:var(--s2);align-items:flex-start}
}

/* ---------- product panels (real interface fragments, not stock art) ---------- */
.panel{border:1px solid var(--line-dark);background:linear-gradient(160deg,rgba(47,111,237,.10),rgba(8,9,12,.6));padding:18px;
  font:400 12.5px/1.65 var(--mono);color:#B9BCC5;overflow:hidden}
.panel .p-top{display:flex;justify-content:space-between;color:var(--mid);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid var(--line-dark)}
.panel b{color:var(--accent-bright);font-weight:500}
.panel .ok{color:#3DDC97}
.panel .row-k{display:flex;justify-content:space-between;gap:16px;padding:3px 0}
.panel .num{font-variant-numeric:tabular-nums}
.chat{display:grid;gap:8px}
.chat p{margin:0;padding:9px 12px;max-width:86%;border-radius:12px;font-size:12.5px;line-height:1.5}
.chat .them{background:rgba(255,255,255,.06);border-top-left-radius:3px}
.chat .me{background:var(--accent);color:#fff;justify-self:end;border-top-right-radius:3px}
.chat .btns{display:flex;gap:6px;justify-self:end}
.chat .btns span{font-size:11px;padding:6px 10px;border:1px solid var(--line-dark);color:#D7D9E0}

/* ---------- writing list ---------- */
.posts{border-top:1px solid var(--line-dark)}
.paper .posts{border-color:var(--line-light)}
.post{display:grid;gap:6px;padding-block:var(--s3);border-bottom:1px solid var(--line-dark);transition:transform .42s var(--ease)}
.paper .post{border-color:var(--line-light)}
.post .m{display:flex;gap:12px;font:400 12px var(--mono);color:var(--mid)}
.post .m b{color:var(--accent-bright);font-weight:500}
.paper .post .m b{color:var(--accent-deep)}
.post .draft{color:#E0A33C}
.post h3{font-size:clamp(20px,3.2vw,28px);font-weight:500;line-height:1.25;letter-spacing:-.02em;transition:color .2s var(--snap)}
.post p{margin:4px 0 0;max-width:58ch;color:#9CA0AB;font-size:15px}
.paper .post p{color:#55555A}
@media (hover:hover){.post:hover{transform:translateX(10px)}.post:hover h3{color:var(--accent-bright)}}
.paper .post:hover h3{color:var(--accent-deep)}
@media (min-width:900px){.post{grid-template-columns:190px minmax(0,1fr);column-gap:var(--s4);align-items:baseline}.post .m{flex-direction:column;gap:2px}}

/* ---------- filters ---------- */
.filters{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:var(--s3)}
.filters button{min-height:40px;padding:0 14px;border:1px solid var(--line-dark);background:transparent;color:inherit;
  font:400 13px var(--font);cursor:pointer;transition:background-color .18s var(--snap),border-color .18s var(--snap),color .18s var(--snap)}
.filters button:hover{border-color:var(--mid)}
.filters button[aria-pressed="true"]{background:var(--off-white);border-color:var(--off-white);color:var(--black)}

/* ---------- forms ---------- */
.field-row{display:flex;flex-wrap:wrap;gap:8px;max-width:540px}
.field-row input{flex:1;min-width:220px;min-height:54px;background:rgba(255,255,255,.04);border:1px solid var(--line-dark);
  color:var(--off-white);font:400 16px var(--font);padding:0 16px;transition:border-color .18s var(--snap),background-color .18s var(--snap)}
.paper .field-row input{background:transparent;border-color:rgba(0,0,0,.22);color:var(--black)}
.field-row input::placeholder{color:#7A7A80}
.paper .field-row input::placeholder{color:#5F5F63}
.field-row input:focus{outline:none;border-color:var(--accent);background:rgba(47,111,237,.06)}
.form-note{margin:10px 0 0;font:400 12px var(--mono);color:var(--mid)}
.paper .form-note{color:var(--dim)}
.form-msg{margin:12px 0 0;font:500 15px var(--font);min-height:1em;opacity:0;transform:translateY(-4px);
  letter-spacing:-.01em;transition:opacity .22s var(--snap),transform .3s var(--ease)}
.form-msg.show{opacity:1;transform:none}
.form-msg.show.ok{display:inline-flex;align-items:center;gap:9px;padding:10px 16px;border-radius:999px;
  background:rgba(61,220,151,.12);box-shadow:inset 0 0 0 1px rgba(61,220,151,.34)}
.form-msg.show.ok::before{content:"";width:7px;height:7px;border-radius:50%;background:#3DDC97;flex:none}
.paper .form-msg.show.ok{background:rgba(47,111,237,.1);box-shadow:inset 0 0 0 1px rgba(47,111,237,.3)}
.paper .form-msg.show.ok::before{background:var(--accent)}
.form-msg.err{color:#FF8A80}
.paper .form-msg.err{color:#B3261E}
.form-msg.ok{color:#3DDC97}
.paper .form-msg.ok{color:var(--accent-deep)}
.invalid input{border-color:#B3261E}
button[disabled]{opacity:.55;cursor:not-allowed}
textarea{width:100%;min-height:150px;background:rgba(255,255,255,.04);border:1px solid var(--line-dark);color:var(--off-white);
  font:400 16px/1.6 var(--font);padding:14px 16px;resize:vertical}
textarea:focus{outline:none;border-color:var(--accent)}

/* ---------- contact channels ---------- */
.channels{display:grid;gap:1px;background:var(--line-light);border:1px solid var(--line-light);margin-top:var(--s4)}
.channels a{background:var(--off-white);padding:20px 16px;min-height:64px;display:flex;justify-content:space-between;align-items:center;gap:12px;
  font-weight:500;font-size:17px;transition:background-color .2s var(--snap),color .2s var(--snap)}
.channels a span{font:400 11px var(--mono);color:var(--dim);letter-spacing:.06em;text-transform:uppercase}
.channels a:hover{background:var(--accent);color:#fff}
.channels a:hover span{color:rgba(255,255,255,.85)}
.channels .soon-row{background:var(--off-white);padding:20px 16px;min-height:64px;display:flex;
  justify-content:space-between;align-items:center;gap:12px;color:var(--mid)}
.channels .soon-row span{font:400 11px var(--mono);color:var(--dim);letter-spacing:.06em;text-transform:uppercase}
@media (min-width:760px){.channels .soon-row{flex-direction:column;align-items:flex-start;gap:var(--s3);
  min-height:124px;padding:20px}}
/* "Coming soon" sits on the near-black footer. --dim reads 3.69:1 there and
   the smaller <i> was 2.76:1, both under the 4.5:1 floor. These pass. */
.soon{color:#9A9AA0}
.soon i{font-style:normal;font-size:.82em;color:#8E9099}
@media (min-width:760px){.channels{grid-template-columns:repeat(4,1fr)}.channels a{flex-direction:column;align-items:flex-start;gap:var(--s3);min-height:124px;padding:20px}}

/* ---------- footer ---------- */
footer.site{border-top:1px solid var(--line-dark);padding-block:var(--s4) calc(var(--s4) + env(safe-area-inset-bottom,0px));font-size:14px}
footer.site .cols{display:grid;gap:var(--s3);grid-template-columns:1fr 1fr}
footer.site .foot-h{margin:0 0 10px;font:500 11px var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--mid)}
footer.site ul{list-style:none;margin:0;padding:0;display:grid;gap:8px}
footer.site a:hover{color:var(--accent-bright)}
footer.site .base{display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;margin-top:var(--s4);padding-top:var(--s2);
  border-top:1px solid var(--line-dark);font:400 12px var(--mono);color:var(--mid)}
@media (min-width:760px){footer.site .cols{grid-template-columns:repeat(4,1fr)}}

/* ---------- reveals (IntersectionObserver adds .in) ---------- */
@media (prefers-reduced-motion:no-preference){
  .r{opacity:0;transform:translateY(18px);transition:opacity .6s var(--ease),transform .7s var(--ease);transition-delay:calc(var(--d,0) * 60ms)}
  .r.in{opacity:1;transform:none}
}

/* ---------- scroll-linked movement ----------
   Where the browser supports scroll-driven animations these run off the
   scroller itself: no scroll listener, no jank, and they scrub backwards when
   you scroll up. Browsers without them simply get the static layout, which is
   why none of these rules change anything that matters for reading. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion:no-preference) and (min-width:700px){
    /* the hero hands the page over as it leaves */
    #hero .cap{animation:hero-hand-over linear both;animation-timeline:view();animation-range:exit -10% exit 80%}
    #hero picture,#hero canvas{animation:hero-settle linear both;animation-timeline:view();animation-range:exit 0% exit 100%}

    /* section labels slide in from the margin */
    .label{animation:slide-in linear both;animation-timeline:view();animation-range:entry 10% entry 55%}

    /* the interface panels drift a little slower than the words beside them */
    .work-row .side,.spec-layout .spec{animation:drift linear both;animation-timeline:view();
      animation-range:entry 0% exit 100%}

    /* photographs breathe */
    .portrait img,.plate-frame img{animation:slow-zoom linear both;animation-timeline:view();
      animation-range:entry 0% exit 100%}

    /* the big opening statement warms up as it arrives */
    .statement em{animation:warm-up linear both;animation-timeline:view();animation-range:entry 20% entry 80%}
  }
}
@keyframes hero-hand-over{to{transform:translateY(-52px);opacity:.25}}
@keyframes hero-settle{to{transform:scale(1.06)}}
@keyframes slide-in{from{transform:translateX(-14px);opacity:.25}to{transform:none;opacity:1}}
@keyframes drift{from{transform:translateY(22px)}to{transform:translateY(-22px)}}
@keyframes slow-zoom{from{transform:scale(1.045)}to{transform:scale(1)}}
@keyframes warm-up{from{color:inherit}to{color:var(--accent-bright)}}

/* ---------- the opening statement, word by word ----------
   site.js wraps each word; without it the paragraph is a normal paragraph. */
@media (prefers-reduced-motion:no-preference){
  .statement .w{display:inline-block;opacity:0;transform:translateY(0.5em);
    transition:opacity .5s var(--ease),transform .6s var(--ease);
    transition-delay:calc(var(--w,0) * 26ms)}
  .statement.in .w{opacity:1;transform:none}
}

/* Nothing stays hidden if the observer never runs. */
.no-js .r{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-delay:0ms!important;transition-duration:.01ms!important}
  #menu li a{transform:none}
}

/* ==========================================================================
   Page-specific
   ========================================================================== */

/* ---------- home hero ---------- */
#hero{position:relative;height:100svh;min-height:540px;overflow:hidden;background:var(--ink)}
#hero canvas,#hero .fallback{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
#hero .fallback{filter:grayscale(1) contrast(1.08) brightness(.85)}
#hero .tint{position:absolute;inset:0;background:linear-gradient(200deg,rgba(47,111,237,.34),rgba(8,9,12,.08) 45%,rgba(8,9,12,.8));mix-blend-mode:multiply}
#hero .vig{position:absolute;inset:0;background:radial-gradient(125% 95% at 50% 32%,transparent 45%,rgba(8,9,12,.72))}
#hero .cap{position:absolute;left:0;right:0;bottom:0;padding:0 var(--gutter) 32px}
#hero h1{margin:0;font-weight:700;font-size:clamp(52px,16vw,180px);line-height:.86;letter-spacing:-.05em}
#hero h1 .l{display:block;overflow:hidden}
#hero h1 .l span{display:block;transform:translateY(102%);animation:heroUp .95s var(--ease) .1s forwards}
#hero h1 .l:nth-child(2) span{animation-delay:.19s}
#hero h1 i{color:var(--accent-bright);font-style:normal}
@keyframes heroUp{to{transform:none}}
#hero .sub{display:flex;flex-wrap:wrap;gap:8px 18px;margin:16px 0 0;font:400 12px var(--mono);color:var(--mid);
  opacity:0;animation:fadeIn .7s var(--ease) .78s forwards}
#hero .scroll{display:none;position:absolute;right:var(--gutter);bottom:20px;font:400 10px var(--mono);letter-spacing:.2em;color:var(--mid);
  opacity:0;animation:fadeIn .7s var(--ease) 1.2s forwards}
#hero .scroll::after{content:"";display:block;width:1px;height:26px;margin:8px auto 0;
  background:linear-gradient(var(--accent-bright),transparent);animation:drop 1.9s ease-in-out infinite}
@keyframes drop{0%,100%{opacity:.3;transform:scaleY(.6)}50%{opacity:1;transform:scaleY(1)}}
@keyframes fadeIn{to{opacity:1}}
@media (min-width:760px){#hero .scroll{display:block}}
@media (min-width:900px){#hero .sub{font-size:13px}}
@media (prefers-reduced-motion:reduce){#hero h1 .l span{transform:none}#hero .sub,#hero .scroll{opacity:1}}

/* ---------- home intro ---------- */
#intro .top{display:flex;justify-content:space-between;border-top:1px solid var(--line-dark);padding-top:14px;margin-bottom:clamp(32px,7vw,80px)}
.statement{margin:0;font-weight:500;font-size:clamp(26px,4.9vw,58px);line-height:1.14;letter-spacing:-.03em;text-wrap:balance;max-width:24ch}
.statement em{font-style:normal;color:var(--accent-bright)}
.pillars{display:grid;grid-template-columns:1fr 1fr;gap:1px;margin-top:clamp(40px,7vw,80px);background:var(--line-dark);border:1px solid var(--line-dark)}
.pillars a{position:relative;background:var(--black);padding:20px;display:flex;flex-direction:column;gap:6px;
  color:inherit;transition:background .3s var(--ease)}
.pillars a:hover{background:#141419}
.pillars b{font-size:21px;font-weight:600;letter-spacing:-.02em}
.pillars .first b{color:var(--accent-bright)}
.pillars span{font:400 12px var(--mono);color:var(--mid);line-height:1.5}
.pillars em{margin-top:auto;padding-top:14px;font:600 13px var(--font);font-style:normal;color:var(--off-white);
  letter-spacing:-.01em}
.pillars svg{position:absolute;top:18px;right:18px;color:var(--dim);opacity:0;transform:translate(-3px,3px);
  transition:opacity .3s var(--ease),transform .4s var(--ease)}
.pillars a:hover svg{opacity:1;transform:none;color:var(--accent-bright)}
@media (min-width:900px){.pillars{grid-template-columns:repeat(4,1fr)}.pillars a{padding:24px;min-height:176px}}

/* ---------- two-column blocks (about, project pages, contact) ---------- */
.about-grid{display:grid;gap:var(--s4)}
@media (min-width:900px){.about-grid{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:var(--s5);align-items:start}}
.portrait{margin:0;position:relative;overflow:hidden;aspect-ratio:4/5;background:#1A1B1E}
.portrait img{width:100%;height:100%;object-fit:cover;filter:grayscale(1) contrast(1.06)}
.portrait figcaption{position:absolute;left:0;bottom:0;background:var(--accent);color:#fff;
  font:500 10px var(--mono);letter-spacing:.14em;text-transform:uppercase;padding:9px 12px}
@media (min-width:900px){.portrait{aspect-ratio:3/4;position:sticky;top:96px}}

/* ---------- tools ---------- */
.tool-grid{display:grid;gap:1px;background:var(--line-dark);border:1px solid var(--line-dark)}
.tool-grid > div{background:var(--black);padding:20px}
.tool-grid .tool-h{margin:0 0 12px;font-weight:500;font:500 11px var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--accent-bright)}
.tool-grid ul{list-style:none;margin:0;padding:0;display:grid;gap:7px;color:#C6C8CF;font-size:15px}
@media (min-width:760px){.tool-grid{grid-template-columns:repeat(4,1fr)}.tool-grid > div{min-height:200px}}

/* ---------- article ---------- */
.post-meta{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin:var(--s3) 0 0;font:400 12px var(--mono);color:var(--mid)}
.draft-badge{color:#E0A33C;border:1px solid rgba(224,163,60,.45);padding:5px 9px;letter-spacing:.12em;text-transform:uppercase;font-size:10px}
.post-body{padding-bottom:var(--s3)}
.post-body h2{font-size:clamp(22px,3.4vw,30px);margin:var(--s4) 0 var(--s2)}
.post-body p{font-size:17.5px;line-height:1.7;max-width:68ch}
.note-line{border-left:2px solid var(--accent);padding:8px 0 8px 14px;color:var(--mid);font:400 13px var(--mono);max-width:60ch}
.paper .note-line{color:var(--dim)}

/* ==========================================================================
   Per-page identities. One system, a different device on each page.
   Dark = things I build. Paper = things I write.
   ========================================================================== */

/* ---------- paper pages (blog, posts, legal) ---------- */
body.paper-page{background:var(--off-white);color:var(--black);color-scheme:light}
body.paper-page .grain{opacity:.045;mix-blend-mode:multiply}
body.paper-page .page-head .lede{color:#3A3A3E}
body.paper-page .prose p{color:#2B2B2E}
body.paper-page .prose a{color:var(--accent-deep);border-bottom-color:rgba(18,55,156,.35)}
body.paper-page .label{color:var(--dim)}
body.paper-page .posts,body.paper-page .post{border-color:var(--line-light)}
body.paper-page .post p{color:#55555A}
body.paper-page .post .m b{color:var(--accent-deep)}
body.paper-page footer.site{border-color:var(--line-light)}
body.paper-page footer.site .foot-h,body.paper-page footer.site .base{color:var(--dim)}
body.paper-page footer.site .base{border-color:var(--line-light)}
body.paper-page :focus-visible{outline-color:var(--accent)}
body.paper-page .filters button{border-color:rgba(0,0,0,.2)}
body.paper-page .filters button[aria-pressed="true"]{background:var(--black);border-color:var(--black);color:var(--off-white)}
body.paper-page .field-row input{background:transparent;border-color:rgba(0,0,0,.22);color:var(--black)}
body.paper-page .btn.ghost{color:var(--black);box-shadow:inset 0 0 0 1px var(--line-light)}

/* ---------- about: sticky rail + long read ---------- */
.rail-layout{display:grid;gap:var(--s4)}
@media (min-width:1000px){.rail-layout{grid-template-columns:190px minmax(0,1fr);gap:var(--s5);align-items:start}}
.rail{position:sticky;top:78px;z-index:20;display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;
  background:var(--black);padding-block:10px;margin-inline:calc(var(--gutter) * -1);padding-inline:var(--gutter)}
.rail::-webkit-scrollbar{display:none}
.rail a{flex:none;display:flex;align-items:center;gap:8px;min-height:38px;padding:0 12px;border:1px solid var(--line-dark);
  font:400 12px var(--mono);color:var(--mid);white-space:nowrap;transition:color .2s var(--snap),border-color .2s var(--snap),background-color .2s var(--snap)}
.rail a i{font-style:normal;opacity:.55;transition:opacity .2s var(--snap)}
.rail a.on{color:var(--black);background:var(--off-white);border-color:var(--off-white)}
.rail a.on i{opacity:.75}
.rail a:hover{color:var(--off-white);border-color:var(--line)}
@media (min-width:1000px){
  .rail{position:sticky;top:110px;flex-direction:column;overflow:visible;margin:0;padding:0;background:none;gap:0;border-left:1px solid var(--line-dark)}
  .rail a{border:0;border-left:2px solid transparent;margin-left:-1px;min-height:46px;padding:0 0 0 16px}
  .rail a:hover{color:var(--off-white);border-left-color:var(--line)}
  .rail a.on{background:none;color:var(--accent-bright);border-left-color:var(--accent-bright);font-weight:500}
}
.chapter{scroll-margin-top:104px;padding-block:var(--s4);border-bottom:1px solid var(--line-dark)}
.chapter:first-of-type{padding-top:0}
.chapter:last-of-type{border-bottom:0}
.chapter h2{margin-top:0;font-size:clamp(24px,3.6vw,38px)}
.warm{filter:grayscale(1) contrast(1.06)}
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .warm{animation:warmUp linear both;animation-timeline:view();animation-range:entry 20% cover 45%}
    @keyframes warmUp{from{filter:grayscale(1) contrast(1.06)}to{filter:grayscale(0) contrast(1)}}
  }
}

/* ---------- projects: dossier index ---------- */
.dossier{border-top:1px solid var(--line-dark)}
.dossier-row{display:grid;grid-template-columns:auto 1fr auto;gap:4px 14px;align-items:baseline;padding-block:var(--s3);
  border-bottom:1px solid var(--line-dark);position:relative}
.dossier-row .idx{font:400 12px var(--mono);color:var(--mid)}
.dossier-row .name{font-weight:700;font-size:clamp(30px,6.6vw,54px);letter-spacing:-.035em;line-height:1;transition:color .2s var(--snap)}
.dossier-row .type{font:400 12px var(--mono);color:var(--mid);text-align:right}
.dossier-row .sum{grid-column:2/-1;margin:8px 0 0;color:#B9BCC5;max-width:56ch}
.dossier-row .inline-panel{grid-column:1/-1;margin-top:var(--s2)}
.dossier-row::before{content:"";position:absolute;left:calc(var(--gutter) * -1);right:calc(var(--gutter) * -1);top:0;bottom:0;
  background:linear-gradient(90deg,rgba(47,111,237,.14),transparent 65%);opacity:0;transition:opacity .3s var(--snap)}
@media (hover:hover){
  .dossier-row:hover::before{opacity:1}
  .dossier-row:hover .name{color:var(--accent-bright)}
}
@media (min-width:1000px){
  .dossier-wrap{display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:var(--s5);align-items:start}
  .dossier-row .inline-panel{display:none}
  .preview{position:sticky;top:110px;border:1px solid var(--line-dark);min-height:280px;display:grid}
  .preview > div{grid-area:1/1;opacity:0;transform:translateY(8px);transition:opacity .35s var(--snap),transform .45s var(--ease);pointer-events:none}
  .preview > div.on{opacity:1;transform:none}
  .preview .panel{border:0;height:100%}
}
@media (max-width:999px){.preview{display:none}}

/* ---------- project pages: spec sheet ---------- */
.spec-layout{display:grid;gap:var(--s4)}
@media (min-width:1000px){.spec-layout{grid-template-columns:300px minmax(0,1fr);gap:var(--s5);align-items:start}}
.spec{position:sticky;top:110px;border:1px solid var(--line-dark)}
.spec dl{display:grid;grid-template-columns:auto 1fr;margin:0;font:400 12.5px var(--mono)}
.spec dt,.spec dd{padding:11px 14px;border-bottom:1px solid var(--line-dark);margin:0}
.spec dt{color:var(--mid);text-transform:uppercase;letter-spacing:.08em;font-size:10.5px;display:flex;align-items:center}
.spec dd{text-align:right;color:var(--off-white)}
.spec dd.ok{color:#3DDC97}
.spec .spec-head{padding:14px;border-bottom:1px solid var(--line-dark);font:500 11px var(--mono);letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent-bright);display:flex;justify-content:space-between}
@media (max-width:999px){.spec{position:static}}
.build-notes h2{font-size:clamp(21px,3vw,28px);margin-top:var(--s4)}
.build-notes h2:first-child{margin-top:0}

/* ---------- reading: post pages ---------- */
.progress{position:fixed;left:0;top:0;height:2px;width:100%;transform:scaleX(0);transform-origin:left;
  background:var(--accent);z-index:70}
.read{font-family:'Newsreader',Georgia,serif}
.read p{font-size:19.5px;line-height:1.72;max-width:66ch;color:#26262A;margin:0 0 var(--s3)}
.read h2{font-family:var(--font);font-size:clamp(22px,3.2vw,30px);margin:var(--s5) 0 var(--s2)}
.read > p:first-of-type::first-letter{float:left;font-size:4.1em;line-height:.84;padding:6px 10px 0 0;font-weight:600;color:var(--accent-deep)}
.read strong{font-weight:600;color:var(--black)}
.margin-note{border-left:2px solid var(--accent);padding:10px 0 10px 14px;margin:var(--s3) 0;
  font:400 13.5px/1.6 var(--mono);color:#4A4A4F;max-width:52ch}
@media (min-width:1220px){
  .margin-note{position:absolute;right:calc(var(--s5) * -1);width:230px;transform:translateX(100%);margin:0;border-left-width:2px}
  .read{position:relative}
}
.byline{display:flex;flex-wrap:wrap;gap:10px 22px;margin-top:var(--s5);padding-top:18px;padding-bottom:6px;
  border-top:1px solid var(--line-light);font:400 12px var(--mono);color:var(--dim);line-height:1.7}
.byline a{color:var(--accent-deep);text-decoration:underline;text-underline-offset:3px}

/* ---------- blog: the subscribe band and the empty state ---------- */
.subscribe-band{padding:clamp(48px,7vw,86px) 0;border-top:1px solid var(--line-light);background:#E8E7E2}
body:not(.paper-page) .subscribe-band{background:#121216;border-top-color:var(--line-dark)}
.subscribe-band h2{margin:var(--s2) 0 var(--s2);font-size:clamp(30px,5vw,50px);letter-spacing:-.03em}
.subscribe-band .prose{max-width:46ch}
.subscribe-band form{margin-top:var(--s3);max-width:520px}
.empty-note{padding:26px 24px;border:1px solid var(--line-light);background:rgba(0,0,0,.02)}
.form-offline{margin:var(--s3) 0 0;padding:16px 18px;border:1px dashed var(--line-dark);max-width:52ch;
  font-size:14px;line-height:1.6;color:var(--mid)}
.paper .form-offline,body.paper-page .form-offline{border-color:var(--line-light);color:#55555A}
.empty-note b{display:block;font-size:19px;letter-spacing:-.02em;margin-bottom:8px}
.empty-note p{margin:0;max-width:52ch;color:#55555A;line-height:1.65}

/* ---------- contact: the letter ---------- */
.letter{border:1px solid var(--line-dark);background:linear-gradient(170deg,rgba(47,111,237,.08),rgba(8,9,12,.5));padding:18px}
.letter .t-top{display:flex;flex-wrap:wrap;gap:6px 14px;justify-content:space-between;font:400 11px var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--mid);padding-bottom:14px;margin-bottom:16px;border-bottom:1px solid var(--line-dark)}
.letter .t-top .dot{color:#3DDC97}
.composer{display:grid;gap:14px}
.composer .field{position:relative;display:grid;gap:7px}
.composer .field > span{font:400 11px var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--mid)}
.composer .count{position:absolute;right:0;top:0;font:400 11px var(--mono);font-style:normal;color:var(--dim);
  opacity:0;transition:opacity .3s var(--ease)}
.composer .field:focus-within .count,.composer .count:not(:empty){opacity:1}
.composer .two{display:grid;gap:8px}
@media (min-width:600px){.composer .two{grid-template-columns:1fr 1fr}}
.composer input,.composer textarea{width:100%;background:rgba(255,255,255,.04);border:1px solid var(--line-dark);color:var(--off-white);
  font:400 15px var(--font);padding:13px 14px;transition:border-color .18s var(--snap)}
.composer textarea{min-height:110px;resize:vertical;line-height:1.6}
.composer input:focus,.composer textarea:focus{outline:none;border-color:var(--accent)}
.composer .send-row{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}

/* ---------- legal: printed document ---------- */
.doc-meta{display:grid;grid-template-columns:auto 1fr;gap:2px 20px;margin:var(--s3) 0 0;font:400 12px var(--mono);color:var(--dim);
  border-top:1px solid var(--line-light);border-bottom:1px solid var(--line-light);padding:14px 0}
.doc-meta dt{text-transform:uppercase;letter-spacing:.1em;font-size:10.5px}
.doc-meta dd{margin:0;color:var(--black)}
/* The clauses carry their own numbers in the headings, so the stylesheet does
   not add a second set. */
.clauses section{padding-block:var(--s3);border-bottom:1px solid var(--line-light);position:relative}
.clauses h2{font-size:clamp(19px,2.6vw,24px);margin:0 0 10px}
.clauses p{font-size:16.5px;color:#2B2B2E;max-width:68ch;margin:0 0 12px;line-height:1.7}
.clauses ul{margin:0 0 12px;padding-left:20px;max-width:68ch}
.clauses li{font-size:16.5px;color:#2B2B2E;line-height:1.7;margin-bottom:7px}
.clauses strong{color:var(--black)}
.clauses p:last-child{margin-bottom:0}

/* a heading the page needs for its outline, not for the eye */
.sr-head{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap;border:0}

/* ==========================================================================
   Back to top. Appears once there is enough page behind you to want it.
   ========================================================================== */
.to-top{position:fixed;right:max(16px,env(safe-area-inset-right));bottom:calc(16px + env(safe-area-inset-bottom,0px));
  z-index:45;display:flex;align-items:center;justify-content:center;width:46px;height:46px;border:1px solid var(--line-dark);
  background:rgba(14,14,15,.82);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);color:var(--off-white);
  cursor:pointer;opacity:0;transform:translateY(10px);pointer-events:none;
  transition:opacity .3s var(--snap),transform .4s var(--ease),background-color .18s var(--snap)}
.to-top.on{opacity:1;transform:none;pointer-events:auto}
.to-top:hover{background:var(--accent)}
.to-top:active{transform:translateY(1px)}
.to-top svg{width:17px;height:17px}
body.paper-page .to-top{background:rgba(240,239,235,.9);color:var(--black);border-color:var(--line-light)}
body.paper-page .to-top:hover{background:var(--accent);color:#fff}
@media (min-width:900px){.to-top{right:28px;bottom:28px;width:50px;height:50px}}

/* ==========================================================================
   Print. Posts and the legal pages are the things anyone prints.
   ========================================================================== */
@media print{
  @page{margin:18mm}
  #nav,#menu,.to-top,.grain,.progress,.skip,footer.site nav,.filters,form,#hero .scroll,.side{display:none!important}
  html,body{background:#fff!important;color:#000!important}
  body::before,body::after{display:none!important}
  .paper,.page-head,section{background:#fff!important;color:#000!important;padding-block:0!important}
  h1,h2,h3,h4,.page-head h1{color:#000!important;page-break-after:avoid}
  .page-head h1 i,.statement em,.post h3 span{color:#000!important;background:none!important}
  p,li,.lede,.prose p,.read p{color:#000!important;font-size:11pt!important;line-height:1.5!important;orphans:3;widows:3}
  .read > p:first-of-type::first-letter{float:none;font-size:inherit;padding:0;color:#000!important}
  a{color:#000!important;text-decoration:underline}
  /* a printed link is useless without its address */
  .prose a[href^="http"]::after,.read a[href^="http"]::after{content:" (" attr(href) ")";font-size:9pt;word-break:break-all}
  article,.chapter,.post,.clauses section{page-break-inside:avoid}
  img,.portrait,.panel,.plate-frame{max-width:100%!important;filter:none!important}
  #hero{height:auto!important;min-height:0!important;page-break-after:avoid}
  #hero canvas,#hero .tint,#hero .vig{display:none!important}
  .margin-note,.note-line{border-left:2px solid #000!important;color:#000!important}
  .byline,.doc-meta{color:#000!important}
}

/* The honeypot: off-screen for eyes, still in the form for a bot to fill. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* A full-width photograph inside a chapter, to break up a wall of text. */
.wide-shot{margin:var(--s4) 0 0}
.wide-shot img{width:100%;height:auto;display:block;border:1px solid var(--line-dark);
  filter:grayscale(1) contrast(1.05)}
.wide-shot figcaption{margin-top:10px;font:400 11px var(--mono);letter-spacing:.08em;
  text-transform:uppercase;color:var(--dim)}
