/* ============================================================
   Dreadlabs — designer & programmer
   Light editorial. Same hand as brackleytattoo / petesplace,
   turned into daylight.
   ============================================================ */

:root{
  --bone:      #f7f4ee;   /* page ground */
  --paper:     #fffdf9;   /* raised surfaces */
  --bone-dim:  #efe9df;   /* sunken / alt bands */
  --ink:       #14120f;   /* headings, body */
  --ink-2:     #4a443b;   /* secondary text */
  --dim:       #857d70;   /* meta, eyebrows */
  --rule:      #e2dacd;   /* hairlines */
  --accent:    #a0392e;   /* deep oxblood — carried over */
  --accent-2:  #b8863c;   /* aged brass */
  --accent-wash: rgba(160,57,46,.07);

  --max: 1320px;
  --pad: clamp(20px, 4vw, 56px);
  --ease: cubic-bezier(.22,.61,.36,1);
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  background:var(--bone);
  color:var(--ink);
  font-family:'Inter',system-ui,-apple-system,sans-serif;
  font-weight:400;
  font-size:17px;
  line-height:1.6;
  letter-spacing:.005em;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
::selection{background:var(--accent);color:var(--bone)}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}

/* ---------- type ---------- */
.display{
  font-family:'Fraunces',Georgia,serif;
  font-weight:400;
  font-variation-settings:"opsz" 144,"SOFT" 30,"WONK" 1;
  line-height:.94;
  letter-spacing:-.025em;
}
.eyebrow{
  text-transform:uppercase;
  font-size:11px;
  font-weight:500;
  letter-spacing:.32em;
  color:var(--dim);
}
.mono{
  font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,monospace;
  font-size:12px;
  letter-spacing:.04em;
}
.accent-word{color:var(--accent);font-style:italic}
.rule{height:1px;background:var(--rule);width:100%;border:0}

.wrap{max-width:var(--max);margin:0 auto;padding:0 var(--pad)}
section{padding:clamp(72px,10vw,140px) 0}

.section-head{
  display:flex;
  justify-content:space-between;
  align-items:baseline;
  gap:32px;
  padding-bottom:22px;
  border-bottom:1px solid var(--rule);
  margin-bottom:clamp(36px,5vw,64px);
}
.section-head h2{
  font-size:clamp(34px,5.5vw,68px);
  font-weight:400;
}

/* ---------- nav ---------- */
nav.top{
  position:fixed;top:0;left:0;right:0;z-index:60;
  display:flex;align-items:center;justify-content:space-between;
  gap:24px;
  padding:18px var(--pad);
  background:rgba(247,244,238,0);
  transition:background .4s var(--ease), border-color .4s var(--ease), padding .4s var(--ease);
  border-bottom:1px solid transparent;
}
nav.top.stuck{
  background:rgba(247,244,238,.88);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  border-bottom-color:var(--rule);
  padding-top:12px;padding-bottom:12px;
}
nav.top .brand{
  display:flex;align-items:center;gap:10px;
  font-family:'JetBrains Mono',monospace;
  font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink);
}
nav.top .brand img{width:26px;height:26px;border-radius:50%}
nav.top ul{display:flex;gap:32px;list-style:none}
nav.top ul a{
  font-size:12px;text-transform:uppercase;letter-spacing:.26em;
  color:var(--ink-2);position:relative;
  transition:color .3s var(--ease);
}
nav.top ul a::after{
  content:"";position:absolute;left:0;bottom:-6px;height:1px;width:0;
  background:var(--accent);transition:width .4s var(--ease);
}
nav.top ul a:hover{color:var(--ink)}
nav.top ul a:hover::after{width:100%}
@media (max-width:820px){ nav.top ul{display:none} }
/* four-line wrap looks broken on a phone - drop it */
@media (max-width:560px){ .hero-meta .right-text{display:none} }

/* ---------- hero ---------- */
/* No longer a full-viewport block with the content pinned to the bottom - that
   left a large dead area under the nav and pushed the whole page down. The hero
   is now only as tall as what is in it. */
header.hero{
  padding:clamp(92px,11vh,124px) var(--pad) clamp(30px,4vh,46px);
  position:relative;
  overflow:hidden;
}
header.hero::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(90% 70% at 82% 8%,  rgba(160,57,46,.09), transparent 62%),
    radial-gradient(70% 55% at 0% 100%, rgba(184,134,60,.10), transparent 60%);
}
.hero-inner{
  width:100%;max-width:var(--max);margin:0 auto;
  position:relative;z-index:1;
}
.hero-meta{
  position:relative;
  display:flex;justify-content:space-between;align-items:flex-end;
  gap:40px;margin-bottom:clamp(14px,2vw,22px);
}
.hero-meta .right{
  position:absolute;top:0;right:0;
  display:flex;flex-direction:column;align-items:flex-end;gap:14px;
  text-align:right;
}
.hero-meta .right-text{
  color:var(--dim);font-size:12px;letter-spacing:.2em;text-transform:uppercase;
  line-height:1.7;
}
.hero-avatar-wrap{position:relative;display:inline-block;line-height:0;width:clamp(120px,15vw,190px)}
.hero-avatar-wrap::before{
  content:"";position:absolute;inset:-22%;
  background:radial-gradient(ellipse at center, rgba(184,134,60,.22) 0%, rgba(184,134,60,0) 68%);
  pointer-events:none;
}
.hero-avatar{position:relative;animation:bob 6s ease-in-out infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}

.title{
  font-size:clamp(58px,15vw,200px);
  margin-bottom:clamp(24px,4vw,44px);
}
.title .row2{display:block}

.hero-base{
  display:flex;justify-content:space-between;align-items:flex-end;
  gap:40px;flex-wrap:wrap;
  border-top:1px solid var(--rule);padding-top:22px;
}
.hero-base .lede{
  max-width:46ch;color:var(--ink-2);font-size:clamp(16px,1.4vw,19px);
}
.hero-base .lede strong{font-weight:600;color:var(--ink)}

/* The hero is a stack of fixed lumps plus a very large title, and sized on
   width alone it outgrows the viewport on any short screen - a 1440x900
   MacBook, a 1366x768 laptop, even 1080p - clipping the name at the fold and
   pushing the lede under it. So on desktop every lump is sized against the
   viewport HEIGHT as well, and the whole hero lands above the fold at any
   shape. Mobile keeps the width-only sizing: portrait has height to spare. */
@media (min-width:900px){
  .hero-meta{margin-bottom:clamp(12px,2vh,22px)}
  .hero-avatar-wrap{width:clamp(110px,min(15vw,14vh),190px)}
  .title{
    font-size:clamp(58px,min(15vw,17vh),200px);
    margin-bottom:clamp(20px,4vh,44px);
  }
  .hero-base{padding-top:clamp(18px,2.4vh,22px)}
}

/* ---------- work grid ---------- */
.work-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(330px,1fr));
  gap:clamp(20px,2.4vw,34px);
}
.card{
  background:var(--paper);
  border:1px solid var(--rule);
  display:flex;flex-direction:column;
  overflow:hidden;
  transition:transform .5s var(--ease), box-shadow .5s var(--ease), border-color .5s var(--ease);
}
.card:hover{
  transform:translateY(-5px);
  border-color:#d3c8b6;
  box-shadow:0 18px 44px -22px rgba(20,18,15,.30);
}
.card-media{
  aspect-ratio:16/10;position:relative;overflow:hidden;
  background:var(--bone-dim);
  border-bottom:1px solid var(--rule);
}
.card-media img{width:100%;height:100%;object-fit:cover;transition:transform .8s var(--ease)}
.card:hover .card-media img{transform:scale(1.045)}
/* typographic fallback when a project has no cover yet */
.card-media.placeholder{
  display:grid;place-items:center;
  background:
    linear-gradient(135deg, var(--accent-wash), transparent 60%),
    repeating-linear-gradient(45deg, transparent 0 11px, rgba(20,18,15,.028) 11px 22px),
    var(--bone-dim);
}
.card-media.placeholder .initials{
  font-family:'Fraunces',serif;font-size:clamp(40px,6vw,64px);
  font-variation-settings:"opsz" 144,"WONK" 1;
  color:var(--accent);opacity:.5;letter-spacing:-.03em;
}
.card-body{padding:22px 24px 26px;display:flex;flex-direction:column;gap:12px;flex:1}
.card-top{display:flex;justify-content:space-between;align-items:baseline;gap:14px}
.card-top h3{font-family:'Fraunces',serif;font-weight:400;font-size:25px;letter-spacing:-.015em;line-height:1.15}
.card-year{color:var(--dim);font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.12em;white-space:nowrap}
.card p{color:var(--ink-2);font-size:15px;line-height:1.62;flex:1}
.tags{display:flex;flex-wrap:wrap;gap:7px;margin-top:2px}
.tag{
  font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.09em;
  text-transform:lowercase;color:var(--ink-2);
  border:1px solid var(--rule);border-radius:999px;padding:3.5px 10px;
  background:var(--bone);
}
.card-cta{
  display:flex;align-items:center;gap:8px;
  font-size:11px;text-transform:uppercase;letter-spacing:.22em;
  color:var(--accent);margin-top:6px;
}
.card-cta .arrow{transition:transform .4s var(--ease);display:inline-block}
.card:hover .card-cta .arrow{transform:translateX(5px)}
.badge-wip{
  position:absolute;top:12px;left:12px;z-index:2;
  background:var(--accent);color:var(--bone);
  font-family:'JetBrains Mono',monospace;font-size:9.5px;
  letter-spacing:.18em;text-transform:uppercase;
  padding:4px 9px;
}

/* ---------- filters ---------- */
.filters{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:34px}
.filters button{
  font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-2);
  border:1px solid var(--rule);border-radius:999px;padding:7px 15px;
  background:var(--paper);
  transition:all .3s var(--ease);
}
.filters button:hover{border-color:var(--accent);color:var(--accent)}
.filters button[aria-pressed="true"]{background:var(--ink);color:var(--bone);border-color:var(--ink)}

/* ---------- what I do ---------- */
.band{background:var(--bone-dim);border-block:1px solid var(--rule)}
/* Reads as a list someone wrote, rather than a grid of identical cards. */
.doing{display:grid}
.do{
  display:grid;grid-template-columns:minmax(150px,.26fr) 1fr;
  gap:clamp(14px,3vw,52px);
  padding:clamp(20px,2.4vw,30px) 0;
  border-top:1px solid var(--rule);
}
.do:last-child{border-bottom:1px solid var(--rule)}
.do h3{
  font-family:'Fraunces',serif;font-weight:400;
  font-size:clamp(20px,2.2vw,28px);letter-spacing:-.015em;line-height:1.15;
}
.do p{color:var(--ink-2);font-size:clamp(15px,1.25vw,17px);line-height:1.68;max-width:64ch}
@media (max-width:700px){
  .do{grid-template-columns:1fr;gap:8px}
}

/* ---------- about ---------- */
.about-grid{display:grid;gap:clamp(32px,5vw,72px);align-items:start}
/* No portrait beside it any more, so hold the text to a readable measure. */
.about-body{max-width:68ch}
.about-body p{margin-bottom:1.15em;color:var(--ink-2);font-size:clamp(16px,1.3vw,18px)}
.about-body p:first-child{font-size:clamp(19px,1.9vw,25px);color:var(--ink);line-height:1.45}
.about-body p:last-child{margin-bottom:0}

/* ---------- contact ---------- */
.contact{text-align:left}
.contact .big{
  font-size:clamp(20px,4vw,55px);display:inline-block;
  border-bottom:2px solid transparent;transition:border-color .4s var(--ease), color .4s var(--ease);
  word-break:break-word;
}
.contact .big:hover{color:var(--accent);border-bottom-color:var(--accent)}

/* ---------- downloads ---------- */
.downloads{margin-bottom:clamp(40px,6vw,72px)}
.dl-row{display:flex;flex-wrap:wrap;gap:12px}
.dl{
  display:flex;flex-direction:column;gap:3px;
  padding:14px 22px;
  background:var(--paper);border:1px solid var(--rule);
  transition:border-color .3s var(--ease), transform .3s var(--ease), box-shadow .3s var(--ease);
}
.dl:hover{
  border-color:var(--accent);transform:translateY(-2px);
  box-shadow:0 14px 30px -20px rgba(20,18,15,.4);
}
.dl-name{
  font-family:'JetBrains Mono',monospace;font-size:12px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--accent);
}
.dl-size{color:var(--dim);font-size:12.5px}
.dl-note{margin-top:16px;color:var(--ink-2);font-size:14px;max-width:64ch;line-height:1.65}
.dl-note code{
  font-family:'JetBrains Mono',monospace;font-size:12.5px;
  background:var(--bone-dim);border:1px solid var(--rule);padding:1px 5px;
}

/* ---------- footer ---------- */
footer{
  border-top:1px solid var(--rule);
  padding:34px 0;
  color:var(--dim);
}
footer .wrap{display:flex;justify-content:space-between;align-items:center;gap:24px;flex-wrap:wrap}
footer .mono{font-size:11px;letter-spacing:.14em;text-transform:uppercase}
footer a:hover{color:var(--accent)}

/* ---------- reveal ---------- */
/* Gated on .js - if main.js is blocked or throws, nothing stays hidden and
   the page below the hero still reads. */
.js .reveal{opacity:0;transform:translateY(22px);transition:opacity .9s var(--ease),transform .9s var(--ease)}
.js .reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.js .reveal{opacity:1;transform:none;transition:none}}

/* ---------- project detail page ---------- */
.proj-hero{padding:150px var(--pad) 0;max-width:var(--max);margin:0 auto}
.back{
  display:inline-flex;align-items:center;gap:9px;color:var(--dim);
  font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.18em;
  text-transform:uppercase;margin-bottom:34px;
}
.back:hover{color:var(--accent)}
.proj-title{font-size:clamp(42px,9vw,120px);margin-bottom:22px}
.proj-sub{max-width:62ch;color:var(--ink-2);font-size:clamp(17px,1.6vw,21px);margin-bottom:28px}
.proj-facts{
  display:flex;flex-wrap:wrap;gap:clamp(22px,4vw,52px);
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
  padding:22px 0;margin-bottom:clamp(40px,6vw,72px);
}
.proj-facts div span{display:block;color:var(--dim);font-size:10.5px;text-transform:uppercase;letter-spacing:.24em;margin-bottom:6px}
.proj-facts div p,.proj-facts div a{font-size:15px}
.proj-facts div a{color:var(--accent);border-bottom:1px solid transparent}
.proj-facts div a:hover{border-bottom-color:var(--accent)}

/* Covers arrive at whatever size the project produced - a 320x208 render, a
   square logo, a tall phone screenshot. Rather than stretching each one to the
   column (which blurs the small ones and makes the tall ones enormous), sit it
   on a panel at its own size, capped to a sensible band. */
.proj-cover{
  display:grid;place-items:center;overflow:hidden;
  background:var(--bone-dim);
  border:1px solid var(--rule);
  margin-bottom:clamp(40px,6vw,72px);
}
.proj-cover img{
  max-width:100%;
  max-height:min(72vh,660px);
  width:auto;height:auto;
}

.prose{max-width:74ch;padding-bottom:clamp(56px,8vw,110px)}
.prose h2{font-family:'Fraunces',serif;font-weight:400;font-size:clamp(27px,3.4vw,40px);letter-spacing:-.02em;margin:1.9em 0 .55em;line-height:1.12}
.prose h3{font-family:'Fraunces',serif;font-weight:400;font-size:clamp(21px,2.4vw,27px);margin:1.7em 0 .5em}
.prose h2:first-child,.prose h3:first-child{margin-top:0}
.prose p{margin-bottom:1.15em;color:var(--ink-2)}
.prose ul,.prose ol{margin:0 0 1.3em 1.15em;color:var(--ink-2)}
.prose li{margin-bottom:.45em}
.prose li::marker{color:var(--accent-2)}
.prose a{color:var(--accent);border-bottom:1px solid rgba(160,57,46,.35)}
.prose a:hover{border-bottom-color:var(--accent)}
.prose strong{color:var(--ink);font-weight:600}
.prose blockquote{
  border-left:2px solid var(--accent);padding:4px 0 4px 22px;margin:1.6em 0;
  color:var(--ink-2);font-style:italic;
}
.prose code{
  font-family:'JetBrains Mono',monospace;font-size:.86em;
  background:var(--bone-dim);border:1px solid var(--rule);
  padding:1.5px 5px;border-radius:3px;color:var(--accent);
}
.prose pre{
  background:var(--ink);color:#e8e2d6;
  padding:20px 22px;overflow-x:auto;margin:1.5em 0;
  border-radius:2px;font-size:13.5px;line-height:1.62;
}
.prose pre code{background:none;border:0;padding:0;color:inherit;font-size:inherit}
.prose hr{border:0;height:1px;background:var(--rule);margin:2.4em 0}
.prose img{margin:1.6em 0;border:1px solid var(--rule)}

.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:clamp(14px,2vw,24px);padding-bottom:clamp(56px,8vw,110px)}
.gallery img{border:1px solid var(--rule);background:var(--paper);width:100%}

.notice{
  background:var(--paper);border:1px solid var(--rule);border-left:2px solid var(--accent-2);
  padding:22px 26px;color:var(--ink-2);font-size:15px;max-width:74ch;
}

/* ============================================================
   The hand-made layer
   Paper grain, drawn strokes and a few things sitting slightly
   off-square, so the page looks made rather than generated.
   ============================================================ */

/* Paper grain over the whole page. Fine, low-contrast, and it sits
   under the pointer so it never eats a click. */
body::after{
  content:"";position:fixed;inset:0;z-index:9999;pointer-events:none;
  opacity:.5;mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='.34'/%3E%3C/svg%3E");
}
@media print{ body::after{display:none} }

/* Marginal notes, in a hand. */
.note{
  font-family:'Caveat',cursive;
  font-size:clamp(19px,1.7vw,23px);
  color:var(--dim);
  line-height:1.25;
}
.section-head .note{text-align:right;transform:rotate(-.6deg);max-width:22ch}
@media (max-width:700px){ .section-head .note{display:none} }
.contact-note{margin:6px 0 clamp(30px,4vw,44px);transform:rotate(-.4deg)}
.note .arrow-hand{
  display:inline-block;width:34px;height:14px;vertical-align:middle;margin-right:6px;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34' height='14' viewBox='0 0 34 14'%3E%3Cpath d='M1 8.6C7 5 15 3.2 24 3.4M24 3.4l-4.4-2.1M24 3.4l-2.8 3.9' fill='none' stroke='%23857d70' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center/contain;
}

/* Pinned up by hand, not placed by a grid. */
.badge-wip{transform:rotate(-1.6deg)}

/* Cards sit a hair off-square, alternating, and straighten up when you point
   at one. The tilt rides in a variable because the reveal animation owns the
   transform property - otherwise one would cancel the other out. */
.card{--tilt:0deg}
.card:nth-child(3n+1){--tilt:-.28deg}
.card:nth-child(3n+2){--tilt:.2deg}
.card:nth-child(3n+3){--tilt:-.14deg}
.card{transform:rotate(var(--tilt))}
.js .card.reveal{transform:translateY(22px) rotate(var(--tilt))}
.js .card.reveal.in{transform:rotate(var(--tilt))}
.js .card.reveal.in:hover,.card:hover{transform:translateY(-5px) rotate(0deg)}
@media (prefers-reduced-motion:reduce){
  .card{--tilt:0deg}
  .badge-wip{transform:none}
}

/* ---------- headings in the SELECTED WORK face ----------
   JetBrains Mono, caps, tracked out - the same treatment as the little scroll
   cue. Mono is a wide face and caps are wider still, so the sizes come down
   from the Fraunces settings and the tracking is lighter than the 11px cue's
   .24em, which falls apart at display size. */
.title,.section-head h2,.proj-title{
  font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,monospace;
  font-variation-settings:normal;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.04em;
  line-height:1.08;
}
/* Upright: a slanted mono cap reads as a typo, not emphasis. The red and the
   drawn stroke carry the accent on their own. */
.title .accent-word,.section-head h2 .accent-word,.proj-title .accent-word{font-style:normal}

.title{font-size:clamp(40px,10.5vw,148px)}
.section-head h2{font-size:clamp(22px,3.6vw,44px)}
.proj-title{font-size:clamp(24px,4.2vw,56px)}
@media (min-width:900px){
  .title{font-size:clamp(40px,min(10.5vw,13vh),148px)}
}
