/* ═══════════════════════════════════════════════════════════════════════════
   brutal.css — the scrapbook page.

   You rarely need to touch this. Colours come from content.js (main.js writes
   them into the custom properties below), so a reskin is a palette edit there,
   not a stylesheet edit here.

   The look is built from four primitives, reused everywhere:
     .box     thick black border + hard offset shadow, no blur, no radius
     .sticker small rotated label
     .tape    a strip of "washi tape" pinned across a corner
     .mark    highlighter swipe that animates in on scroll
   ═══════════════════════════════════════════════════════════════════════════ */

@font-face{font-family:"Archivo Black";src:url(fonts/archivo-black.woff2) format("woff2");
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Plex Mono";src:url(fonts/mono.woff2) format("woff2");
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Grotesk Fallback";src:local("Arial");
  size-adjust:107.9%;ascent-override:98%;descent-override:26%;line-gap-override:0%}
@font-face{font-family:"Space Grotesk";src:url(fonts/space-grotesk.woff2) format("woff2-variations");
  font-weight:300 700;font-style:normal;font-display:swap}

:root{
  /* defaults; main.js overwrites these from content.js palette */
  --ink:#111111; --paper:#FFFDF5;
  --yellow:#FFD84D; --pink:#FF6B9D; --cyan:#38D9E8;
  --lime:#B8FF3C; --orange:#FF7A2F; --violet:#B388FF; --teal:#1C6B61;

  /* Fallbacks are METRIC-MATCHED so the webfont swap cannot move layout:
     Arial Black and Courier New measure within 0.1% of the webfonts they stand
     in for (measured, not assumed), and the Grotesk stand-in is Arial stretched
     7.9% via size-adjust below. This is what holds CLS at zero on a slow line. */
  --display:"Archivo Black","Arial Black",system-ui,sans-serif;
  --body:"Space Grotesk","Grotesk Fallback",system-ui,sans-serif;
  --mono:"Plex Mono","Courier New",monospace;

  /* Constants that do NOT flip with the theme. The bright palette colours are light
     surfaces in both modes, so anything painted on one keeps dark ink and a dark
     border whichever theme is running — flipping them would put pale text on lime. */
  --on-bright:#111111;
  --bright-paper:#FFFDF5;
  --grid:rgba(17,17,17,.055);
  /* the shading either side of a fold — a folded paper map catches light along
     each crease, which is most of what makes it read as folded rather than printed */
  --fold-dark:rgba(17,17,17,.10);
  --fold-light:rgba(17,17,17,0);
  /* the horizontal fold has to out-shout the page's own grid ruling, so it gets a
     shadow either side of a lit ridge rather than a single soft band */
  --fold-strong:rgba(17,17,17,.20);
  --fold-hi:rgba(255,255,255,.55);

  --bw:4px;                 /* border weight  */
  --off:8px;                /* shadow offset  */
  --shell:1180px;
  --gut:clamp(18px,4vw,48px);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--body);font-size:18px;line-height:1.6;
  overflow-x:hidden;-webkit-font-smoothing:antialiased;
  /* faint grid, so the paper reads as a workbook page rather than flat white */
  background-image:linear-gradient(var(--grid,rgba(17,17,17,.05)) 1px,transparent 1px),
                   linear-gradient(90deg,var(--grid,rgba(17,17,17,.05)) 1px,transparent 1px);
  background-size:28px 28px;
}
h1,h2,h3,h4{font-family:var(--display);font-weight:400;line-height:.95;
  letter-spacing:-.02em;margin:0;text-wrap:balance}
a{color:inherit}
img{max-width:100%;display:block}
:focus-visible{outline:4px solid var(--ink);outline-offset:3px}
::selection{background:var(--yellow);color:var(--ink)}

.shell{width:100%;max-width:var(--shell);margin-inline:auto;padding-inline:var(--gut)}
.skip{position:absolute;left:-9999px;top:0;z-index:99;background:var(--yellow);
  color:var(--ink);padding:14px 20px;border:var(--bw) solid var(--ink);font-weight:700}
.skip:focus{left:8px;top:8px}

/* ── primitives ─────────────────────────────────────────────────────────── */
.box{border:var(--bw) solid var(--ink);box-shadow:var(--off) var(--off) 0 var(--ink);
  background:var(--paper)}
.sticker{display:inline-block;border:3px solid var(--ink);padding:4px 12px;
  font-family:var(--mono);font-size:13px;font-weight:700;text-transform:uppercase;
  letter-spacing:.08em;box-shadow:3px 3px 0 var(--ink);background:var(--yellow)}
.tape{position:absolute;width:120px;height:30px;background:rgba(255,216,77,.85);
  border:2px solid rgba(17,17,17,.55);transform:rotate(-6deg);pointer-events:none}
.hand{font-family:var(--mono);font-size:15px;transform:rotate(-1.4deg);
  display:inline-block;color:var(--ink)}
/* margin notes: uniform blocks, alternating tilt, so three of them read as a set */
#intro .meta{gap:14px 18px;margin-top:26px}
#intro .meta li{display:flex;align-items:center;min-height:44px;
  border-left:4px solid var(--pink);padding-left:12px}
#intro .meta li:nth-child(2) .hand{transform:rotate(1.1deg)}
#intro .meta li:nth-child(3) .hand{transform:rotate(-.6deg)}
/* highlighter swipe — scales in from the left once the line scrolls into view */
.mark{position:relative;display:inline;background-image:linear-gradient(var(--lime),var(--lime));
  background-repeat:no-repeat;background-position:0 88%;background-size:0 42%;
  transition:background-size .55s cubic-bezier(.22,1,.36,1)}
.mark.lit{background-size:100% 42%}

/* ── top bar ────────────────────────────────────────────────────────────── */
.bar{position:sticky;top:0;z-index:40;background:var(--paper);
  border-bottom:var(--bw) solid var(--ink)}
.bar-in{display:flex;align-items:center;justify-content:space-between;gap:16px;
  min-height:66px;flex-wrap:wrap}
.brand{font-family:var(--display);font-size:20px;text-transform:uppercase;
  letter-spacing:-.01em;display:inline-flex;align-items:center;gap:10px;min-height:48px}
.brand .dot{width:14px;height:14px;background:var(--pink);border:3px solid var(--ink)}
.bar nav{display:flex;gap:6px;flex-wrap:wrap}
.bar nav a{font-family:var(--mono);font-size:13px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;text-decoration:none;padding:0 12px;min-height:44px;
  display:inline-flex;align-items:center;border:3px solid transparent}
.bar nav a:hover,.bar nav a[aria-current="true"]{border-color:var(--ink);background:var(--cyan)}

/* ── hero ───────────────────────────────────────────────────────────────── */
.hero{padding:clamp(40px,7vw,84px) 0 clamp(30px,5vw,60px);position:relative;overflow:hidden}
.hero-grid{display:grid;gap:clamp(24px,4vw,52px);align-items:center}
@media (min-width:900px){.hero-grid{grid-template-columns:1.35fr .65fr}}
.hero h1{font-size:clamp(3.4rem,13vw,9rem);text-transform:uppercase}
.hero h1 .l2{display:block;color:var(--lime);-webkit-text-stroke:3px var(--ink);
  text-shadow:6px 6px 0 var(--pink)}
.hero .role{font-family:var(--mono);font-size:clamp(14px,2.2vw,18px);font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;margin:20px 0 0;
  border:var(--bw) solid var(--ink);display:inline-block;padding:8px 14px;background:var(--cyan);
  box-shadow:5px 5px 0 var(--ink)}
.hero .meta{display:flex;flex-wrap:wrap;gap:10px;margin:22px 0 0;list-style:none;padding:0}
.polaroid{position:relative;background:var(--paper);padding:14px 14px 54px;
  border:var(--bw) solid var(--ink);box-shadow:10px 10px 0 var(--ink);
  transform:rotate(2.4deg);max-width:330px;margin-inline:auto}
.polaroid img{border:3px solid var(--ink);aspect-ratio:4/5;object-fit:cover;width:100%;
  /* height:auto is load-bearing. The <img height> attribute is a presentational hint,
     so without this the height is DEFINITE, aspect-ratio is ignored, and the portrait
     renders as a full-height slab with ~59% of its width cropped away. */
  /* crop from the bottom (sweater), never the top (hair) — the frame is 4:5 and both
     portraits are 3:4, so ~6% has to go somewhere */
  object-position:50% 0%;
  height:auto}
.polaroid figcaption{position:absolute;left:0;right:0;bottom:14px;text-align:center;
  font-family:var(--mono);font-size:14px}
.polaroid .tape{top:-16px;left:50%;margin-left:-60px}
.cue{margin-top:34px;font-family:var(--mono);font-size:13px;text-transform:uppercase;
  letter-spacing:.12em;display:inline-flex;align-items:center;gap:10px}
.cue span{display:inline-block;animation:bob 1.6s ease-in-out infinite}

/* ── section frame ──────────────────────────────────────────────────────── */
section{padding:clamp(46px,7vw,86px) 0;position:relative}
.eyebrow{font-family:var(--mono);font-size:13px;font-weight:700;text-transform:uppercase;
  letter-spacing:.14em;margin:0 0 12px;display:inline-block;
  border-bottom:4px solid var(--ink);padding-bottom:3px}
section h2{font-size:clamp(2.1rem,6vw,3.9rem);text-transform:uppercase;margin:0 0 14px}
.sub{max-width:60ch;margin:0 0 34px;font-size:clamp(17px,2vw,20px)}
/* torn paper divider */
.torn{display:block;width:100%;height:26px;color:var(--ink)}

/* ── pillars ────────────────────────────────────────────────────────────── */
.pillars{display:grid;gap:22px}
@media (min-width:740px){.pillars{grid-template-columns:repeat(3,1fr)}}
.pillar{padding:24px 22px;position:relative}
.pillar:nth-child(1){background:var(--yellow);transform:rotate(-1deg)}
.pillar:nth-child(2){background:var(--cyan)}
.pillar:nth-child(3){background:var(--violet);transform:rotate(1deg)}
.pillar .n{font-family:var(--mono);font-weight:700;font-size:13px}
.pillar h3{font-size:1.7rem;text-transform:uppercase;margin:6px 0 10px}
.pillar p{margin:0;font-size:16px;line-height:1.55}

/* ── sticker wall ───────────────────────────────────────────────────────── */
.wall{display:grid;gap:26px}
@media (min-width:760px){.wall{grid-template-columns:repeat(2,1fr)}}
.wall-group h3{font-size:1.35rem;text-transform:uppercase;margin:0 0 14px}
.chips{display:flex;flex-wrap:wrap;gap:9px;list-style:none;margin:0;padding:0}
.chips li{border:3px solid var(--ink);padding:6px 12px;font-family:var(--mono);
  font-size:13px;font-weight:700;box-shadow:3px 3px 0 var(--ink);background:var(--paper)}

/* ── timeline ───────────────────────────────────────────────────────────── */
.timeline{list-style:none;margin:0;padding:0;position:relative}
.timeline::before{content:"";position:absolute;left:19px;top:14px;bottom:14px;
  width:5px;background:var(--ink)}
@media (min-width:900px){.timeline::before{left:50%;margin-left:-2.5px}}
.stop{position:relative;padding-left:64px;margin-bottom:30px}
@media (max-width:620px){
  /* the rail was taking 64px out of ~342px, squeezing the card text to 244px */
  .stop{padding-left:30px}
  .timeline::before{left:8px;width:4px}
  .stop::before{left:0;width:18px;height:18px;top:24px}
  .stop .card{padding:16px 14px 15px}
  .stop ul{padding-left:16px}
}
@media (min-width:900px){
  .stop{width:50%;padding-left:0;padding-right:52px}
  .stop:nth-child(even){margin-left:50%;padding-right:0;padding-left:52px}
}
.stop::before{content:"";position:absolute;left:8px;top:26px;width:27px;height:27px;
  background:var(--lime);border:var(--bw) solid var(--ink);border-radius:50%}
@media (min-width:900px){
  .stop::before{left:auto;right:-13.5px}
  .stop:nth-child(even)::before{left:-13.5px;right:auto}
}
.stop .card{padding:20px 20px 18px;background:var(--paper);transform:rotate(-.5deg)}
.stop:nth-child(even) .card{transform:rotate(.7deg)}
@media (max-width:620px){.stop .card,.stop:nth-child(even) .card{transform:none}}
.stop .when{font-family:var(--mono);font-size:13px;font-weight:700;
  background:var(--yellow);border:3px solid var(--ink);display:inline-block;padding:3px 9px}
.stop h3{font-size:1.4rem;margin:12px 0 4px;text-transform:uppercase}
.stop .where{font-family:var(--mono);font-size:14px;margin:0 0 12px}
.stop ul{margin:0;padding-left:20px;font-size:16px;line-height:1.55}
.stop li{margin-bottom:7px}
.stop li::marker{color:var(--pink)}

/* ── project cards ──────────────────────────────────────────────────────── */
.cards{display:grid;gap:26px}
@media (min-width:700px){.cards{grid-template-columns:repeat(2,1fr)}}
.card-proj{padding:22px;position:relative;background:var(--paper);
  transition:transform .18s ease,box-shadow .18s ease}
.card-proj:hover{transform:translate(-3px,-3px) rotate(-.5deg);
  box-shadow:calc(var(--off) + 4px) calc(var(--off) + 4px) 0 var(--ink)}
.card-proj .code{position:absolute;top:-16px;right:16px;width:42px;height:42px;
  display:grid;place-items:center;font-family:var(--display);font-size:20px;
  background:var(--orange);border:var(--bw) solid var(--ink)}
.card-proj h3{font-size:1.35rem;text-transform:uppercase;margin:0 42px 8px 0}
.card-proj .outcome{font-family:var(--mono);font-size:14px;font-weight:700;
  background:var(--lime);display:inline-block;padding:4px 10px;border:3px solid var(--ink);
  margin-bottom:12px}
.card-proj p{margin:0 0 14px;font-size:16px;line-height:1.55}

/* ── faq ────────────────────────────────────────────────────────────────── */
.faq{display:grid;gap:16px}
.faq details{border:var(--bw) solid var(--ink);background:var(--paper);
  box-shadow:6px 6px 0 var(--ink)}
.faq summary{cursor:pointer;list-style:none;padding:16px 20px;font-family:var(--display);
  font-size:1.12rem;display:flex;justify-content:space-between;gap:16px;align-items:center;
  min-height:56px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";font-size:1.6rem;line-height:1}
.faq details[open] summary{background:var(--yellow);border-bottom:var(--bw) solid var(--ink)}
.faq details[open] summary::after{content:"–"}
.faq .a{padding:16px 20px;margin:0;font-size:16px;line-height:1.6}

/* ── contact ────────────────────────────────────────────────────────────── */
.big-links{display:flex;flex-wrap:wrap;gap:16px;list-style:none;margin:0;padding:0}
.big-links button{font:inherit;cursor:pointer}
.big-links a,.big-links button{display:inline-flex;align-items:center;gap:10px;min-height:60px;padding:0 24px;
  border:var(--bw) solid var(--ink);box-shadow:var(--off) var(--off) 0 var(--ink);
  font-family:var(--display);font-size:1.05rem;text-transform:uppercase;text-decoration:none;
  transition:transform .14s ease,box-shadow .14s ease}
.big-links a:hover,.big-links button:hover{transform:translate(3px,3px);box-shadow:3px 3px 0 var(--ink)}

/* ── footer ─────────────────────────────────────────────────────────────── */
.foot{border-top:var(--bw) solid var(--ink);background:var(--ink);color:var(--paper);
  padding:36px 0 46px}
.foot a{color:var(--paper)}
.foot .row{display:flex;flex-wrap:wrap;gap:18px;justify-content:space-between;align-items:center}
.foot .note{font-family:var(--mono);font-size:13px;margin:0}
.foot a.to-terminal{display:inline-flex;align-items:center;gap:10px;min-height:56px;padding:0 22px;
  background:var(--lime);color:var(--ink);border:var(--bw) solid var(--paper);
  font-family:var(--display);text-transform:uppercase;text-decoration:none;font-size:1rem}
.foot a.to-terminal:hover{background:var(--yellow);color:var(--ink)}

/* ── decorative falling icons ───────────────────────────────────────────── */
.confetti{position:fixed;inset:0;pointer-events:none;z-index:0;overflow:hidden}
/* Decoration belongs BEHIND the words. At z-index 1 the falling shapes painted over
   headings and labels — it was a map label that made it obvious, but it could land
   on any text on the page. The content layers sit above it. */
header.hero,main,footer.foot,.bar{position:relative;z-index:1}
.confetti svg{position:absolute;top:-40px;animation:fall linear infinite}

@keyframes fall{to{transform:translateY(112vh) rotate(360deg)}}
@keyframes bob{50%{transform:translateY(6px)}}

/* reveal on scroll */
.rise{opacity:0;transform:translateY(22px);transition:opacity .5s ease,transform .5s ease}
.rise.lit{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
  .rise{opacity:1;transform:none}
  .mark{background-size:100% 42%}
  .confetti{display:none}
}

@media (max-width:560px){
  :root{--bw:3px;--off:6px}
  body{font-size:17px}
  .polaroid{transform:none}
  .pillar{transform:none!important}
}

@media print{
  body{background:#fff;background-image:none}
  .bar,.confetti,.cue,.to-terminal{display:none!important}
  .box,.card-proj,.pillar,.stop .card{box-shadow:none;transform:none!important}
  section{padding:18px 0;break-inside:avoid}
}


/* ── reading aids for a very long page ─────────────────────────────────────
   The page is ~8000px tall. A position indicator and a way back to the top are
   not decoration at that length, they are wayfinding.                        */
.progress{position:fixed;top:0;left:0;height:10px;width:0;z-index:60;
  background:var(--lime);border-bottom:var(--bw) solid var(--ink);
  transition:width .08s linear}
@media (prefers-reduced-motion:reduce){.progress{transition:none}}

.totop{position:fixed;right:18px;bottom:18px;z-index:60;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-width:56px;min-height:56px;padding:0 16px;
  font-family:var(--mono);font-weight:700;font-size:14px;text-transform:uppercase;
  color:var(--ink);background:var(--cyan);text-decoration:none;
  border:var(--bw) solid var(--ink);box-shadow:5px 5px 0 var(--ink);
  opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity .18s ease,transform .18s ease,visibility .18s}
.totop.show{opacity:1;visibility:visible;transform:none}
.totop:hover{transform:translate(2px,2px);box-shadow:3px 3px 0 var(--ink)}
.totop:focus-visible{outline:4px solid var(--ink);outline-offset:3px}
@media (prefers-reduced-motion:reduce){.totop{transition:none}}

.copied{margin-left:10px;font-family:var(--mono);font-size:13px;font-weight:700;
  text-transform:uppercase;background:var(--lime);color:var(--ink);
  border:3px solid var(--ink);padding:3px 8px;display:inline-block}

/* ── print: this is a résumé, so it should survive Ctrl+P ──────────────────
   Flat colour and hard shadows cost a fortune in toner and read as mud in
   greyscale, so print gets the content on white with the structure intact.  */
@media print{
  @page{margin:14mm}
  :root{--bw:1.5px}
  *{box-shadow:none !important;text-shadow:none !important;
    transform:none !important;animation:none !important;transition:none !important}
  body{background:#fff;color:#000;font-size:11pt}
  .bar,.confetti,.progress,.totop,.cue,.tape,.torn,.foot a.to-terminal{display:none !important}
  .hero h1{font-size:34pt;-webkit-text-stroke:0}
  .hero h1 .l2{color:#000}
  section{padding:0 0 10mm !important;break-inside:avoid}
  .shell{padding-inline:0;max-width:none}
  .box,.card,.chip,.sticker,.pillar{background:#fff !important;border-color:#000 !important}
  .stop,.card,.pillar,details{break-inside:avoid}
  details{display:block}
  details>summary{list-style:none}
  details[open]>*, details:not([open])>*{display:revert}
  /* an unopened FAQ prints as a question with no answer, which is useless */
  #faq details>div,#faq details>p{display:block !important}
  a{text-decoration:underline;color:#000}
  /* a printed page cannot be clicked, so surface the destination */
  .big-links a::after,.foot a::after{content:" (" attr(href) ")";font-size:9pt;word-break:break-all}
  .big-links a[href^="mailto:"]::after{content:" (" attr(href) ")"}
}


/* ── grid-paper ground ─────────────────────────────────────────────────────
   A drafting-table grid under everything. Geometric, so it reinforces the
   blocky rules rather than softening them the way a texture would.         */
body{
  background-image:
    repeating-linear-gradient(to right, var(--grid) 0 1px, transparent 1px 34px),
    repeating-linear-gradient(to bottom, var(--grid) 0 1px, transparent 1px 34px);
}
/* fixed attachment repaints every scrolled frame on mobile GPUs, so only
   pointer-fine devices pay for the stationary-desk effect */
@media (min-width:1024px) and (pointer:fine){
  body{background-attachment:fixed}
}

/* ── the journey map ─────────────────────────────────────────────────────── */
.map{margin:46px 0 0;padding:18px 18px 12px;background:var(--paper);
  border:var(--bw) solid var(--ink);box-shadow:10px 10px 0 var(--ink);
  transform:rotate(-.5deg)}
.map figcaption{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  font-family:var(--mono);font-size:14px;font-weight:700;text-transform:uppercase;
  letter-spacing:.04em;margin:0 0 14px}
.map .map-flag{background:var(--cyan)}
.map svg{display:block;width:100%;height:auto}
.map .usa{fill:var(--yellow);stroke:var(--ink);stroke-width:5;stroke-linejoin:round}
.map .route{fill:none;stroke:var(--ink);stroke-width:5;stroke-dasharray:16 14;
  stroke-linecap:round}
.map-note{margin:10px 0 0;font-size:17px}

/* Clients served are a different claim from places worked, so they get a marker
   that could not be mistaken for a pin, and a key that spells out which is which. */
.map .cx{stroke:var(--ink);stroke-width:5;stroke-linecap:round;fill:none;opacity:.75}
.map-key{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:12px 0 0;
  font-family:var(--mono);font-size:14px;line-height:1.5}
.map-key .k{display:inline-flex;align-items:center;justify-content:center;
  width:22px;height:22px;border:3px solid var(--ink);background:var(--paper)}
.map-key .k-pin{border-radius:50%;background:var(--bright-paper)}
.map-key .k-x{font-weight:700;border-color:transparent;background:none;font-size:17px}
/* Hovering a pin highlights its timeline card — which is usually a couple of
   thousand pixels off-screen. So the map answers where the pointer already is. */
.map-read{margin:12px 0 0;padding:12px 14px;min-height:58px;
  background:var(--paper);border:var(--bw) solid var(--ink);box-shadow:5px 5px 0 var(--ink);
  font-family:var(--mono);font-size:15px;line-height:1.45}
.map-read.filled{background:var(--cyan)}
.map-read b{display:block;font-size:17px}
.map-read .yr{font-weight:700;text-transform:uppercase;letter-spacing:.04em}

.pin{cursor:pointer}
.pin .pin-halo{fill:var(--pink);stroke:var(--ink);stroke-width:4;opacity:0}
.pin .pin-dot{fill:var(--paper);stroke:var(--ink);stroke-width:5}
.pin .pin-tag rect{fill:var(--paper);stroke:var(--ink);stroke-width:4}
/* Home base is not one stop among three — it is where he is, permanently. */
.pin.home .pin-dot{fill:var(--lime);stroke-width:6}
.pin.home .pin-halo{fill:none;stroke:var(--ink);stroke-width:4;stroke-dasharray:7 6;opacity:1}
.pin.home .pin-tag rect{fill:var(--lime)}
/* These sit after the home rules on purpose: same specificity, so without them the
   home styling would win on source order and the pin would lose its hover state. */
.pin.home:hover .pin-dot,.pin.home:focus-visible .pin-dot,.pin.home.on .pin-dot{fill:var(--pink);r:15}
.pin.home:hover .pin-tag rect,.pin.home.on .pin-tag rect{fill:var(--cyan)}
.pin .pin-tag text{font-family:var(--mono);font-size:20px;font-weight:700;fill:var(--ink)}
.pin .pin-tag{filter:drop-shadow(5px 5px 0 var(--ink))}
.pin:hover .pin-halo,.pin:focus-visible .pin-halo,.pin.on .pin-halo{opacity:1}
.pin:hover .pin-dot,.pin:focus-visible .pin-dot,.pin.on .pin-dot{fill:var(--pink);r:15}
.pin:focus{outline:none}
.pin:focus-visible .pin-tag rect{fill:var(--cyan)}
/* the matching timeline card lights up from the map, and vice versa */
.stop.on .card{background:var(--cyan)}

@media (max-width:700px){
  .map{transform:none;padding:14px 12px 10px}
  .map .usa{stroke-width:7}
  /* Label size is set by main.js, not here: the map scales with the viewport, so a
     fixed size in user units renders at whatever CSS pixel size falls out — 8.6px on
     a phone, which is unreadable. main.js holds a 12px floor instead. */
  .map .pin-dot{r:14}
  .map .cx{stroke-width:7}
}
@media (prefers-reduced-motion:no-preference){
  .pin .pin-halo{transition:opacity .16s ease}
  .pin .pin-dot{transition:fill .16s ease}
  .stop .card{transition:background .16s ease}
  /* the route draws itself once the map scrolls in */
  .map.lit .route{animation:draw 1.5s ease forwards}
  .map .route{stroke-dashoffset:0}
  @keyframes draw{from{stroke-dasharray:0 600}to{stroke-dasharray:16 14}}
}

/* ── letter-by-letter entrance on the display name ─────────────────────── */
.hero h1 .ch{display:inline-block;will-change:transform}
@media (prefers-reduced-motion:no-preference){
  .hero h1 .ch{animation:pop .5s cubic-bezier(.2,1.5,.4,1) both}
}
@keyframes pop{
  from{transform:translateY(-.42em) rotate(-7deg);opacity:0}
  to{transform:none;opacity:1}
}

@media print{
  body{background-image:none}
  .map{transform:none;box-shadow:none;break-inside:avoid}
  .map .usa{fill:#fff;stroke:#000}
  .pin .pin-dot{fill:#000}
  .pin .pin-tag rect{fill:#fff;stroke:#000}
  .pin .pin-tag{filter:none}
}


/* ── night mode ────────────────────────────────────────────────────────────
   Only two things change: the page surface and the ink on it. Every bright colour
   stays exactly as it is, because a lime sticker is a lime sticker at midnight —
   it just has to keep its dark text, which --on-bright does.
   main.js writes the palette as INLINE custom properties, which outrank any
   stylesheet rule, so it sets inkDark/paperDark itself rather than relying on the
   selector below to win. This block is the no-JS fallback.                     */
:root[data-theme="dark"]{
  --ink:#F4F1E6; --paper:#16161C;
  --grid:rgba(244,241,230,.06);
}

/* everything that sits on a bright fill keeps dark ink and a dark edge */
.sticker,
.big-links a,.big-links button,
.hero .role,
.bar nav a:hover,.bar nav a[aria-current="true"],
.foot a.to-terminal,
.totop,.copied,
.map .map-flag,.map-read.filled,
.skip,
.pillar,.pillar h3,.pillar p,.pillar .n,
.card-proj .code,.card-proj .outcome,
.stop .when,
.stop.on .card,.stop.on .card h3,.stop.on .card p,.stop.on .card li{
  color:var(--on-bright);
  border-color:var(--on-bright);
}

/* the map is a bright object in both themes, so it is drawn in fixed ink */
.map .usa,.map .route,.map .cx{stroke:var(--on-bright)}
.pin .pin-dot{fill:var(--bright-paper);stroke:var(--on-bright)}
.pin .pin-tag rect{fill:var(--bright-paper);stroke:var(--on-bright)}
.pin .pin-tag text{fill:var(--on-bright)}
.pin .pin-halo,.pin.home .pin-halo{stroke:var(--on-bright)}
.pin .pin-tag{filter:drop-shadow(5px 5px 0 var(--on-bright))}

/* ── the day / night switch ───────────────────────────────────────────────── */
.themer{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 14px;
  font-family:var(--mono);font-size:13px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;cursor:pointer;
  color:var(--on-bright);background:var(--yellow);
  border:3px solid var(--on-bright);box-shadow:4px 4px 0 var(--on-bright)}
.themer:hover{transform:translate(2px,2px);box-shadow:2px 2px 0 var(--on-bright)}
.themer:focus-visible{outline:4px solid var(--ink);outline-offset:3px}
.themer .ico{font-size:15px;line-height:1}

/* ── the tools, stated up front ──────────────────────────────────────────
   Pulled from the first skill group rather than typed again here, so the hero
   and the sticker wall cannot drift apart. */
.tools{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:18px 0 0;padding:0}
.tools li{font-family:var(--mono);font-size:13px;font-weight:700;padding:5px 10px;
  background:var(--paper);color:var(--ink);border:3px solid var(--ink);
  box-shadow:3px 3px 0 var(--ink)}
@media (max-width:560px){.tools li{font-size:12px;padding:4px 8px}}

:root[data-theme="dark"] .mark{
  background-image:linear-gradient(var(--teal),var(--teal));
  color:var(--ink);
}
/* ...unless the swipe is inside a card that is bright in BOTH themes, where the
   glyph tops sit on a light surface and the rule above would invert the wrong way. */
:root[data-theme="dark"] .pillar .mark,
:root[data-theme="dark"] .card-proj .mark{
  background-image:linear-gradient(var(--lime),var(--lime));
  color:var(--on-bright);
}

/* ── the map, as a paper map that has been folded and carried ────────────── */
.map .crease{mix-blend-mode:multiply}
.map .foldline{stroke:var(--on-bright);stroke-width:1.5;opacity:.28;fill:none;
  stroke-dasharray:3 5}
.map .compass circle{fill:var(--bright-paper);stroke:var(--on-bright);stroke-width:5}
.map .compass .rose{fill:none;stroke:var(--on-bright);stroke-width:4;stroke-linejoin:round}
.map .compass .needle{fill:var(--pink);stroke:var(--on-bright);stroke-width:4;stroke-linejoin:round}
.map .compass text{font-family:var(--display);font-size:22px;fill:var(--on-bright);
  text-anchor:middle}
:root[data-theme="dark"]{--fold-dark:rgba(17,17,17,.16);
  --fold-strong:rgba(17,17,17,.30);--fold-hi:rgba(255,255,255,.30)}
@media (max-width:700px){
  .map .compass{transform:translate(84px,676px) scale(1.25)}
  .map .foldline{stroke-width:2.5}
}

/* ── colour cards ─────────────────────────────────────────────────────────
   Projects cycle the palette the way the pillars do, so the section reads as a
   spread of cards rather than a column of identical boxes. Bright fills in both
   themes, so their ink is fixed. */
.card-proj[data-hue="0"]{background:var(--lime)}
.card-proj[data-hue="1"]{background:var(--cyan)}
.card-proj[data-hue="2"]{background:var(--yellow)}
.card-proj[data-hue="3"]{background:var(--violet)}
.card-proj[data-hue="4"]{background:var(--pink)}
.card-proj[data-hue],.card-proj[data-hue] h3,.card-proj[data-hue] p,
.card-proj[data-hue] li,.card-proj[data-hue] .outcome,.card-proj[data-hue] .tag{
  color:var(--on-bright);border-color:var(--on-bright)}
/* the stamp and the stack chips sit ON the colour card, so their own fill has to
   stay light in both themes — --paper goes dark at night and would swallow them */
.card-proj[data-hue] .code,
.card-proj[data-hue] .chips li{background:var(--bright-paper)}

/* ── floating decoration ──────────────────────────────────────────────────
   The confetti falls; these drift in place. Both are aria-hidden, both sit
   behind the content layer, and both stop dead under reduced motion. */
.floater{position:absolute;z-index:0;pointer-events:none;color:var(--ink);opacity:.5}
.floater svg{display:block}
@media (prefers-reduced-motion:no-preference){
  .floater{animation:drift var(--dur,9s) ease-in-out infinite alternate}
}
@keyframes drift{
  from{transform:translateY(-10px) rotate(-6deg)}
  to{transform:translateY(12px) rotate(6deg)}
}
@media (max-width:1279px){.floater{display:none}}
@media print{.floater{display:none}}

/* ── the map unfolds when you reach it ────────────────────────────────────
   The reveal observer already stamps .lit on the map; the resting state is flat
   so nothing measured before the reveal is ever transformed. The creases are
   inside the svg, so they open with the paper. */
.map{perspective:1400px}
@media (prefers-reduced-motion:no-preference){
  .map.lit svg{animation:unfold .9s cubic-bezier(.2,.85,.3,1) both;
    transform-origin:50% 0}
}
@keyframes unfold{
  0%{transform:rotateX(64deg) scaleY(.42);opacity:.35}
  62%{transform:rotateX(-13deg) scaleY(1.05)}
  100%{transform:none;opacity:1}
}
/* a strip of tape on the folded map, like it was pinned into the scrapbook */
.map>.tape{top:-16px;right:52px;left:auto;margin-left:0;transform:rotate(4deg)}

/* ── the sticker wall gets its group headers as colour chips ─────────────── */
.wall-group h3{display:inline-block;padding:3px 12px;border:3px solid var(--on-bright);
  color:var(--on-bright);box-shadow:3px 3px 0 var(--on-bright);text-transform:uppercase;
  font-size:15px;letter-spacing:.04em}
.wall-group:nth-of-type(5n+1) h3{background:var(--yellow)}
.wall-group:nth-of-type(5n+2) h3{background:var(--cyan)}
.wall-group:nth-of-type(5n+3) h3{background:var(--pink)}
.wall-group:nth-of-type(5n+4) h3{background:var(--lime)}
.wall-group:nth-of-type(5n+5) h3{background:var(--violet)}

:root[data-theme="dark"] .stop.on .card{background:var(--teal)}
:root[data-theme="dark"] .stop.on .card,:root[data-theme="dark"] .stop.on .card h3,
:root[data-theme="dark"] .stop.on .card p,:root[data-theme="dark"] .stop.on .card li{
  color:var(--ink);border-color:var(--ink)}

/* -- here be dragons ------------------------------------------------------- */
.map .dragons .serp{fill:none;stroke:var(--on-bright);stroke-width:4;stroke-linecap:round}
.map .dragons .head{fill:var(--on-bright)}
.map .dragons text{font-family:var(--mono);font-size:15px;font-style:italic;
  fill:var(--on-bright);text-anchor:middle;opacity:.85}
.map .grain{pointer-events:none}

/* -- fly to a stop ----------------------------------------------------------
   The reference flies its Leaflet map to a marker when a timeline entry is
   clicked; an SVG viewBox does the same flight with no library at all. While
   zoomed, chrome that would scale up absurdly is hidden - the readout under
   the map carries the naming, which is what it is for. */
.fly{display:inline-flex;align-items:center;margin:8px 10px 2px 0;padding:5px 12px;
  font-family:var(--mono);font-size:12px;font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink);background:var(--paper);
  border:3px solid var(--ink);box-shadow:3px 3px 0 var(--ink);cursor:pointer}
/* fingers need 44px; mice get the compact version (WCAG 2.5.5 / 2.5.8) */
@media (pointer:coarse){.fly{min-height:44px}}
.fly:hover{transform:translate(2px,2px);box-shadow:1px 1px 0 var(--ink)}
.fly:focus-visible{outline:4px solid var(--ink);outline-offset:2px}

.map svg.zoomed .pin-tag,.map svg.zoomed .clients,.map svg.zoomed .compass,
.map svg.zoomed .dragons,.map svg.zoomed .folds,.map svg.zoomed .grain{display:none}
.pin.zoom-target .pin-halo{opacity:1}
@media (prefers-reduced-motion:no-preference){
  .pin.zoom-target .pin-halo{animation:pulse 1.3s ease-in-out infinite}
}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.2}}

.map-reset{position:absolute;top:-16px;left:18px;display:inline-flex;align-items:center;
  gap:6px;min-height:40px;padding:0 14px;font-family:var(--mono);font-size:12px;
  font-weight:700;text-transform:uppercase;letter-spacing:.05em;cursor:pointer;
  color:var(--on-bright);background:var(--cyan);border:3px solid var(--on-bright);
  box-shadow:4px 4px 0 var(--on-bright)}
/* a class display rule beats the [hidden] UA default, so spell it out — without
   this the reset button is visible before any zoom has ever happened */
.map-reset[hidden]{display:none}
@media (pointer:coarse){.map-reset{min-height:44px}}
.map-reset:hover{transform:translate(2px,2px);box-shadow:2px 2px 0 var(--on-bright)}
.map-reset:focus-visible{outline:4px solid var(--ink);outline-offset:3px}
@media print{.fly,.map-reset{display:none}}

/* At night the footer's inversion trick inverts the wrong way: background:var(--ink)
   becomes a large cream band — 15.9:1 readable, but it reads as a light-mode leftover.
   A panel darker than the page keeps the "contrast band" idea in night vocabulary.
   Scoped to .note so the to-terminal button keeps its bright fill + dark ink. */
:root[data-theme="dark"] .foot{background:#101016;color:var(--ink);border-top-color:var(--ink)}
:root[data-theme="dark"] .foot .note{color:var(--ink)}
:root[data-theme="dark"] .foot .note a{color:var(--ink)}
