/* kaseyschram.com: shared system (loaded by every page)
   All palette, type and scale values come from tokens.css. Do not add a
   literal colour, font-size or shadow to this file: add a token instead. */
@import 'tokens.css';

*{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:64px}
body{margin:0;background:var(--color-paper);color:var(--color-ink);font-family:var(--font-sans);
  line-height:var(--leading-body);font-size:18px;-webkit-font-smoothing:antialiased}
a{color:inherit}

/* ---- the label voice -------------------------------------------------
   Every uppercase mono label on the site is one of three sizes. This
   grouped rule is the whole vocabulary; the rules below only set colour.
   (Stage 2 replaces these selectors with a single .eyebrow class.)     */
.skip,.role,.eyebrow,.lbl,.mast-nav a,footer,.proj .m,.cta .eye,.cform label,
.sax,.lstatus,.nums,.pill{font-family:var(--font-mono)}
.role,.eyebrow,.lbl,.mast-nav a,.cta .eye,.cform label,.sax,.lstatus{text-transform:uppercase}
.role,.eyebrow,.lbl,.mast-nav a,footer,.proj .m,.skip{font-size:var(--label-lg)}
.cta .eye,.cform label,.lstatus,.nums{font-size:var(--label-md)}
.sax,.pill{font-size:var(--label-sm)}
.mast-nav a,.cform label{letter-spacing:var(--track-label)}
.role,.eyebrow{letter-spacing:var(--track-label)}
.lbl,.cta .eye{letter-spacing:var(--track-wide)}
.sax,.lstatus{letter-spacing:var(--track-label)}
.nums,.pill{letter-spacing:var(--track-tight)}
footer,.proj .m,.skip{letter-spacing:var(--track-tight)}

/* skip link + focus */
.skip{position:absolute;left:12px;top:-64px;z-index:100;background:var(--color-ink);color:var(--color-paper);
  padding:10px var(--space-4);border-radius:var(--radius-3);
  text-decoration:none;transition:top .16s ease}
.skip:focus{top:12px}
#main:focus{outline:none}

/* headings + type */
header{padding:clamp(34px,8vw,72px) 0 0}
header h1{font-family:var(--font-display);font-weight:400;text-transform:uppercase;letter-spacing:-.5px;
  line-height:1.26;margin:var(--space-4) 0 0;font-size:var(--display-4);max-width:15ch}
.role,.eyebrow{color:var(--color-accent)}
section{margin-top:var(--space-section)}
.lbl{font-weight:500;color:var(--color-faint);margin:0 0 18px}
p.body{font-size:var(--text-md);color:var(--color-soft);margin:0 0 18px;max-width:60ch}
p.body b{color:var(--color-ink);font-weight:700}
.lead{font-size:var(--text-xl);color:var(--color-ink);font-weight:500}
.h2{font-weight:800;font-size:var(--display-2);letter-spacing:-.4px;line-height:1.18;margin:0 0 var(--space-4);max-width:24ch}
a.inline{color:var(--color-accent);text-decoration:underline;text-underline-offset:2px}

/* button system
   The signature control: hard 2px border, hard offset shadow, no blur.
   Hover shortens the offset and nudges the button into it, so it presses. */
.btnrow{display:flex;gap:var(--space-4);flex-wrap:wrap}
.btn{display:inline-flex;align-items:center;font-family:var(--font-sans);font-weight:700;font-size:var(--text-control);
  letter-spacing:-.1px;padding:13px 22px;border-radius:var(--radius-2);text-decoration:none;border:2px solid var(--color-ink);
  transition:transform var(--ease-press),box-shadow var(--ease-press)}
.btn.sm{font-size:var(--text-control-sm);padding:10px var(--space-4)}
.btn.primary{background:var(--color-ink);color:var(--color-paper);box-shadow:var(--press) var(--color-accent)}
.btn.ghost{background:var(--color-paper);color:var(--color-ink);box-shadow:var(--press) var(--color-ink)}
.btn.sm.ghost{box-shadow:var(--press-md) var(--color-ink)}
.btn:hover{transform:translate(2px,2px)}
.btn.primary:hover{box-shadow:var(--press-sm) var(--color-accent)}
.btn.ghost:hover{box-shadow:var(--press-sm) var(--color-ink)}
.btn.sm.ghost:hover{box-shadow:var(--press-xs) var(--color-ink)}
.btn:active{transform:translate(4px,4px);box-shadow:0 0 0 transparent}
.fineprint{font-family:var(--font-mono);font-size:var(--text-mono);letter-spacing:.02em;color:var(--color-faint);
  margin:34px 0 0;max-width:54ch;line-height:1.75}
.fineprint b{color:var(--color-ink);font-weight:500}

/* footer */
footer{margin-top:60px;padding-bottom:var(--space-9);border-top:1px solid var(--color-line);padding-top:var(--space-6);
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:var(--space-3);color:var(--color-faint)}
footer nav{display:flex;gap:var(--space-5)}
footer nav a{text-decoration:none;color:var(--color-faint)}
footer nav a:hover{color:var(--color-accent)}

/* ---- two-column masthead ---- */
.page{max-width:1280px;margin:0 auto;padding:0 clamp(24px,4vw,56px);
  display:grid;grid-template-columns:minmax(210px,280px) 1fr;gap:clamp(32px,5vw,88px);align-items:start}
.masthead{position:sticky;top:56px;padding-top:clamp(52px,8vw,96px)}
.avatar{display:block;width:104px;height:104px;border-radius:50%;object-fit:cover;
  object-position:50% 50%;margin:0 0 22px;border:2px solid var(--color-ink);box-shadow:var(--press-md) var(--color-accent);
  background:var(--color-paper-2)}
.masthead h1,.wordmark{font-family:var(--font-display);font-weight:400;text-transform:uppercase;letter-spacing:-.5px;
  line-height:1.24;margin:14px 0 0;font-size:var(--display-wordmark)}
.wordmark{display:block;text-decoration:none;color:var(--color-ink);transition:color var(--ease-hover)}
.wordmark:hover{color:var(--color-accent)}
.mast-nav{display:flex;flex-direction:column;gap:11px;margin-top:30px}
.mast-nav a{color:var(--color-faint);text-decoration:none;transition:color var(--ease-hover);width:max-content}
.mast-nav a:hover,.mast-nav a[aria-current="page"]{color:var(--color-accent)}
.content{padding-top:clamp(52px,8vw,96px);min-width:0}
.content>header{padding:0}
@media(max-width:820px){
  .page{grid-template-columns:1fr;gap:0;padding:0 30px}
  .masthead{position:static;padding-top:clamp(30px,10vw,48px)}
  .avatar{width:76px;height:76px;margin-bottom:var(--space-4);box-shadow:var(--press-sm) var(--color-accent)}
  /* one-off: the wordmark scales on viewport width here, not on the
     display ladder, because it is the only thing in the column */
  .masthead h1{font-size:clamp(1.5rem,7vw,2.1rem)}
  .mast-nav{flex-direction:row;flex-wrap:wrap;gap:var(--space-5);margin-top:var(--space-5)}
  .content{padding-top:var(--space-8)}
}

/* ---- home ---- */
.intro{font-size:var(--text-xl);line-height:var(--leading-copy);color:var(--color-ink);margin:0;max-width:50ch}
header + .intro{margin-top:var(--space-section)}
.intro + .intro{margin-top:22px}
.intro a{color:var(--color-accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}
.proj{display:block;text-decoration:none;color:inherit;padding:var(--space-5) 0;border-top:1px solid var(--color-line)}
.proj:last-child{border-bottom:1px solid var(--color-line)}
.proj .t{font-weight:700;font-size:var(--text-xl);letter-spacing:-.2px}
.proj:hover .t{color:var(--color-accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}
.proj .d{color:var(--color-soft);font-size:var(--text-md);margin-top:5px;max-width:46ch}
.proj .m{color:var(--color-faint);margin-top:11px}
.contact p{font-size:var(--text-lg);color:var(--color-soft);margin:0 0 var(--space-7);max-width:38ch}
.cform{max-width:460px}
.cform .hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.cform .field{display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--space-5)}
.cform label{color:var(--color-faint)}
.cform input,.cform textarea{font-family:var(--font-sans);font-size:var(--text-control);color:var(--color-ink);background:var(--color-paper-2);
  border:2px solid var(--color-ink);border-radius:var(--radius-2);padding:var(--space-3) 14px;width:100%;
  box-shadow:var(--press-sm) var(--color-ink);transition:box-shadow .14s ease}
.cform input:focus,.cform textarea:focus{outline:none;box-shadow:var(--press-sm) var(--color-accent)}
.cform textarea{resize:vertical;min-height:120px;line-height:var(--leading-copy)}
.cform button{margin-top:6px;cursor:pointer}

/* ---- about ---- */
.stage{position:relative}
.stage>header,.stage>section{position:relative;z-index:2;padding-right:clamp(0px,24vw,320px)}
.scatter{position:absolute;inset:0;z-index:0;pointer-events:none}
.scatter img{position:absolute;display:block;height:auto;
  left:calc(var(--x)*1%);top:calc(var(--y)*1%);width:calc(var(--w)*1px);
  transform:rotate(calc(var(--r)*1deg));opacity:var(--o,.9);
  filter:drop-shadow(1px 3px 3px rgba(28,26,22,.20))}
.figure-cut{position:absolute;right:-6px;bottom:0;z-index:1;pointer-events:none;
  width:clamp(150px,21vw,262px);height:auto}
@media(max-width:820px){
  .stage>header,.stage>section{padding-right:0}
  /* figure is 0.645 aspect, so 150px wide is ~233px tall - reserve more than
     that below the copy or it climbs into the last paragraph */
  .stage{padding-bottom:270px}
  .figure-cut{width:150px;right:0}
  /* stacked layout leaves no margins, so notes fall behind body copy - fade them */
  .scatter img{width:calc(var(--w)*0.66px);opacity:calc(var(--o)*0.42)}
}
@media(prefers-reduced-motion:no-preference){
  .scatter img{transition:transform .4s ease}
}
.lede{font-size:var(--text-xl);line-height:1.45;color:var(--color-ink);margin:22px 0 0;max-width:34ch;font-weight:500}
.believe{margin-top:6px}
.believe .row{padding:var(--space-5) 0;border-top:1px solid var(--color-line)}
.believe .row:last-child{border-bottom:1px solid var(--color-line)}
.believe .t{font-weight:700;font-size:var(--text-lg);letter-spacing:-.2px;display:flex;gap:10px}
.believe .t::before{content:"";flex:none;width:17px;height:16px;margin-top:5px;border-radius:1px;
  background:url(about/note-03.png) center/contain no-repeat;
  filter:drop-shadow(1px 2px 2px rgba(28,26,22,.18));transform:rotate(-6deg)}
.believe .row:nth-child(2) .t::before{background-image:url(about/note-05.png);transform:rotate(5deg)}
.believe .row:nth-child(3) .t::before{background-image:url(about/note-01.png);transform:rotate(-3deg)}
.believe .row:nth-child(4) .t::before{background-image:url(about/note-07.png);transform:rotate(7deg)}
.believe .row p{margin:var(--space-2) 0 0 27px;color:var(--color-soft);font-size:var(--text-md)}

/* ---- closing CTA (home, work, about) ---- */
.cta{margin-top:var(--space-section-lg);border-top:1px solid var(--color-line);padding-top:clamp(30px,5vw,44px);
  position:relative}
.cta .eye{color:var(--color-accent)}
.cta h2{font-weight:800;font-size:var(--display-4);letter-spacing:-.5px;line-height:1.12;margin:var(--space-3) 0 var(--space-6);max-width:18ch}
.cta>*{position:relative;z-index:2}
.cta .scatter{position:absolute;inset:-30px -10px -10px 0;z-index:0}

/* ---- bare pages (404, thanks): one centred card, no chrome ---- */
body.bare{min-height:100vh;display:grid;place-content:center;text-align:center;padding:var(--space-8) var(--space-6)}
body.bare .eye{font-family:var(--font-mono);font-size:var(--label-lg);letter-spacing:var(--track-wide);
  text-transform:uppercase;color:var(--color-accent)}
body.bare h1{font-family:var(--font-display);font-weight:400;font-size:var(--display-5);text-transform:uppercase;
  letter-spacing:-.5px;line-height:var(--leading-tight);margin:14px 0 0}
body.bare p{color:var(--color-soft);font-size:var(--text-lg);margin:18px auto 0;max-width:34ch}
body.bare .btn{margin-top:30px}

/* ---- work index: stack spine + ledger ----
   Adding a project = one .sname + four .cell in the grid, and one .lrow below.
   Bar length is inline (width %) so it stays editable without touching this file. */

/* notebook margin rule, Work page only */
.notebook>.content{padding-left:clamp(18px,2.4vw,30px);border-left:1px solid var(--color-accent-rule)}
.stack,.ledger{margin-top:clamp(32px,6vw,50px)}
.cap{font-size:var(--text-xs);color:var(--color-soft);margin:-4px 0 var(--space-4);max-width:52ch;line-height:1.55}
.stackgrid{display:grid;grid-template-columns:minmax(132px,180px) repeat(4,1fr);
  gap:7px 10px;align-items:center;border-top:1px solid var(--color-line);padding-top:13px}
.sax{color:var(--color-faint)}
.sname{font-weight:700;font-size:var(--text-sm);letter-spacing:-.2px;padding:7px 0}
.cell{height:19px;background:var(--color-paper-2);border-radius:var(--radius-0);overflow:hidden}
.cell i{display:block;height:100%;background:var(--color-accent)}

/* Ruled like a notebook page. Pitch divides the row height exactly, so a rule
   lands on every row edge and one sits mid-row - the rules and the list agree
   instead of the list floating over wallpaper. */
.ledger{--pitch:32px}
/* only the list is ruled - the section heading sits above the page, not on it */
.ledger .rows{border-top:1px solid var(--color-line);
  background-image:repeating-linear-gradient(to bottom,var(--color-line-faint) 0 1px,transparent 1px var(--pitch))}
.lrow{display:grid;grid-template-columns:minmax(140px,1fr) minmax(140px,200px) minmax(120px,1fr);
  gap:18px;align-items:center;padding:0;min-height:calc(var(--pitch) * 3)}
.lname{font-weight:700;font-size:var(--text-md);letter-spacing:-.2px;text-decoration:none;color:inherit}
.lname:hover{color:var(--color-accent);text-decoration:underline;text-underline-offset:3px}
.lstatus{color:var(--color-faint)}
.lstatus.on{color:var(--color-accent)}
.levid{justify-self:end;text-align:right}
.nums{color:var(--color-soft)}
.nums b{color:var(--color-ink);font-size:var(--text-sm);margin:0 2px 0 6px}
.nums b:first-child{margin-left:0}
.pill{display:inline-flex;align-items:center;
  border:2px solid var(--color-ink);border-radius:var(--radius-2);padding:6px 11px;text-decoration:none;color:var(--color-ink);
  background:var(--color-paper);box-shadow:var(--press-sm) var(--color-accent);
  transition:transform var(--ease-press),box-shadow var(--ease-press)}
.pill:hover{transform:translate(2px,2px);box-shadow:var(--press-2xs) var(--color-accent)}
.artifact{display:block;height:84px;width:auto;margin-left:auto;
  filter:drop-shadow(2px 4px 6px rgba(28,26,22,.20))}
@media(max-width:700px){
  .stackgrid{grid-template-columns:repeat(4,1fr);gap:6px}
  .stackgrid>div:first-child{display:none}
  .sname{grid-column:1/-1;padding:15px 0 3px}
  /* stacked rows cannot hold the rhythm, so the ruling comes off on mobile */
  .ledger .rows{background-image:none}
  .lrow{grid-template-columns:1fr;gap:9px;padding:var(--space-4) 0;min-height:0;border-top:1px solid var(--color-line)}
  .lrow:first-child{border-top:0}
  .notebook>.content{padding-left:14px}
  .levid{justify-self:start;text-align:left}
  .artifact{margin-left:0}
}

/* ---- the seal: a claim covered until you ask ----------------------------
   The real words stay in the DOM and are only covered for sighted visitors,
   so a screen reader reads the sentence whatever the bar is doing. The bar
   wipes away while you hold it and returns the moment you stop asking, which
   is selective disclosure performed rather than described.
   Behaviour: assets/site.js. */
.seal{font:inherit;letter-spacing:inherit;text-transform:inherit;background:none;border:0;
  padding:0;margin:0;cursor:pointer;display:inline-block;vertical-align:baseline;
  position:relative;color:transparent;-webkit-tap-highlight-color:transparent}
.seal:focus-visible{outline:2px solid var(--color-accent);outline-offset:6px;border-radius:var(--radius-0)}
.seal .word{position:relative;z-index:1;transition:color .18s ease}
/* One solid block, deliberately NOT the two-block press treatment the buttons
   use. This is a seal, not a control: the offset shadow made it read as a
   button and put a second block in the headline. */
.seal .bar{position:absolute;inset:-.06em -.1em;background:var(--color-ink);
  border-radius:var(--radius-0);z-index:2;
  transition:clip-path .34s cubic-bezier(.4,0,.2,1)}
.seal.open .word{color:var(--color-ink)}
.seal.open .bar{clip-path:inset(0 0 0 100%)}
@media(prefers-reduced-motion:reduce){.seal .bar,.seal .word{transition:none}}

/* the home headline wants a wider measure than the 15ch page default */
h1.wide{max-width:22ch}
