/* Portfolio canvas. Without JS (or with reduced motion / list view) the pieces fall back to a static scatter of stills. */
.portfolio-page main{max-width:none}
.pf-head{max-width:var(--max);margin:auto;padding:12px var(--gutter);display:grid;grid-template-columns:auto minmax(280px,440px) auto;gap:28px;align-items:center;border-bottom:1px solid var(--line)}
.pf-title .eyebrow{display:flex;gap:10px;align-items:center;color:#cacdc0;margin-bottom:6px}.pf-sub{margin:6px 0 0;font-size:11px;color:#9fa394}
.pf-title h1{font-size:clamp(30px,2.8vw,42px);font-weight:600;letter-spacing:-.07em;line-height:.95;margin:0}
.pf-title h1 em{color:var(--acid);letter-spacing:-.05em}
.pf-brand{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;align-items:center}.pf-brand .pf-help{grid-column:1/-1}
.pf-head>*,.pf-brand{min-width:0}
.pf-brand label{font:10px/1.4 'Courier New',monospace;letter-spacing:.14em;color:var(--acid)}
.pf-brand input{background:#0b0d0a;border:1px solid #5b5e50;color:var(--paper);padding:10px 14px;font-size:18px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;width:100%}
.pf-brand input::placeholder{text-transform:none;letter-spacing:0;font-weight:400;color:#8d9083;font-size:15px}
.pf-brand input:focus{border-color:var(--acid);outline:none}
.pf-help{font-size:10px;line-height:1.5;color:#9fa394}
.pf-tools{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.pf-tools button{background:none;color:var(--paper);border:1px solid #5b5e50;padding:11px 13px;font-size:11px;min-width:42px;display:inline-flex;gap:8px;align-items:center}
.pf-tools button:hover,.pf-tools button[aria-pressed="true"]{background:var(--acid);color:var(--ink);border-color:var(--acid)}
.pf-tools kbd{font:9px monospace;border:1px solid currentColor;padding:1px 4px;opacity:.7}
.pf-canvas{position:relative;outline:none}
.pf-canvas:focus-visible{box-shadow:inset 0 0 0 3px #638020}
/* static scatter (default) */
.pf-world{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:40px 30px;padding:46px var(--gutter);max-width:var(--max);margin:auto}
.pf-piece{margin:0;position:relative}
.pf-piece:nth-child(3n+2){transform:translateY(38px) rotate(1.2deg)}.pf-piece:nth-child(3n){transform:translateY(-14px) rotate(-1deg)}
.pf-art{position:relative;aspect-ratio:900/760;-webkit-mask-image:radial-gradient(closest-side,#000 62%,transparent 100%);mask-image:radial-gradient(closest-side,#000 62%,transparent 100%)}
.pf-blob .pf-art{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='b'%3E%3CfeGaussianBlur stdDeviation='5'/%3E%3C/filter%3E%3Cpath filter='url(%23b)' d='M100 18c26 0 52 9 66 32s12 50 4 74-27 49-56 56-60-2-79-24S9 106 17 80 47 28 70 21c10-2 20-3 30-3z'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='b'%3E%3CfeGaussianBlur stdDeviation='5'/%3E%3C/filter%3E%3Cpath filter='url(%23b)' d='M100 18c26 0 52 9 66 32s12 50 4 74-27 49-56 56-60-2-79-24S9 106 17 80 47 28 70 21c10-2 20-3 30-3z'/%3E%3C/svg%3E");-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
.pf-art img,.pf-art iframe{position:absolute;inset:0;width:100%;height:100%;display:block;border:0;object-fit:contain}
.pf-art iframe{opacity:0;transition:opacity .45s;pointer-events:none;background:#11130f}
.pf-art iframe.on{opacity:1}
.pf-piece figcaption{display:flex;gap:10px;align-items:baseline;justify-content:center;font:11px/1.4 'Courier New',monospace;letter-spacing:.04em;color:#babdae;margin-top:-6px;position:relative;z-index:3}
.pf-piece figcaption a{color:var(--paper)}.pf-piece figcaption a span{color:var(--acid)}.pf-piece figcaption a:hover{color:var(--acid)}
.pf-num{color:#6f7465}
.pf-state:not(:empty){color:var(--acid);font-size:9px;letter-spacing:.12em}
.pf-xray{display:none}
.pf-hud,.pf-minimap{display:none}
/* live canvas */
.pf-on .pf-canvas{height:calc(100vh - 96px - 120px);min-height:520px;overflow:hidden;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;background:radial-gradient(circle at 50% 40%,#171a13,#11130f 70%)}
.pf-on .pf-canvas::before{content:'';position:absolute;inset:0;background-image:radial-gradient(#a1b18418 1px,transparent 1.4px);background-size:var(--dot,46px) var(--dot,46px);background-position:var(--dx,0) var(--dy,0);pointer-events:none}
.pf-on .pf-canvas.dragging{cursor:grabbing}
.pf-on .pf-world{display:block;position:absolute;left:0;top:0;padding:0;margin:0;max-width:none;width:4400px;height:2900px;transform-origin:0 0;will-change:transform}
.pf-on .pf-piece{position:absolute;left:calc(var(--x) * 1px);top:calc(var(--y) * 1px);width:calc(var(--w) * 1px);transform:none}
.pf-on .pf-piece figcaption{font-size:15px;margin-top:-18px}
.pf-on .pf-piece.focus .pf-art{filter:drop-shadow(0 0 30px #c8f04a22)}
.pf-on .pf-hud{display:flex;gap:16px;position:absolute;left:18px;top:14px;font:10px/1.4 'Courier New',monospace;letter-spacing:.1em;color:#b4b7aa;pointer-events:none}
.pf-on .pf-hud [data-pf-live]{color:var(--acid)}
.pf-on .pf-minimap{display:block;overflow:hidden;width:220px!important;position:absolute;right:16px;top:14px;width:200px;height:132px;background:#0b0d0acc;border:1px solid #3c4033;cursor:pointer;backdrop-filter:blur(4px)}
.pf-minimap b{position:absolute;background:color-mix(in srgb,var(--glow,#c8f04a) 45%,transparent);border-radius:40%}
.pf-minimap b.live{background:var(--glow,#c8f04a);box-shadow:0 0 0 1px var(--acid)}
.pf-minimap i{position:absolute;border:1px solid var(--paper);box-shadow:0 0 0 999px #0000;pointer-events:none}
/* x-ray */
.pf-x .xr .pf-xray{display:block;position:absolute;left:0;right:0;top:0;aspect-ratio:900/760;outline:1px dashed #c8f04a99;outline-offset:-1px;pointer-events:none;z-index:2;background-image:linear-gradient(#c8f04a14 1px,transparent 1px),linear-gradient(90deg,#c8f04a14 1px,transparent 1px);background-size:10% 10%}
.pf-x .xr .pf-art{-webkit-mask-image:none;mask-image:none}
.pf-x .xr .pf-art img,.pf-x .xr .pf-art iframe.on{opacity:.28}
.pf-edge{position:absolute;inset:0;width:100%;height:100%;filter:url(#pf-edge-f)}
.pf-cross{position:absolute;left:50%;top:50%;width:26px;height:26px;margin:-13px;border:1px solid #c8f04a;border-radius:50%}
.pf-cross::before,.pf-cross::after{content:'';position:absolute;background:#c8f04a;left:50%;top:-14px;bottom:-14px;width:1px}.pf-cross::after{top:50%;left:-14px;right:-14px;width:auto;height:1px;bottom:auto}
.pf-xray ol{position:absolute;left:10px;top:10px;margin:0;padding:8px 10px;list-style:none;background:#0b0d0ae6;border:1px solid #3c4033;font:11px/1.6 'Courier New',monospace;color:#d8dbcd;max-width:80%}
.pf-xray ol b{color:var(--acid);font-weight:400;margin-right:6px}
.pf-kb{position:absolute;right:10px;bottom:10px;margin:0;padding:6px 9px;background:var(--acid);color:var(--ink);font:11px/1.5 'Courier New',monospace;max-width:70%}
.pf-foot{max-width:var(--max);margin:auto;padding:36px var(--gutter) 60px;display:flex;gap:18px;align-items:center;flex-wrap:wrap;border-top:1px solid var(--line)}
.pf-foot p{flex:1 1 380px;color:#bdc0b3;font-size:13px;line-height:1.8;margin:0}
@media(max-width:1100px){.pf-head{grid-template-columns:1fr 1fr}.pf-tools{grid-column:1/-1;justify-content:flex-start}}
@media(max-width:700px){.pf-brand{grid-column:1/-1}.pf-brand input{width:100%;max-width:100%;box-sizing:border-box}.pf-head{grid-template-columns:1fr;gap:16px;padding-top:20px}.pf-title h1{font-size:44px}.pf-on .pf-canvas{height:68vh;min-height:420px}.pf-on .pf-minimap{width:120px;height:79px;right:10px;bottom:10px}.pf-hint{display:none}.pf-on .pf-hud{left:10px;bottom:10px}.pf-world{grid-template-columns:1fr;gap:18px}.pf-piece:nth-child(n){transform:none}}
body:not(.pf-js) .pf-brand,body:not(.pf-js) .pf-tools,body:not(.pf-on) .pf-brand,body:not(.pf-on) [data-pf-zoom],body:not(.pf-on) [data-pf-fit]{display:none}
.pf-x .pf-piece.xr.is-live .pf-edge{display:none}.pf-x .xr .pf-art iframe.on{opacity:.6}
.pf-x .pf-piece.xr.is-live .pf-art img{opacity:0}
.pf-on .pf-xray ol{font-size:calc(11px * var(--xinv,1))}.pf-on .pf-kb{font-size:calc(11px * var(--xinv,1))}.pf-canvas.mid .pf-xray ol{display:none}
.pf-on .pf-piece figcaption{font-size:calc(13px * var(--inv,1));margin-top:calc(-14px * var(--inv,1))}
/* v2: canvas is the hero: at least 85vh; overview captions are scale-compensated to ~11px on screen. */
.pf-on .pf-canvas{min-height:85vh}
.pf-on .pf-piece figcaption{font-size:calc(11px * var(--inv,1));margin-top:calc(-10px * var(--inv,1));flex-wrap:wrap;row-gap:0;line-height:1.25}
.pf-on .pf-piece figcaption a{display:inline-flex;flex-wrap:wrap;justify-content:center;column-gap:.6em}
.pf-wheelhint{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;padding:12px 16px;background:#0b0d0ae8;border:1px solid #5b5e50;font:12px/1.5 'Courier New',monospace;color:var(--paper);opacity:0;transition:opacity .25s;pointer-events:none;z-index:5;display:none}
.pf-on .pf-wheelhint{display:block}.pf-wheelhint.on{opacity:1}.pf-wheelhint kbd{border:1px solid #8d9083;padding:0 4px;font:inherit}
.pf-canvas.engaged{box-shadow:inset 0 0 0 1px #c8f04a66}
.pf-piece .pf-art img.pf-named{opacity:1}
@media(max-width:1100px){.pf-head{grid-template-columns:1fr 1fr}.pf-brand{grid-template-columns:1fr}}
@media(max-width:700px){.pf-head{padding:10px var(--gutter);gap:8px}.pf-title h1{font-size:28px}.pf-sub,.pf-title .eyebrow{display:none}.pf-brand label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}.pf-help{display:none}.pf-tools button{padding:8px 10px;font-size:10px}.pf-on .pf-canvas{min-height:0}.pf-on .pf-minimap{top:10px;bottom:auto}.pf-on .pf-hud{top:auto;bottom:10px}}
@media(max-width:700px){.pf-canvas.far .pf-piece figcaption{display:none}}
/* v3 atmosphere: each piece throws a soft pool of its own hue onto the dark world (one cheap radial gradient, no blur filters). */
.pf-piece::before{content:'';position:absolute;left:-30%;right:-30%;top:-28%;aspect-ratio:900/760;background:radial-gradient(closest-side,color-mix(in srgb,var(--glow,#c8f04a) 26%,transparent),color-mix(in srgb,var(--glow,#c8f04a) 9%,transparent) 55%,transparent 100%);pointer-events:none;z-index:-1;opacity:.9;transition:opacity .6s}
.pf-piece.is-live::before{opacity:1}
.pf-art{z-index:0}
.pf-piece figcaption a span{color:color-mix(in srgb,var(--glow) 70%,#f4f0e8)}
.pf-on .pf-canvas{background:radial-gradient(60% 50% at 30% 30%,#1a1222,transparent 70%),radial-gradient(55% 45% at 75% 70%,#0f1a24,transparent 70%),#0d0f0c}
.pf-x .pf-piece.xr::before{opacity:.25}
/* Stills and live frames sit on #11130f; lighten lets the light pool show through their dark ground instead of a dark disc. */
.pf-art{mix-blend-mode:lighten}.pf-x .xr .pf-art{mix-blend-mode:normal}
/* v4 expansion: districts, printed-sheet pieces, fixed-size live frames. */
.pf-district{grid-column:1/-1;margin:30px 0 0;font:600 22px/1.2 'Plus Jakarta Sans',sans-serif;letter-spacing:-.02em;color:var(--paper);display:flex;gap:14px;align-items:baseline;border-top:1px solid var(--line);padding-top:16px}
.pf-district span{font:11px 'Courier New',monospace;color:var(--acid);letter-spacing:.1em}
.pf-district small{font:11px 'Courier New',monospace;color:#8d9083;letter-spacing:.08em;text-transform:uppercase}
.pf-on .pf-district{position:absolute;left:calc(var(--x) * 1px);top:calc(var(--y) * 1px);width:calc(var(--dw) * 1px);margin:0;padding-top:28px;font-size:calc(40px * min(var(--inv,1), 3.2));border-top:2px solid #3a3d33;pointer-events:none;z-index:1}
.pf-on .pf-district span,.pf-on .pf-district small{font-size:calc(13px * min(var(--inv,1), 3.2))}
.pf-on .pf-district::after{content:'';position:absolute;left:-60px;right:-60px;top:-60px;height:calc(var(--dh) * 1px + 120px);border-radius:80px;background:radial-gradient(120% 90% at 0 0,#ffffff05,transparent 60%);z-index:-2}
.pf-paper .pf-art{-webkit-mask-image:none!important;mask-image:none!important;mix-blend-mode:normal;border-radius:10px;overflow:hidden;box-shadow:0 30px 60px -20px #000c,0 0 0 1px #ffffff14;transform:rotate(-1.2deg) scale(.92)}
.pf-paper:nth-of-type(2n) .pf-art{transform:rotate(1deg) scale(.92)}
.pf-paper::before{opacity:.35}
.pf-on .pf-art iframe{width:900px!important;height:760px!important;transform:scale(var(--fs,1));transform-origin:0 0}
/* Big world: captions step down when zoomed out, and give way to district labels in the overview. */
.pf-canvas.mid .pf-piece figcaption{font-size:calc(11px * min(var(--inv,1), 2.6));margin-top:calc(-10px * min(var(--inv,1), 2.6))}
.pf-canvas.far .pf-piece figcaption{display:none}
/* v4 motion layer (Molly, 13 Oct): ambient hue, travel, ripple, scanline, HUD, Show me. */
@property --amb{syntax:'<color>';inherits:true;initial-value:#0d0f0c}
.pf-on .pf-canvas{transition:--amb 1.4s ease}
.pf-on .pf-canvas::before{content:'';position:absolute;inset:0;pointer-events:none;z-index:0;background:radial-gradient(70% 65% at 50% 55%,color-mix(in srgb,var(--amb) 16%,transparent),transparent 72%)}
.pf-canvas.moving .pf-art iframe{opacity:0!important}
@keyframes pf-flash{0%{filter:brightness(2.2) saturate(1.4)}100%{filter:none}}
.pf-flash .pf-art{animation:pf-flash .7s ease-out}
.pf-scan{position:absolute;top:0;bottom:0;width:2px;left:0;background:var(--acid);box-shadow:0 0 18px 3px #c8f04a88;z-index:6;pointer-events:none;opacity:0}
.pf-scan.go{animation:pf-scan .9s cubic-bezier(.6,0,.4,1) forwards}
@keyframes pf-scan{0%{left:0;opacity:1}92%{opacity:1}100%{left:100%;opacity:0}}
.pf-where{position:absolute;left:12px;bottom:10px;z-index:5;display:none;gap:14px;font:10px 'Courier New',monospace;letter-spacing:.12em;text-transform:uppercase;color:#a9ad9d;pointer-events:none}
.pf-where b{color:var(--acid);font-weight:400}
.pf-on .pf-where{display:flex}
.pf-show{display:none;gap:8px;flex-wrap:wrap;align-items:center;padding:8px var(--gutter);font:10px 'Courier New',monospace;letter-spacing:.12em;text-transform:uppercase;color:#8d9083;border-bottom:1px solid var(--line)}
.pf-js.pf-on .pf-show{display:flex}
.pf-show button{font:inherit;letter-spacing:inherit;color:var(--paper);background:transparent;border:1px solid #3a3d33;border-radius:999px;padding:5px 12px;cursor:pointer}
.pf-show button[aria-pressed="true"],.pf-show button:hover{border-color:var(--acid);color:var(--acid)}
.pf-showing .pf-piece:not(.hit){opacity:.18;filter:grayscale(.7);transition:opacity .4s,filter .4s}
.pf-showing .pf-piece.hit::before{opacity:1}
@media(max-width:700px){.pf-where span:nth-child(2){display:none}}
@media(prefers-reduced-motion:reduce){.pf-flash .pf-art{animation:none}}
/* v4 motion layer, part 2: lens, focus veil, label on stop, shuffle. */
.pf-on .pf-piece{transition:left .6s cubic-bezier(.34,1.5,.64,1),top .6s cubic-bezier(.34,1.5,.64,1)}
.pf-canvas.dragging .pf-piece{transition:none}
.pf-veil{position:absolute;inset:0;z-index:3;pointer-events:none;opacity:0;transition:opacity .45s;background:#0b0c0a8c;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  --hx:50%;--hy:50%;--hr:300px;-webkit-mask:radial-gradient(var(--hr) calc(var(--hr) * .86) at var(--hx) var(--hy),transparent 70%,#000 100%);mask:radial-gradient(var(--hr) calc(var(--hr) * .86) at var(--hx) var(--hy),transparent 70%,#000 100%)}
.pf-canvas.veiled .pf-veil{opacity:1}
.pf-lens{position:absolute;left:0;top:0;width:220px;height:220px;margin:-110px 0 0 -110px;border-radius:50%;border:1.5px solid var(--acid);box-shadow:0 0 0 1px #0008,0 0 30px #c8f04a44 inset;z-index:6;pointer-events:none;display:none;background:repeating-linear-gradient(0deg,#c8f04a10 0 1px,transparent 1px 4px)}
.pf-canvas.lensing .pf-lens{display:block}
.pf-pill{position:absolute;left:0;top:0;z-index:5;display:flex;gap:10px;align-items:center;transform:translate(-50%,0);padding:6px 6px 6px 14px;border-radius:999px;background:#0d0f0ce6;border:1px solid #3a3d33;font:11px 'Courier New',monospace;letter-spacing:.1em;text-transform:uppercase;color:var(--paper);opacity:0;pointer-events:none;transition:opacity .25s}
.pf-pill a{pointer-events:auto;background:var(--acid);color:#0d0f0c;border-radius:999px;padding:4px 10px;text-decoration:none}
.pf-canvas.pilled .pf-pill{opacity:1}
.pf-canvas.pilled .pf-pill:not(:hover){pointer-events:none}
@media(prefers-reduced-motion:reduce){.pf-on .pf-piece{transition:none}}
.pf-on .pf-minimap,.pf-on .pf-hud,.pf-where{z-index:7}
