/* graymade.co v2: styles for everything the site script builds (wall, live pieces, viewer, knife stage, transitions).
   Layout, type, color and spacing of the Webflow-built elements live in Webflow classes (gm-*) so Sam can edit them in the
   Designer. This file only adds what classes can't: motion, hover effects drawn with ::before, states the script sets,
   and the script-built pieces. Never override a Designer property here (2026-10-19). */
:root{--bg:#0f0f0e;--fg:#ecebe7;--muted:#8b8a85;--faint:#5c5b57;--line:#262624;--accent:#ffe47a;--ink:#121212;
 --sans:"Geist",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;--mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,monospace;--gap:20px;--ease:cubic-bezier(.2,.75,.15,1)}
html{background:var(--bg);color-scheme:dark}
body{background:transparent;margin:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
[hidden]{display:none!important}
html.k-lock{overflow:hidden}
.lb,.kstage{font-family:var(--sans)}
/* the page's fonts come from Webflow (Body is Geist, tags inherit it), so the Designer shows what ships; only the script-built layers set theirs here */
:where(.lb,.kstage) :is(p,h1,h2,h3,h4,h5,h6,a,span,div,figcaption,li,blockquote){font-family:var(--sans);letter-spacing:inherit}
.gm-page :focus-visible,.lb :focus-visible,.kstage :focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.gm-side{scrollbar-width:none}.gm-side::-webkit-scrollbar{display:none}
.gm-logo{transition:opacity .3s}.gm-logo:hover{opacity:.75}
.gm-portrait{transition:width .6s var(--ease),height .6s var(--ease),border-radius .6s}
/* the aurora sits behind the page, so the page layers stay clear and html carries the ground */
body.body,.gm-page{background:transparent}
/* refraction leak v3: Sam's prism photographs keyed to alpha, out of the bottom-left corner, behind everything (Sam, 2026-10-17). leak.js builds the DOM. */
.gm-leak{--gm-leak-ground:var(--bg);position:fixed;inset-inline-start:0;inset-block-end:0;inline-size:min(96vmin,1040px);block-size:min(96vmin,1040px);
 pointer-events:none;z-index:-1;overflow:clip;opacity:0;transition:opacity 2.4s cubic-bezier(.22,1,.36,1)}
.gm-leak.gm-leak-on{opacity:.62}
/* hold to pull (2026-10-18): the whole light scales from its corner, and fades out before its box edges so no crop line shows at any size */
.gm-leak{transform-origin:0 100%;will-change:transform,opacity;-webkit-mask-image:radial-gradient(circle farthest-side at 0 100%,#000 72%,transparent 100%);mask-image:radial-gradient(circle farthest-side at 0 100%,#000 72%,transparent 100%)}
html.gm-holding,html.gm-holding *{user-select:none;-webkit-user-select:none;cursor:grabbing}
html.gm-ringmode.gm-holding,html.gm-ringmode.gm-holding *{cursor:none!important}
.gm-pull-hint{position:fixed;inset-inline-start:40px;inset-block-end:84px;margin:0;z-index:2;pointer-events:none;font:400 11px/1 var(--mono);letter-spacing:.04em;color:#8b8a85;opacity:0;animation:gmHintIn 1.6s 3s var(--ease) forwards;transition:opacity .5s var(--ease)}
/* the words ring like struck glass: the line breathes, and two fainter copies rise off it, spread and fade, like an echo */
.gm-pull-hint>span{display:inline-block;position:relative;white-space:nowrap;animation:gmHintBreath 5.2s 4.6s ease-in-out infinite both}
.gm-pull-hint>span::before,.gm-pull-hint>span::after{content:attr(data-t);position:absolute;left:0;top:0;white-space:nowrap;opacity:0;animation:gmHintEcho 5.2s 4.6s cubic-bezier(.2,.7,.3,1) infinite both}
.gm-pull-hint>span::after{animation-delay:5s}
.gm-pull-hint.gm-gone,html.gm-holding .gm-pull-hint{opacity:0!important;animation:none}
@keyframes gmHintIn{to{opacity:1}}
@keyframes gmHintBreath{0%,100%{opacity:.5}38%{opacity:1}70%{opacity:.62}}
@keyframes gmHintEcho{0%,30%{opacity:0;translate:0 0;letter-spacing:.04em}42%{opacity:.34}100%{opacity:0;translate:2px -11px;letter-spacing:.2em}}
.gm-leak-s{position:absolute;inset:0;transform-origin:0 100%}
.gm-leak-s>div{position:absolute;background:no-repeat center/100% 100%;will-change:transform,opacity}
/* the fan's light source sits just past the corner; it turns about that point */
.gm-leak-fan{inset-inline-start:-26%;inset-block-end:-30%;inline-size:135%;aspect-ratio:4/3;transform-origin:0 100%}
.gm-leak-glints{inset-inline-start:2%;inset-block-end:-4%;inline-size:70%;aspect-ratio:900/860}
.gm-leak-bloom{inset-inline-start:-192px;inset-block-end:-192px;inline-size:384px;block-size:384px;scale:3.4;transform-origin:50% 50%}
.gm-leak-grain{position:absolute;inset:0;background-size:256px 256px;opacity:.4;mask-image:radial-gradient(circle at 0 100%,#000 20%,transparent 75%)}
/* falloff toward the far ends, and low along the bottom edge so the footer line reads */
.gm-leak-fade{position:absolute;inset:0;
 background:linear-gradient(to top,color-mix(in oklch,var(--gm-leak-ground) 70%,transparent),transparent 18%),
  radial-gradient(circle at 0 100%,transparent 30%,color-mix(in oklch,var(--gm-leak-ground) 50%,transparent) 62%,var(--gm-leak-ground) 94%)}

@media (hover:hover){html:not([data-view]) :is([data-page=home],[data-page=archive]) .gm-portrait:hover{width:min(100%,200px);height:min(100%,200px);border-radius:4px}}
/* pages without the small portrait: case studies and About (it grows into the About page) */
[data-page=about] .gm-side .gm-portrait,html[data-view=about] .gm-side .gm-portrait{display:none}
/* Get in touch: outlined, the yellow wipes in on hover */
/* email: plain text that dims on hover, like samuelgrayart.com; click copies it */
.gm-mail{color:inherit;text-decoration:none;transition:color .3s}
:is(.gm-bio a,.gm-work,.gm-ask a,.gm-filter a){position:relative;color:inherit;text-decoration:underline;text-decoration-color:oklch(.75 0 none / .45);text-decoration-thickness:1px;text-underline-offset:3px;background:linear-gradient(100deg,var(--fg) 0 36%,oklch(1 .04 95) 46%,oklch(.95 .09 90) 50%,oklch(1 .04 95) 54%,currentColor 64% 100%) 100% 0/280% 100% no-repeat;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;transition:background-position .9s cubic-bezier(.45,0,.2,1),text-decoration-color .3s}
:is(.gm-bio a,.gm-work,.gm-ask a,.gm-filter a)::before{content:"";position:absolute;inset-inline:0;inset-block-end:-1px;block-size:1px;pointer-events:none;background:linear-gradient(90deg,oklch(.9 .03 90 / .35),oklch(.95 .03 92) 22%,oklch(.97 .02 95));box-shadow:0 0 4px oklch(.9 .08 92 / .28);transform:scaleX(0);transform-origin:100% 50%;transition:transform .55s cubic-bezier(.65,0,.25,1)}
/* What I do: no underline at rest, only the hover ray (Sam, 2026-11-01) */
a.gm-work{text-decoration:none}
.gm-mail{cursor:copy}
.gm-mail.gm-copied{color:var(--accent)}
.gm-cta{isolation:isolate;cursor:pointer;transition:color .35s,border-color .35s}
.gm-cta::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--accent);transform:scaleX(0);transform-origin:left;transition:transform .5s var(--ease)}
.gm-cta:hover,.gm-cta:focus-visible{color:var(--ink)!important;border-color:var(--accent)!important}
.gm-cta:hover::before,.gm-cta:focus-visible::before{transform:scaleX(1)}
.gm-cta-arrow{transition:transform .5s var(--ease)}.gm-cta:hover .gm-cta-arrow{transform:translateX(5px)}
.gm-toast{color:var(--accent);font-size:14px}

/* wall: the static piece list (an embed, once the CMS list) is the data source; the script lays the pieces out in columns */
.gm-js .gm-wall .w-dyn-list{display:none}
.w-dyn-bind-empty{display:none!important}
.wall{display:flex;gap:var(--gap);align-items:flex-start}
.col{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:calc(var(--gap) + 14px)}
.gm-cycle{position:relative;display:block;inline-size:100%;overflow:clip;border-radius:3px;background:#1a1a19;cursor:pointer}
.gm-cycle img{position:absolute;inset:0;inline-size:100%;block-size:100%;object-fit:cover;opacity:0;transform:scale(1.02)}
.gm-cycle img.on{opacity:1}
.gm-pop .gm-pop-s{position:absolute;inset:0;opacity:0}
.gm-pop .gm-pop-s.on{opacity:1}
.gm-pop .gm-pop-s img{opacity:1;transform:none}
.gm-pop .gm-pop-s img.gm-pop-logo{inset:auto;left:50%;top:50%;inline-size:auto;object-fit:contain;transform:translate(-50%,-50%);filter:drop-shadow(0 6px 14px rgb(0 0 0 / .35))}
.lb .gm-cycle{inline-size:100%;block-size:100%}
.wall.wall-abs{display:block;position:relative}
.wall-abs>.item{position:absolute}
.wall-abs>.item.gm-fit>.gm-tilemedia{height:100%;object-fit:cover}
/* some exported images carry a 1px light edge; crop a hair inside the frame (Sam, 2026-10-17) */
.wall-abs>.item{overflow:clip;border-radius:3px}
.wall-abs>.item>img.gm-tilemedia,.wall-abs>.item>video.gm-tilemedia{scale:1.012}
.item{position:relative;margin:0;min-width:0}
.media{display:block;width:100%;height:auto;border-radius:3px;background:#1a1a19;cursor:pointer}
.item{opacity:0;transform:translateY(14px);transition:opacity .9s var(--ease),transform .9s var(--ease)}
.item.in{opacity:1;transform:none}
/* hovering a tile shows a small pill with the project name, inside the frame; always on for touch screens */
.gm-pill{position:absolute;left:10px;bottom:10px;z-index:4;max-width:calc(100% - 20px);padding:5px 10px 6px;border-radius:999px;background:rgba(15,15,14,.62);color:#ecebe7;font:500 12px/1.2 var(--sans);letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);opacity:0;transform:translateY(4px);transition:opacity .3s var(--ease),transform .4s var(--ease);pointer-events:none}
.item:hover .gm-pill,.item:focus-within .gm-pill{opacity:1;transform:none}
/* cursor (desktop mouse, 2026-10-18): the cursor is a small dot everywhere, links included. It is the system cursor (an image),
   so it never lags behind the page; over wall tiles the page swaps in its own dot and the ring grows out of it. */
html.gm-ringmode,html.gm-ringmode body{cursor:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 12 12,auto;cursor:-webkit-image-set(url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 1x,url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2248%22%20height%3D%2248%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 2x) 12 12,auto;cursor:image-set(url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 1x,url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2248%22%20height%3D%2248%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 2x) 12 12,auto}
html.gm-ringmode :is(a,button,[role=button],label,summary,select,.expand,.gm-row,.gm-next){cursor:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 12 12,pointer;cursor:-webkit-image-set(url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 1x,url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2248%22%20height%3D%2248%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 2x) 12 12,pointer;cursor:image-set(url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 1x,url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2248%22%20height%3D%2248%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223.2%22%20fill%3D%22%23ecebe7%22%20stroke%3D%22rgba%280%2C0%2C0%2C.45%29%22%20stroke-width%3D%22.8%22/%3E%3C/svg%3E") 2x) 12 12,pointer}
html.gm-ringmode :is(input,textarea,[contenteditable]){cursor:text}
html.gm-ring-on,html.gm-ring-on *{cursor:none!important}
.gm-ring{position:fixed;left:0;top:0;z-index:71;pointer-events:none;border-radius:50%;translate:-200px -200px;will-change:translate,scale;
 width:22px;height:22px;margin:-11px 0 0 -11px;border:1.2px solid #ecebe7;background:#ecebe7;box-shadow:0 0 0 .6px rgba(0,0,0,.4);opacity:0;scale:.29;
 transition:scale .55s cubic-bezier(.45,0,.2,1),background-color .3s .2s,opacity 0s .6s}      /* off: drawn back into a filled dot the size of the cursor (6.4px); ring halved to 22px per Sam 2026-10-19 */
.gm-ring.on{opacity:1;scale:1;background-color:rgba(236,235,231,0);box-shadow:0 0 0 .5px rgba(0,0,0,.25),inset 0 0 0 .5px rgba(0,0,0,.18);
 transition:scale .8s cubic-bezier(.33,0,.14,1),background-color .45s cubic-bezier(.4,0,.2,1),opacity 0s}   /* on: the dot itself opens into the ring */
.gm-ring.back{opacity:1;transition:scale .55s cubic-bezier(.45,0,.2,1),background-color .3s .2s,opacity 0s}
/* touch screens: no name pills on the tiles (Sam, 2026-10-17) */
.knifetile{cursor:pointer}.knifetile img{transition:filter .3s}.knifetile:hover img{filter:brightness(1.1)}
/* compare slider */
.slider{position:relative;width:100%;border-radius:3px;overflow:hidden;background:#1a1a19;--p:50%;touch-action:pan-y;user-select:none}
.slider img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;pointer-events:none;transition:opacity .4s}
.slider.s-fade img{opacity:0}
.slider.s-wait img,.slider.s-wait .s-line{opacity:0}
.slider .s-line{transition:opacity .4s}
.slider.s-edge .s-line{opacity:0}
.slider .s-b{clip-path:inset(0 0 0 var(--p))}
.slider .s-line{position:absolute;top:0;bottom:0;left:var(--p);width:2px;margin-left:-1px;background:rgba(255,255,255,.92);pointer-events:none;box-shadow:0 0 0 1px rgba(0,0,0,.08)}
.slider .s-line i{position:absolute;top:50%;left:50%;width:34px;height:34px;margin:-17px 0 0 -17px;border-radius:50%;background:#fff;box-shadow:0 2px 10px rgba(0,0,0,.35)}
.slider .s-line i::before,.slider .s-line i::after{content:"";position:absolute;top:50%;width:0;height:0;margin-top:-5px;border:5px solid transparent}
.slider .s-line i::before{left:5px;border-right-color:#111}.slider .s-line i::after{right:5px;border-left-color:#111}
.slider input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:ew-resize;-webkit-appearance:none;appearance:none}
.slider input:focus-visible~.s-line i{outline:2px solid var(--accent);outline-offset:3px}
.slider .s-tag{display:none;position:absolute;bottom:10px;font:500 11px var(--mono);letter-spacing:.04em;color:#fff;text-shadow:0 1px 6px rgba(0,0,0,.6);pointer-events:none}
.slider .s-tag.l{left:12px;color:#1b1a18;text-shadow:0 0 6px rgba(255,255,255,.9)}.slider .s-tag.r{right:12px}
.slot{position:relative}
.slot .expand{border:0;padding:0;font:inherit;line-height:1;position:absolute;top:10px;right:10px;width:32px;height:32px;border-radius:50%;display:grid;place-items:center;background:rgba(15,15,14,.55);color:#fff;font-size:15px;cursor:pointer;opacity:0;transition:opacity .3s;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);z-index:3}
.slot:hover .expand,.slot .expand:focus-visible{opacity:1}
@media (hover:none){.slot .expand{opacity:1}}
/* live code tiles */
.cu{position:relative;width:100%;border-radius:3px;overflow:hidden;background:#47134c;display:grid;place-items:center;cursor:pointer}
.cu .rings{position:absolute;top:50%;left:50%;width:108%;aspect-ratio:1;transform:translate(-50%,-50%);pointer-events:none}
.cu .ring{position:absolute;inset:0;opacity:0;transform:scale(0)}
.cu .ring svg{width:100%;height:100%;display:block}
.cu .logo{position:relative;z-index:2;width:28%;height:auto;opacity:0}
.cu.run .ring{animation:cuRing 1s cubic-bezier(.25,1,.5,1) forwards}
.cu.run .ring:nth-child(2){animation-delay:.12s}.cu.run .ring:nth-child(3){animation-delay:.24s}.cu.run .ring:nth-child(4){animation-delay:.36s}
.cu.run .logo{animation:cuLogo .7s cubic-bezier(.25,1,.5,1) .7s forwards}
.cu.out .rings,.cu.out .logo{transition:opacity .6s;opacity:0!important}
@keyframes cuRing{from{opacity:0;transform:scale(0)}to{opacity:1;transform:scale(1)}}
@keyframes cuLogo{from{opacity:0;transform:translateY(8%)}to{opacity:1;transform:none}}
.fm .w,.fm .body{position:absolute;display:block;pointer-events:none;will-change:transform,opacity,filter}
.fm .w{opacity:0;transform:translateY(16%)}
.fm.on .w{transition:opacity 1.1s cubic-bezier(.16,1,.3,1),transform 1.1s cubic-bezier(.16,1,.3,1)}
.fm .body{opacity:0}
.lot{position:relative;width:100%;border-radius:3px;overflow:hidden;background:#243b33;cursor:pointer}
.lot .cells{position:absolute;inset:4%;display:grid;gap:2%}
.lot .cells>div{min-width:0;min-height:0}
.lot svg{display:block}
.lot-cycle .cells>.lot-slide{grid-area:1/1;opacity:0;transition:opacity .6s}
.lot-cycle .cells>.lot-slide.on{opacity:1}
/* Arly: each UI animation in its own softly bevelled cream tile on a lighter ground (Sam, 2026-10-18).
   A tile is the animation's own 491x400 artboard, as it sat on the Arly site, so the cards cropped at its bottom meet the tile edge. */
.lot.lot-tiles{background:#fcfaf4;container-type:inline-size}
.lot-tiles .cells{inset:0;padding:3cqw;gap:2.4cqw;grid-template-rows:auto auto;align-content:center}
.lot-tiles .cells>div{aspect-ratio:491/400;overflow:hidden;border-radius:clamp(8px,1.3cqw,18px);background:#f8f1d8;
 box-shadow:inset 0 1px 0 rgba(255,255,255,.9),inset 0 -1px 0 rgba(122,96,44,.12),inset 0 0 0 1px rgba(122,96,44,.06),0 1px 2px rgba(84,64,28,.07),0 10px 24px -14px rgba(84,64,28,.28)}
.shirtbox{position:relative;width:100%;border-radius:3px;overflow:hidden;background:radial-gradient(60% 50% at 50% 46%,#1d1c1a 0%,#0e0e0d 70%,#0a0a09 100%)}
.shirtbox .stage{position:absolute;inset:0}
/* tee arrows sit at the middle of the left and right edges (Sam, 2026-10-12) */
.shirtbox .ui{position:absolute;inset:0;display:flex;justify-content:space-between;align-items:center;padding-inline:12px;pointer-events:none}
.shirtbox .ui button:active{background:rgba(20,20,19,.9)}
.shirtbox .ui button{pointer-events:auto;width:32px;height:32px;border-radius:50%;border:1px solid rgba(236,235,231,.18);background:rgba(20,20,19,.5);color:var(--fg);font:15px var(--sans);cursor:pointer;display:grid;place-items:center;transition:border-color .25s,background .25s}
.shirtbox .ui button:hover{border-color:var(--accent);background:rgba(20,20,19,.8)}
.shirtbox .hint{position:absolute;top:12px;left:0;right:0;text-align:center;font:500 11px var(--mono);color:var(--faint);pointer-events:none;transition:opacity .6s}
/* Marketage stickers on a laptop lid. Apple logo brighter and a touch larger so it reads (Sam, 2026-10-12) */
.stkdesk{position:relative;width:100%;border-radius:3px;overflow:hidden;background:#6e6f72;user-select:none;-webkit-user-select:none}
.stkdesk .lid{position:absolute;inset:0;border-radius:inherit;touch-action:none;
 background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23f1f2f4'/%3E%3Cstop offset='.44' stop-color='%23a4a5a8'/%3E%3Cstop offset='.53' stop-color='%23494a4d'/%3E%3Cstop offset='1' stop-color='%23d6d7da'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' d='M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701'/%3E%3C/svg%3E") center/10.6% auto no-repeat,radial-gradient(120% 90% at 28% 0%,rgba(255,255,255,.13),transparent 58%),linear-gradient(180deg,#7b7c7f 0%,#717275 55%,#68696c 100%);
 box-shadow:inset 0 0 0 1px rgba(255,255,255,.1),inset 0 1px 0 rgba(255,255,255,.22),inset 0 -1px 0 rgba(0,0,0,.22)}
.stkdesk .lid::before{content:"";position:absolute;inset:0;border-radius:inherit;opacity:.22;mix-blend-mode:overlay;pointer-events:none;
 background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E")}
.stkdesk .lid.grabbing{cursor:grabbing!important}
/* email line at the end of each case study, just before Next (2026-10-25) */
.gm-ask{margin:0;font-size:15px;line-height:1.5;color:var(--muted)}
.gm-ask a{color:var(--fg)}
/* What I do lines on About open the archive filtered to that kind of work (2026-10-25) */
.gm-filter{margin:10px 0 0;font:400 13px/1.4 var(--mono);color:var(--muted)}
.stkdesk .hint{position:absolute;top:14px;left:0;right:0;text-align:center;font:500 12px var(--mono);letter-spacing:.02em;color:rgba(255,255,255,.92);text-shadow:0 1px 2px rgba(0,0,0,.35);pointer-events:none;transition:opacity .6s;z-index:2}
.stk{position:absolute;pointer-events:none;filter:drop-shadow(0 .5px .5px rgba(0,0,0,.55)) drop-shadow(0 1px 2px rgba(0,0,0,.2));transition:filter .3s}
.stk .bd{position:relative;width:100%;height:100%;transition:transform .25s var(--ease)}
.stk .face,.stk .fs,.stk .fm,.stk .back{position:absolute;inset:0}
.stk .face img{display:block;width:100%;height:100%}
.stk .gloss,.stk .back{-webkit-mask:var(--m) center/100% 100% no-repeat;mask:var(--m) center/100% 100% no-repeat}
.stk .gloss{position:absolute;inset:0;opacity:.55;transition:opacity .35s;background:radial-gradient(55% 75% at var(--sx,30%) var(--sy,15%),rgba(255,255,255,.16),transparent 62%),linear-gradient(118deg,transparent 30%,rgba(255,255,255,.06) 45%,transparent 60%)}
.stk.hov .gloss{opacity:1}
.stk.hov{filter:drop-shadow(0 .5px .5px rgba(0,0,0,.55)) drop-shadow(0 3px 6px rgba(0,0,0,.24))}
.stk .fm{transform-origin:0 0}
.stk.held{filter:drop-shadow(0 16px 20px rgba(0,0,0,.42)) drop-shadow(0 4px 6px rgba(0,0,0,.28))}
.stk.held .bd{transform:scale(1.05)}
.stk.pop{transition:filter .3s,left .2s var(--ease),top .2s var(--ease)}
.stk.press .bd{transition-duration:.18s}
.au-host{position:relative;width:100%;border-radius:3px;overflow:hidden;background:#f2f3ff;cursor:pointer}
.lb .au-host{cursor:auto}
.live{position:relative;width:100%;border-radius:3px;overflow:hidden;background:#42071b;cursor:crosshair}
.prism{background:#0e0e0d center/cover no-repeat;cursor:default}
.vsn-host{background:#122125 center/cover no-repeat;cursor:pointer}
.lb .vsn-host{width:100%;height:100%;cursor:default}
.live canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
/* notes between pieces */
.note{border-top:1px solid var(--line);padding-top:12px;font-size:13px;line-height:1.5;color:var(--fg)}
.note b{display:block;font-weight:400;color:var(--muted);margin-bottom:4px}
.note .big{font:400 26px/1.1 var(--mono);letter-spacing:-.03em;font-variant-numeric:tabular-nums;display:block;margin:2px 0 4px}
.note a{border-bottom:1px solid var(--line);text-decoration:none}
.note a:hover{border-color:var(--muted)}
.note .then{display:block;color:var(--muted)}
.knifenote{cursor:pointer}
.knifenote img{display:block;width:100%;height:auto;border-radius:3px;margin:8px 0 8px;background:#1e1e1d;transition:filter .3s}
.knifenote:hover img{filter:brightness(1.12)}
@media (prefers-reduced-motion:reduce){.item{opacity:1;transform:none;transition:none}}

/* case study: hero and story pieces at true proportions */
.gm-hero video{display:block;width:100%;height:auto;border-radius:3px}
.gm-hero .gm-live{width:100%;border-radius:3px}
.gm-hero video{background:#1a1a19}
.gm-story-wrap .w-richtext{display:flex;flex-direction:column;gap:44px}
.gm-story-wrap .w-richtext>*{margin:0!important}
.gm-story-wrap :is(h2,h3){padding-top:8px;font-size:17px;font-weight:500;letter-spacing:-.01em;line-height:1.5}
.gm-story-wrap .w-richtext>h3+p{margin-top:-32px!important}
.gm-story-wrap .w-richtext>p+p{margin-top:-24px!important}
/* tagline headlines over the story breaks (2026-10-25): big, short, the value in one line; the paragraph sits under it */
.gm-story-wrap h2.gm-tag{max-width:18ch;padding-top:28px;font-size:clamp(26px,2.4vw,38px);font-weight:500;line-height:1.1;letter-spacing:-.025em;text-wrap:balance}
.gm-story-wrap .w-richtext>h2.gm-tag+p{margin-top:-24px!important}
.gm-story-wrap .w-richtext>h2.gm-tag:first-child{padding-top:0}
.gm-story-wrap p{max-width:600px;font-size:17px;line-height:1.5;letter-spacing:-.01em;color:var(--fg)}
.gm-story-wrap figure{margin:0!important;max-width:100%!important;width:100%!important}
.gm-story-wrap figure>div{width:100%!important}
/* portrait live pieces (the ISB pencil slider) sit centred at a phone-like width instead of filling the column */
.gm-story-wrap figure.gm-fig-narrow{width:100%!important;padding:clamp(28px,6%,72px) 0;border-radius:3px;background:#3166e6}
.gm-story-wrap figure.gm-fig-narrow>.gm-live,.gm-story-wrap figure.gm-fig-narrow>img{width:min(48%,460px)!important;margin-inline:auto;border-radius:3px;box-shadow:0 18px 40px -18px rgba(0,0,0,.45)}
/* About: Dad of two daughters opens a small print of the family (Sam, 2026-10-18) */
.gm-fam{font:inherit;color:inherit;letter-spacing:inherit;background:none;border:0;padding:0 0 2px;margin:0;cursor:pointer;text-align:left;position:relative}
.gm-fam::before{content:"";position:absolute;inset-inline:0;inset-block-end:0;block-size:1px;pointer-events:none;background:linear-gradient(90deg,oklch(.9 .03 90 / .35),oklch(.95 .03 92) 22%,oklch(.97 .02 95));box-shadow:0 0 4px oklch(.9 .08 92 / .28);transform:scaleX(0);transform-origin:100% 50%;transition:transform .55s cubic-bezier(.65,0,.25,1)}
.gm-fam:hover::before,.gm-fam:focus-visible::before,.gm-fam[aria-expanded=true]::before{transform:scaleX(1);transform-origin:0 50%}
.gm-fampop{position:fixed;z-index:60;margin:0;padding:7px 7px 26px;background:#efede8;border-radius:2px;pointer-events:none;
 box-shadow:0 1px 0 rgba(255,255,255,.5) inset,0 2px 4px rgba(0,0,0,.25),0 22px 40px -16px rgba(0,0,0,.6);
 opacity:0;translate:-10px 0;rotate:-.5deg;scale:.96;transform-origin:0 50%;transition:opacity .28s var(--ease),translate .45s var(--ease),rotate .55s var(--ease),scale .45s var(--ease)}
.gm-fampop.on{opacity:1;translate:0 0;rotate:-3.2deg;scale:1}
.gm-fampop img{display:block;width:100%;height:auto;border-radius:1px;background:#d9d7d1}
/* About hovers (Sam, 2026-10-19): Prisma shows the glass turning, the art link a framed piece, the email a Compose button that copies it */
.gm-vpop,.gm-artpop{position:fixed;z-index:60;margin:0;pointer-events:none;opacity:0;transition:opacity .28s var(--ease)}
.gm-vpop{aspect-ratio:1;overflow:clip;border-radius:14px;background:#000;isolation:isolate;box-shadow:0 22px 44px -18px rgba(0,0,0,.8)}
.gm-vpop::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;box-shadow:inset 0 1px 0 rgba(255,255,255,.16),inset 0 0 0 1px rgba(255,255,255,.07),inset 0 -1px 0 rgba(0,0,0,.45)}
.gm-vpop video{display:block;inline-size:100%;block-size:100%;object-fit:cover}
/* the film grain is drawn live at screen resolution instead of baked into the small video, so the loop stays clean */
.gm-vpop::before{content:"";position:absolute;inset:-20%;z-index:1;pointer-events:none;opacity:.06;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 1.4 -.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E") 0 0/160px 160px}
.gm-artpop img{display:block;inline-size:100%;block-size:auto;background:#16130f;box-shadow:0 2px 4px rgba(0,0,0,.35),0 26px 44px -18px rgba(0,0,0,.75)}
.gm-vpop.on,.gm-artpop.on{opacity:1}
.gm-post{position:fixed;z-index:61;margin:0;block-size:124px;pointer-events:none;opacity:0;transition:opacity .28s var(--ease)}
.gm-post.on{opacity:1}
.gm-post.gm-post-reset,.gm-post.gm-post-reset *{transition:none!important;animation:none!important}
.gm-post-card{position:relative;display:grid;grid-template-columns:1fr 1fr;block-size:100%;overflow:clip;border-radius:3px;background:oklch(.965 .012 85);
 box-shadow:inset 0 1px 0 oklch(1 0 none / .6),0 1px 2px oklch(0 0 none / .3),0 20px 36px -16px oklch(0 0 none / .7)}
.gm-post-img{display:block;inline-size:100%;block-size:100%;object-fit:cover}
.gm-post-note{position:relative}
.gm-post-note>*{position:absolute}
.gm-post-slot,.gm-post-stamp{inset-block-start:8px;inset-inline-end:8px;inline-size:21px;block-size:25px}
/* the handwritten note sits on the four rules (Caveat rendered to a transparent PNG at 4x, sources in 2026-10 New material/about-pops/postcard/hand) */
.gm-post-hand{inset-inline-start:9px;inset-block-start:58px;inline-size:75px;block-size:52px}
.gm-post-slot{border:1px dashed oklch(.78 .015 80);border-radius:1px}
.gm-post-lines{inset-inline:9px;inset-block:58px 18px;background:repeating-linear-gradient(to bottom,transparent 0 11px,oklch(.82 .012 80) 11px 12px)}
/* postage stamp: perforated edge cut from the paper border, the crag as its picture */
.gm-post-stamp{box-sizing:border-box;padding:2.5px;background:30% 55%/cover no-repeat content-box,oklch(.985 .006 85);
 mask:radial-gradient(circle 1.25px,#0000 95%,#000) -1.75px -1.75px/3.5px 3.5px,linear-gradient(#000 0 0) content-box;
 filter:drop-shadow(0 .5px .5px oklch(0 0 none / .25));opacity:0}
.gm-post-mark{inset-block-start:4px;inset-inline-end:3px;inline-size:84px;block-size:34px;color:oklch(.3 .01 260 / .78);mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='90'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' seed='4'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2.2 0 0 0 1.85'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");opacity:0}
.gm-post-msg{inset-block-start:38px;inset-inline-start:10px;padding:3px 5px 2px;border:1.3px solid currentColor;border-radius:3px;
 font:600 8.5px/1.1 var(--mono);letter-spacing:.02em;white-space:nowrap;color:oklch(.5 .16 28);rotate:-7deg;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='90'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' seed='4'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2.2 0 0 0 1.85'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");opacity:0}
.gm-post.stamp :is(.gm-post-stamp,.gm-post-mark,.gm-post-msg){opacity:1}
.gm-post.stamp .gm-post-slot{opacity:0}
.gm-post.sent{opacity:0}
/* Next project: the name underlines and the arrow nudges along on hover (Sam, 2026-10-18) */
.gm-next-t{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.16em;text-decoration-color:transparent;transition:text-decoration-color .3s var(--ease)}
.gm-next-a{display:inline-block;margin-inline-start:.32em;transition:translate .35s var(--ease)}
.gm-next:hover .gm-next-t,.gm-next:focus-visible .gm-next-t{text-decoration-color:currentColor}
.gm-next:hover .gm-next-a,.gm-next:focus-visible .gm-next-a{translate:.22em 0}
/* Vusion platform and shelf (Sam, 2026-10-21): two square loops side by side, stacked on phones */
.gm-trio.gm-duo{grid-template-columns:repeat(2,minmax(0,1fr));inline-size:100%;gap:clamp(10px,1.6%,20px)}
.gm-trio.gm-duo>:is(img,video){box-shadow:none;border-radius:3px}
/* ISB pencil to scene (Sam, 2026-10-20): three recorded loops side by side in the blue frame, each a third of the way along; phones show the first */
.gm-story-wrap figure.gm-fig-trio{padding-inline:clamp(16px,5%,64px)}
.gm-trio{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(10px,2.4%,28px);inline-size:min(100%,1080px);margin-inline:auto}
.gm-trio>:is(img,video){box-shadow:0 18px 40px -18px rgb(0 0 0 / .45)}
.gm-story-wrap figure img,.gm-story-wrap figure video{display:block;width:100%!important;height:auto;max-width:none;border-radius:3px}
.gm-story-wrap .gm-live{width:100%!important;max-width:none;border-radius:3px}
.gm-story-wrap figure img,.gm-story-wrap figure video{background:#1a1a19}
/* live pieces inside a figure draw their own images: no loading ground or rounding on them (the stickers showed it as black squares) */
.gm-story-wrap .gm-live img,.gm-story-wrap .gm-live video{background:none;border-radius:0}
/* case studies: no captions on images, and the role row is a plain list without its label (Sam, 2026-10-12) */
.gm-story-wrap figcaption,.gm-hero-cap{display:none}
.gm-meta-row:has([data-b="role"]){display:block}
.gm-meta-row:has([data-b="role"]) .gm-meta-k{display:none}
[data-b="role"]{white-space:pre-line}
[data-b="role"].gm-roles{white-space:normal;display:flex;flex-wrap:wrap;gap:6px}
/* a little more air between the role pills and the Built with line (Sam, 2026-10-18) */
.gm-meta-row:has([data-b="role"])+.gm-meta-row{margin-top:12px}
.gm-role-pill{display:inline-block;padding-block:4px;padding-inline:10px;border:1px solid rgba(236,235,231,.18);border-radius:999px;font-size:12.5px;line-height:1.35;color:var(--fg)}
.gm-case [data-gm=opt].gm-off,.gm-info [data-gm=opt].gm-off{display:none}

/* archive: the row's still follows the pointer */
.gm-row{transition:color .2s}
@media (hover:hover){.gm-row:hover .gm-row-name{color:var(--accent)}
 .gm-row-cs{display:flex;align-items:center;color:var(--accent);opacity:0;transform:translateX(-14px);transition:opacity .35s var(--ease),transform .5s var(--ease)}
 .gm-row:hover .gm-row-cs,.gm-row:focus-visible .gm-row-cs{opacity:1;transform:none}}
.gm-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.gm-peek{position:fixed;z-index:40;left:0;top:0;width:min(34vw,460px);aspect-ratio:16/10;pointer-events:none;will-change:transform}
.gm-peek-in{position:relative;width:100%;height:100%;overflow:hidden;border-radius:6px;clip-path:inset(50% 50% 50% 50% round 6px);transform:scale(.86);opacity:0;box-shadow:0 30px 60px -20px rgba(0,0,0,.7);transition:clip-path .6s var(--ease),transform .7s var(--ease),opacity .25s}
.gm-peek.on .gm-peek-in{clip-path:inset(0 0 0 0 round 6px);transform:none;opacity:1}
.gm-peek img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transform:scale(1.08);transition:opacity .45s var(--ease),transform .9s var(--ease)}
.gm-peek img.on{opacity:1;transform:none}

/* viewer */
.lb{position:fixed;inset:0;z-index:70;background:rgba(10,10,9,.985);display:flex;align-items:center;justify-content:center;box-sizing:border-box;color:var(--fg);font:400 14px/1.5 var(--sans)}
.lb figure{margin:0;display:flex;flex-direction:column;gap:12px;min-width:0}
.lb figcaption{margin:0;font-size:13px;line-height:1.35;display:flex;gap:8px;flex-wrap:wrap}
.lb figcaption .w{color:var(--muted)}
.lb figcaption a{color:var(--muted);border-bottom:1px solid var(--line);text-decoration:none}
.lb figcaption a:hover{color:var(--fg)}
.lb-frame{position:relative;overflow:hidden;border-radius:18px;background:#141413;isolation:isolate;box-shadow:0 40px 90px -40px rgba(0,0,0,.9)}
.lb-frame::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:50;box-shadow:inset 0 1px 0 rgba(255,255,255,.16),inset 0 0 0 1px rgba(255,255,255,.07),inset 0 -1px 0 rgba(0,0,0,.45)}
.lb-frame>*{position:absolute!important;inset:0;width:100%!important;height:100%!important;max-width:none!important;max-height:none!important;aspect-ratio:auto!important;border-radius:0!important;margin:0}
.lb-frame>img,.lb-frame>video{display:block;object-fit:contain;background:#141413}
.lb-ctl{position:absolute;z-index:3;top:calc(12px + env(safe-area-inset-top,0px));right:14px;display:flex;gap:6px;transition:opacity .4s}
.lb-ctl button{all:unset;box-sizing:border-box;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;cursor:pointer;color:var(--muted);background:rgba(236,235,231,.05);border:1px solid rgba(236,235,231,.1);transition:color .25s,background .25s,border-color .25s}
.lb-ctl button:hover{color:var(--fg);background:rgba(236,235,231,.1);border-color:rgba(236,235,231,.22)}
.lb-ctl svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.lb-ctl .i,.lb.lb-full .lb-ctl .o{display:none}
.lb.lb-full .lb-ctl .i{display:inline}
.lb.lb-full .lb-frame{border-radius:0;box-shadow:none}
.lb.lb-full .lb-frame::after{display:none}
.lb.lb-full figcaption,.lb.lb-full .nav{display:none}
.lb.lb-full .lb-ctl{top:auto;bottom:calc(14px + env(safe-area-inset-bottom,0px));right:14px}
.lb.lb-full .lb-ctl button{color:#ecebe7;background:rgba(15,15,14,.55);border-color:rgba(236,235,231,.16);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
.lb.lb-full.idle .lb-ctl{opacity:0}
.lb .nav{all:unset;position:absolute;top:50%;transform:translateY(-50%);padding:16px 12px;cursor:pointer;color:var(--muted);font-size:18px;line-height:1;transition:color .25s}
.lb .nav:hover{color:var(--fg)}
.lb .prev{left:clamp(2px,1.2vw,18px)}.lb .next{right:clamp(2px,1.2vw,18px)}
.lb-vid{background:#000;cursor:pointer}
.lb-vid video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;display:block}
.lb-vc{position:absolute;left:0;right:0;bottom:0;z-index:2;display:flex;align-items:center;gap:10px;padding:34px 16px 14px;background:linear-gradient(transparent,rgba(0,0,0,.6));color:#ecebe7;font:500 12px var(--mono);cursor:default;transition:opacity .4s}
.lb-vid.idle .lb-vc{opacity:0}.lb-vid.idle{cursor:none}
.lb-vc button{all:unset;cursor:pointer;width:32px;height:32px;display:grid;place-items:center;border-radius:50%;flex:none;transition:background .2s}
.lb-vc button:hover{background:rgba(255,255,255,.14)}
.lb-vc svg{width:16px;height:16px;fill:currentColor;stroke:currentColor;stroke-width:0}
.lb-vc input{flex:1;min-width:60px;margin:0;-webkit-appearance:none;appearance:none;height:16px;background:none;cursor:pointer}
.lb-vc input::-webkit-slider-runnable-track{height:3px;border-radius:2px;background:linear-gradient(90deg,#ecebe7 var(--p,0%),rgba(255,255,255,.28) var(--p,0%))}
.lb-vc input::-moz-range-track{height:3px;border-radius:2px;background:linear-gradient(90deg,#ecebe7 var(--p,0%),rgba(255,255,255,.28) var(--p,0%))}
.lb-vc input::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;margin-top:-4.5px;border-radius:50%;background:#fff;border:0}
.lb-vc input::-moz-range-thumb{width:12px;height:12px;border-radius:50%;background:#fff;border:0}
.lb-vc .tm{font-variant-numeric:tabular-nums;color:rgba(236,235,231,.82);white-space:nowrap}
@media (hover:none),(max-width:640px){.lb .nav{top:auto;bottom:calc(10px + env(safe-area-inset-bottom,0px));transform:none}}
/* multi-tool tile (2026-11-01, from swiss-army-knife/multitool-v2/mt-tile.css; wear textures on the media host). Strokes don't scale with the drawing, so lines stay crisp at any tile size. */
.mtt { --mtt-bg: #171717; --mtt-line: #ECEAE4; --mtt-gold: #FFE47A;
  position: relative; display: block; aspect-ratio: 4 / 3; overflow: clip; cursor: pointer; border-radius: 3px; color: var(--mtt-line);
  background-color: var(--mtt-bg);
  background-image: linear-gradient(rgba(236, 234, 228, 0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(236, 234, 228, 0.05) 1px, transparent 1px);
  background-size: 6.25% 8.333%; background-position: -1px -1px; }
.mtt-wear { position: absolute; inset: 0; overflow: clip; pointer-events: none; }
.mtt-wear i { position: absolute; aspect-ratio: 1400 / 788; background-position: center; background-size: contain; background-repeat: no-repeat; }
.mw-cut { inset-inline-start: -14%; inset-block-end: -16%; inline-size: 78%; background-image: url("https://media.samuelgrayart.com/multitool/media/wear-cut-cluster.webp"); opacity: 0.16; }
.mw-scuff { inset-inline-start: 18%; inset-block-start: 30%; inline-size: 70%; background-image: url("https://media.samuelgrayart.com/multitool/media/wear-scuffs.webp"); transform: rotate(-8deg); opacity: 0.1; }
.mw-ruler { inset-inline-end: -20%; inset-block-start: -6%; inline-size: 100%; background-image: url("https://media.samuelgrayart.com/multitool/media/wear-ruler-cuts.webp"); transform: rotate(-3deg); opacity: 0.08; }
.mw-res { inset-inline-end: -4%; inset-block-end: -6%; inline-size: 56%; background-image: url("https://media.samuelgrayart.com/multitool/media/wear-residue.webp"); opacity: 0.16; }
.mtt svg { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; display: block; }
.mtt svg * { vector-effect: non-scaling-stroke; }
.mtt .ring { fill: none; stroke: var(--mtt-line); stroke-width: 1; }
.mtt .r-a { stroke-dasharray: 1 4; opacity: 0.4; }
.mtt .r-b { stroke-dasharray: 1 3; opacity: 0.2; }
.mtt .r-c { stroke-dasharray: 3 6; opacity: 0.14; }
.mtt .cross { stroke: var(--mtt-line); stroke-width: 1; opacity: 0.3; fill: none; }
.mtt .tool { color: var(--mtt-line); transition: color 320ms cubic-bezier(0.23, 1, 0.32, 1), opacity 320ms cubic-bezier(0.23, 1, 0.32, 1); }
.mtt .tool .ol { fill: none; stroke: currentColor; stroke-width: 1; stroke-linejoin: round; stroke-linecap: round; }
.mtt .tool .dt { fill: none; stroke: currentColor; stroke-width: 0.7; opacity: 0.5; stroke-linecap: round; }
.mtt .tool .th { fill: none; stroke: currentColor; stroke-width: 0.7; opacity: 0.32; }
.mtt .th2 { opacity: 0.14; stroke-dasharray: 2 3; }
.mtt .thf { opacity: 0.8; }
.mtt .bd { fill: var(--mtt-bg); }
.mtt .tool .hw { transition: opacity 320ms; }
.mtt .tool .hg { opacity: 0; transition: opacity 320ms; }
/* the corkscrew wire is a tube drawn in tool space, so it scales with the tool */
.mtt .tool .tube { fill: none; stroke: currentColor; stroke-width: 6.2; stroke-linecap: round; vector-effect: none; }
.mtt .tool .tube-in { fill: none; stroke: var(--mtt-bg); stroke-width: 3.9; stroke-linecap: round; vector-effect: none; }
.mtt .tool .back { opacity: 0.5; }
.mtt .tool.on { color: var(--mtt-gold); }
.mtt .tool.on .hg { opacity: 1; }
.mtt .tool.on .hw { opacity: 0; }
.mtt.lit .tool:not(.on) { opacity: 0.55; }
.mtt .handle .ol { fill: none; stroke: var(--mtt-line); stroke-width: 1.1; }
.mtt .handle .in { fill: none; stroke: var(--mtt-line); stroke-width: 0.7; opacity: 0.35; }
.mtt .handle .th { fill: none; stroke: var(--mtt-line); stroke-width: 0.7; opacity: 0.32; }
.mtt .handle .bd, .mtt .handle .rv { fill: var(--mtt-bg); }
.mtt .handle .rv { stroke: var(--mtt-line); stroke-width: 0.9; }
.mtt .handle .rv-in { fill: none; stroke: var(--mtt-line); stroke-width: 0.7; opacity: 0.6; }
.mtt .handle text { font-family: "Geist", system-ui, sans-serif; font-size: 36px; font-weight: 600; letter-spacing: 0.02em; }
.mtt .handle .etch-hi { fill: rgba(236, 234, 228, 0.16); }
.mtt .handle .etch-in { fill: #4E4D4A; }
.mtt .handle .etch-r { font-size: 11px; font-weight: 500; }
.mtt:focus-visible { outline: 2px solid var(--mtt-gold); outline-offset: 2px; }
/* multi-tool stage: grows out of the tile and holds the full piece in an iframe from the media host */
.mtstage{position:fixed;inset:0;z-index:60;background:#171717;clip-path:inset(var(--ct,50%) var(--cr,50%) var(--cb,50%) var(--cl,50%) round 3px);transition:clip-path .75s var(--ease)}
.mtstage.on{clip-path:inset(0 0 0 0 round 0)}
.mtstage[hidden]{display:none}
.mtstage iframe{position:absolute;inset:0;inline-size:100%;block-size:100%;border:0;display:block;background:#171717;opacity:0;transition:opacity .4s ease}
.mtstage iframe.ready{opacity:1}
html.gm-mt-on{overflow:hidden}
html.gm-mt-on .gm-ring{display:none}
@media (prefers-reduced-motion:reduce){.gm-cta::before,.gm-cta-arrow{transition:none}}

/* page to page: same-site navigations crossfade, and the in-place swaps (case study, About) morph the tile or portrait */
@view-transition{navigation:auto}
::view-transition-group(*){animation-duration:.55s;animation-timing-function:var(--ease)}
::view-transition-old(gm-panel){animation:gmOutUp .25s ease-in both}
::view-transition-new(gm-panel){animation:gmInUp .45s var(--ease) .3s both}
::view-transition-old(gm-main){animation:gmFade .2s ease-in reverse both}
::view-transition-new(gm-main){animation:gmInUp .45s var(--ease) .35s both}
::view-transition-old(gm-hero),::view-transition-new(gm-hero),::view-transition-old(gm-portrait),::view-transition-new(gm-portrait){animation:none;mix-blend-mode:normal;height:100%;object-fit:cover}
::view-transition-old(gm-hero){display:none}
@keyframes gmOutUp{to{opacity:0;transform:translateY(-16px)}}
@keyframes gmInUp{from{opacity:0;transform:translateY(16px)}}
@keyframes gmFade{from{opacity:0}}
@media (prefers-reduced-motion:reduce){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation-duration:.15s!important;animation-delay:0s!important}}

/* case study panel: a faint way back, room above the site link, a quiet Prisma credit */
.gm-back{transition:color .25s}

/* About: the portrait travels between the sidebar and the page */
.gm-fly{position:fixed;z-index:80;margin:0;object-fit:cover;filter:grayscale(100%);pointer-events:none}
/* a tile flying to its case study and back (graymade.js openCase, homeFromCase) */
.gm-flyer{position:fixed;z-index:80;margin:0;overflow:clip;pointer-events:none;contain:layout paint}
.gm-flyer>*{position:absolute;inset:0;inline-size:100%;block-size:100%;object-fit:cover;display:block}
.gm-side .gm-portrait{cursor:pointer}
/* résumé download box in the About sidebar */
.gm-resume-box{transition:border-color .3s,background-color .3s}
.gm-resume-box:hover{border-color:rgba(236,235,231,.32)!important;background-color:rgba(236,235,231,.03)}
.gm-rb-icon{transition:border-color .3s,background-color .3s,color .3s}
.gm-rb-icon svg{transition:transform .45s var(--ease)}
.gm-resume-box:hover .gm-rb-icon{border-color:var(--accent)!important;background-color:var(--accent);color:var(--ink)!important}
.gm-resume-box:hover .gm-rb-icon svg{transform:translateY(2px)}
.gm-fly{display:block}
/* Get in touch: the confirmation slides in inside the button */
.gm-cta-a,.gm-cta-b{display:inline-flex;align-items:center;column-gap:10px;transition:transform .55s var(--ease),opacity .4s var(--ease)}
.gm-cta-b{position:absolute;inset:0;justify-content:center;column-gap:8px;transform:translateY(110%);opacity:0;color:var(--ink)}
.gm-cta.gm-copied{color:var(--ink)!important;border-color:var(--accent)!important}
.gm-cta.gm-copied::before{transform:scaleX(1)}
.gm-cta.gm-copied .gm-cta-a{transform:translateY(-110%);opacity:0}
.gm-cta.gm-copied .gm-cta-b{transform:none;opacity:1}
.gm-cta-b svg{transform:scale(.4);opacity:0;transition:transform .5s var(--ease) .15s,opacity .3s .15s}
.gm-cta.gm-copied .gm-cta-b svg{transform:none;opacity:1}
/* a subtle moving grain over everything */
body::after{content:"";position:fixed;inset:-60px;z-index:65;pointer-events:none;opacity:.055;
 background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E") repeat;
 animation:gmGrain .8s steps(5) infinite}
@keyframes gmGrain{0%{transform:translate(0,0)}20%{transform:translate(-22px,14px)}40%{transform:translate(18px,-26px)}60%{transform:translate(-12px,-8px)}80%{transform:translate(26px,20px)}100%{transform:translate(0,0)}}
@media (prefers-reduced-motion:reduce){body::after{animation:none}}
/* case study pieces settle in as they scroll into view */
.gm-rv{opacity:0;transform:translateY(22px);clip-path:inset(0 0 6% 0);transition:opacity .9s var(--ease),transform 1s var(--ease),clip-path 1s var(--ease)}
.gm-rv.in{opacity:1;transform:none;clip-path:inset(0 0 -2% 0)}
/* images fade in once they arrive instead of popping */
img.gm-fade{opacity:0;transition:opacity .5s var(--ease)}
img.gm-fade.gm-loaded{opacity:1}
video.gm-vfade{opacity:0;transition:opacity .45s var(--ease)}
video.gm-vfade.gm-ready{opacity:1}
/* the phone fallback loop over a video that wasn't allowed to play */
.gm-altloop{position:absolute;object-fit:cover;pointer-events:none;opacity:0;transition:opacity .45s var(--ease)}
.gm-altloop.on{opacity:1}
/* phones in Low Power Mode: a video shows its still with a play button; a tap plays it (graymade.js tapPlay) */
.gm-tapplay{all:unset;box-sizing:border-box;position:absolute;z-index:2;inline-size:48px;block-size:48px;margin:-24px 0 0 -24px;border-radius:50%;background:rgba(15,15,14,.58);cursor:pointer;-webkit-tap-highlight-color:transparent}
.gm-tapplay::before{content:"";position:absolute;inset:0;margin:auto;inline-size:14px;block-size:16px;translate:2px 0;background:#ecebe7;clip-path:polygon(0 0,100% 50%,0 100%)}
.gm-tapplay:active{scale:.94}
.gm-tapplay:focus-visible{outline:2px solid #ecebe7;outline-offset:2px}
.gm-tapplay[hidden]{display:none}
/* first visit: hold the sidebar until the intro plays (shows anyway after 2.5s if the script fails) */
@keyframes gmShow{to{opacity:1}}
/* links: no resting underline. On hover a thin ray of light draws in from the left with a soft glow, and leaving sends it out to the right (Sam, 2026-10-17) */
.gm-link,:is(.gm-meta-link,.gm-meta a.gm-meta-v),.gm-site-link,:not(.gm-fine)>.gm-mail{position:relative;transition:color .25s}
:not(.gm-fine)>.gm-mail{border-bottom:0;padding-bottom:2px;background:none!important}
.gm-link::before,:is(.gm-meta-link,.gm-meta a.gm-meta-v)::before,.gm-site-link::before,:not(.gm-fine)>.gm-mail::before{content:"";position:absolute;inset-inline:0;inset-block-end:0;block-size:1px;pointer-events:none;
 background:linear-gradient(90deg,oklch(.9 .03 90 / .35),oklch(.95 .03 92) 22%,oklch(.97 .02 95));box-shadow:0 0 4px oklch(.9 .08 92 / .28);
 transform:scaleX(0);transform-origin:100% 50%;transition:transform .55s cubic-bezier(.65,0,.25,1)}
@media (prefers-reduced-motion:reduce){.gm-rv{opacity:1;transform:none;clip-path:none;transition:none}img.gm-fade{opacity:1;transition:none}}

@media (hover:hover) and (pointer:fine){.gm-fine .gm-mail:hover{color:var(--fg)}
 .gm-link:hover::before,:is(.gm-meta-link,.gm-meta a.gm-meta-v):hover::before,.gm-site-link:hover::before,.gm-link:focus-visible::before,:not(.gm-fine)>.gm-mail:hover::before,:not(.gm-fine)>.gm-mail:focus-visible::before{transform:scaleX(1);transform-origin:0 50%}
 :is(.gm-bio a,.gm-work,.gm-ask a,.gm-filter a):is(:hover,:focus-visible){background-position:0 0;text-decoration-color:transparent}
 :is(.gm-bio a,.gm-work,.gm-ask a,.gm-filter a):is(:hover,:focus-visible)::before{transform:scaleX(1);transform-origin:0 50%}}
@media (width < 720px){.gm-leak{inline-size:min(110vw,520px);block-size:min(110vw,520px)}
 .gm-leak-x{display:none}
}

/* ISB case hero: the 2:3 slider sits centered at a readable size instead of filling the column */
.gm-hero .slider{width:min(100%,calc(84svh * 2 / 3));margin-inline:auto}
@media (prefers-reduced-motion:reduce){.gm-cycle img{transform:none;transition:opacity 1s}}
/* touch: small links get a 44px hit area without changing the layout */
@media (pointer:coarse){
 .gm-links a,.gm-back,.gm-fine a,.gm-meta-v,.gm-site-link,.gm-mail,.gm-fam,.gm-work{position:relative}
 .gm-links a::after,.gm-back::after,.gm-fine a::after,a.gm-meta-v::after,.gm-site-link::after,.gm-mail::after,.gm-fam::after{content:"";position:absolute;inset:-11px -8px}
 .gm-work::after{content:"";position:absolute;inset:-4px -8px}
}
/* first visit: the portrait develops and the words come into focus as soon as this stylesheet lands (the script only
   develops the work). gm-pre is set in the head on the first visit of a session and never with reduced motion (Sam, 2026-10-17).
   Shortened 2026-10-22 so the page is all there in about a second. */
@keyframes gmFocus{from{opacity:0;filter:blur(7px);translate:0 6px}to{opacity:1;filter:blur(0);translate:0 0}}
@keyframes gmDevelop{from{opacity:0;filter:blur(10px) brightness(.35);scale:1.04}to{opacity:1;filter:blur(0) brightness(1);scale:1}}
.gm-pre canvas.gm-portrait{animation:gmDevelop 1s cubic-bezier(.16,1,.3,1) .04s both}
.gm-pre img.gm-portrait{opacity:0;animation:gmShow 0s 1.4s forwards}
.gm-pre .gm-info>*,.gm-pre .gm-fine{animation:gmFocus .8s cubic-bezier(.16,1,.3,1) .1s both}
.gm-pre .gm-info>:nth-child(2){animation-delay:.15s}.gm-pre .gm-info>:nth-child(3){animation-delay:.2s}.gm-pre .gm-info>:nth-child(4){animation-delay:.25s}.gm-pre .gm-fine{animation-delay:.3s}
@media (prefers-reduced-motion:reduce){.gm-link::before,:is(.gm-meta-link,.gm-meta a.gm-meta-v)::before,.gm-site-link::before,:not(.gm-fine)>.gm-mail::before,.gm-bio a::before{transition:opacity .3s}.gm-bio a{transition:none}}
/* About intro sizes live in the Webflow combo gm-is-about; this only balances the line endings */
.gm-profile :is(.gm-lead,.gm-bio){text-wrap:pretty}
/* phones: no page-to-page crossfade; the two layouts don't line up there, so text landed on text (Sam, 2026-10-17) */
@media (width < 720px){@view-transition{navigation:none}}
/* phones (Sam, 2026-10-18, smoother scrolling): the expand buttons drop their live blur, which redraws over playing video,
   and the full-page grain layer is off; it barely reads on a small screen and costs a blend over every frame */
@media (hover:none) and (pointer:coarse){.slot .expand{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(15,15,14,.72)}body::after{display:none}}
/* the pull is a mouse gesture: no hint where there is no mouse */
@media (hover:none),(pointer:coarse){.gm-pull-hint{display:none}}
@media (prefers-reduced-motion:reduce){.gm-pull-hint>span,.gm-pull-hint>span::before,.gm-pull-hint>span::after{animation:none}.gm-pull-hint>span::before,.gm-pull-hint>span::after{display:none}}
@media (prefers-reduced-motion:reduce){.gm-ring,.gm-ring.on,.gm-ring.back{transition-duration:.15s;transition-delay:0s}.gm-ring.on.down{scale:1}}
@media (prefers-reduced-motion:reduce){.gm-next-a{transition:none}}
@media (prefers-reduced-motion:reduce){.gm-fampop{translate:0 0;scale:1;rotate:-3.2deg;transition:opacity .2s}}
/* About hovers: they slide and settle in; the art hangs a touch off level */
@media (prefers-reduced-motion:no-preference){
 .gm-vpop::before{animation:sgp-grain .45s steps(1) infinite}
 .gm-vpop,.gm-artpop{translate:-10px 0;scale:.96;transform-origin:0 50%;transition:opacity .28s var(--ease),translate .45s var(--ease),rotate .55s var(--ease),scale .45s var(--ease)}
 .gm-vpop.on,.gm-artpop.on{translate:0 0;scale:1}
 .gm-artpop{rotate:-.4deg}.gm-artpop.on{rotate:1.4deg}
 .gm-post{translate:-10px 0;scale:.96;rotate:-.5deg;transform-origin:0 50%;transition:opacity .28s var(--ease),translate .45s var(--ease),rotate .55s var(--ease),scale .45s var(--ease)}
 .gm-post.on{translate:0 0;scale:1;rotate:-2.6deg}
 /* the stamp hit: the card gives under it, everything inked lands at once */
 .gm-post.stamp .gm-post-card{animation:gmPostHit .5s cubic-bezier(.3,.7,.3,1)}
 .gm-post.stamp :is(.gm-post-stamp,.gm-post-mark,.gm-post-msg){animation:gmPostInk .32s cubic-bezier(.2,.8,.25,1) backwards}
 .gm-post.stamp .gm-post-stamp{animation-duration:.26s}
 /* then it is mailed: off up and to the right, turning as it goes */
 .gm-post.sent{translate:90px -46px;rotate:9deg;scale:.9;transition:opacity .55s .1s cubic-bezier(.45,0,.7,.4),translate .65s cubic-bezier(.5,0,.6,1),rotate .65s cubic-bezier(.5,0,.6,1),scale .65s cubic-bezier(.5,0,.6,1)}}
@keyframes gmPostHit{0%{scale:1}22%{scale:.93}55%{scale:1.012}100%{scale:1}}
@keyframes gmPostInk{0%{opacity:0;scale:1.3}60%{opacity:1;scale:.97}100%{opacity:1;scale:1}}
@media (prefers-reduced-motion:reduce){.gm-artpop{rotate:1.4deg}.gm-post{rotate:-2.6deg}.gm-post :is(.gm-post-stamp,.gm-post-mark,.gm-post-msg){transition:opacity .15s}.gm-post.sent{transition:opacity .4s}}
@keyframes sgp-grain{0%,100%{transform:translate(0,0)}20%{transform:translate(-4%,3%)}40%{transform:translate(3%,-5%)}60%{transform:translate(-5%,-2%)}80%{transform:translate(4%,4%)}}
@media (width < 720px){.gm-trio{grid-template-columns:minmax(0,1fr);inline-size:min(62%,320px)}.gm-trio>:nth-of-type(n+2):not(.gm-altloop){display:none}}
@media (width < 720px){.gm-trio.gm-duo{grid-template-columns:minmax(0,1fr);inline-size:100%}.gm-trio.gm-duo>:nth-of-type(n+2):not(.gm-altloop){display:block}}
@media (prefers-reduced-motion:reduce){.mtstage{clip-path:none;opacity:0;transition:opacity .3s ease}.mtstage.on{clip-path:none;opacity:1}}
