/* Same grey ground as the home page (portfolio-3), with the same grain. Layout: a floor. Works drift on an endless plane, the name stays put in the middle. */
@font-face{font-family:"Redaction";src:url("fonts/redaction-latin-400-normal.woff2") format("woff2");font-weight:400;font-style:normal;font-display:block}
@font-face{font-family:"Redaction";src:url("fonts/redaction-latin-400-italic.woff2") format("woff2");font-weight:400;font-style:italic;font-display:block}
@font-face{font-family:"Redaction";src:url("fonts/redaction-latin-700-normal.woff2") format("woff2");font-weight:700;font-style:normal;font-display:block}
@font-face{font-family:"Redaction 35";src:url("fonts/redaction-35-latin-400-normal.woff2") format("woff2");font-weight:400;font-style:normal;font-display:block}
@font-face{font-family:"Redaction 35";src:url("fonts/redaction-35-latin-400-italic.woff2") format("woff2");font-weight:400;font-style:italic;font-display:block}

:root{
  /* dark is the default; the light values follow below */
  --bg:#2c2c2b; --ink:#ececea; --body:#dcdcda; --muted:#8a8a88; --line:#3b3b3a; --pill:rgba(56,56,55,.92);
  --ball-ink:#1b1b1b; --ball-hi:#ffffff; --ball-light:#dcdcdc; --ball-mid:#b4b4b4; --ball-dark:#7e7e7e; --ball-seam:#5c5c5c; --ball-shadow:#232322;
  --serif:"Redaction","Times New Roman",Times,serif;
  --pixel:"Redaction 35","Redaction","Times New Roman",serif;
  --gutter:clamp(16px,3vw,24px);
  --accent:#B5F918;       /* the green of the h */
  --accent-blend:#B5F918; /* same green for things drawn with mix-blend-mode:difference */
  color-scheme:dark;
}
:root[data-theme="light"]{
  --bg:#9d9d9b; --ink:#161616; --body:#1e1e1e; --muted:#4e4e4c; --line:#b2b2b0; --pill:rgba(182,182,180,.92);
  --ball-ink:#4d4d4d; --ball-hi:#ffffff; --ball-light:#e8e8e8; --ball-mid:#d2d2d2; --ball-dark:#ababab; --ball-seam:#8e8e8e; --ball-shadow:#8b8b89;
  --accent-blend:#4a06e7; /* difference against white turns this into the green */
  color-scheme:light;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
html{background:var(--bg)}
body{background:var(--bg);color:var(--body);font:400 15px/1.5 var(--serif);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
:focus-visible{outline:1px solid var(--ink);outline-offset:4px}
img,video,canvas{display:block}

/* ---------- header ---------- */
.header{position:fixed;inset:0 0 auto 0;z-index:50;display:flex;align-items:center;gap:28px;padding:calc(22px + env(safe-area-inset-top,0px)) var(--gutter) 22px;
  font-style:italic;font-size:13px;line-height:1;color:#fff;mix-blend-mode:difference;pointer-events:none}
.header a,.header button{pointer-events:auto;position:relative;padding:6px 0;opacity:.56;transition:opacity .25s}
.header a:hover,.header button:hover,.header .is-current{opacity:1}
.header a::after{content:"";position:absolute;left:0;right:0;bottom:2px;height:1px;background:currentColor;transform:scaleX(0);transform-origin:left;transition:transform .35s cubic-bezier(.2,.7,.2,1)}
.header a:hover::after,.header .is-current::after{transform:scaleX(1)}
.header a:hover::after{background:var(--accent-blend);height:2px;bottom:1px}
.header .spacer{flex:1}
.header .score{opacity:.56;font-variant-numeric:tabular-nums}
.header .score[hidden]{display:none}
.header .ico{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0}
.header .ico::after{display:none}
.header .ico svg{width:11px;height:auto;fill:currentColor}
.header .theme svg{width:10px}
@media (max-width:420px){.header{gap:16px}}

/* ---------- home: endless plane ---------- */
.is-home{overflow:hidden;overscroll-behavior:none;touch-action:none;user-select:none;-webkit-user-select:none}
.plane{position:fixed;inset:0;cursor:grab}
.plane.is-dragging{cursor:grabbing}
.item{position:absolute;left:0;top:0;will-change:transform}
.item a{display:block;width:100%;height:100%;-webkit-user-drag:none}
.item .media{position:relative;width:100%;height:100%;overflow:hidden;background:var(--line);
  filter:grayscale(1) brightness(.95) contrast(1.2) sepia(.1);transition:filter .5s}
.item .media>*{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;pointer-events:none}
.item:hover .media,.item a:focus-visible .media{filter:none}
.item .cap{position:absolute;left:0;top:100%;padding-top:8px;white-space:nowrap;font:italic 13px/1.2 var(--pixel);color:var(--ink);
  opacity:0;transform:translateY(-4px);transition:opacity .25s,transform .25s;pointer-events:none}
.item .cap span{color:var(--muted);margin-left:8px}
.item:hover .cap,.item a:focus-visible+.cap{opacity:1;transform:none}
.plane.is-dragging .item .cap{opacity:0}

.identity{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);z-index:20;text-align:center;pointer-events:none;
  color:#fff;mix-blend-mode:difference;display:flex;flex-direction:column;gap:10px;width:max-content;max-width:calc(100vw - 32px)}
.identity{gap:18px;align-items:center;width:min(27em,calc(100vw - 48px));max-width:none}
.identity h1,.identity .h1{margin:0;line-height:0}
.identity .mark{display:block;height:clamp(44px,4.6vw,60px);width:auto}
.identity .mark .h{fill:none}
.identity .mark .r{fill:currentColor}
.identity p{margin:0;font-style:italic;font-size:15px;line-height:1.45;opacity:.8;text-wrap:balance}
/* second copy, not blended: only the green h shows */
.identity.is-colour{mix-blend-mode:normal;z-index:21}
.identity.is-colour .mark .h{fill:#B5F918}
.identity.is-colour .mark .r{fill:none}
.identity.is-colour p{visibility:hidden}

.views{position:fixed;left:50%;bottom:calc(22px + env(safe-area-inset-bottom,0px));transform:translateX(-50%);z-index:40;display:flex;gap:0;
  font-size:13px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink)}
.views button{display:flex;align-items:center;gap:10px;padding:11px 20px;opacity:.6;transition:opacity .2s,background .2s}
.views button svg{width:9px;height:9px;fill:currentColor}
.views button[aria-pressed="true"]{background:var(--pill);opacity:1;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.views button:hover{opacity:1}

/* ---------- information ---------- */
.info{display:grid;grid-template-columns:minmax(120px,1fr) minmax(0,1.25fr) minmax(0,1.25fr);column-gap:clamp(24px,5vw,72px);row-gap:64px;
  padding:128px clamp(20px,8.5vw,120px) 140px;max-width:1280px;margin-inline:auto}
.info>*{min-width:0}
.label{margin:0 0 28px;font:italic 400 15px/1.5 var(--serif);color:var(--muted)}
.portrait{margin:0;width:min(100%,168px)}
.portrait img{width:100%;height:auto;aspect-ratio:3/4;object-fit:cover;background:var(--line);filter:grayscale(1) contrast(1.08)}
.portrait img{cursor:pointer;transition:opacity .35s}
.portrait.in-goal img{opacity:.12}
.portrait figcaption{margin-top:10px;font:italic 12px/1.3 var(--pixel);color:var(--muted)}
.lede{grid-column:2/4;display:grid;grid-template-columns:1fr 1fr;column-gap:clamp(24px,5vw,72px);align-items:start}
.lede .label,.lede .links{grid-column:1/-1}
.lede p{margin:0;text-transform:uppercase;font-size:clamp(16px,1.55vw,19px);line-height:1.5;color:var(--body);max-width:22em}
.lede a{font-style:italic;color:var(--muted)}
.lede a:hover{color:var(--ink)}
.links{display:flex;flex-wrap:wrap;gap:8px 24px;margin-top:44px;font-style:italic;font-size:clamp(16px,1.55vw,19px)}
.links a{color:var(--ink)}
.index{display:flex;flex-wrap:wrap;gap:0 26px;font-style:italic;font-size:clamp(16px,1.55vw,19px);line-height:1.6;color:var(--ink)}

.tally{list-style:none;margin:0;padding:0;font-size:clamp(16px,1.55vw,19px);line-height:1.6}
.tally li{display:grid;grid-template-columns:3.2em 1fr;font-style:italic;color:var(--ink)}
.tally b{font:400 13px/2.2 var(--pixel);color:var(--muted);font-variant-numeric:tabular-nums;letter-spacing:.04em}
.tally .live b{color:var(--ink)}
.side{display:flex;flex-direction:column;justify-content:flex-end;font-style:italic;font-size:15px;color:var(--muted);gap:6px}
.col-2{grid-column:2}.col-3{grid-column:3}
@media (max-width:820px){
  .info{grid-template-columns:1fr;row-gap:56px;padding-top:104px}
  .col-2,.col-3{grid-column:1}
  .lede{grid-column:1;grid-template-columns:1fr;row-gap:22px}
}

/* ---------- pitch (ball + goal overlay) ---------- */
.pitch{position:fixed;inset:0;width:100%;height:100%;z-index:30;pointer-events:none;image-rendering:pixelated}
.call{position:fixed;left:50%;bottom:calc(26px + env(safe-area-inset-bottom,0px));z-index:45;transform:translate(-50%,12px);opacity:0;pointer-events:none;
  display:flex;align-items:baseline;gap:14px;padding:11px 20px;background:var(--pill);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  color:var(--ink);white-space:nowrap;transition:opacity .35s,transform .45s cubic-bezier(.2,.8,.2,1)}
.call.is-on{opacity:1;transform:translate(-50%,0)}
.call b{font:400 13px/1 var(--serif);letter-spacing:.09em;text-transform:uppercase}
.call i{font:italic 13px/1 var(--pixel);color:var(--muted)}
.hint{position:fixed;left:var(--gutter);bottom:calc(24px + env(safe-area-inset-bottom,0px));z-index:35;margin:0;font:italic 12px/1.3 var(--pixel);color:var(--muted);
  pointer-events:none;transition:opacity .6s;
  padding:7px 11px;margin-left:-11px;background:var(--pill);max-width:calc(100vw - 2*var(--gutter))}
.hint.is-gone{opacity:0}

/* ---------- project ---------- */
.project{padding:128px clamp(20px,8.5vw,120px) 0;max-width:1280px;margin-inline:auto}
.project h1{margin:0 0 56px;font:400 clamp(34px,6vw,72px)/1.02 var(--serif);letter-spacing:-.015em;color:var(--ink);text-wrap:balance}
.meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:24px 32px;margin:0 0 56px}
.meta div{min-width:0}
.meta dt{font:400 11px/1 var(--serif);letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:10px}
.meta dd{margin:0;font-style:italic;font-size:17px;color:var(--ink);overflow-wrap:anywhere}

.stage{position:relative;width:100%;aspect-ratio:16/10;background:var(--line);overflow:hidden}
.stage>*{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.say{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.6fr);gap:32px;padding-block:72px}
.say .label{margin:0}
.say p{margin:0 0 28px;text-transform:uppercase;font-size:clamp(18px,2.1vw,26px);line-height:1.4;color:var(--ink);max-width:24em;text-wrap:pretty}
.say .go{font-style:italic;font-size:19px}
.next{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:32px;border-top:1px solid var(--line);padding-block:40px 72px;color:var(--ink)}
.next small{display:block;font:italic 13px/1 var(--pixel);color:var(--muted);margin-bottom:14px}
.next strong{font:400 clamp(28px,4.4vw,52px)/1.05 var(--serif);letter-spacing:-.01em}
.next .thumb{position:relative;width:clamp(120px,20vw,240px);aspect-ratio:4/3;overflow:hidden;background:var(--line);filter:grayscale(1) contrast(1.15);transition:filter .5s}
.next:hover .thumb{filter:none}
.next .thumb>*{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
@media (max-width:640px){.say{grid-template-columns:1fr;gap:16px;padding-block:48px}.project h1{margin-bottom:40px}}

@media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}}

/* ---------- project: close ---------- */
.close{position:fixed;top:calc(16px + env(safe-area-inset-top,0px));left:50%;transform:translateX(-50%);z-index:55;display:flex;align-items:center;gap:10px;padding:11px 18px;
  font-size:13px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink);background:var(--pill);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);transition:background .2s,color .2s}
.close svg{width:9px;height:9px;fill:currentColor}
.close:hover,.close:focus-visible{background:var(--accent);color:#0c0c0c}
@media (max-width:560px){.close{top:calc(58px + env(safe-area-inset-top,0px))}} /* narrow screens: below the header, where there is room */

/* ---------- contact panel ---------- */
.contact{position:fixed;inset:0;z-index:60}
.contact[hidden]{display:none}
.contact-back{position:absolute;inset:0;background:var(--bg);opacity:0;transition:opacity .25s}
.contact.is-on .contact-back{opacity:.72}
.contact-panel{position:absolute;top:calc(58px + env(safe-area-inset-top,0px));right:var(--gutter);width:min(380px,calc(100vw - 2*var(--gutter)));max-height:calc(100dvh - 80px);overflow:auto;
  background:var(--bg);border:1px solid var(--line);padding:22px 24px 20px;color:var(--ink);
  opacity:0;transform:translateY(-8px);transition:opacity .25s,transform .3s cubic-bezier(.2,.8,.2,1)}
.contact.is-on .contact-panel{opacity:1;transform:none}
.contact-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:22px}
.contact-head h2{margin:0;font:400 22px/1.1 var(--serif);letter-spacing:-.005em}
.contact-close{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;margin:-8px -10px -8px 0;color:var(--muted);transition:color .2s}
.contact-close:hover{color:var(--ink)}
.contact-close svg{width:9px;height:9px;fill:currentColor}
.contact label{display:block;margin-bottom:18px;font:italic 13px/1.2 var(--pixel);color:var(--muted)}
.contact input,.contact textarea{display:block;width:100%;margin-top:4px;padding:5px 0 8px;border:0;border-bottom:1px solid var(--line);border-radius:0;background:none;
  color:var(--ink);font:400 17px/1.4 var(--serif);outline:none;resize:none;transition:border-color .2s;-webkit-appearance:none;appearance:none}
.contact textarea{min-height:7.2em}
.contact input:focus,.contact textarea:focus{border-bottom-color:var(--accent)}
.contact .is-bad{border-bottom-color:#e5484d}
.contact-hp{position:absolute!important;left:-9999px;width:1px!important;height:1px;opacity:0}
.contact-foot{display:flex;align-items:baseline;gap:18px;margin-top:4px;min-height:2.6em}
.contact-send{flex:none;padding:0 0 4px;font-size:13px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink);
  background:linear-gradient(var(--accent),var(--accent)) no-repeat 0 100%/100% 2px;transition:background-size .3s cubic-bezier(.2,.7,.2,1),color .2s}
.contact-send:hover,.contact-send:focus-visible{background-size:100% 100%;color:#0c0c0c}
.contact-send:disabled{opacity:.5;pointer-events:none}
.contact-status{margin:0;font:italic 13px/1.35 var(--pixel);color:var(--muted)}
.contact-status.is-bad{color:var(--ink)}
.contact-done{margin:0 0 18px;font-style:italic;font-size:17px;line-height:1.45}
.contact-alt{margin:18px 0 0;padding-top:14px;border-top:1px solid var(--line);font:italic 13px/1.3 var(--pixel);color:var(--muted)}
.contact-alt a{color:var(--ink);padding-bottom:2px;background:linear-gradient(var(--accent),var(--accent)) no-repeat 0 100%/0 2px;transition:background-size .4s cubic-bezier(.2,.7,.2,1)}
.contact-alt a:hover{background-size:100% 2px}
@media (max-width:520px){.contact-panel{left:var(--gutter);right:var(--gutter);width:auto}}

/* ---------- text links: a green line draws in underneath on hover ----------
   .u = links that carry a thin line at rest, .index a = the bare list of works. */
.lede a,.links a,.meta dd a,.say .go,.index a{
  padding-bottom:3px;transition:background-size .4s cubic-bezier(.2,.7,.2,1),color .2s;
  background:linear-gradient(var(--accent),var(--accent)) no-repeat 0 100%/0 2px,linear-gradient(currentColor,currentColor) no-repeat 0 100%/100% 1px}
.index a{background:linear-gradient(var(--accent),var(--accent)) no-repeat 0 100%/0 2px}
.lede a:hover,.links a:hover,.meta dd a:hover,.say .go:hover,.lede a:focus-visible,.links a:focus-visible,.meta dd a:focus-visible,.say .go:focus-visible{background-size:100% 2px,100% 1px}
.index a:hover,.index a:focus-visible{background-size:100% 2px}

/* ---------- cursor: the h from the logo ----------
   Two states, each as 1x and 2x pixel art in cursor/:
   hover.png = white letter (everywhere), h.png = the green letter (links, buttons, works, while dragging).
   The hot spot is the top of the stem. Only for mouse pointers. */
@media (hover:hover) and (pointer:fine){
  html,.plane{cursor:url("cursor/hover.png") 7 2,auto;cursor:image-set(url("cursor/hover.png") 1x,url("cursor/hover-2x.png") 2x) 7 2,auto}
  a,button,.plane.is-dragging,.plane.is-dragging a{cursor:url("cursor/h.png") 7 2,pointer;cursor:image-set(url("cursor/h.png") 1x,url("cursor/h-2x.png") 2x) 7 2,pointer}
}
/* about page: a crosshair once the pointer is close enough to the ball to load a shot (set by ball.js) */
@media (hover:hover) and (pointer:fine){
  html.near-ball,html.near-ball *{cursor:url("cursor/aim.png") 13 13,crosshair;cursor:image-set(url("cursor/aim.png") 1x,url("cursor/aim-2x.png") 2x) 13 13,crosshair}
}

/* phones: the line under the mark sets in three lines */
@media (max-width:640px){.identity p{max-width:17.5em;margin-inline:auto}}

/* light mode on the grey ground: the inverting blend turns text mid-grey there, so set it in solid ink instead */
:root[data-theme="light"] .header{mix-blend-mode:normal;color:var(--ink)}
:root[data-theme="light"] .header a,:root[data-theme="light"] .header button,:root[data-theme="light"] .header .score{opacity:.72}
:root[data-theme="light"] .header a:hover,:root[data-theme="light"] .header button:hover,:root[data-theme="light"] .header .is-current{opacity:1}
:root[data-theme="light"] .header a:hover::after{background:currentColor}

/* top centre: the logo, the project counter right below it */
.top{position:fixed;left:50%;top:calc(16px + env(safe-area-inset-top,0px));transform:translateX(-50%);z-index:55;display:flex;flex-direction:column;align-items:center;gap:9px}
.top-mark{display:block;line-height:0;color:var(--ink)}
.top-mark .mark{height:clamp(36px,3.6vw,50px);width:auto}
.top-mark .mark .h{fill:var(--accent)}
.top-mark .mark .r{fill:currentColor}

/* ---------- football: controls, leaderboard, initials ---------- */
.game{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:22px;font-style:italic;font-size:15px}
.game button{color:var(--ink);border-bottom:1px solid currentColor;padding:2px 0;opacity:.8;transition:opacity .2s}
.game button:hover,.game button[aria-pressed="true"]#g-sound{opacity:1}
.game button.is-on{color:var(--accent-blend);border-color:currentColor;opacity:1}
:root[data-theme="dark"] .game button.is-on{color:var(--accent)}
.board{margin-top:48px}
.board .label span{margin-left:10px;font-size:12px}
.board-list{list-style:none;margin:0;padding:0;counter-reset:b;font-size:clamp(15px,1.4vw,17px);line-height:1.7}
.board-list li{display:grid;grid-template-columns:2.2em 3.4em 4.6em 1fr;align-items:baseline;font-style:italic;color:var(--ink);counter-increment:b}
.board-list li::before{content:counter(b,decimal-leading-zero);font:400 12px/1 var(--pixel);color:var(--muted)}
.board-list li b{font:400 13px/1 var(--pixel);letter-spacing:.12em;font-style:normal}
.board-list li span{white-space:nowrap}
.board-list li span i{font-size:.72em;opacity:.6;margin-left:.15em}
.board-list li em{font-size:.72em;opacity:.6;white-space:nowrap}
.board-list li.is-you{color:var(--accent-blend)}
:root[data-theme="dark"] .board-list li.is-you{color:var(--accent)}
.board-list .empty{display:block;color:var(--muted)}
.board-list .empty::before{content:none}
.entry{position:fixed;left:50%;bottom:calc(76px + env(safe-area-inset-bottom,0px));z-index:58;transform:translate(-50%,12px);opacity:0;visibility:hidden;
  display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;padding:14px 16px;background:var(--pill);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  color:var(--ink);max-width:calc(100vw - 32px);transition:opacity .3s,transform .4s cubic-bezier(.2,.8,.2,1),visibility .3s}
.entry.is-on{opacity:1;visibility:visible;transform:translate(-50%,0)}
.entry p{margin:0;font:italic 14px/1.3 var(--serif)}
.entry input{width:4.4em;padding:6px 8px;background:transparent;border:1px solid var(--muted);color:var(--ink);font:400 15px/1 var(--pixel);letter-spacing:.3em;text-transform:uppercase;text-align:center}
.entry input:focus{outline:none;border-color:var(--ink)}
.entry button{font:italic 14px/1 var(--serif);border-bottom:1px solid currentColor;padding:2px 0}
.entry .skip{color:var(--muted)}

/* ---------- header switches: pages, and light / dark ----------
   Both sit top left as small pills. They ignore the inverting blend of the header so their fills stay true. */
.header .hswitch,.header .tswitch{mix-blend-mode:normal}
.header:has(.hswitch){mix-blend-mode:normal;color:var(--ink);gap:10px}
.hswitch{pointer-events:auto;position:relative;display:flex;padding:3px;border-radius:999px;background:var(--pill);
  box-shadow:inset 0 0 0 1px var(--line);
  font:500 12.5px/1 "Inter Tight","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;letter-spacing:-.005em}
.header .hswitch a{opacity:1;padding:8px 13px;border-radius:999px;color:var(--muted);transition:color .2s,background .25s}
.header .hswitch a::after{display:none}
.header .hswitch a:hover{color:var(--ink)}
.header .hswitch a.is-current{background:var(--ink);color:var(--bg)}
.hswitch sup{font-size:.68em;font-weight:700;margin-left:3px;vertical-align:.55em;line-height:0;font-variant-numeric:tabular-nums}
.tswitch{pointer-events:auto;position:relative;width:62px;height:34px;border-radius:999px;background:var(--pill);padding:0;
  box-shadow:inset 0 0 0 1px var(--line);display:block;flex:none}
.header .tswitch{opacity:1}
.tswitch .ts-ico{position:absolute;top:50%;width:28px;height:28px;margin-top:-14px;display:grid;place-items:center;z-index:2;color:var(--muted);transition:color .3s}
.tswitch .ts-ico svg{width:11px;height:11px;fill:currentColor;display:block}
.tswitch .ts-sun{left:3px}.tswitch .ts-moon{right:3px}
.tswitch .ts-knob{position:absolute;top:3px;left:3px;width:28px;height:28px;border-radius:50%;background:var(--ink);z-index:1;
  box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .45s cubic-bezier(.3,1.5,.5,1),background .3s}
.tswitch[aria-checked="true"] .ts-knob{transform:translateX(28px)}
.tswitch[aria-checked="false"] .ts-sun,.tswitch[aria-checked="true"] .ts-moon{color:var(--bg)}
.tswitch:hover .ts-knob{box-shadow:0 0 0 3px var(--line),0 1px 3px rgba(0,0,0,.25)}
.tswitch:active .ts-knob{width:32px}
.tswitch[aria-checked="true"]:active .ts-knob{transform:translateX(24px)}
.tswitch:focus-visible{outline:1px solid var(--ink);outline-offset:3px}
.header .score{margin-left:8px}
@media (max-width:640px){
  .header{gap:8px}
  .hswitch{font-size:12px}.header .hswitch a{padding:7px 10px}
  .header .tswitch{order:3}            /* phones: the logo sits in the middle, so light / dark moves to the right */
  .header .spacer{order:2}.header #mail{order:4}
  .header .score{display:none}
}
@media (prefers-reduced-motion:reduce){.tswitch .ts-knob{transition:none}}
@media (max-width:640px){
  .hswitch{font-size:11.5px}.header .hswitch a{padding:7px 9px}
  .hswitch sup{display:none}
  .top-mark .mark{height:30px}
}
/* mail: a round pill like the two switches */
.header #mail{width:34px;height:34px;border-radius:999px;background:var(--pill);box-shadow:inset 0 0 0 1px var(--line);opacity:1;
  color:var(--muted);mix-blend-mode:normal;transition:color .2s,background .25s,transform .35s cubic-bezier(.3,1.5,.5,1)}
.header #mail svg{width:12px}
.header #mail:hover{background:var(--ink);color:var(--bg);transform:scale(1.06)}
.header #mail:active{transform:scale(.96)}

/* phones: Projects / About as a floating pill at the bottom; logo and counter stay top centre,
   light / dark and mail stay top right */
@media (max-width:640px){
  .header .hswitch{position:fixed;left:50%;bottom:calc(16px + env(safe-area-inset-bottom,0px));transform:translateX(-50%);z-index:60;
    font-size:13px;padding:4px;box-shadow:inset 0 0 0 1px var(--line),0 8px 24px rgba(0,0,0,.28)}
  .header .hswitch a{padding:10px 18px}
  .hswitch sup{display:inline}
  .tswitch .ts-ico svg{width:12px;height:12px}
  .info{padding-bottom:120px}
  .hint{bottom:calc(80px + env(safe-area-inset-bottom,0px))}
}
.tswitch .ts-ico svg{width:12px;height:12px}

/* full bleed: let the grain run on under the browser bars and the status bar (iOS Safari, home-screen app) */
#grain{inset:auto 0!important;top:calc(-40px - env(safe-area-inset-top,0px))!important;bottom:calc(-40px - env(safe-area-inset-bottom,0px))!important}

/* ---------- page switch: cross-fade instead of a hard reload (Chrome, Safari 18.2+) ----------
   header and logo stay put, the black pill slides from Projects to About */
@view-transition{navigation:auto}
.header{view-transition-name:header}
.hswitch a.is-current{view-transition-name:hs-pill}
.top{view-transition-name:top}
#grain{view-transition-name:grain}
::view-transition-group(*){animation-duration:.5s;animation-timing-function:cubic-bezier(.2,.7,.2,1)}
::view-transition-old(root){animation:vt-out .28s cubic-bezier(.4,0,1,1) both}
::view-transition-new(root){animation:vt-in .5s cubic-bezier(.2,.7,.2,1) .08s both}
@keyframes vt-out{to{opacity:0;transform:scale(.985)}}
@keyframes vt-in{from{opacity:0;transform:scale(1.012)}}
@media (prefers-reduced-motion:reduce){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}}

/* ---------- review fixes (2026-10-17) ---------- */
/* About / project: the logo stays put and inverts over the text that scrolls under it (no band behind it).
   Colours are picked so that, blended by "difference" against the page grey, the logo looks as usual. */
body:not(.is-reel) .top{mix-blend-mode:difference}
body:not(.is-reel) .top-mark{color:#ffffff}                              /* dark: |d3 - 2c| ≈ the usual off-white */
:root[data-theme="light"] body:not(.is-reel) .top-mark{color:#b3b3b1}     /* light: comes out near-black on the grey */
body:not(.is-reel) .top .mark .h{fill:none}                                /* the inverting copy: letters only */
body:not(.is-reel) .top-h{mix-blend-mode:normal;pointer-events:none}
body:not(.is-reel) .top-h .mark .r{fill:none}
body:not(.is-reel) .top-h .mark .h{fill:var(--accent)}                         /* the h: always the brand green */
.info{padding-bottom:calc(120px + env(safe-area-inset-bottom,0px))}   /* text never ends under the floating pill */
.hint{font-size:13px;transition:opacity .4s,visibility .4s}
.hint.is-gone{opacity:0;visibility:hidden}
.meta dt{font-size:12px}
.tally b,.board-list li span,.board-list li em,.score{font-variant-numeric:tabular-nums}
/* hit areas: 40px on desktop, 44px on touch */
.header .hswitch a{min-height:40px;display:inline-flex;align-items:center}
.header #mail{width:40px;height:40px}
@media (pointer:coarse){.header .hswitch a{min-height:44px}.header #mail{width:44px;height:44px}}
/* game stats appear with the first shot */
.game-col .tally-wrap{transition:opacity .5s}
html:not(.has-played) .game-col .tally-wrap{display:none}

/* ---------- contact form: lifted off the page (2026-10-17) ----------
   own surface a step lighter than the page, darker blurred backdrop, filled fields, a real Send button */
:root{--panel:#363635;--field:rgba(255,255,255,.055);--field-hover:rgba(255,255,255,.085)}
:root[data-theme="light"]{--panel:#d0d0ce;--field:rgba(255,255,255,.55);--field-hover:rgba(255,255,255,.75)}
.contact.is-on .contact-back{opacity:.6}
.contact-back{background:#0c0c0c;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.contact-panel{background:var(--panel);border:0;border-radius:20px;padding:24px 22px 20px;
  box-shadow:0 0 0 1px rgba(255,255,255,.06),0 2px 6px rgba(0,0,0,.18),0 24px 60px rgba(0,0,0,.38)}
:root[data-theme="light"] .contact-panel{box-shadow:0 0 0 1px rgba(0,0,0,.06),0 2px 6px rgba(0,0,0,.08),0 24px 60px rgba(0,0,0,.22)}
.contact-close{width:40px;height:40px;border-radius:50%;margin:-10px -10px -10px 0;transition:color .2s,background-color .2s}
.contact-close:hover{background:var(--field)}
.contact label{color:var(--body);font-size:13.5px;margin-bottom:14px}
.contact input,.contact textarea{margin-top:7px;padding:11px 13px;border:0;border-radius:10px;background:var(--field);
  box-shadow:inset 0 0 0 1px transparent;transition:background-color .2s,box-shadow .2s}
.contact input:hover,.contact textarea:hover{background:var(--field-hover)}
.contact input:focus,.contact textarea:focus{background:var(--field-hover);box-shadow:inset 0 0 0 1.5px var(--accent)}
:root[data-theme="light"] .contact input:focus,:root[data-theme="light"] .contact textarea:focus{box-shadow:inset 0 0 0 1.5px var(--ink)}
.contact .is-bad{box-shadow:inset 0 0 0 1.5px #e5484d}
.contact input::placeholder,.contact textarea::placeholder{color:var(--muted)}
.contact-foot{align-items:center;margin-top:8px}
.contact-send{padding:12px 20px;border-radius:999px;background:var(--accent);color:#0c0c0c;font-weight:500;
  transition:transform .15s ease-out,filter .2s}
.contact-send:hover,.contact-send:focus-visible{background:var(--accent);filter:brightness(1.06)}
.contact-send:active{transform:scale(.96)}
.contact-alt{border-top-color:rgba(127,127,127,.25)}
