/* ═══ Vingraphix v3 · "Sticker Desk" ═══
   Leads: Robin notebook + Bazil giant type/portrait.
   Light = ruled paper + yellow/red/blue pop. Dark = midnight desk, yellow family. */

:root{
  --paper:#FAF7EF; --line:rgba(47,107,255,.14); --margin:rgba(255,77,61,.25);
  --ink:#17151A; --ink-dim:#5A5560;
  --yellow:#FFD43A; --red:#E8402F; --blue:#2F6BFF; --green:#2FA866; --pink:#F0619E;
  --card:#FFFFFF; --shadow:rgba(23,21,26,.16);
  --tape:rgba(255,212,58,.75);
  --r:18px;
  --nav-h:74px;          /* fixed navbar height — stickers must clear it */
  --ease:cubic-bezier(.22,.61,0,1);
  --ease-out-quart:cubic-bezier(.25,1,.5,1);   /* drawer + burger: decelerating, no overshoot */
}
[data-theme="dark"]{
  --paper:#161309; --line:rgba(255,212,58,.10); --margin:rgba(227,179,65,.28);
  --ink:#F6EFD8; --ink-dim:#B5AB8C;
  --yellow:#FFD43A; --red:#E0564A; --blue:#8FAEFF; --green:#57C08A; --pink:#E58BB4;
  --card:#211B0E; --shadow:rgba(0,0,0,.55);
  --tape:rgba(200,155,60,.6);
}

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  background:
    repeating-linear-gradient(180deg,transparent 0 30px,var(--line) 30px 31px),
    linear-gradient(90deg,transparent 0 44px,var(--margin) 44px 45px,transparent 45px),
    var(--paper);
  color:var(--ink);
  font:400 clamp(15px,1.4vw,17px)/1.6 'Outfit',system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  transition:background .5s,color .5s;
}
h1,h2,h3{letter-spacing:-.01em}
a{color:inherit;text-decoration:none}
img{max-width:100%;height:auto;display:block}
.caveat{font-family:'Caveat',cursive}

/* ── NAV ── */
.v3-nav{position:fixed;top:0;left:0;right:0;z-index:50;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px clamp(16px,4vw,40px);background:color-mix(in srgb,var(--paper) 86%,transparent);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-bottom:2px solid var(--ink)}
/* gap:0 — the wordmark is "Vin" + <span>graphix</span>, which flex treats as two
   items, so a gap here would split the brand name in half. The mark carries its
   own margin instead. */
.v3-nav .wm{font:800 22px 'Outfit',sans-serif;letter-spacing:-.02em;display:inline-flex;align-items:center;gap:0}
.v3-nav .wm .mk{width:32px;height:32px;flex:none;display:block;margin-right:9px;border-radius:50%;border:2px solid var(--ink);box-shadow:2px 2px 0 var(--ink);overflow:hidden;transform:rotate(-4deg);transition:transform .3s var(--ease)}
.v3-nav .wm:hover .mk{transform:rotate(6deg) scale(1.06)}
.v3-nav .wm .mk svg{width:100%;height:100%;display:block}
.v3-nav .wm span{color:var(--red)}
.v3-nav .wm .dot{display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--yellow);border:2px solid var(--ink);margin-left:3px;animation:v3-blink 2.4s ease-in-out infinite}
@keyframes v3-blink{0%,88%,100%{transform:scale(1)}94%{transform:scale(1.5)}}
.v3-nav nav{display:flex;gap:22px;font-weight:600;font-size:15px}
.v3-nav nav a{position:relative}
.v3-nav nav a::after{content:"";position:absolute;left:0;right:100%;bottom:-4px;height:3px;background:var(--yellow);transition:right .3s var(--ease)}
.v3-nav nav a:hover::after{right:0}
.v3-nav .right{display:flex;align-items:center;gap:12px}
.v3-nav .mode{width:42px;height:42px;border-radius:50%;border:2px solid var(--ink);background:var(--card);cursor:pointer;display:grid;place-items:center;color:var(--ink);transition:transform .3s var(--ease),background .5s}
.v3-nav .mode:hover{transform:rotate(18deg)}
.v3-nav .mode:active{transform:scale(.92)}
.v3-nav .mode svg{width:20px;height:20px}
[data-theme="light"] .mode .moon{display:none}
[data-theme="dark"] .mode .sun{display:none}
.v3-nav .hire{font-weight:800;font-size:14px;padding:10px 18px;background:var(--yellow);color:#17151A;border:2px solid var(--ink);border-radius:999px;box-shadow:3px 3px 0 var(--ink);transition:transform .2s,box-shadow .2s}
.v3-nav .hire:hover{transform:translate(-2px,-2px);box-shadow:5px 5px 0 var(--ink)}
.v3-nav .hire:active{transform:translate(1px,1px);box-shadow:2px 2px 0 var(--ink)}
.v3-nav nav a.on::after{right:0}
.v3-nav .burger{display:none;width:42px;height:42px;border-radius:12px;border:2px solid var(--ink);background:var(--card);cursor:pointer;padding:0;place-items:center;gap:4px;flex-direction:column;transition:transform .2s var(--ease-out-quart),box-shadow .2s}
.v3-nav .burger span{display:block;width:18px;height:2.5px;border-radius:2px;background:var(--ink);transition:transform .3s var(--ease-out-quart),opacity .2s}
.v3-nav .burger:active{transform:scale(.92)}
/* burger morphs to an X while the drawer is open — the control shows its state */
.v3-nav .burger[aria-expanded="true"] span:nth-child(1){transform:translateY(6.5px) rotate(45deg)}
.v3-nav .burger[aria-expanded="true"] span:nth-child(2){opacity:0;transform:scaleX(.3)}
.v3-nav .burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-6.5px) rotate(-45deg)}

/* ── mobile drawer ──────────────────────────────────────────────────────────
   The old rule was just `.v3-nav nav{display:none}` under 640px, which left a
   phone with no way into any section from the header. */
.v3-scrim{position:fixed;inset:0;z-index:48;background:rgba(23,21,26,.42);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);opacity:0;transition:opacity .3s var(--ease-out-quart)}
.v3-scrim.on{opacity:1}
.v3-scrim[hidden]{display:none}

/* top:var(--nav-h) — the panel hangs below the bar rather than over it, so the
   burger stays on screen as the X that closes it. */
.v3-drawer{position:fixed;top:var(--nav-h);right:0;bottom:0;z-index:49;width:min(320px,86vw);
  display:flex;flex-direction:column;gap:6px;padding:20px 22px calc(20px + env(safe-area-inset-bottom));
  background:var(--card);border-left:2.5px solid var(--ink);box-shadow:-14px 0 40px -18px var(--shadow);
  transform:translateX(100%);transition:transform .34s var(--ease-out-quart);overflow-y:auto;overscroll-behavior:contain}
.v3-drawer.on{transform:translateX(0)}
.v3-drawer[hidden]{display:none}
.v3-drawer .dhead{display:flex;align-items:center;margin-bottom:6px}
.v3-drawer .dtitle{font-size:27px;color:var(--red);transform:rotate(-2deg);display:inline-block}
.v3-drawer .dlinks{display:flex;flex-direction:column}
.v3-drawer .dlinks a{display:flex;align-items:baseline;gap:10px;padding:15px 4px;border-bottom:2px dashed color-mix(in srgb,var(--ink) 22%,transparent);
  font:800 22px/1.1 'Outfit',sans-serif;color:var(--ink)}
.v3-drawer .dlinks a b{margin-left:auto;font:700 12px/1 'Outfit',sans-serif;letter-spacing:.1em;color:var(--ink-dim)}
.v3-drawer .dlinks a.on span{box-shadow:inset 0 -8px 0 var(--yellow)}
.v3-drawer .dlinks a:active span{color:var(--red)}
.v3-drawer .dhire{margin-top:18px;text-align:center;font-weight:800;font-size:16px;padding:14px 18px;background:var(--yellow);color:#17151A;border:2px solid var(--ink);border-radius:999px;box-shadow:4px 4px 0 var(--ink)}
.v3-drawer .dhire:active{transform:translate(2px,2px);box-shadow:2px 2px 0 var(--ink)}
.v3-drawer .dtape{position:absolute;top:4px;left:26px;width:92px;height:26px;background:var(--tape);transform:rotate(-6deg);opacity:.9;pointer-events:none}
/* links slide in behind the panel so the drawer reads as opening, not appearing */
.v3-drawer .dlinks a,.v3-drawer .dhire{opacity:0;transform:translateX(18px)}
.v3-drawer.on .dlinks a,.v3-drawer.on .dhire{opacity:1;transform:none;
  transition:opacity .3s var(--ease-out-quart) calc(90ms + var(--i) * 45ms),transform .3s var(--ease-out-quart) calc(90ms + var(--i) * 45ms)}

@media (max-width:860px){
  .v3-nav nav{display:none}
  .v3-nav .burger{display:flex}
  .v3-nav .hire{display:none}          /* it lives in the drawer on small screens */
}
@media (prefers-reduced-motion:reduce){
  .v3-drawer,.v3-scrim,.v3-drawer .dlinks a,.v3-drawer .dhire,.v3-nav .burger span{transition:none}
  .v3-drawer .dlinks a,.v3-drawer .dhire{opacity:1;transform:none}
}

/* ── HERO ── */
.v3-hero{position:relative;min-height:100dvh;padding:max(clamp(96px,14vh,150px),calc(var(--nav-h) + 34px)) clamp(16px,5vw,64px) 60px;display:flex;flex-direction:column;justify-content:center}
.v3-hero .hi{font-size:clamp(22px,2.6vw,32px);color:var(--ink-dim);transform:rotate(-2deg);margin-bottom:4px}
.v3-hero .stack{position:relative;z-index:1;font-family:'Archivo Black',sans-serif;font-weight:400;line-height:.86;font-size:clamp(40px,11.5vw,96px);text-transform:uppercase}
@media (min-width:900px){.v3-hero .stack{font-size:clamp(96px,13vw,176px)}}
.v3-hero .stack .fill{display:block;color:var(--ink)}
.v3-hero .stack .line{display:block;color:transparent;-webkit-text-stroke:2.5px var(--ink);letter-spacing:.01em}
.v3-hero .stack .flipbox{display:grid;perspective:700px}
.v3-hero .stack .flip{grid-area:1/1;opacity:0;transform-origin:50% 60%;will-change:transform,opacity;backface-visibility:hidden}
html:not(.js) .v3-hero .flip:first-child,html.js .v3-hero .flip.on{opacity:1}
@media (prefers-reduced-motion:reduce){.v3-hero .flip{opacity:0 !important}.v3-hero .flip:first-child{opacity:1 !important;transform:none !important}}
/* portrait — a stack of the same pose in different media, cross-faded */
.v3-hero .me{position:absolute;z-index:2;right:clamp(2vw,8vw,14vw);bottom:0;width:clamp(240px,34vw,480px);aspect-ratio:640/853;filter:drop-shadow(0 24px 40px var(--shadow));-webkit-mask-image:linear-gradient(180deg,#000 84%,transparent 99%);mask-image:linear-gradient(180deg,#000 84%,transparent 99%);cursor:pointer;-webkit-tap-highlight-color:transparent}
.v3-hero .me .frame{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity .45s var(--ease)}
.v3-hero .me img.frame{object-fit:contain;object-position:bottom center}
.v3-hero .me .frame.on{opacity:1}
.v3-hero .me img.missing{display:none}

/* ── live code silhouette ───────────────────────────────────────────────────
   The same cut-out shape as the other frames, used as a mask. Behind it the
   rows of code actually scroll, so the figure reads as a window onto a
   running terminal rather than a picture of one. */
.v3-hero .me .codeframe{
  background:#0B0F14;overflow:hidden;
  -webkit-mask-image:url('/v3/assets/media/me/code-mask.webp');
          mask-image:url('/v3/assets/media/me/code-mask.webp');
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-position:bottom center;mask-position:bottom center;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
}
.v3-hero .me .codeflow{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;gap:.35em;padding:2% 0}
.v3-hero .me .crow{
  display:flex;flex:none;white-space:nowrap;width:max-content;
  font:400 clamp(7px,1.05vw,13px)/1.5 'Courier New',ui-monospace,monospace;
  color:#5FE3C0;text-shadow:0 0 6px rgba(95,227,192,.45);
  animation:v3-code var(--dur,22s) linear infinite;
  animation-delay:var(--delay,0s);
  /* no will-change: 40 rows would each hold a compositor layer for a frame
     that is on screen one second in six. The running animation promotes them. */
  animation-play-state:paused;               /* only runs while this frame shows */
}
.v3-hero .me .crow i{font-style:normal;padding-right:2.5em}
.v3-hero .me .crow.rev{animation-direction:reverse;color:#7FD4FF;text-shadow:0 0 6px rgba(127,212,255,.4)}
.v3-hero .me .crow.dim{opacity:.42}
.v3-hero .me .crow.hot{color:#FFC65C;text-shadow:0 0 6px rgba(255,198,92,.4)}
.v3-hero .me .frame.on .crow,
.v3-hero .me .codeframe.on .crow{animation-play-state:running}
@keyframes v3-code{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* scanline sheen over the silhouette */
.v3-hero .me .codeframe::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:repeating-linear-gradient(180deg,rgba(255,255,255,.05) 0 1px,transparent 1px 3px);
}
@media (prefers-reduced-motion:reduce){.v3-hero .me .crow{animation:none !important}}
.v3-hero .me.missing{display:none}
.v3-hero .me:focus-visible{outline:3px solid var(--blue);outline-offset:6px;border-radius:12px}
.v3-hero .tag{position:relative;z-index:3;max-width:44ch;margin-top:26px;font-size:clamp(17px,1.9vw,21px)}
.v3-hero .tag b{background:var(--yellow);color:#17151A;padding:0 6px;border-radius:6px;box-decoration-break:clone;-webkit-box-decoration-break:clone}
.v3-hero .tag .note{display:block;color:var(--red);font-size:clamp(19px,2vw,24px);transform:rotate(-1.4deg)}
.v3-hero .cta{position:relative;z-index:3;display:flex;gap:14px;margin-top:30px;flex-wrap:wrap}
.v3-btn{display:inline-flex;align-items:center;gap:10px;font-weight:800;font-size:16px;padding:16px 28px;border-radius:999px;border:2px solid var(--ink);min-height:48px;transition:transform .2s,box-shadow .2s;box-shadow:4px 4px 0 var(--ink)}
.v3-btn.red{background:var(--red);color:#fff}
.v3-btn.ghost{background:var(--card);color:var(--ink)}
.v3-btn:hover{transform:translate(-2px,-2px);box-shadow:6px 6px 0 var(--ink)}
.v3-btn:active{transform:translate(2px,2px);box-shadow:2px 2px 0 var(--ink)}
.v3-hero .scrollhint{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);font-weight:600;font-size:13px;color:var(--ink-dim);animation:v3-hop 2s ease-in-out infinite}
@keyframes v3-hop{0%,100%{transform:translate(-50%,0)}50%{transform:translate(-50%,7px)}}

/* ── stickers + chips ──────────────────────────────────────────────────────
   Pinned, not floating. They read as stickers pressed onto the page, and
   holding still means the eye settles on the headline instead of chasing
   motion. Each keeps its own tilt so the arrangement stays hand-placed. */
.stk,.chip{position:absolute;z-index:3;filter:drop-shadow(0 10px 18px var(--shadow))}
/* top band — flanking the headline, clear of the nav */
.stk.s2{top:calc(var(--nav-h) + 22px);left:34%;transform:rotate(-12deg)}          /* star    */
.stk.s1{top:calc(var(--nav-h) + 40px);right:7%;transform:rotate(9deg)}            /* ps5     */
/* left margin — down the side of the text column */
.stk.s5{top:46%;left:2.5%;transform:rotate(-6deg)}                                 /* macbook */
/* bottom band — under the CTA row */
.stk.s6{bottom:7%;left:26%;transform:rotate(8deg)}                                 /* iphone  */
.stk.s4{bottom:9%;right:38%;transform:rotate(-7deg)}                               /* speaker */
/* a tap still needs to feel alive even though nothing drifts */
.stk[data-fx]{transition:transform .25s var(--ease)}
.stk[data-fx]:hover{transform:scale(1.08) rotate(0deg)}
/* CSS handles the entrance, not GSAP — a stalled timeline used to leave every
   sticker stuck at opacity 0 with nothing to fall back on */
.stk,.chip{opacity:0;animation:v3-stick .5s var(--ease) forwards}
.stk.s1{animation-delay:.30s} .stk.s2{animation-delay:.36s}
.stk.s4{animation-delay:.48s}
.stk.s5{animation-delay:.54s} .stk.s6{animation-delay:.60s}
.chip.c2{animation-delay:.52s}
@keyframes v3-stick{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){.stk,.chip{opacity:1;animation:none}}
/* tappable device stickers */
.stk[data-fx]{cursor:pointer;-webkit-tap-highlight-color:transparent}
.stk[data-fx]:focus-visible{outline:3px solid var(--blue);outline-offset:4px;border-radius:10px}
/* particles thrown by the speaker + phone · body-level so no parent clips them */
.fxbit{position:fixed;z-index:6;pointer-events:none;will-change:transform,opacity}
.fxbit.note{font:700 26px 'Outfit',sans-serif;color:var(--red);text-shadow:0 2px 6px var(--shadow)}
.fxbit.ring{width:54px;height:54px;margin:-27px 0 0 -27px;border:3px solid var(--green);border-radius:50%}
@media (prefers-reduced-motion:reduce){.fxbit{display:none}}

.chip{font-size:clamp(20px,2.2vw,26px);font-weight:700;color:#17151A;background:var(--yellow);padding:6px 16px;border:2px solid var(--ink);border-radius:999px;box-shadow:3px 3px 0 var(--ink)}
.chip.c2{top:52%;right:8%;transform:rotate(3.5deg)}
.tape{position:absolute;width:110px;height:30px;background:var(--tape);transform:rotate(-8deg);z-index:4;opacity:.85}
.tape.t1{top:24%;left:6.4%}
.tape.t2{top:48%;right:7%;transform:rotate(6deg)}
@media (min-width:761px) and (max-width:1060px){
    .stk.s4{bottom:4%;right:36%;width:88px}
}
@media (max-width:760px){
  .v3-hero{display:flex;flex-direction:column;padding-bottom:90px}
  .v3-hero .me{position:relative;right:auto;bottom:auto;width:min(70vw,340px);margin:18px auto 0;order:5}
  .stk{width:84px;height:84px}
  /* three is plenty on a phone — the stacked hero is already busy */
  .stk.s5,.stk.s6{display:none}
  /* The stacked hero runs text full-bleed from ~y88 to ~y410, so there is no
     room beside it. Both top stickers used to land on the headline; they now
     sit in the band below the CTA, flanking the portrait. */
  .stk.s2{top:auto;bottom:40%;left:2%}
  .stk.s1{top:auto;bottom:34%;right:2%}
  .stk.s4{bottom:11%;right:6%}
  .chip.c2{top:auto;bottom:2%;right:5%}
  .tape{display:none}
}

/* ── sections shared ── */
.v3-do,.v3-work{padding:clamp(80px,13vh,150px) clamp(16px,5vw,64px);max-width:1180px;margin:0 auto;width:100%}
/* work gets more room than the rest — the cards are the whole point of the page */
.v3-work{max-width:1340px}
.v3-do h2,.v3-work h2{font-family:'Archivo Black',sans-serif;font-weight:400;font-size:clamp(34px,5.4vw,64px);text-transform:uppercase;line-height:1;margin-bottom:clamp(30px,5vh,54px)}
.kick{display:block;font-size:clamp(22px,2.4vw,30px);color:var(--red);text-transform:none;transform:rotate(-1.6deg);margin-bottom:6px}

/* ── WHAT I DO · zig-zag sticker rows ── */
.do-list{list-style:none;display:flex;flex-direction:column;gap:clamp(16px,2.6vh,26px)}
.do-item{display:flex;align-items:center;gap:clamp(16px,2.4vw,26px);background:var(--card);border:2px solid var(--ink);border-radius:var(--r);padding:clamp(12px,1.8vw,20px) clamp(16px,2.4vw,26px);box-shadow:5px 5px 0 var(--ink);width:min(620px,100%);transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
.do-item.tilt-l{transform:rotate(-.7deg);align-self:flex-start}
.do-item.tilt-r{transform:rotate(.8deg);align-self:flex-end}
.do-item:hover{transform:rotate(0) translate(-3px,-3px);box-shadow:8px 8px 0 var(--ink)}
.do-item .ic{width:clamp(60px,7vw,96px);height:auto;flex:none;transition:transform .4s var(--ease)}
.do-item:hover .ic{transform:rotate(-8deg) scale(1.12)}
.do-item h3{font-size:clamp(18px,2vw,23px);font-weight:800}
.do-item p{color:var(--ink-dim);font-size:15px}
.hue-yellow h3{text-decoration:underline;text-decoration-color:var(--yellow);text-decoration-thickness:5px;text-underline-offset:4px}
.hue-blue h3{text-decoration:underline;text-decoration-color:var(--blue);text-decoration-thickness:5px;text-underline-offset:4px}
.hue-green h3{text-decoration:underline;text-decoration-color:var(--green);text-decoration-thickness:5px;text-underline-offset:4px}
.hue-red h3{text-decoration:underline;text-decoration-color:var(--red);text-decoration-thickness:5px;text-underline-offset:4px}
.hue-pink h3{text-decoration:underline;text-decoration-color:var(--pink);text-decoration-thickness:5px;text-underline-offset:4px}

/* ── WORK · bezel-less overlay cards with flipping glimpse ── */
.v3-work .grid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(16px,2.6vw,30px);width:100%}
/* caption sits under the picture, not on top of it — on a phone an overlay
   covers the part of the work you actually want to see */
.pol{position:relative;overflow:hidden;border-radius:16px;border:2.5px solid var(--ink);box-shadow:0 16px 34px -14px var(--shadow);transform:rotate(var(--rot));transition:transform .35s var(--ease),box-shadow .35s;cursor:pointer;will-change:transform;background:var(--card);display:flex;flex-direction:column}
.pol:hover{transform:rotate(0) scale(1.02) translateY(-5px);box-shadow:0 28px 46px -14px var(--shadow);z-index:2}
.pol .tape{display:none}
.pol .ph{position:relative;flex:none;aspect-ratio:4/3;display:block;overflow:hidden;border:0;border-radius:0;background:var(--card)}
/* Base state is VISIBLE — work.php renders one plain <img> with no .on class,
   so the cross-fade must be opt-in via .multi rather than the default. */
.pol .ph img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border:0;border-radius:0;transition:transform .55s var(--ease)}
.pol:not(.multi):hover .ph img{transform:scale(1.06)}
/* multi-shot cards cross-fade between shots */
.pol.multi .ph img{opacity:0;transform:scale(1.045);transition:opacity .7s var(--ease),transform 1.2s var(--ease);will-change:opacity}
.pol.multi .ph img.on{opacity:1;transform:scale(1)}
.pol .shots{position:absolute;top:10px;left:10px;z-index:3;display:flex;gap:5px;padding:5px 8px;border-radius:999px;background:rgba(10,9,12,.42);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);opacity:0;transition:opacity .3s}
.pol.multi .shots{opacity:1}
.pol .shots i{display:block;width:6px;height:6px;border-radius:50%;background:rgba(255,255,255,.42);transition:background .4s,transform .4s var(--ease)}
.pol .shots i.on{background:var(--yellow);transform:scale(1.45)}
.pol figcaption{position:relative;z-index:2;display:grid;grid-template-columns:1fr auto;align-items:center;gap:2px 10px;padding:12px 14px 13px;background:var(--card);border-top:2px solid var(--ink);color:var(--ink)}
.pol .name{grid-column:1;font-family:'Outfit',sans-serif;font-weight:800;font-size:clamp(15px,1.6vw,19px);line-height:1.25;letter-spacing:-.01em;color:var(--ink)}
.pol .type{grid-column:1;grid-row:2;font-family:'Outfit',sans-serif;font-size:clamp(11.5px,1.05vw,13px);font-weight:600;color:var(--ink-dim)}
.pol .live,.pol .soon{grid-column:2;grid-row:1/span 2;align-self:center;justify-self:end}
/* flat inline SVG rather than emoji or text arrows — emoji render as colour
   glyphs that change per platform and ignore the palette */
.v3-ic{width:1em;height:1em;flex:none;display:inline-block;vertical-align:-.1em;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.pol .live{display:inline-flex;align-items:center;gap:5px;font:800 11.5px 'Outfit',sans-serif;background:var(--green);color:#fff;border:2px solid var(--ink);padding:4px 10px;border-radius:999px;box-shadow:2px 2px 0 var(--ink);transition:transform .2s}
.pol .live:hover{transform:translate(-1px,-1px)}
.pol .soon{font:600 10.5px 'Outfit',sans-serif;color:var(--ink-dim);border:1.5px dashed color-mix(in srgb,var(--ink) 40%,transparent);padding:2px 8px;border-radius:999px}
.pol .peek{position:absolute;top:10px;right:10px;z-index:3;display:inline-flex;align-items:center;gap:5px;font:800 11px 'Outfit',sans-serif;background:var(--yellow);color:#17151A;border:2px solid #17151A;border-radius:999px;padding:4px 10px;box-shadow:2px 2px 0 #17151A;opacity:0;transform:translateY(-6px) rotate(4deg);transition:opacity .25s,transform .25s var(--ease)}
.pol:hover .peek,.pol:focus-visible .peek{opacity:1;transform:translateY(0) rotate(-2deg)}
.pol:focus-visible{outline:3px solid var(--blue);outline-offset:3px}
/* "See all work" — the homepage shows a reel, /work.php has the catalogue */
.work-more{display:flex;align-items:center;justify-content:center;gap:18px;flex-wrap:wrap;margin-top:clamp(30px,5vh,48px)}
.work-more .v3-btn{display:inline-flex;align-items:center;gap:10px}
.work-more .ct{font:800 12px 'Outfit',sans-serif;background:var(--yellow);color:#17151A;border:2px solid #17151A;border-radius:999px;padding:2px 9px;line-height:1.5}
.work-more .hint{font-size:22px;color:var(--ink-dim);transform:rotate(-1.4deg)}
@media (max-width:520px){.work-more .hint{display:none}}

/* ── boot screen ────────────────────────────────────────────────────────────
   Covers the first paint while fonts and the hero art settle. JS removes it on
   load; the animation below is a hard 3s failsafe so a stalled asset can never
   leave a visitor staring at a blank sheet. */
/* CSS failsafe clears the curtain even if the script never runs — kept short so
   a stalled asset cannot sit on Largest Contentful Paint */
.v3-boot{position:fixed;inset:0;z-index:200;display:grid;place-items:center;background:var(--paper);
  animation:v3-boot-out .4s var(--ease) 1.8s forwards}
.v3-boot.gone{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .45s var(--ease),visibility 0s .45s}
html:not(.js) .v3-boot{display:none}                 /* no JS, no curtain */
.v3-boot .bmark{width:74px;height:74px;border-radius:50%;border:2.5px solid var(--ink);
  box-shadow:4px 4px 0 var(--ink);overflow:hidden;animation:v3-boot-pop .7s var(--ease) both}
.v3-boot .bmark svg{width:100%;height:100%;display:block}
.v3-boot .bword{margin-top:20px;font:800 15px 'Outfit',sans-serif;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-dim)}
.v3-boot .bbar{margin-top:14px;width:132px;height:7px;border:2px solid var(--ink);border-radius:999px;overflow:hidden;background:var(--card)}
.v3-boot .bbar i{display:block;height:100%;width:40%;background:var(--yellow);border-right:2px solid var(--ink);
  animation:v3-boot-run 1.1s var(--ease) infinite}
.v3-boot .inner{display:flex;flex-direction:column;align-items:center}
@keyframes v3-boot-pop{from{transform:scale(.6) rotate(-18deg);opacity:0}to{transform:scale(1) rotate(-4deg);opacity:1}}
@keyframes v3-boot-run{0%{transform:translateX(-105%)}100%{transform:translateX(265%)}}
@keyframes v3-boot-out{to{opacity:0;visibility:hidden;pointer-events:none}}
@media (prefers-reduced-motion:reduce){
  .v3-boot .bmark,.v3-boot .bbar i{animation:none}
  .v3-boot{animation-duration:.01s;animation-delay:.2s}
}

.v3-wipe{position:fixed;inset:0;z-index:80;background:var(--paper);opacity:0;pointer-events:none;transition:opacity .28s ease}
.v3-wipe.on{opacity:1;pointer-events:auto}
.v3-snd{position:fixed;left:clamp(12px,2.5vw,26px);bottom:clamp(12px,2.5vw,26px);z-index:45;font:700 12px 'Outfit',sans-serif;background:var(--card);color:var(--ink);border:2px solid var(--ink);border-radius:999px;padding:8px 14px;box-shadow:3px 3px 0 var(--ink);cursor:pointer;transition:transform .2s}
.v3-snd:active{transform:scale(.94)}
@media (max-width:640px){.v3-snd{display:none}}
@media (max-width:520px){.v3-work .grid{gap:12px}.pol{border-width:2px}.pol .ph{aspect-ratio:5/4}.pol figcaption{padding:10px 10px 11px}.pol .shots{top:8px;left:8px;padding:4px 7px}}

/* ── TALK ── */
.v3-talk{text-align:center;padding:clamp(90px,15vh,170px) 20px 0}
.v3-talk .big{font-family:'Archivo Black',sans-serif;font-weight:400;font-size:clamp(40px,7vw,88px);line-height:.95;text-transform:uppercase}
.v3-talk .big span{color:transparent;-webkit-text-stroke:2px var(--ink)}
.wa-btn{display:inline-flex;align-items:center;gap:14px;margin-top:36px;font-weight:800;font-size:clamp(18px,2vw,22px);background:var(--green);color:#fff;border:2.5px solid var(--ink);border-radius:999px;padding:16px 30px;box-shadow:5px 5px 0 var(--ink);transition:transform .2s,box-shadow .2s}
.wa-btn img{width:44px;height:44px}
.wa-btn .wa-ic{width:30px;height:30px;flex:none}
.wa-btn:hover{transform:translate(-2px,-2px) rotate(-1deg);box-shadow:7px 7px 0 var(--ink)}
.wa-btn:active{transform:translate(2px,2px);box-shadow:2px 2px 0 var(--ink)}
.v3-talk .alt{margin-top:22px;color:var(--ink-dim);font-size:15px}
.v3-talk .alt a{text-decoration:underline;text-decoration-color:var(--yellow);text-decoration-thickness:3px;text-underline-offset:3px}
.v3-talk footer{margin-top:clamp(60px,9vh,110px);padding:24px;border-top:2px solid var(--ink);font-size:14px;color:var(--ink-dim)}
.v3-talk footer .caveat{color:var(--red);font-size:18px}

/* ── VOICE ORB · chunky pill button ── */
.v3-orb{position:fixed;right:clamp(14px,3vw,30px);bottom:clamp(14px,3vw,30px);z-index:45;display:inline-flex;align-items:center;gap:12px;padding:14px 22px 14px 14px;border-radius:999px;border:2.5px solid var(--ink);background:var(--yellow);color:#17151A;cursor:pointer;box-shadow:5px 5px 0 var(--ink);font:800 17px 'Outfit',sans-serif;animation:v3-orb-nudge 5s ease-in-out infinite;transition:transform .22s var(--ease),box-shadow .22s,background .3s}
.v3-orb:hover{transform:translate(-3px,-3px);box-shadow:8px 8px 0 var(--ink);background:var(--card);animation-play-state:paused}
.v3-orb:active{transform:translate(2px,2px) scale(.97);box-shadow:2px 2px 0 var(--ink)}
@keyframes v3-orb-nudge{0%,84%,100%{transform:translate(0,0) rotate(0)}88%{transform:translate(0,-4px) rotate(-2deg)}92%{transform:translate(0,1px) rotate(1.4deg)}96%{transform:translate(0,-2px) rotate(0)}}
.v3-orb .face{width:44px;height:44px;border-radius:50%;border:2px solid var(--ink);overflow:hidden;display:grid;place-items:center;flex:none;background:var(--red);position:relative}
.v3-orb .face img{width:100%;height:100%;object-fit:cover;animation:v3-orbspin 9s linear infinite,v3-orbpulse 2.6s ease-in-out infinite}
@keyframes v3-orbspin{to{transform:rotate(360deg)}}
@keyframes v3-orbpulse{0%,100%{filter:saturate(1) brightness(1)}50%{filter:saturate(1.4) brightness(1.14)}}
@media (prefers-reduced-motion:reduce){.v3-orb .face img{animation:none}}
.v3-orb .txt{white-space:nowrap}
.v3-orb .txt b{color:var(--red)}
.v3-orb:hover .txt b{text-decoration:underline;text-decoration-thickness:3px;text-underline-offset:3px}
.v3-orb .ring{position:absolute;left:8px;top:8px;width:44px;height:44px;border-radius:50%;border:2.5px solid var(--red);animation:v3-ring 2.4s ease-out infinite;pointer-events:none}
@keyframes v3-ring{0%{transform:scale(1);opacity:.85}70%,100%{transform:scale(1.6);opacity:0}}
.v3-orb .tap{position:absolute;top:-26px;right:10px;font-size:21px;font-weight:700;color:var(--red);transform:rotate(8deg);animation:v3-hop 1.8s ease-in-out infinite}
@media (max-width:640px){.v3-orb{padding:12px 16px 12px 12px;font-size:15px}.v3-orb .face{width:38px;height:38px}.v3-orb .ring{left:7px;top:7px;width:38px;height:38px}}

/* ── VOICE CALL POPUP ── */
.v3-call{position:fixed;inset:0;z-index:70;display:grid;place-items:end center;background:color-mix(in srgb,var(--ink) 32%,transparent);opacity:0;pointer-events:none;transition:opacity .3s}
.v3-call.on{opacity:1;pointer-events:auto}
.v3-call .card{width:min(440px,calc(100vw - 24px));margin-bottom:clamp(12px,4vh,40px);background:var(--card);border:2.5px solid var(--ink);border-radius:22px;box-shadow:8px 8px 0 var(--ink);overflow:hidden;transform:translateY(24px) rotate(.6deg);transition:transform .35s var(--ease)}
.v3-call.on .card{transform:translateY(0) rotate(0)}
.v3-call .head{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:2px solid var(--ink);background:var(--yellow);color:#17151A;font:800 16px 'Outfit',sans-serif}
.v3-call .head .dot{width:12px;height:12px;border-radius:50%;background:var(--red);border:2px solid var(--ink);animation:v3-breathe 1.6s ease-in-out infinite}
.v3-call.speaking .head .dot{background:var(--green)}
@keyframes v3-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.35)}}
.v3-call .head .st{font-weight:600;font-size:13px;opacity:.75;margin-left:2px}
.v3-call .head .x{margin-left:auto;width:34px;height:34px;border-radius:50%;border:2px solid var(--ink);background:var(--card);color:var(--ink);font-size:20px;font-weight:800;cursor:pointer;line-height:1}
.v3-call .feed{height:min(300px,42vh);overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;background:var(--paper)}
.v3-call .bub{max-width:82%;padding:10px 14px;border:2px solid var(--ink);border-radius:14px;font-size:14.5px;line-height:1.45}
.v3-call .bub.ai{align-self:flex-start;background:var(--card);border-bottom-left-radius:4px}
.v3-call .bub.me{align-self:flex-end;background:var(--yellow);color:#17151A;border-bottom-right-radius:4px}
.v3-call .hint{margin:8px 16px 0;font-size:18px;color:var(--ink-dim);transform:rotate(-1deg)}
/* While the gate is up there is no call yet — hide the transcript, the
   "speak normally" hint and End call so the card is just the form. */
.v3-call.gating .feed,
.v3-call.gating .hint,
.v3-call.gating .end,
.v3-call.gating .compose{display:none}

/* ── gate · name + phone before the session opens ── */
.v3-call .gate{display:flex;flex-direction:column;gap:12px;padding:20px 18px 18px;background:var(--paper)}
.v3-call .gate[hidden]{display:none}
.v3-call .gtitle{margin:0;font:800 17px/1.35 'Outfit',sans-serif;color:var(--ink)}
.v3-call .gate label{display:flex;flex-direction:column;gap:6px;font:700 12px 'Outfit',sans-serif;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-dim)}
.v3-call .gate input{font:500 15.5px 'Outfit',sans-serif;color:var(--ink);background:var(--card);border:2px solid var(--ink);border-radius:12px;padding:12px 14px;outline:none;text-transform:none;letter-spacing:0}
.v3-call .gate input::placeholder{color:color-mix(in srgb,var(--ink) 34%,transparent)}
.v3-call .gate input:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 45%,transparent)}
.v3-call .gerr{margin:0;font:600 13px 'Outfit',sans-serif;color:var(--red)}
.v3-call .gerr[hidden]{display:none}
.v3-call .gbtn{margin-top:2px;font:800 15px 'Outfit',sans-serif;background:var(--red);color:#fff;border:2.5px solid var(--ink);border-radius:999px;padding:13px 22px;box-shadow:4px 4px 0 var(--ink);cursor:pointer;transition:transform .2s,box-shadow .2s}
.v3-call .gbtn:hover{transform:translate(-2px,-2px);box-shadow:6px 6px 0 var(--ink)}
.v3-call .gbtn:active{transform:translate(2px,2px);box-shadow:1px 1px 0 var(--ink)}
.v3-call .gnote{margin:0;font:500 12px/1.5 'Outfit',sans-serif;color:var(--ink-dim)}
.v3-call .gnote a{text-decoration:underline;text-decoration-color:var(--yellow);text-decoration-thickness:2px}

/* voice-blocked notice · sits above the transcript so it cannot scroll away */
.v3-call .micwarn{display:flex;flex-direction:column;gap:7px;margin:12px 16px 0;padding:12px 14px;background:color-mix(in srgb,var(--red) 12%,var(--card));border:2px solid var(--ink);border-radius:12px}
.v3-call .micwarn[hidden]{display:none}
.v3-call .micwarn b{font:800 13.5px 'Outfit',sans-serif;color:var(--ink)}
.v3-call .micwarn .how{font:500 13px/1.5 'Outfit',sans-serif;color:var(--ink-dim)}
.v3-call .micwarn .retry{align-self:flex-start;margin-top:2px;font:800 12.5px 'Outfit',sans-serif;background:var(--yellow);color:#17151A;border:2px solid var(--ink);border-radius:999px;padding:8px 14px;box-shadow:2px 2px 0 var(--ink);cursor:pointer;transition:transform .2s}
.v3-call .micwarn .retry:active{transform:translate(2px,2px);box-shadow:0 0 0 var(--ink)}

/* typing fallback — shown when the mic is blocked, so the agent still works */
.v3-call .compose{display:flex;gap:8px;margin:10px 16px 0}
.v3-call .compose[hidden]{display:none}
.v3-call .compose input{flex:1;min-width:0;font:500 14.5px 'Outfit',sans-serif;color:var(--ink);background:var(--paper);border:2px solid var(--ink);border-radius:999px;padding:11px 15px;outline:none}
.v3-call .compose input::placeholder{color:var(--ink-dim)}
.v3-call .compose input:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 45%,transparent)}
.v3-call .compose button{flex:none;font:800 13px 'Outfit',sans-serif;background:var(--yellow);color:#17151A;border:2px solid var(--ink);border-radius:999px;padding:11px 18px;box-shadow:2px 2px 0 var(--ink);cursor:pointer;transition:transform .2s}
.v3-call .compose button:active{transform:translate(2px,2px);box-shadow:0 0 0 var(--ink)}
.v3-call .end{margin:10px 16px 16px;padding:13px 22px;font:800 15px 'Outfit',sans-serif;background:var(--red);color:#fff;border:2.5px solid var(--ink);border-radius:999px;box-shadow:4px 4px 0 var(--ink);cursor:pointer;transition:transform .2s,box-shadow .2s}
.v3-call .end:hover{transform:translate(-2px,-2px);box-shadow:6px 6px 0 var(--ink)}
.v3-call .end:active{transform:translate(2px,2px);box-shadow:1px 1px 0 var(--ink)}
@media (prefers-reduced-motion:reduce){.v3-call .head .dot{animation:none}}

/* focus */
a:focus-visible,button:focus-visible{outline:3px solid var(--blue);outline-offset:3px;border-radius:8px}

/* reveals (JS adds .in) */
html.js .v3-reveal{opacity:0;transform:translateY(26px) rotate(var(--rrot,0deg))}
html.js .v3-reveal.in{opacity:1;transform:translateY(0) rotate(var(--rrot,0deg));transition:opacity .7s var(--ease),transform .7s var(--ease)}

/* reduced motion */
@media (prefers-reduced-motion:reduce){
  .stk,.v3-nav .wm .dot,.v3-hero .scrollhint,.v3-orb .ring{animation:none}
  html.js .v3-reveal{opacity:1;transform:none}
  .do-item,.pol,.v3-btn,.wa-btn,.v3-orb{transition:none}
  /* glimpse still swaps shots on hover, it just does not fade or drift */
  .pol .ph img,.v3-gal figure{transition:none}
  .pol .ph img{transform:none}
}

/* ── REELS · silent autoplay strip, tap for sound ── */
.v3-reels{padding:clamp(30px,6vh,56px) 0 clamp(50px,8vh,80px)}
.v3-reels .rail{display:flex;gap:clamp(10px,2vw,18px);overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;padding:6px clamp(16px,5vw,64px) 14px;scrollbar-width:none}
.v3-reels .rail::-webkit-scrollbar{display:none}
.v3-reels .reel{position:relative;flex:0 0 auto;width:clamp(160px,42vw,232px);aspect-ratio:9/16;border:2px solid var(--ink);border-radius:16px;overflow:hidden;background:#0d0c10;box-shadow:0 12px 26px -12px var(--shadow);scroll-snap-align:center;cursor:pointer;transition:transform .3s var(--ease),box-shadow .3s}
.v3-reels .reel:hover{transform:translateY(-4px) scale(1.015);box-shadow:0 20px 34px -12px var(--shadow)}
.v3-reels .reel:active{transform:scale(.985)}
.v3-reels .reel:focus-visible{outline:3px solid var(--blue);outline-offset:3px}
.v3-reels .reel video{width:100%;height:100%;object-fit:cover;display:block}
.v3-reels .snd{position:absolute;right:8px;bottom:8px;width:34px;height:34px;border-radius:50%;background:rgba(10,9,12,.62);border:2px solid rgba(255,255,255,.9);display:grid;place-items:center;color:#fff;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.v3-reels .snd svg{width:17px;height:17px}
.v3-reels .snd .on{display:none}
.v3-reels .reel.loud .snd{background:var(--yellow);border-color:#17151A;color:#17151A}
.v3-reels .reel.loud .snd .on{display:block}
.v3-reels .reel.loud .snd .off{display:none}
@media (max-width:520px){.v3-reels .reel{width:min(64vw,240px)}}
@media (prefers-reduced-motion:reduce){.v3-reels .reel{transition:none}}
