/* ======================================================================
   /work and /work/<entry>: the fast path.

   The résumé's palette and voice on a page built to be skimmed. Silkscreen
   is kept to the name, the section rules and the small labels; everything
   read at length is a system face. One file for every generated page, so
   the eleven of them load it once.
   ====================================================================== */
:root{
  --ink:#17161b; --paper:#f7f4ea; --shell:#1c1c1e;
  --gold:#e5be45; --cyan:#6fc9df;
  --quiet:#6b6870; --rule:#d8d2c2; --body:#2a2830;
  --accent:var(--gold); --hl:rgba(229,190,69,.42);
  --card:#fffdf6;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --ink:#f1ede2; --paper:#211f24; --quiet:#a29fa8; --rule:#3a3740; --body:#dcd8ce;
    --hl:rgba(229,190,69,.30); --card:#2a272e;
  }
}
:root[data-theme="dark"]{
  --ink:#f1ede2; --paper:#211f24; --quiet:#a29fa8; --rule:#3a3740; --body:#dcd8ce;
  --hl:rgba(229,190,69,.30); --card:#2a272e;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%; scroll-behavior:smooth}
@media (prefers-reduced-motion: reduce){ html{scroll-behavior:auto} }
body{
  margin:0; background:var(--shell);
  background-image:radial-gradient(120% 90% at 50% 0%, #2e2e31 0%, #1f1f22 55%, #141416 100%);
  background-attachment:fixed;
  color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,Helvetica,Arial,sans-serif;
  font-size:15.5px; line-height:1.55;
  padding:0 16px 64px;
}
a{color:inherit}
img,video{max-width:100%; display:block}

/* ---------- the bar ---------- */
.bar{
  position:sticky; top:0; z-index:5;
  display:flex; gap:8px; flex-wrap:wrap; align-items:center;
  max-width:920px; margin:0 auto; padding:14px 0;
  background:linear-gradient(#1f1f22 62%, rgba(31,31,34,0));
}
.bar .spacer{flex:1}
.k{
  font-family:"Silkscreen","Courier New",monospace;
  font-size:11px; letter-spacing:.04em; text-decoration:none;
  color:#f7f4ea; background:#2a2a2e;
  border:1px solid #4a4952; border-bottom-width:3px;
  padding:8px 12px; border-radius:3px; display:inline-block;
}
.k:hover{background:#34343a; border-color:var(--accent); color:var(--accent)}
.k.gold{background:var(--accent); color:#17161b; border-color:rgba(0,0,0,.4)}
.k.gold:hover{filter:brightness(1.1); color:#17161b}

/* ---------- the sheet ---------- */
.sheet{
  max-width:920px; margin:0 auto; background:var(--paper);
  border:1px solid #000; border-radius:2px;
  box-shadow:0 18px 48px rgba(0,0,0,.45);
  padding:44px 52px 48px;
}
.name{
  font-family:"Silkscreen","Courier New",monospace; font-weight:700;
  font-size:34px; line-height:1.1; letter-spacing:.02em; margin:0 0 6px;
}
.role, .kicker{
  font-family:"Silkscreen","Courier New",monospace;
  font-size:12px; letter-spacing:.06em; color:var(--quiet); margin:0 0 14px;
}
/* The title screen's pixel shadow, so the two doors share a face. */
.name{text-shadow:2px 2px 0 var(--accent)}
.lede{margin:0 0 14px; font-size:17.5px; line-height:1.5; max-width:64ch; color:var(--body)}
.q{color:var(--quiet)}
.contact{list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:4px 14px; font-size:14px}
.contact a{text-decoration:none; border-bottom:1px solid var(--accent)}
.contact a:hover{background:var(--hl)}
.contact li::before{content:"▸ "; color:var(--accent)}

section{margin-top:30px}
h2{
  font-family:"Silkscreen","Courier New",monospace; font-weight:700;
  font-size:12px; letter-spacing:.12em; margin:0 0 14px; padding-bottom:5px;
  border-bottom:2px solid var(--ink);
}
h2::after{
  content:""; display:block; height:2px; width:46px;
  background:var(--accent); margin-bottom:-7px; position:relative; top:5px;
}

/* ---------- the results strip ----------
   The numbers were scattered across nine case studies and a résumé. Here
   they are the first thing under the name, each one a link to the case
   that earned it. */
.results{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px;
}
.results li{background:var(--card); border:1px solid var(--rule); border-radius:3px}
.results li > a, .results li > b:first-child{display:block}
.results a, .results li{text-decoration:none}
.results a{display:block; height:100%; padding:12px 14px}
.results li:not(:has(a)){padding:12px 14px}
.results a:hover{background:var(--hl)}
.rn{display:block; font-size:24px; font-weight:700; line-height:1.15; letter-spacing:-.01em}
.rl{display:block; font-size:14px; font-weight:600; margin-top:2px}
.rc{display:block; font-size:13px; line-height:1.4; margin-top:4px}
.rs{display:block; font-size:12.5px; color:var(--quiet); margin-top:3px}

/* ---------- roles ---------- */
.roles{list-style:none; margin:0; padding:0}
.roles li{
  display:grid; grid-template-columns:auto 1fr auto; gap:0 10px; align-items:baseline;
  padding:8px 0; border-bottom:1px solid var(--rule);
}
.roles .co{font-family:"Silkscreen","Courier New",monospace; font-weight:700; font-size:13px; letter-spacing:.03em}
.roles .rr{font-style:italic; font-size:14px; color:var(--quiet)}
.roles .when{font-family:"Silkscreen","Courier New",monospace; font-size:11px; color:var(--quiet); white-space:nowrap}
.roles .rline{grid-column:1 / -1; font-size:14px; color:var(--body)}
.more{font-size:14px; margin:10px 0 0}
.more a, .room a, .go a, .pn a, .write a{border-bottom:1px solid var(--accent); text-decoration:none}

/* ---------- work cards ---------- */
.cards{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:14px}
.card{background:var(--card); border:1px solid var(--rule); border-radius:3px; display:flex; flex-direction:column; overflow:hidden;
      transition:transform .18s ease, box-shadow .18s ease}
.card:hover{transform:translateY(-2px); box-shadow:0 14px 30px -18px rgba(0,0,0,.5)}
@media (prefers-reduced-motion: reduce){ .card, .card:hover{transition:none; transform:none} }
.cbody{padding:16px 18px; display:flex; flex-direction:column; flex:1}

/* The cover: the case's lead picture on the stage's dark ground, handsets
   drawn as handsets. Fixed proportions, so the grid stays even whatever
   shape the work is. */
.cover{
  display:flex; align-items:center; justify-content:center; gap:14px;
  aspect-ratio:16 / 9; overflow:hidden; text-decoration:none;
  background:
    radial-gradient(60% 80% at 50% 45%, rgba(229,190,69,.15), transparent 72%),
    radial-gradient(rgba(247,244,234,.07) 1px, transparent 1.4px) 0 0 / 12px 12px,
    #151517;
  border-bottom:1px solid #000;
}
.cover > img{width:100%; height:100%; object-fit:cover; object-position:top center; transition:transform .4s ease}
.cover > img[src$=".png"]{object-fit:contain; padding:14px}
/* A recording's still is a frame from the middle of something moving; it
   crops from the middle. A still keeps its top, which on a page is the hero. */
.cover > img.fromvideo{object-position:center}
.card:hover .cover > img{transform:scale(1.03)}
.cover.phones{padding-top:22px; align-items:flex-start}
.cover .hand{height:118%; width:auto; flex:0 0 auto; border-width:5px; border-radius:20px;
              box-shadow:0 0 0 1px #45434d, 0 18px 30px -14px rgba(0,0,0,.8)}
.cover .hand img{border-radius:15px}
.cover .hand + .hand{margin-top:28px}

.card.feature{grid-column:1 / -1; display:grid; grid-template-columns:minmax(0,1.1fr) minmax(0,1fr)}
.card.feature .cover{aspect-ratio:auto; height:100%; min-height:340px; border-bottom:0; border-right:1px solid #000}
.card.feature .cover .hand{height:400px}
.card.feature .cbody{padding:22px 24px; justify-content:center}
.card.feature .flv{font-size:16px}
.cardhead{display:flex; gap:12px; align-items:center; text-decoration:none; margin-bottom:8px}
.cardhead b{font-family:"Silkscreen","Courier New",monospace; font-size:14px; letter-spacing:.03em}
.cardhead .q{font-size:13px}
.ic{width:40px; height:40px; border-radius:9px; flex:0 0 auto; object-fit:contain; background:#e9e2cc}
.ic.blank{background:repeating-linear-gradient(45deg,#cfc8b4 0 3px,#ded7c3 3px 6px)}
.ic.big{width:56px; height:56px; border-radius:12px}
.flv{margin:0 0 8px; font-size:14.5px; color:var(--body)}
.out{margin:0 0 10px; font-size:14.5px}
.lbl{
  font-family:"Silkscreen","Courier New",monospace; font-size:11px; letter-spacing:.06em;
  background:var(--hl); padding:1px 5px; margin-right:4px; white-space:nowrap;
}
.go{margin:auto 0 0; font-size:14px; display:flex; flex-wrap:wrap; gap:4px 14px}
.ext{color:var(--quiet)}
.room{margin:34px 0 0; padding-top:12px; border-top:1px solid var(--rule); font-size:14px; color:var(--quiet)}

/* ---------- a case study ---------- */
.ehead{display:flex; gap:14px; align-items:center; margin-bottom:10px}
.ehead .kicker{margin:0 0 4px}
.ehead .name{margin:0}
.note{font-size:14px; font-family:-apple-system,BlinkMacSystemFont,sans-serif; letter-spacing:0}
.brief{
  display:grid; grid-template-columns:auto 1fr; gap:8px 16px; margin:0 0 16px;
  padding:14px 16px; background:var(--card); border:1px solid var(--rule); border-radius:3px;
}
.brief dt{font-family:"Silkscreen","Courier New",monospace; font-size:11.5px; letter-spacing:.08em; color:var(--quiet); padding-top:3px}
.brief dd{margin:0; font-size:15px}
.brief .res{font-weight:600}
.brief dt.res{color:var(--ink)}
.kv{display:flex; flex-wrap:wrap; gap:4px 18px; margin:0 0 14px; font-size:13.5px}
.kv dt{font-family:"Silkscreen","Courier New",monospace; font-size:11px; letter-spacing:.08em; color:var(--quiet); align-self:center}
.kv dd{margin:0 8px 0 -12px}
.links{display:flex; flex-wrap:wrap; gap:8px; margin:0 0 10px}
.toc{display:flex; flex-wrap:wrap; gap:6px; margin:22px 0 0}
.toc a{
  font-family:"Silkscreen","Courier New",monospace; font-size:11px; letter-spacing:.04em;
  text-decoration:none; padding:6px 9px; border:1px solid var(--rule); border-radius:3px; background:var(--card);
}
.toc a:hover{border-color:var(--accent); background:var(--hl)}
/* ---------- media ----------
   build-work.mjs measures every picture and sorts it by shape, and each
   shape gets the size it reads at: a phone recording at roughly the size of
   a phone, a long landing page in a window you scroll, a wide screen at the
   full width of the column. One auto-fill grid used to draw them all at
   230px. */
.gal, .inline{display:flex; flex-direction:column; gap:22px}
.inline{margin:6px 0 18px}
.row{display:flex; gap:22px; align-items:flex-start}
.fig{margin:0; min-width:0}
.m{position:relative}
.m img, .m video{width:100%; height:auto; border-radius:4px}
.m video{background:#111}                       /* letterbox; a transparent PNG keeps the page behind it */
.fig figcaption{font-size:13px; color:var(--quiet); margin-top:8px}
.hint{font-family:"Silkscreen","Courier New",monospace; font-size:10px; letter-spacing:.06em; margin-left:6px; color:var(--ink); opacity:.6}
img[data-zoom]{cursor:zoom-in}

/* wide: the lead picture at full width, the rest in pairs */
.row.wide .fig, .row.pair .fig{flex:1 1 0}
.row.wide .m img, .row.wide .m video, .row.pair .m img, .row.pair .m video{
  border:1px solid var(--rule); box-shadow:0 10px 28px -18px rgba(0,0,0,.45);
}
.row.pair{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:22px}
/* A screen in a plain browser window */
.m.web{border:1px solid var(--rule); border-radius:4px; overflow:hidden; background:#fff; box-shadow:0 10px 28px -18px rgba(0,0,0,.45)}
.m.web .chrome{display:grid; grid-template-columns:1fr minmax(0,34%) 1fr; align-items:center; height:24px; padding:0 10px;
               background:#ececef; border-bottom:1px solid #dcdce0}
.m.web .chrome span{display:flex; gap:5px}
.m.web .chrome i{width:8px; height:8px; border-radius:50%; background:#c9c9cf}
.m.web .chrome b{height:12px; border-radius:6px; background:#fff}
.row .m.web img, .row .m.web video{display:block; border:0; border-radius:0; box-shadow:none}
@media (max-width:560px){ .m.web .chrome{height:18px; padding:0 7px} .m.web .chrome i{width:6px; height:6px} .m.web .chrome b{height:9px} }
/* A flow: one window, its screens side by side in a strip that snaps */
.fl-track{display:flex; overflow-x:auto; scroll-snap-type:x mandatory; overscroll-behavior-x:contain; scrollbar-width:none; outline-offset:-3px}
.fl-track::-webkit-scrollbar{display:none}
.fl-slide{flex:0 0 100%; scroll-snap-align:start}
.row .fl-slide img{display:block; width:100%; height:auto; border:0; border-radius:0; box-shadow:none; cursor:pointer}
.fl-nav{position:absolute; top:calc(50% + 12px); transform:translateY(-50%); width:40px; height:40px; border:0; border-radius:50%;
        background:rgba(23,22,27,.75); color:#fff; font-size:24px; line-height:1; cursor:pointer; transition:opacity .2s}
.fl-nav.prev{left:10px} .fl-nav.next{right:10px}
.fl-nav:disabled{opacity:0; pointer-events:none}
.fl-steps{list-style:none; display:flex; flex-wrap:wrap; gap:6px; margin:12px 0 0; padding:0}
.fl-steps button{display:flex; align-items:center; gap:7px; font:inherit; font-size:12px; padding:4px 10px 4px 4px; border-radius:4px;
                 border:1px solid var(--rule); background:transparent; color:var(--quiet); cursor:pointer}
.fl-steps button span{display:grid; place-items:center; width:18px; height:18px; border-radius:3px; background:var(--rule); color:var(--ink); font-size:10px; font-weight:700}
.fl-steps button:hover{color:var(--ink)}
.fl-steps button[aria-current]{color:var(--ink); border-color:var(--accent)}
.fl-steps button[aria-current] span{background:var(--accent); color:#17161b}
@media (max-width:560px){
  .fl-steps{flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none; padding-bottom:4px}
  .fl-steps button{white-space:nowrap}
  .fl-nav{width:32px; height:32px; font-size:19px}
}

/* phone: a handset, side by side, scrolling sideways when they do not fit.
   The auto margins centre the row without clipping its left edge once it
   overflows, which justify-content:center does. */
.row.phone{overflow-x:auto; scroll-snap-type:x mandatory; padding:6px 4px 14px; margin:0 -4px;
           scrollbar-width:thin; -webkit-overflow-scrolling:touch}
.row.phone > :first-child{margin-left:auto}
.row.phone > :last-child{margin-right:auto}
.row.phone .fig{flex:0 0 max(176px, min(var(--pmax,250px), calc((100% - (var(--n) - 1) * 22px) / var(--n))));
                scroll-snap-align:center}
.hand{
  display:block; background:#000; overflow:hidden;
  border:8px solid #0d0d10; border-radius:34px;
  box-shadow:0 0 0 1px #45434d, 0 0 0 3px #1a1a1e, 0 26px 50px -22px rgba(0,0,0,.65);
}
.hand img, .hand video{width:100%; height:100%; object-fit:cover; border-radius:26px; display:block}
.fig.phone figcaption{text-align:center}

/* long: a page too tall to draw whole, in a window that scrolls */
.row.long{flex-wrap:wrap; justify-content:center}
.row.long .fig{flex:1 1 300px; max-width:100%}
.row.long .fig:has(.narrow){flex:0 1 320px}
.win{
  max-height:620px; overflow:auto; overscroll-behavior:contain;
  border:1px solid var(--rule); border-radius:4px; background:var(--card);
  box-shadow:inset 0 -24px 18px -18px rgba(0,0,0,.25), 0 10px 28px -18px rgba(0,0,0,.45);
  scrollbar-width:thin;
}
.win img{border-radius:0}
.win:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

/* portrait: photos, printed cards, a poster */
.row.portrait{flex-wrap:wrap; justify-content:center}
.row.portrait .fig{flex:0 1 auto}
.row.portrait .m img, .row.portrait .m video{max-height:520px; width:auto; max-width:100%;
  border:1px solid var(--rule); box-shadow:0 10px 28px -18px rgba(0,0,0,.45)}

/* A recording plays while it is on screen; paused, it shows a play mark. */
.m.v{cursor:pointer}
.m.v::after{
  content:"\25B6"; position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:54px; height:54px; border-radius:50%; display:grid; place-items:center; padding-left:4px;
  background:rgba(20,20,22,.72); color:#f7f4ea; font-size:20px; pointer-events:none;
  box-shadow:0 0 0 2px rgba(247,244,234,.5); transition:opacity .2s;
}
.m.v.playing::after{opacity:0}

/* ---------- the stage ----------
   The first thing under the title on every case: the work itself, large,
   on the room's dark shell, with the room's grid of dots behind it and a
   little of its gold in the light. It runs to the sheet's edges so it reads
   as a stage rather than as one more box on the paper. */
.stage{
  margin:22px -52px 26px; padding:34px 52px 26px;
  background:
    radial-gradient(60% 75% at 50% 42%, rgba(229,190,69,.16), transparent 72%),
    radial-gradient(rgba(247,244,234,.07) 1px, transparent 1.4px) 0 0 / 14px 14px,
    #151517;
  border-top:1px solid #000; border-bottom:1px solid #000;
  --rule:#34333a; --card:#1d1d20; --quiet:#a29fa8; --ink:#f1ede2;
}
.stage .row.phone{--pmax:270px}
.stage .row.wide .m img, .stage .row.wide .m video, .stage .row.pair .m img{border-color:#2f2e35; box-shadow:0 30px 60px -28px rgba(0,0,0,.9)}
.stage .row.portrait .m img, .stage .row.portrait .m video{max-height:500px; border-color:#2f2e35}
.stage img[src$=".png"]{border:0 !important; box-shadow:none !important}
.stagecap{
  font-family:"Silkscreen","Courier New",monospace; font-size:11px; letter-spacing:.12em;
  color:var(--accent); margin:0 0 18px; text-align:center;
}
.stage figcaption{color:#a29fa8}

/* ---------- full size ---------- */
.lb{
  border:0; padding:0; margin:auto; background:transparent; max-width:96vw; max-height:94vh;
  overflow:visible;
}
.lb::backdrop{background:rgba(12,12,14,.9)}
.lb .lbin{max-width:96vw; max-height:88vh; overflow:auto; border-radius:4px}
.lb img{display:block; max-width:96vw; max-height:88vh; width:auto; height:auto; margin:0 auto}
.lb.tallimg .lbin{width:min(760px,96vw)}
.lb.tallimg img{max-height:none; width:100%}
.lb button{position:absolute; top:-44px; right:0}
@media (max-width: 720px){ .lb button{top:auto; bottom:-48px} }
.write h3{
  font-family:"Silkscreen","Courier New",monospace; font-size:13px; letter-spacing:.06em;
  margin:26px 0 6px; scroll-margin-top:70px;
}
.write p, .write li{max-width:68ch; color:var(--body)}
.write p{margin:0 0 10px}
.galw{margin:0 0 18px}
.galw p:last-child{margin-bottom:0}
.galw.more{margin:24px 0 0}
.galw h3:first-child{margin-top:0}
.pn{display:flex; justify-content:space-between; flex-wrap:wrap; gap:10px; margin:40px 0 0; padding-top:14px; border-top:1px solid var(--rule); font-size:14px}

/* ---------- phones ---------- */
@media (max-width: 720px){
  .sheet{padding:26px 18px 30px}
  .name{font-size:26px}
  .lede{font-size:16px}
  .results{grid-template-columns:repeat(2,minmax(0,1fr))}
  .rn{font-size:20px}
  .cards{grid-template-columns:1fr}
  .roles li{grid-template-columns:1fr auto}
  .roles .rr{grid-column:1 / -1; grid-row:2}
  .brief{grid-template-columns:1fr}
  .brief dt{padding-top:0}
  .stage{margin:18px -18px 22px; padding:24px 18px 18px}
  .row.pair{grid-template-columns:1fr}
  .row.phone .fig{flex-basis:min(62vw, 250px)}
  .win{max-height:520px}
  .card.feature{display:flex}
  .card.feature .cover{aspect-ratio:16 / 10; height:auto; min-height:0; border-right:0; border-bottom:1px solid #000}
  .card.feature .cover .hand{height:118%}
}
/* The bar is two rows on a phone if it carries everything, and sticky that
   is a fifth of the screen gone. It keeps the two ways out (résumé, the
   room), scrolls away, and the email is still in the masthead. */
@media (max-width: 560px){
  .bar{position:static}
  .bar .opt{display:none}
  .bar{gap:6px}
  .bar .k{padding:7px 9px; font-size:10px}
  .results{gap:8px}
  .results a, .results li:not(:has(a)){padding:10px 11px}
  .rn{font-size:18px}
  .rl{font-size:13px}
  .rc{font-size:12.5px}
  .rs{font-size:12px}
}
@media (max-width: 330px){ .results{grid-template-columns:1fr} }
