/* ============================================================
   Nabhak, portfolio v6 (system pass 15 Oct 2026; full spec: docs/decisions.md "v6 system pass")
   Cream ground, white cards, ink type, ONE sun accent. Vivid colour = client-work project cards only (--case-*).
   Shape: pills = buttons/chips, --r-card = every card, --r-inner = media/icons/inner tiles.
   Buttons: primary .btn-ink, secondary .btn-ghost, tertiary .link. Focus: one 2px ink ring.
   ============================================================ */

/* ---------- Fonts ---------- */
@font-face{font-family:"Silka";src:url("../fonts/silka-regular-webfont.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Silka";src:url("../fonts/silka-medium-webfont.woff2") format("woff2");font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"Silka";src:url("../fonts/silka-bold-webfont.woff2") format("woff2");font-weight:700;font-style:normal;font-display:swap}
/* ONE type voice: Silka 400 / 500 / 700. Emphasis = the sun marker (.hl) under one bold ink word per heading. Mono only in real code blocks. */

/* ---------- Tokens ---------- */
:root{
  /* colour roles */
  --cream:#F7F5F4;        /* the only page ground */
  --white:#FFFFFF;        /* card surface; white bands only where they alternate with cream */
  --ink:#191A1E;
  --body:#5E5F62;         /* 5.6:1 on ground */
  --muted:#676C6F;        /* 4.7:1 on ground */
  --sun:#FFC94A;          /* the one accent: marker, primary hover, nav current, sticker, one full-bleed block per page */
  --line-soft:color-mix(in srgb,var(--ink) 8%,transparent);    /* hairline */
  --line-mid:color-mix(in srgb,var(--ink) 16%,transparent);    /* strong hairline: secondary button, dividers */
  --fill-soft:var(--line-soft);                                 /* pale tag / number-square fill */
  --grid-line:var(--line-soft);                                 /* .grid-spot */
  --ink-20:rgba(25,26,30,.20);
  --ink-50:rgba(25,26,30,.5);
  --white-85:rgba(247,245,244,.86);

  /* case hues: one per client project, the same on every surface it appears on (Home, Work, Work menu, case hero,
     Next project). Letters, not names: this file ships public. Ink text on all but --case-a (white text, 7.2:1). */
  --case-a:#4B32E6;
  --case-b:#C8EE5A;
  --case-c:#FF7A66;
  --case-d:#3FB5FF;
  --case-e:#FFB27A;
  --case-f:#9BE15D;
  --case-g:#FF9F2E;
  --case-h:#5BC9B6;       /* 7 Nov 2026: replaces --case-b for client b (the product's own teal; --case-b stays for the public lime tiles) */

  /* illustration-only colours (app icons, article figures and covers, demo mock-ups). Never UI chrome. */
  --teal:#009D8F;
  --teal-text:#007A6E;
  --teal-deep:#006A60;
  --mint:#3EE6C8;
  --teal-tint:#E6F7F5;
  --sun-art:#EDAF29;
  --sun-tint:#FDF3DC;
  --tangerine:#EE7633;
  --tangerine-tint:#FDEBDF;
  --tangerine-hl:#FBD1B3;
  --pinpoint-blue:#0072E8;

  /* elevation: 3 levels + hairline */
  --edge:inset 0 0 0 1px var(--line-soft);
  --edge-out:0 0 0 1px var(--line-soft);
  --shadow-rest:0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),0 18px 40px -26px color-mix(in srgb,var(--ink) 22%,transparent);
  --shadow-hover:0 2px 4px color-mix(in srgb,var(--ink) 6%,transparent),0 30px 56px -28px color-mix(in srgb,var(--ink) 32%,transparent);
  --shadow-overlay:0 32px 64px -28px rgba(25,26,30,.26),0 10px 24px -16px rgba(25,26,30,.14);

  /* Thai words fall back to the system Thai faces, no web font download for two words */
  --font:"Silka","Sukhumvit Set","Thonburi","Noto Sans Thai",system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;   /* code and prompt blocks only */

  /* type: 7 sizes (1440 / 390), weights 400 / 500 / 700 */
  --fs-cap:.8125rem;                            /* 13: captions, meta, tags */
  --fs-body:1rem;                               /* 16: body, buttons, nav, card lines */
  --fs-title:1.25rem;                           /* 20: lead, card and step titles */
  --fs-sub:clamp(1.5rem,1rem + 1.6vw,2rem);     /* 32 / 24: sub-heads, strip title, big stats, project word */
  --fs-section:clamp(2rem,1.2rem + 2.6vw,3rem); /* 48 / 32: section titles, project hero word */
  --fs-page:clamp(2.5rem,1.4rem + 3.4vw,4rem);  /* 64 / 40: every page title, the contact headline */
  --fs-hero:clamp(2.75rem,6vw,5.375rem);        /* 86 / 44: Home hero, the 7+ stat */
  --lh-tight:1.05; --lh-snug:1.3; --lh-body:1.6;
  --ls-display:-.04em; --ls-title:-.02em;

  /* shape */
  --r-inner:12px;          /* media, icons, inner tiles, inputs, number squares */
  --r-card:24px;           /* every card, sheet, strip, stage */
  --pill:999px;            /* buttons, chips, circles */
  --stroke:2px;            /* focus ring + illustration strokes */

  /* space: 4-base */
  --s-1:.25rem; --s-2:.5rem; --s-3:.75rem; --s-4:1rem; --s-5:1.5rem; --s-6:2rem;
  --s-7:3rem; --s-8:4rem; --s-9:6rem; --s-10:8rem;
  --section:clamp(4rem,2.4rem + 4.4vw,6rem);   /* 96 / 64: the one section padding */
  --gutter:clamp(1rem,4vw,2.5rem);
  --container:1200px;
  --nav-h:56px;

  /* motion (docs/motion-spec.md): three durations, three easings + one spring, two loop speeds, one lift */
  --dur-1:.15s;            /* hover / focus: colour, fill, underline, opacity */
  --dur-2:.3s;             /* lift, menus, toggles, hero fade-up, one-shot pops */
  --dur-3:.6s;             /* reveal on scroll, marker wipe, count-up */
  --dur-out:200ms;         /* exits leave faster than they arrived: mobile menu close, toast leaving (B1, 19 Oct 2026) */
  --ease:cubic-bezier(.2,.7,.2,1);          /* every interactive transition */
  --ease-out:cubic-bezier(.22,.8,.2,1);     /* entrances: reveal, hero, marker, pops, sheet */
  --ease-inout:cubic-bezier(.45,0,.55,1);   /* ambient loops */
  --ease-spring:cubic-bezier(.34,1.56,.64,1);   /* ONE playful object: the contact email icon */
  --loop:6s;               /* ambient loop period (covers: 7s) */
  --loop-vg:8s;            /* project vignettes (one story each); the mesh ground drifts at 2x */
  --lift:-4px;             /* the one hover lift for clickable cards */
  --reveal-y:16px;

  /* surfaces (owner 16 Oct 2026, Rachel-style: "gradient backgrounds and the texture in the colour, the whole website"):
     ONE grain tile for the whole site (SVG fractal noise, 4 octaves, Rachel's frequency and tile size; drawn once and
     cached by the browser), laid over the page as a fixed film (html::after) and inside every coloured .mesh surface.
     The tile is DARK-ONLY ALPHA (feColorMatrix: black, alpha = .37 - .48 x noise), so it composites as plain alpha: no
     mix-blend-mode anywhere (her multiply film cost ~40% of scroll frames > 33 ms at 1440; measured 16 Oct). Calibrated
     to her look: cream 247 -> ~238, sd ~3.6, white -> ~246. Knobs: --tex-ground = the film's strength (0 removes it),
     --tex-scale = the tile size (240px = her grain size), --mesh-grain = the extra grain inside coloured surfaces. */
  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='n' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -.48 0 0 0 .37'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --tex-ground:.26;
  --tex-scale:240px;
  --mesh-grain:.1;
}

/* ---------- Base ---------- */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;background:var(--cream)}
body{
  margin:0;background:var(--cream);color:var(--ink);
  font-family:var(--font);font-size:var(--fs-body);line-height:var(--lh-body);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
/* the page film: one fixed grain layer over everything (cream ground, white cards, photos, nav), static, no pointer
   events, plain alpha (no blend mode: one cheap composited quad). On html, not body: a body pseudo was attributed the
   hire-unlock swap's layout shift (CLS .22 on Work). Print = plain paper. */
html::after{content:"";position:fixed;inset:0;z-index:9999;pointer-events:none;opacity:var(--tex-ground);background:var(--grain) 0 0/var(--tex-scale) auto}
@media print{html::after,.mesh::before,.mesh::after{display:none}}
img,svg{display:block;max-width:100%}
img{height:auto}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;padding:0}
h1,h2,h3,h4,p{margin:0}
ul,ol{margin:0;padding:0;list-style:none}
figure{margin:0}
/* ONE focus ring site-wide: 2px ink, 3px off (works on cream, white, sun and every case hue) */
:focus-visible{outline:var(--stroke) solid var(--ink);outline-offset:3px}
[lang="th"]{font-family:"Sukhumvit Set","Thonburi","Noto Sans Thai",var(--font)}
/* anchor jumps land below the fixed nav */
[id]{scroll-margin-top:calc(var(--nav-h) + var(--s-7))}
::selection{background:var(--sun);color:var(--ink)}

.container{width:100%;max-width:var(--container);margin-inline:auto;padding-inline:var(--gutter)}
.section{padding-block:var(--section)}
.section-white{background:var(--white)}
.skip{position:absolute;left:var(--s-4);top:-100px;background:var(--ink);color:var(--white);padding:var(--s-3) var(--s-5);border-radius:var(--pill);z-index:100}
.skip:focus{top:var(--s-4)}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ---------- Type ---------- */
.h1{font-size:var(--fs-page);font-weight:700;line-height:var(--lh-tight);letter-spacing:var(--ls-display)}
.h2{font-size:var(--fs-section);font-weight:700;line-height:var(--lh-tight);letter-spacing:var(--ls-display)}
.h3{font-size:var(--fs-title);font-weight:700;line-height:var(--lh-snug);letter-spacing:var(--ls-title)}
.display{font-size:var(--fs-hero);font-weight:700;line-height:var(--lh-tight);letter-spacing:var(--ls-display)}
.lead{font-size:var(--fs-title);color:var(--body);max-width:52ch;line-height:var(--lh-body)}
.small{font-size:var(--fs-cap);color:var(--muted)}

.section-head{display:flex;flex-direction:column;gap:var(--s-4);margin-bottom:var(--s-7);align-items:flex-start}
.section-head .h2{max-width:18ch}
.section-head .lead{font-size:var(--fs-body);max-width:48ch}
.page-head{padding-top:calc(var(--nav-h) + var(--section));padding-bottom:var(--s-7)}
.page-head .h1{max-width:18ch}
.page-head .lead{margin-top:var(--s-5)}
.page-head .kicker{margin-bottom:var(--s-4)}
.kicker{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--s-3);font-size:var(--fs-cap);font-weight:500;color:var(--body)}
.kicker img{width:28px;height:28px;border-radius:var(--r-inner);box-shadow:var(--edge)}

/* Highlighter: sun marker swipes in behind a word (wraps across lines) */
.hl{display:inline;background-image:linear-gradient(var(--sun),var(--sun));background-repeat:no-repeat;background-size:0% 42%;background-position:0 90%;-webkit-box-decoration-break:clone;box-decoration-break:clone;padding:0 .06em;margin:0 -.06em;transition:background-size var(--dur-3) var(--ease-out) .1s}
.is-in .hl,.hl.is-on{background-size:100% 42%}

/* Name: plain ink (one marked word per heading: the hero's marker sits under "designer.") */
.name{display:inline-block}


/* Rotating role line (js/site.js): the typed text sits in a cell as wide as the longest word (an invisible ghost copy),
   so typing never reflows the hero (CLS 0). Caret = the typing-cursor convention, 1s steps (documented loop exception).
   Pauses offscreen, in a hidden tab and under Motion: off. */
.rotator{display:inline-grid;color:var(--ink);font-weight:700;vertical-align:bottom}
.rotator>span{grid-area:1 / 1;white-space:nowrap}
.rotator-ghost{visibility:hidden}
.rotator-txt::after{content:"";display:inline-block;width:.08em;height:.9em;margin-left:.06em;background:var(--ink);vertical-align:-.08em;animation:blink 1s steps(2) infinite}
.is-paused .rotator-txt::after{animation-play-state:paused}
@keyframes blink{to{opacity:0}}

/* ---------- Stickers + the hand-drawn arrow (the v4 outline squares / rings are gone, v6 system pass) ---------- */
.sticker{display:inline-flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-4);border-radius:var(--pill);background:var(--sun);color:var(--ink);font-size:var(--fs-cap);font-weight:700;box-shadow:var(--shadow-rest);white-space:nowrap;transform:rotate(var(--rot,-4deg))}
.doodle{position:absolute;pointer-events:none;color:var(--ink)}
.doodle path{stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:var(--len,300);stroke-dashoffset:var(--len,300)}
.is-in .doodle path,.doodle.is-on path{animation:draw var(--dur-3) var(--ease-out) forwards .25s}
@keyframes draw{to{stroke-dashoffset:0}}
.doodle-label{font-size:var(--fs-body);font-weight:500;color:var(--body)}

/* ---------- Buttons: three tiers ----------
   primary .btn-ink (ink pill; hover = sun + ink) · secondary .btn-ghost (white pill + strong hairline; hover = ink ring)
   tertiary .link (ink text + arrow; underline on hover). Sizes: 48 (default) and 40 (.btn-sm; 44 on touch).
   Arrows: → internal, ↗ external. One primary per block. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);
  min-height:48px;padding:0 var(--s-5);border-radius:var(--pill);
  font-weight:500;font-size:var(--fs-body);white-space:nowrap;
  transition:transform var(--dur-1) var(--ease),background var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease),color var(--dur-1) var(--ease);
}
.btn:active{transform:scale(.97)}
.btn svg{width:16px;height:16px;flex:0 0 auto;transition:transform var(--dur-1) var(--ease)}
.btn:hover svg{transform:translateX(3px)}
.btn[target]:hover svg{transform:translate(2px,-2px)}
.btn-ink{background:var(--ink);color:var(--white)}
.btn-ink:hover{background:var(--sun);color:var(--ink)}
.hue-sun .btn-ink:hover{background:var(--white);color:var(--ink)}   /* on a sun ground the sun hover disappears into it (owner pin 19 Oct, Home Whisper block) */
.btn-ghost{background:var(--white);color:var(--ink);box-shadow:inset 0 0 0 1px var(--line-mid)}
.btn-ghost:hover{box-shadow:inset 0 0 0 1px var(--ink)}
.btn-sm{min-height:40px;padding:0 var(--s-4)}
@media(pointer:coarse){.btn-sm{min-height:44px}}
.link{display:inline-flex;align-items:center;gap:var(--s-2);min-height:44px;font-size:var(--fs-body);font-weight:500;color:var(--ink);text-decoration:underline var(--stroke) transparent;text-underline-offset:5px;transition:text-decoration-color var(--dur-1) var(--ease)}
.link svg{width:16px;height:16px;transition:transform var(--dur-1) var(--ease)}
.link:hover{text-decoration-color:currentColor}
.link:hover svg{transform:translateX(3px)}
.link[target]:hover svg{transform:translate(2px,-2px)}

/* ---------- Labels (not clickable): .tag (+ .tag-sun dot) and .label (ink) ---------- */
.tag,.label{display:inline-flex;align-items:center;gap:var(--s-2);min-height:28px;padding:0 var(--s-3);border-radius:var(--pill);background:var(--fill-soft);font-size:var(--fs-cap);font-weight:500;color:var(--body);white-space:nowrap}
.label{font-weight:700;color:var(--ink)}
.tag-sun{background:transparent;color:var(--ink);font-weight:700}
.tag-sun::before{content:"";flex:none;width:8px;height:8px;border-radius:var(--pill);background:var(--sun)}
.tags{display:flex;flex-wrap:wrap;gap:var(--s-2)}

/* ---------- Number square + bullet ----------
   .nsq = ONE number square: pale fill, --r-inner, ink numeral; sun when active / hovered. Size --nsq (40px), fill --nsq-bg.
   Used by the article number, Home writing list, About process + skills, case-study moves. `::before` counters in
   .steps-n / .tldr (article.css) repeat these declarations because a pseudo-element cannot take a class. */
.nsq{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:var(--nsq,40px);height:var(--nsq,40px);border-radius:var(--r-inner);background:var(--nsq-bg,var(--fill-soft));color:var(--ink);font-style:normal;font-size:var(--fs-cap);font-weight:700;font-variant-numeric:tabular-nums}
/* .sqb = the site's bullet: a sun dot (same dot as .tag-sun). Size --sqb (8px), fill --sqb-bg.
   ul.list / .cs-list / .layers draw it with ::before (same declarations, see article.css + case.css). */
.sqb{display:inline-block;flex:0 0 auto;width:var(--sqb,8px);height:var(--sqb,8px);border-radius:var(--pill);background:var(--sqb-bg,var(--sun))}

/* ---------- Story text marks (articles + case studies) ----------
   p.stress mark = sun marker under the one key phrase of a point. ul.list-emoji = the emoji is the list marker (site rule). */
.stress mark,.wcv-snip mark{color:inherit;background:linear-gradient(transparent 55%,var(--mark,var(--sun)) 55%);-webkit-box-decoration-break:clone;box-decoration-break:clone}
.list-emoji li{display:grid;grid-template-columns:1.6em minmax(0,1fr);gap:var(--s-2);align-items:start}
.list-emoji .li-em{line-height:var(--lh-body);text-align:center}

/* ---------- Reveal ---------- */
/* ONE reveal: opacity + 16px rise, 600ms ease-out, once, stagger 60ms (--d on singles, nth-child on groups, max 6 steps) */
[data-reveal]{opacity:0;transform:translateY(var(--reveal-y));transition:opacity var(--dur-3) var(--ease-out),transform var(--dur-3) var(--ease-out);transition-delay:calc(var(--d,0)*60ms)}
[data-reveal].is-in{opacity:1;transform:none}
[data-reveal-children]>*{opacity:0;transform:translateY(var(--reveal-y));transition:opacity var(--dur-3) var(--ease-out),transform var(--dur-3) var(--ease-out)}
[data-reveal-children].is-in>*{opacity:1;transform:none}
[data-reveal-children].is-in>*:nth-child(2){transition-delay:60ms}
[data-reveal-children].is-in>*:nth-child(3){transition-delay:120ms}
[data-reveal-children].is-in>*:nth-child(4){transition-delay:180ms}
[data-reveal-children].is-in>*:nth-child(5){transition-delay:240ms}
[data-reveal-children].is-in>*:nth-child(6){transition-delay:300ms}
[data-reveal-children].is-in>*:nth-child(n+7){transition-delay:360ms}
/* no page wipe, no page fade: content paints at once (motion pass 15 Oct 2026) */

/* ---------- Nav ---------- */
.nav{position:fixed;inset-inline:0;top:var(--s-4);z-index:60;display:flex;justify-content:center;padding-inline:var(--s-4);pointer-events:none;transition:transform var(--dur-2) var(--ease),opacity var(--dur-2) var(--ease)}
.nav.is-hidden{transform:translateY(-140%);opacity:0}
.nav-inner{

  pointer-events:auto;display:flex;flex-direction:column;
  width:100%;max-width:calc(var(--container) - 2 * var(--gutter));padding:var(--s-2);   /* as wide as the page content and the mega sheet (owner 20 Oct) */
  background:var(--white);
  box-shadow:var(--shadow-overlay);border-radius:var(--pill);
  transition:border-radius var(--dur-2) var(--ease),background var(--dur-2) var(--ease);
}
/* light blur only where it is cheap: fine-pointer desktops. Phones get a solid pill. */
@media(min-width:900px) and (hover:hover){.nav-inner{background:var(--white-85);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}}
.nav-bar{display:flex;align-items:center;gap:var(--s-4);min-height:var(--nav-h);padding-inline:var(--s-5) var(--s-4)}
.brand{min-height:44px;font-size:var(--fs-title);font-weight:700;letter-spacing:var(--ls-title);line-height:1;flex:0 0 auto;white-space:nowrap;display:inline-flex;align-items:center;gap:2px}
.brand i{font-style:normal;color:var(--sun);display:inline-block;transition:transform var(--dur-2) var(--ease)}
.brand:hover i{transform:translateY(-4px) scale(1.3)}
.nav-links{display:none;align-items:center;gap:var(--s-1);margin-inline:auto}
.nav-links a{position:relative;padding:var(--s-2) var(--s-3);border-radius:var(--pill);font-size:var(--fs-body);font-weight:500;color:var(--body);transition:color var(--dur-1) var(--ease),background var(--dur-1) var(--ease);white-space:nowrap}
.nav-links a::after{content:"";position:absolute;left:var(--s-3);right:var(--s-3);bottom:6px;height:var(--stroke);border-radius:var(--pill);background:var(--ink);transform:scaleX(0);transform-origin:left;transition:transform var(--dur-1) var(--ease)}
.nav-links a:hover{color:var(--ink)}
.nav-links a:hover::after{transform:scaleX(1)}
.nav-links a[aria-current="page"]::after{display:none}
.nav-links a[aria-current="page"]{color:var(--ink);background:var(--sun)}
.nav-cta{display:none;margin-left:auto}
.nav-toggle{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:var(--pill);background:var(--sun);flex:0 0 auto;margin-left:auto;transition:background var(--dur-1) var(--ease)}
.nav-toggle:hover{background:var(--ink);color:var(--white)}
.nav-toggle svg{width:20px;height:20px}
.nav-toggle .ic-close{display:none}
.menu-open .nav-toggle .ic-menu{display:none}
.menu-open .nav-toggle .ic-close{display:block}
@media(min-width:900px){.nav-links{display:flex}.nav-toggle{display:none}.nav-cta{display:inline-flex;margin-left:0}}

/* ---------- Mega menu (desktop ≥900px) ----------
   One sheet for every menu, drawn like a piece of the page: cream ground, --r-card, --shadow-overlay, under the nav at
   page-content width. Inside: the page's own cards. Work = small project cards (.wk, case hues); Vibe Code = white cards;
   'list' (Writing, About) = labelled white cards of rows. Bottom strip = one more white card. */
.nav-links a[data-menu]{display:inline-flex;align-items:center;gap:2px;padding-right:var(--s-2)}
.nav-links a[data-menu]::after{display:none}
.nav-links a[data-menu]:not([aria-current="page"]):hover,.nav-links a.is-open:not([aria-current="page"]){color:var(--ink);background:var(--line-soft)}
.nav-chev{flex:none;width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;opacity:.6;transition:transform var(--dur-1) var(--ease),opacity var(--dur-1) var(--ease)}
.nav-links a.is-open .nav-chev{transform:rotate(180deg);opacity:1}
.nav-mega{position:absolute;top:100%;left:0;right:0;display:none;justify-content:center;padding-inline:var(--s-4);pointer-events:none}
@media(min-width:900px){.nav-mega{display:flex}}
.mega-sheet{
  position:relative;width:min(100%,calc(var(--container) - 2 * var(--gutter)));margin-top:var(--s-3);
  border-radius:var(--r-card);background:var(--cream);box-shadow:var(--shadow-overlay);
  opacity:0;visibility:hidden;transform:translateY(-8px);
  transition:opacity var(--dur-1) var(--ease),transform var(--dur-1) var(--ease),visibility 0s linear var(--dur-1);
}
.mega-sheet::before{content:"";position:absolute;left:0;right:0;bottom:100%;height:calc(var(--s-3) + var(--s-2))}  /* hover bridge over the gap to the nav */
.nav.is-mega .mega-sheet{opacity:1;visibility:visible;transform:none;pointer-events:auto;transition:opacity var(--dur-1) var(--ease),transform var(--dur-2) var(--ease-out),visibility 0s}
.mega-panel{display:none;border-radius:inherit;overflow:hidden}
.mega-panel.is-on{display:block;animation:megaSwap var(--dur-1) var(--ease) both}
@keyframes megaSwap{from{opacity:0}}

/* ----- 'cards': tall preview cards ----- */
.mega-cards{display:grid;gap:var(--s-4);padding:var(--s-4)}
.mega-top{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4)}
/* tall cards share row tracks (icon / title / line / preview), so previews line up when a title or line wraps */
@supports (grid-template-rows:subgrid){
  .mega-top{grid-template-rows:auto auto auto minmax(0,1fr);row-gap:0;height:clamp(232px,34vh,296px)}
  .mega-top>.mega-card{display:grid;grid-row:span 4;grid-template-rows:subgrid;justify-items:start;height:auto}
}
/* white card on the cream sheet (rest shadow, no ring); the grid only shows in the pointer spotlight (.grid-spot, js/site.js) */
.mega-card{
  position:relative;isolation:isolate;display:flex;flex-direction:column;align-items:flex-start;min-width:0;
  height:clamp(232px,34vh,296px);padding:var(--s-5) var(--s-5) 0;border-radius:var(--r-card);overflow:hidden;
  background:var(--white);box-shadow:var(--shadow-rest);
}
.mega-card{transition:box-shadow var(--dur-2) var(--ease),translate var(--dur-2) var(--ease)}
.mega-card:is(:hover,:focus-within){translate:0 var(--lift);box-shadow:var(--shadow-hover)}
.mega-ic{display:flex;margin-bottom:var(--s-4)}
/* real app icons (Vibe Code) */
.mega-app{display:block;flex:none;width:36px;height:36px;border-radius:var(--r-inner);overflow:hidden;box-shadow:var(--shadow-rest)}
.mega-app-light{outline:1px solid var(--line-mid);outline-offset:-1px}
.mega-title{font-size:var(--fs-body);font-weight:700;line-height:var(--lh-snug);color:var(--ink)}
.mega-cover::after{content:"";position:absolute;inset:0;z-index:2;border-radius:inherit}  /* the whole card is the link */
.mega-card p{margin-top:var(--s-1);font-size:var(--fs-cap);line-height:var(--lh-snug);color:var(--body)}
.mega-view{position:relative;align-self:stretch;justify-self:stretch;flex:1;min-height:0;margin-top:var(--s-4)}
/* tall-card preview: a window inset from the card edges, cropped crisp by the card's rounded bottom (no fade) */
.mega-top .mega-view{margin-inline:var(--s-2)}
.mega-top .mega-view>*{position:absolute;top:0;left:0;right:0;transition:translate var(--dur-2) var(--ease)}
/* the window always runs past the card's bottom edge (the card clips it): its own bottom corners never show */
.mega-top .mega-view>.mega-win{bottom:calc(-1 * var(--s-6))}
.mega-top .mega-shot img{height:100%;object-fit:cover;object-position:top}
.mega-top .mega-card:is(:hover,:focus-within) .mega-view>*{translate:0 -4px}
/* Work panel: three small project cards (.wk.wk-mini), same height as the Vibe Code cards */
.mega-top.mega-work{grid-template-rows:minmax(0,1fr);height:clamp(272px,38vh,336px)}
.mega-win{position:relative;display:block;border-radius:var(--r-inner);background:var(--white);box-shadow:var(--shadow-overlay);overflow:hidden}
/* ring painted over the content: a ring under a dark screenshot left a light seam at the rounded corners */
.mega-win::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:var(--edge);pointer-events:none}
.mega-shot{background:none}
.mega-win.is-empty{min-height:160px}
.mega-shot img{width:100%}

/* wide cards (Vibe Code): text left, visual right, cropped, fading in from the left */
.mega-bottom{display:grid;grid-template-columns:minmax(0,9fr) minmax(0,11fr);gap:var(--s-4)}
.mega-bottom .mega-card{display:grid;grid-template-columns:fit-content(46%) minmax(0,1fr);grid-template-rows:1fr auto auto 1fr;column-gap:var(--s-3);height:clamp(112px,15vh,128px);padding:0 0 0 var(--s-5)}
.mega-bottom .mega-title{grid-area:2 / 1}
.mega-bottom .mega-card p{grid-area:3 / 1}
@media(max-width:1099px){.mega-bottom .mega-card{grid-template-columns:fit-content(38%) minmax(0,1fr)}}
.mega-bottom .mega-view{grid-area:1 / 2 / -1 / 3;margin:0;overflow:hidden;
  -webkit-mask-image:linear-gradient(to right,transparent,var(--ink) var(--s-5));mask-image:linear-gradient(to right,transparent,var(--ink) var(--s-5))}
.mega-bottom .mega-view>*{position:absolute;top:50%;left:var(--s-6);right:var(--s-5);translate:0 -50%}  /* starts where the left fade ends */
.mega-apps{display:grid;grid-template-columns:repeat(4,minmax(0,48px));gap:var(--s-2);justify-content:start}
.mega-apps .mega-app{width:100%;height:auto;aspect-ratio:1;border-radius:var(--r-inner);box-shadow:none}  /* tiles shrink with the card so all 8 stay inside */
/* three plugin windows side by side, equal widths and gaps, name above each */
.mega-bottom .mega-view>.mega-plugs{top:var(--s-6);right:var(--s-4);translate:none}   /* the three windows sit lower and run off the bottom edge (cropped) instead of stopping a few px short of it (owner 20 Oct) */
.mega-plugs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-3)}
.mega-plug{position:relative;z-index:4;display:grid;gap:var(--s-1);min-width:0;transition:translate var(--dur-2) var(--ease)}
.mega-plug:hover,.mega-plug:focus-visible{translate:0 var(--lift)}
.mega-plug-name{overflow:hidden;font-size:var(--fs-cap);font-weight:500;color:var(--muted);white-space:nowrap;text-overflow:ellipsis;transition:color var(--dur-1) var(--ease)}
.mega-plug:is(:hover,:focus-visible) .mega-plug-name{color:var(--ink)}
.mega-plug .mega-win{box-shadow:var(--shadow-rest)}

/* ----- 'list': three labelled white cards of rows (Writing: number squares; About: text rows) ----- */
.mega-cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4);padding:var(--s-4)}
.mega-col{display:flex;flex-direction:column;gap:var(--s-1);min-width:0;padding:var(--s-5) var(--s-3) var(--s-4);border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-rest)}
.mega-col .mega-label{margin:0 var(--s-3) var(--s-2)}  /* + .micro */
.mega-item{display:flex;align-items:center;gap:var(--s-3);min-width:0;min-height:44px;padding:var(--s-2) var(--s-3);border-radius:var(--r-inner);color:var(--ink);transition:background var(--dur-1) var(--ease)}
.mega-item:is(:hover,:focus-visible){background:var(--cream)}
.mega-item:has(.mega-num){align-items:flex-start}   /* numbered rows (Writing): the number sits at the top left, level with the title's first line, not centred on a 2-3 line block (owner 20 Oct) */
.mega-item:focus-visible{outline-offset:0}
/* Writing rows lead with the number square (.nsq look, sun on hover); About rows are text only (no thin-line icons) */
.mega-tile{flex:none;display:grid;place-items:center;width:36px;height:36px;border-radius:var(--r-inner);background:var(--fill-soft);color:var(--ink);transition:background var(--dur-1) var(--ease)}
.mega-item:is(:hover,:focus-visible) .mega-tile{background:var(--sun)}
.mega-num{font-size:var(--fs-cap);font-weight:700}
.mega-item-t{display:grid;flex:1;min-width:0}
.mega-item-t b{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:var(--fs-body);font-weight:700;line-height:var(--lh-snug)}  /* long titles wrap to 2 lines */
.mega-item-t small{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:var(--fs-cap);line-height:var(--lh-snug);color:var(--muted);overflow-wrap:anywhere}  /* wraps to 2 lines on narrow sheets */
.mega-go{flex:none;width:14px;height:14px;color:var(--ink);opacity:0;transform:translateX(-4px);transition:opacity var(--dur-1) var(--ease),transform var(--dur-1) var(--ease)}
.mega-item:is(:hover,:focus-visible) .mega-go{opacity:1;transform:none}
/* row with a copy button: the button (secondary, small) sits on the row's right, outside the link */
.mega-item-wrap{position:relative}
.mega-item-wrap .mega-item{padding-right:calc(var(--s-3) + 88px)}
.mega-item-wrap .mega-go{display:none}
.mega-copy{position:absolute;top:50%;right:var(--s-2);translate:0 -50%}  /* + .btn .btn-ghost .btn-sm */
.mega-copy svg{width:14px;height:14px}
/* narrow sheets: tighter cards, icon-only copy button (its aria-label keeps the name) */
@media(max-width:1099px){
  .mega-col{padding-inline:var(--s-2)}
  .mega-item-wrap .mega-item{padding-right:calc(var(--s-3) + 44px)}
  .mega-copy{width:40px;padding:0;font-size:0;gap:0}
}
.mega-note{display:flex;align-items:baseline;gap:var(--s-2);margin:auto var(--s-3) 0;padding-top:var(--s-3);font-size:var(--fs-cap);color:var(--muted)}
.mega-note i{flex:none;align-self:center;width:8px;height:8px;border-radius:var(--pill);background:var(--sun)}
.mega-note b{color:var(--ink)}

/* ----- bottom strip (Writing, Work): one more white card. Title + count tag + line left; a light decoration right ----- */
.mega-banner{position:relative;display:flex;align-items:center;justify-content:space-between;gap:var(--s-5);min-height:84px;margin:0 var(--s-4) var(--s-4);padding:var(--s-4) var(--s-5);overflow:hidden;border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-rest)}
.mega-banner-main{position:relative;z-index:1;display:grid;gap:2px;flex:none;color:var(--ink)}
.mega-banner-t{display:flex;align-items:center;gap:var(--s-2)}
.mega-banner-t b{font-size:var(--fs-body);font-weight:700}
.mega-new{min-height:24px}  /* + .tag */
.mega-banner small{display:inline-flex;align-items:center;gap:var(--s-1);font-size:var(--fs-cap);color:var(--body)}
.mega-banner small .mega-go{opacity:1;transform:none;color:currentColor}
.mega-banner-main:is(:hover,:focus-visible) b{text-decoration:underline var(--stroke);text-underline-offset:4px}
.mega-banner-main:is(:hover,:focus-visible) .mega-go{transform:translateX(3px)}
.mega-scatter{position:absolute;top:0;right:0;bottom:0;left:46%;pointer-events:none;
  -webkit-mask-image:linear-gradient(to right,transparent,var(--ink) 16%);mask-image:linear-gradient(to right,transparent,var(--ink) 16%)}
.mega-scatter .tag{position:absolute;background:var(--cream);box-shadow:var(--edge)}
.mega-scatter .mega-sun{background:var(--sun);color:var(--ink);box-shadow:none}
.mega-scatter .mega-white{background:var(--white)}
.mega-scatter .mega-sky{background:color-mix(in srgb,var(--pinpoint-blue) 22%,var(--white));color:var(--ink);box-shadow:none}
.mega-scatter .mega-peach{background:color-mix(in srgb,var(--tangerine) 30%,var(--white));color:var(--ink);box-shadow:none}
.mega-scatter .is-faded{opacity:.45}
@media(max-width:1099px){.mega-scatter .is-wide{display:none}}
/* Work strip: client logos in a row, greyed until the pointer is on the strip */
.mega-logos{position:absolute;top:var(--s-2);right:var(--s-5);bottom:var(--s-2);left:42%;pointer-events:none}
.mega-logos img{position:absolute;width:12.5%;max-width:92px;height:auto;filter:grayscale(1);opacity:.7;transition:filter var(--dur-1) var(--ease),opacity var(--dur-1) var(--ease)}
.mega-banner:hover .mega-logos img{filter:none;opacity:1}
@media(prefers-reduced-motion:reduce){.mega-sheet{transform:none}}

/* ---------- Mobile menu: full-screen sun sheet (.mesh .hue-sun), big ink links; current page = white underline ---------- */
.menu{position:fixed;inset:0;z-index:55;background:var(--sun);display:flex;flex-direction:column;justify-content:center;padding:var(--s-8) var(--s-6);opacity:0;visibility:hidden;transition:opacity var(--dur-out) var(--ease),visibility 0s linear var(--dur-out);overflow:hidden}   /* closed state = the exit: 200 ms, links fade with it (no stagger on close) */
.menu.mesh{position:fixed}   /* .mesh sets position:relative; the sheet must stay fixed (an in-flow 700px gap = CLS .48) */
.menu-open .menu{opacity:1;visibility:visible;transition:opacity var(--dur-2) var(--ease),visibility 0s}
.menu a{display:block;font-size:var(--fs-page);font-weight:700;line-height:var(--lh-snug);letter-spacing:var(--ls-display);padding:var(--s-2) 0;opacity:0;transform:translateY(var(--reveal-y));transition:opacity var(--dur-out) var(--ease),transform var(--dur-out) var(--ease)}
.menu-open .menu a{opacity:1;transform:none;transition:opacity var(--dur-2) var(--ease-out),transform var(--dur-2) var(--ease-out);transition-delay:calc(var(--i)*60ms + 60ms)}
.menu a[aria-current="page"]{text-decoration:underline 6px var(--white);text-underline-offset:8px}
.menu-open{overflow:hidden}
.menu-foot{margin-top:var(--s-7);color:var(--ink);font-size:var(--fs-body);font-weight:500;opacity:0;transition:opacity var(--dur-out) var(--ease)}
.menu-open .menu-foot{opacity:1;transition:opacity var(--dur-2) var(--ease) .3s}

/* ---------- Footer ---------- */
.footer{border-top:1px solid var(--line-soft);padding-block:var(--s-6);font-size:var(--fs-body);color:var(--body);background:var(--white)}
.footer-inner{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:var(--s-3) var(--s-5)}
.footer-inner>span{white-space:nowrap}
.footer-links{display:flex;flex-wrap:wrap;gap:var(--s-2) var(--s-4)}
.footer-links a{min-height:44px;display:inline-flex;align-items:center;font-weight:500;transition:color var(--dur-1) var(--ease)}
.footer-links a:hover{color:var(--ink)}
.footer b{font-weight:700;color:var(--ink)}
/* footer tools row (centred under the links): Motion: on / off (WCAG 2.2.2 pause control, js/site.js; aria-pressed = motion on,
   44px target) and the hire / private mode pill when a mode is on */
.footer-tools{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:var(--s-3);margin-top:var(--s-5)}
.motion-toggle{min-height:44px;gap:var(--s-2);font-size:var(--fs-cap)}  /* + .btn .btn-ghost .btn-sm */
.motion-toggle i{width:8px;height:8px;border-radius:var(--pill);background:var(--sun);transition:background var(--dur-1) var(--ease)}
.motion-toggle[aria-pressed="false"] i{background:var(--line-mid)}

/* ---------- Toast ---------- */
.toast{position:fixed;left:50%;bottom:var(--s-6);z-index:70;transform:translate(-50%,16px);opacity:0;display:inline-flex;align-items:center;gap:var(--s-2);padding:var(--s-3) var(--s-5);border-radius:var(--pill);background:var(--ink);color:var(--white);font-size:var(--fs-body);font-weight:500;box-shadow:var(--shadow-overlay);transition:transform var(--dur-out) var(--ease),opacity var(--dur-out) var(--ease);pointer-events:none;white-space:nowrap}   /* base = leaving: 200 ms */
.toast svg{width:16px;height:16px;color:var(--sun)}
/* no-JS fallback nav (JS replaces [data-site-nav] with the real one) */
.nojs-nav{display:flex;flex-wrap:wrap;gap:var(--s-2) var(--s-4);padding:var(--s-4) var(--gutter);border-bottom:1px solid var(--line-soft);font-weight:500;font-size:var(--fs-body)}
.toast.is-on{transform:translate(-50%,0);opacity:1;transition:transform var(--dur-2) var(--ease-out),opacity var(--dur-2) var(--ease)}

/* ---------- Cursor: native arrow drawn in the site's line style ---------- */
/* SVG colours mirror --sun / --ink / --white (url() data can't read CSS variables): sun arrow at rest, ink arrow on links */
:root{
  --cursor-arrow:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28'%3E%3Cpath d='M5 3v19.5l5.4-5.1 3.6 8.1 3.6-1.6-3.5-7.9H21.5z' fill='%23FFC94A' stroke='%23191A1E' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E") 5 3, auto;
  --cursor-link:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28'%3E%3Cpath d='M5 3v19.5l5.4-5.1 3.6 8.1 3.6-1.6-3.5-7.9H21.5z' fill='%23191A1E' stroke='%23FFFFFF' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E") 5 3, pointer;
}
html,body{cursor:var(--cursor-arrow)}
a,button,label,summary,select,[role="button"]{cursor:var(--cursor-link)}
input[type="text"],input[type="email"],input[type="search"],textarea{cursor:text}

/* ---------- Grid spotlight (.grid-spot): a neutral hairline grid that shows ONLY inside a soft circle under the pointer.
   No colour fill. One shared pointermove in js/site.js writes --mx/--my (rAF, fine pointers only).
   Knobs: --spot (circle radius), --grid-cell, --grid-line. Touch / reduced motion / no JS: nothing shows. ---------- */
.grid-spot{--mx:-999px;--my:-999px;--spot:160px;position:relative;isolation:isolate}
.grid-spot::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;
  background-image:linear-gradient(var(--grid-line) 1px,transparent 1px),linear-gradient(90deg,var(--grid-line) 1px,transparent 1px);
  background-size:var(--grid-cell,28px) var(--grid-cell,28px);background-position:-1px -1px;
  -webkit-mask-image:radial-gradient(var(--spot) circle at var(--mx) var(--my),var(--ink) 0,var(--ink) 30%,transparent 100%);
  mask-image:radial-gradient(var(--spot) circle at var(--mx) var(--my),var(--ink) 0,var(--ink) 30%,transparent 100%);
  opacity:0;transition:opacity var(--dur-1) var(--ease)}
.grid-spot.is-spot::before{opacity:1}
@media(hover:none),(pointer:coarse){.grid-spot::before{display:none}}

/* Client logo wall (Home, hire; owner pin 20 Oct 2026: a still grid like ElevenLabs' customer wall, not a sliding row): 8 / 4 columns, flat light-grey logos,
   the hovered one turns to its real colours. Replaces the old marquee (engine, clone script and its reduced-motion rules removed). */
.logo-wall{max-width:var(--container);margin-inline:auto;padding-inline:var(--gutter)}   /* the page content width */
.logo-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));margin:0;padding:0;list-style:none}
@media(min-width:640px){.logo-row{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(min-width:1100px){.logo-row{grid-template-columns:repeat(8,minmax(0,1fr))}}
/* owner pin 20 Oct: the first logo wall (heading + counter, 8 x 2 equal cells, big grey logos) but without the hairlines: equal cells, no lines, logos optically the same size, grey -> brand colour on hover */
.logo-row li{display:flex;align-items:center;justify-content:center;height:96px;padding:0 var(--s-5)}
@media(min-width:1100px){.logo-row li{height:128px}}
.logo-row img{display:block;width:100%;height:56px;object-fit:contain;transform:scale(calc(var(--s,1.35) / 1.35 * 1.1));filter:grayscale(1) contrast(.9) brightness(var(--b,1.08));opacity:.62;transition:filter var(--dur-1) var(--ease),opacity var(--dur-1) var(--ease),transform var(--dur-2) var(--ease)}
.logo-row li:is(:hover,:focus-within) img{filter:none;opacity:1;transform:scale(calc(var(--s,1.35) / 1.35 * 1.1)) translateY(var(--lift))}

/* a stat without a number: overlapping app tiles sized to the figure (home + about) */
.facts-row .stat-tiles{display:flex;align-self:center;align-items:center}
.stat-tiles::before{content:"\200b"}  /* text strut: the tile row is as tall as a number line */
.stat-tiles>span{flex:none;width:.72em;height:.72em;border-radius:var(--r-inner);overflow:hidden;box-shadow:var(--shadow-rest)}
.stat-tiles>span+span{margin-left:-.2em}
/* full bleed: the lineup art is pre-rounded with a hairline of transparent edge, so it is scaled past the tile */
.stat-tiles img{display:block;width:100%;height:100%;scale:1.1}
.stat-tiles .is-light{outline:1px solid var(--line-mid);outline-offset:-1px}
.stat-tiles .is-light img{scale:1}
/* ---------- Device mockups (screens inside cards, case figures, the Work gallery) ---------- */
.browser{position:relative;border-radius:var(--r-inner);overflow:hidden;background:var(--white);box-shadow:var(--shadow-overlay)}
.browser-bar{display:flex;align-items:center;gap:var(--s-3);height:36px;padding:0 var(--s-3);background:var(--cream);border-bottom:1px solid var(--line-soft)}
.browser-bar .dots{display:flex;gap:6px}
.browser-bar .dots i{width:9px;height:9px;border-radius:var(--pill);background:var(--line-mid)}
.browser-bar .url{flex:1;max-width:260px;height:24px;margin-inline:auto;border-radius:var(--pill);background:var(--white);box-shadow:var(--edge);font-size:var(--fs-cap);line-height:24px;color:var(--muted);text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:0 var(--s-3)}
.browser-body{position:relative;overflow:hidden;background:var(--cream)}
.browser-body img{width:100%;height:100%;object-fit:cover;object-position:top}

.phone{position:relative;width:100%}
.phone img{width:100%;height:auto;filter:drop-shadow(0 30px 40px rgba(25,26,30,.35))}

/* device mocks that hover on a case stage (one ambient owner: the stage carries data-pause) */
.float{animation:float var(--loop) var(--ease-inout) infinite}
.float-slow{animation:float calc(var(--loop) * 1.3) var(--ease-inout) infinite reverse}
@keyframes float{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(0,-8px,0)}}
.is-paused .float,.is-paused .float-slow{animation-play-state:paused}

/* ---------- Project card (.wk): ONE anatomy for client work everywhere ----------
   Home Selected work, the Work page, the Work mega menu (.wk-mini) and every case page's Next project.
   Fill = the project's case hue (.case-a..g, set once in :root) as a mesh ground, r24, padding 24, a 40px
   white arrow chip top-right, one-word hook + one line, ONE white UI vignette (.vg) centred in the stage, caption row:
   "Real name · type" left, "role · status" right. Loop owner (data-pause): the vignette story + mesh drift run only while
   the card is one of the two playing owners in the viewport (js/site.js "Loop budget"); otherwise it shows the end frame.
   .wk-plain = the white skin (side projects, Soon cases). A div.wk (no link) gets no chip, no lift, no pointer.
   PUBLIC FILE: no client names here; the name → letter mapping lives in the hire-locked markup + docs/decisions.md.
   Everything that moves is transform / opacity only; off = the finished frame (reduced motion, Motion: off, menu). */
/* Hue classes: the base (--wk-bg, + --wk-fg when the text is white) and --m1..3, the three analogous blob hues of the
   mesh ground (lighter than an ink-text hue; deeper than a white-text hue). Client hues = letters (public file);
   .hue-* = the sun and the side-project / illustration colours. Any .mesh surface takes one of these. */
.case-a{--wk-bg:var(--case-a);--wk-fg:var(--white);--m1:#3620B8;--m2:#2E5BFF;--m3:#7A3FD6}
.case-b{--wk-bg:var(--case-b);--m1:#EFFFA6;--m2:#7FE3B5;--m3:#FFE98A}
.case-c{--wk-bg:var(--case-c);--m1:#FFC9B8;--m2:#FF9FD0;--m3:#FFB347}
.case-d{--wk-bg:var(--case-d);--m1:#BDEBFF;--m2:#8A9BFF;--m3:#5EF0D8}
.case-e{--wk-bg:var(--case-e);--m1:#FFE2C8;--m2:#FF9A9A;--m3:#E8C4FF}
.case-f{--wk-bg:var(--case-f);--m1:#DDFFB0;--m2:#5FD9C8;--m3:#F2F07A}
.case-g{--wk-bg:var(--case-g);--m1:#FFDFA3;--m2:#FF8A8A;--m3:#E0C0FF}
.case-h{--wk-bg:var(--case-h);--m1:#B8F0E4;--m2:#7ED9E8;--m3:#A9EBC7}
.hue-sun{--wk-bg:var(--sun);--m1:#FFE48A;--m2:#FFB45C;--m3:#FFDDB3}           /* warm yellow / amber / peach */
.hue-tan{--wk-bg:var(--tangerine);--m1:#FF9D5E;--m2:#FFBE8E;--m3:#F5865B}
.hue-mint{--wk-bg:var(--mint);--m1:#8DF5DF;--m2:#62DBF0;--m3:#BFFFE7}
.hue-teal{--wk-bg:#12B0A1;--m1:#3FC9B8;--m2:#33B8CF;--m3:#6ED6B5}      /* a notch lighter than --teal: ink text measured 4.4:1 on the teal + grain, 6:1 here */
.hue-soft{--wk-bg:var(--cream);--m1:var(--sun-tint);--m2:var(--teal-tint);--m3:var(--tangerine-tint)}   /* pale: "soon" tiles, the cream Vibe tile */
.wk-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-4)}
.wk-soon{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-4);margin-top:var(--s-4)}
.wk{position:relative;display:flex;flex-direction:column;gap:var(--s-4);min-width:0;padding:var(--s-5);border-radius:var(--r-card);background:var(--wk-bg,var(--white));color:var(--wk-fg,var(--ink));isolation:isolate}
.wk-plain{--wk-bg:var(--white);--wk-fg:var(--ink);box-shadow:var(--shadow-rest)}
.wk.is-in,a.wk{transition:transform var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease);transition-delay:0s}
a.wk:hover{transform:translateY(var(--lift));box-shadow:var(--shadow-hover)}
.wk-go{position:absolute;top:var(--s-4);right:var(--s-4);z-index:4;display:grid;place-items:center;width:40px;height:40px;border-radius:var(--pill);background:var(--white);color:var(--ink);box-shadow:var(--shadow-rest);transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.wk-plain .wk-go{background:var(--fill-soft);box-shadow:none}
.wk-go svg{width:18px;height:18px;transition:transform var(--dur-1) var(--ease)}
a.wk:hover .wk-go,a.wk:focus-visible .wk-go{background:var(--ink);color:var(--white)}
a.wk:hover .wk-go svg{transform:translateX(3px)}
a.wk[target]:hover .wk-go svg{transform:translate(2px,-2px)}
/* not a link yet: a label where the chip would be */
.wk-chip{position:absolute;top:var(--s-4);right:var(--s-4);z-index:4;min-height:32px;background:var(--white);color:var(--ink)}  /* + .tag */
.wk-plain .wk-chip{background:var(--fill-soft);color:var(--body)}
.wk-copy{position:relative;z-index:3;padding-right:var(--s-7)}
.wk-word{font-size:var(--fs-sub);font-weight:700;line-height:var(--lh-tight);letter-spacing:var(--ls-display)}
.wk-hero .wk-word{font-size:var(--fs-section)}
.wk-line{display:block;max-width:34ch;text-wrap:pretty;margin-top:var(--s-2);font-size:var(--fs-body);font-weight:500;line-height:var(--lh-snug)}
.wk-cap{position:relative;z-index:3;display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--s-1) var(--s-3);padding-top:var(--s-3);border-top:1px solid color-mix(in srgb,currentColor 24%,transparent);font-size:var(--fs-cap);font-weight:500;line-height:var(--lh-snug)}
.wk-cap>span{text-wrap:balance}
.wk-cap>span:first-child{font-weight:700}

/* media: the stage. Side-project / plain cards keep one tilted screenshot tile (.wk-tile). Client cards (.case-a..g)
   show ONE white UI vignette (.vg, below) centred on the mesh ground, nothing else: no device frames, no screenshots. */
.wk-media{position:relative;z-index:2;flex:1 1 auto;min-height:clamp(220px,58vw,320px);display:flex;align-items:flex-end;justify-content:flex-end;container-type:inline-size}
.wk-tile{position:relative;display:block;width:86%;aspect-ratio:4/3;max-height:100%;overflow:hidden;border-radius:var(--r-inner);background:var(--white);box-shadow:var(--shadow-overlay);rotate:-4deg;transition:rotate var(--dur-2) var(--ease)}
.wk-tile>img{width:100%;height:100%;object-fit:cover}
.wk-tile::after{content:"";position:absolute;inset:0;background:linear-gradient(105deg,transparent 35%,color-mix(in srgb,var(--white) 40%,transparent) 50%,transparent 65%);translate:-130% 0;transition:translate var(--dur-3) var(--ease);pointer-events:none}
a.wk:hover .wk-tile{rotate:-2deg}
a.wk:hover .wk-tile::after{translate:130% 0}
.wk-plain .wk-tile{background:var(--cream)}
.wk-tile-icon{display:grid;place-items:center}
.wk-tile-icon svg{width:56px;height:56px}

/* ---------- Surfaces: mesh + grain (.mesh) = ONE finish for every coloured surface ----------
   Client cards, case hero stages, the sun strips and the Whisper block, skills and Vibe Code tiles, article covers, the Soon tiles. The element keeps its own background colour (the hue class sets
   --wk-bg); ::before stacks three soft radial blobs in analogous hues (--m1..3 from the hue class), inset -20%, soft
   68-72% falloff, NO filter blur (an A/B against blur(28px) was indistinguishable at card scale, so the layer composites
   cheaply); ::after is the grain (the shared --grain alpha tile, --mesh-grain, no blend mode) on top of the colour. Both sit under
   the content (z -1 inside the element's own stacking context), so text, buttons and white UI stay clean.
   Static by default. The blobs drift (transform only, 2 x --loop-vg, alternate) ONLY while the element, or the loop
   owner it sits in, is a playing owner (js/site.js "Loop budget": top-most 2 on screen, so at most two mesh layers move
   at once); .is-paused, reduced motion and Motion: off = the resting pose. Blob rule for contrast: lighter than an
   ink-text hue, deeper than a white-text hue (a, blue, ink); measured per surface in docs/decisions.md "Mesh everywhere". */
.mesh{position:relative;isolation:isolate;overflow:hidden}
.mesh::before,.mesh::after{content:"";position:absolute;z-index:-1;pointer-events:none}
.mesh::before{inset:-20%;
  background:
    radial-gradient(54% 66% at 20% 20%,var(--m1) 0%,transparent 72%),
    radial-gradient(50% 64% at 84% 14%,var(--m2) 0%,transparent 70%),
    radial-gradient(62% 56% at 76% 92%,var(--m3) 0%,transparent 72%),
    radial-gradient(40% 50% at 34% 90%,var(--m2) 0%,transparent 68%)}
.mesh::after{inset:0;opacity:var(--mesh-grain);background:var(--grain) 0 0/var(--tex-scale) auto}
.mesh[data-pause]::before,[data-pause] .mesh::before{will-change:transform;animation:mesh-drift calc(var(--loop-vg) * 2) var(--ease-inout) infinite alternate}
.mesh.is-paused::before,.is-paused .mesh::before{will-change:auto;animation:none}
@keyframes mesh-drift{0%{transform:translate(0,0) scale(1) rotate(0)}50%{transform:translate(2%,-1.5%) scale(1.06) rotate(2deg)}100%{transform:translate(-2%,1.5%) scale(1.03) rotate(-2deg)}}
.wk.mesh .wk-media{display:grid;place-items:center;place-content:center;overflow:visible}

/* ---------- Vignette (.vg): one white UI card, centred in the stage, that plays the project's story in 8 s ----------
   Scale: 1em = 3% of the stage width (floor 9px), so the same card reads on the 244px bento tile and the 630px feature.
   Base markup = the END frame (the result); the keyframes carry the start states. So motion off / reduced motion / a
   paused loop owner / the Work menu (animation:none) show the finished UI, and a card that becomes a player restarts its
   story from the top. Transform + opacity only; one easing; a hard cut back to the start, like a looped clip.
   Stories are letters (vg-a..g = the case hues); every word inside them lives in hire-locked markup (tools/vignettes). */
.vg{--u:max(1cqw,3px);position:relative;width:18em;font-size:calc(3 * var(--u));line-height:1.35;font-weight:400;letter-spacing:0;text-align:left;color:var(--ink);background:var(--white);border-radius:1.07em;padding:1.53em 1.6em;box-shadow:0 .07em .17em rgba(0,0,0,.06),0 .8em 2em rgba(25,26,30,.16),inset 0 0 0 .07em var(--line-soft)}
.vg *{animation-duration:var(--loop-vg);animation-timing-function:var(--ease-out);animation-iteration-count:infinite;animation-fill-mode:both}
.wk-hero .vg{--u:max(1.3cqw,3px)}   /* the tall hero card carries the largest vignette */
.wk-wide .vg{--u:max(.85cqw,3px)}
@media(min-width:900px){.wk-grid-home .wk:not(.wk-hero) .vg{--u:max(.92cqw,3px)}}   /* the four small bento cards: a little more air round the card */
.wk-mini .vg{font-size:calc(2.7 * var(--u))}   /* the menu snapshot: a notch smaller, so the tallest story fits the mini card */
.wk.is-paused .vg *,.wk-mini .vg *{animation:none}
.vg i{font-style:normal}
.vg-ttl{display:block;font-weight:500;font-size:1.13em;line-height:1.25;margin:0 0 .2em}
.vg-sub{display:block;color:var(--muted);font-size:.9em}
.vg-chip{display:inline-flex;align-items:center;gap:.33em;height:1.73em;padding:0 .73em;border-radius:var(--pill);background:var(--sun-tint);color:var(--ink);font-size:.83em;font-weight:500;white-space:nowrap}
.vg-chip.ink{background:var(--ink);color:var(--cream)}
.vg-chip.dim{background:var(--fill-soft);color:var(--muted)}
.vg-bar{display:block;height:.67em;border-radius:.33em;background:var(--line-mid)}
.vg-ck{display:inline-grid;place-items:center;width:1.4em;height:1.4em;border-radius:var(--pill);background:var(--ink);color:var(--cream);flex:none}
.vg-ck svg,.vg-ft svg,.vg-badge svg,.vg-srch svg,.vg-send svg{display:block;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.vg-ck svg{width:.8em;height:.8em}
.vg-ptr{position:absolute;left:0;top:0;z-index:9;width:1.47em;height:1.47em;fill:var(--white);stroke:var(--ink);stroke-width:1.4;stroke-linejoin:round;filter:drop-shadow(0 .1em .2em rgba(0,0,0,.25));opacity:0}
.vg-cw{opacity:0}
.vg-caret{display:inline-block;width:.12em;height:1.07em;background:var(--ink);vertical-align:-.13em;margin-left:.1em;animation:blink 1s steps(2) infinite}

/* a: pick an identity method, the forms fill themselves */
.vg-a{height:16em}
.vg-ph{position:absolute;inset:1.53em 1.6em}
.vg-a .vg-pa{opacity:0;transform:translateX(-1.33em);animation-name:vga-pa}
.vg-a .vg-pb{animation-name:vga-pb}
.vg-a .vg-row{position:relative;display:flex;align-items:center;gap:.8em;height:2.67em;padding:0 .8em;margin-top:.53em;border-radius:.6em;box-shadow:inset 0 0 0 .07em var(--line-mid);font-size:.97em}
.vg-a .vg-sq{width:1.27em;height:1.27em;border-radius:.33em;background:var(--case-a)}
.vg-a .vg-sq.b{background:var(--ink)}
.vg-a .vg-sq.c{background:var(--case-g)}
.vg-a .vg-hl{position:absolute;inset:0;border-radius:.6em;background:color-mix(in srgb,var(--case-a) 10%,transparent);box-shadow:inset 0 0 0 .1em var(--case-a);animation-name:vga-hl}
.vg-a .vg-ck{margin-left:auto;animation-name:vga-ck}
.vg-a .vg-f{display:block;margin-top:.6em}
.vg-a .vg-l{display:block;font-size:.8em;color:var(--muted);margin-bottom:.2em}
.vg-a .vg-in{display:flex;align-items:center;height:2em;padding:0 .73em;border-radius:.47em;background:var(--fill-soft);font-size:.93em}
.vg-a .vg-in>span{animation-name:vga-f1}
.vg-a .vg-f:nth-of-type(2) .vg-in>span{animation-name:vga-f2}
.vg-a .vg-f:nth-of-type(3) .vg-in>span{animation-name:vga-f3}
.vg-a .vg-chip{position:absolute;right:0;top:0;animation-name:vga-chip}
.vg-a .vg-ptr{animation-name:vga-cur}
@keyframes vga-cur{0%{transform:translate(17em,14em);opacity:0}6%{transform:translate(17em,14em);opacity:1}20%{transform:translate(7em,5.8em) scale(1)}24%{transform:translate(7em,5.8em) scale(.85)}27%{transform:translate(7em,5.8em) scale(1)}38%{opacity:1}44%,100%{opacity:0;transform:translate(7em,5.8em)}}
@keyframes vga-hl{0%,24%{opacity:0}27%,100%{opacity:1}}
@keyframes vga-ck{0%,25%{opacity:0;transform:scale(.6)}29%,100%{opacity:1;transform:scale(1)}}
@keyframes vga-pa{0%,40%{opacity:1;transform:none}48%,100%{opacity:0;transform:translateX(-1.33em)}}
@keyframes vga-pb{0%,44%{opacity:0;transform:translateX(1.33em)}52%,100%{opacity:1;transform:none}}
@keyframes vga-f1{0%,56%{opacity:0;transform:translateY(.2em)}60%,100%{opacity:1;transform:none}}
@keyframes vga-f2{0%,62%{opacity:0;transform:translateY(.2em)}66%,100%{opacity:1;transform:none}}
@keyframes vga-f3{0%,68%{opacity:0;transform:translateY(.2em)}72%,100%{opacity:1;transform:none}}
@keyframes vga-chip{0%,74%{opacity:0;transform:translateY(.33em)}78%,100%{opacity:1;transform:none}}

/* b: search the market, results arrive, the rank chip */
.vg-b .vg-srch{display:flex;align-items:center;gap:.53em;height:2.67em;border-radius:.67em;box-shadow:inset 0 0 0 .08em var(--line-mid);padding:0 .87em}
.vg-b .vg-srch svg{width:1em;height:1em;color:var(--muted);flex:none;stroke-width:1.8}
.vg-b .vg-typed{position:relative;display:inline-block;white-space:nowrap}
.vg-b .vg-mask{position:absolute;inset:-.13em 0;background:var(--white);transform:translateX(101%);animation-name:vgb-type;animation-timing-function:steps(30,end)}
.vg-b .vg-cw{animation-name:vgb-cw}
.vg-b .vg-list{display:block;margin-top:.4em;min-height:6.4em}
.vg-b .vg-res{display:flex;align-items:center;gap:.73em;padding:.67em 0;box-shadow:0 .07em 0 var(--line-soft);animation-name:vgb-r1}
.vg-b .vg-res.r2{animation-name:vgb-r2;box-shadow:none}
.vg-b .vg-o{width:2em;height:2em;border-radius:50%;background:var(--sun-art);flex:none}
.vg-b .vg-res.r2 .vg-o{background:var(--teal);border-radius:50% 50% 50% 0;transform:rotate(-45deg)}
.vg-b .vg-res>span{min-width:0}
.vg-b .vg-n{display:block;font-size:.97em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vg-b .vg-d{display:block;font-size:.8em;color:var(--muted);white-space:nowrap}
.vg-b .vg-p{margin-left:auto;font-size:.83em;color:var(--muted);white-space:nowrap}
.vg-b .vg-chip{margin-top:.8em;animation-name:vgb-chip}
@keyframes vgb-type{0%,6%{transform:translateX(0)}24%,100%{transform:translateX(101%)}}
@keyframes vgb-cw{0%,4%{opacity:0}5%,50%{opacity:1}51%,100%{opacity:0}}
@keyframes vgb-r1{0%,28%{opacity:0;transform:translateY(.53em)}34%,100%{opacity:1;transform:none}}
@keyframes vgb-r2{0%,34%{opacity:0;transform:translateY(.53em)}40%,100%{opacity:1;transform:none}}
@keyframes vgb-chip{0%,52%{opacity:0;transform:translateY(.5em)}58%,100%{opacity:1;transform:none}}

/* c: selfie check, then the wallet (crossfade, no 3D flip) */
.vg-c{width:14em}
.vg-c .vg-front{position:relative;display:block;opacity:0;transform:scale(.96);animation-name:vgc-front}
.vg-c .vg-frame{position:relative;display:block;height:8.67em;border-radius:.67em;background:var(--fill-soft);overflow:hidden}
.vg-c .vg-face{position:absolute;left:50%;top:1.67em;width:2.67em;height:2.67em;margin-left:-1.33em;border-radius:50%;background:var(--ink-20)}
.vg-c .vg-body{position:absolute;left:50%;top:4.83em;width:5.33em;height:4.67em;margin-left:-2.67em;border-radius:2.67em 2.67em 0 0;background:var(--ink-20)}
.vg-c .vg-cn{position:absolute;width:1.33em;height:1.33em;border:.13em solid var(--ink);opacity:.7}
.vg-c .vg-cn.tl{left:.53em;top:.53em;border-right:0;border-bottom:0;border-radius:.33em 0 0 0}
.vg-c .vg-cn.tr{right:.53em;top:.53em;border-left:0;border-bottom:0;border-radius:0 .33em 0 0}
.vg-c .vg-cn.bl{left:.53em;bottom:.53em;border-right:0;border-top:0;border-radius:0 0 0 .33em}
.vg-c .vg-cn.br{right:.53em;bottom:.53em;border-left:0;border-top:0;border-radius:0 0 .33em 0}
.vg-c .vg-scan{position:absolute;left:.67em;right:.67em;top:.67em;height:.2em;border-radius:.33em;background:var(--sun);box-shadow:0 0 .67em var(--sun);opacity:0;animation-name:vgc-scan}
.vg-c .vg-badge{position:absolute;right:-.53em;top:-.53em;width:2.33em;height:2.33em;border-radius:50%;background:var(--sun);display:grid;place-items:center;animation-name:vgc-badge}
.vg-c .vg-badge svg{width:1.13em;height:1.13em;color:var(--ink)}
.vg-c .vg-cap2{display:block;margin-top:.73em;font-size:.87em;color:var(--muted);text-align:center}
.vg-c .vg-wallet{position:absolute;inset:0;padding:1.53em 1.6em;display:flex;flex-direction:column;animation-name:vgc-wallet}
.vg-c .vg-brand{font-size:.8em;letter-spacing:.1em;color:var(--muted)}
.vg-c .vg-wt{font-size:1.2em;font-weight:500;margin-top:.13em}
.vg-c .vg-msk{margin-top:auto;font-size:1.2em;letter-spacing:.2em;color:var(--body)}
.vg-c .vg-wallet .vg-chip{position:absolute;right:1.6em;bottom:1.53em;background:var(--sun);color:var(--ink)}
@keyframes vgc-front{0%,50%{opacity:1;transform:none}58%,100%{opacity:0;transform:scale(.96)}}
@keyframes vgc-wallet{0%,54%{opacity:0;transform:translateY(.5em)}62%,100%{opacity:1;transform:none}}
@keyframes vgc-scan{0%{opacity:0;transform:translateY(0)}8%{opacity:1;transform:translateY(0)}22%{transform:translateY(7em)}36%{opacity:1;transform:translateY(0)}38%,100%{opacity:0;transform:translateY(0)}}
@keyframes vgc-badge{0%,38%{opacity:0;transform:scale(.5)}43%,100%{opacity:1;transform:scale(1)}}

/* d: a payment row gets paid */
.vg-d{width:20.67em;padding:1.2em 1.33em}
.vg-d .vg-hd,.vg-d .vg-r{display:grid;grid-template-columns:1.4fr 1fr 1fr auto;align-items:center;gap:.67em}
.vg-d .vg-hd{font-size:.77em;color:var(--muted);padding-bottom:.6em;box-shadow:0 .07em 0 var(--line-soft)}
.vg-d .vg-r{height:2.73em;box-shadow:0 .07em 0 var(--line-soft)}
.vg-d .vg-r .vg-bar{height:.6em}
.vg-d .vg-bar.a{width:70%}
.vg-d .vg-bar.b{width:45%}
.vg-d .vg-st{position:relative;height:1.73em}
.vg-d .vg-st .vg-chip{position:absolute;left:0;top:0}
.vg-d .hit .due{opacity:0;transform:translateY(-.33em);animation-name:vgd-due}
.vg-d .hit .paid{animation-name:vgd-paid}
.vg-d .vg-pay{position:relative;width:3em;height:1.73em}
.vg-d .vg-pay .vg-chip{position:absolute;left:0;top:0}
.vg-d .hit .vg-pay .vg-chip{opacity:0;transform:translateY(-.33em);animation-name:vgd-due}
.vg-d .hit .vg-ck{position:absolute;left:.8em;top:.17em;animation-name:vgd-ck}
.vg-d .vg-ft{display:flex;align-items:center;gap:.53em;padding-top:.8em;font-size:.83em;color:var(--muted);animation-name:vgd-ft}
.vg-d .vg-ft svg{width:.87em;height:.87em;color:var(--ink)}
.vg-d .vg-ptr{animation-name:vgd-cur}
@keyframes vgd-cur{0%{transform:translate(19em,14em);opacity:0}6%{opacity:1;transform:translate(19em,14em)}22%{transform:translate(17.2em,6.6em) scale(1)}26%{transform:translate(17.2em,6.6em) scale(.85)}29%{transform:translate(17.2em,6.6em) scale(1)}42%{opacity:1;transform:translate(17.2em,6.6em)}48%,100%{opacity:0;transform:translate(19em,10em)}}
@keyframes vgd-due{0%,28%{opacity:1;transform:none}33%,100%{opacity:0;transform:translateY(-.33em)}}
@keyframes vgd-paid{0%,29%{opacity:0;transform:translateY(.33em)}34%,100%{opacity:1;transform:none}}
@keyframes vgd-ck{0%,30%{opacity:0;transform:scale(.6)}35%,100%{opacity:1;transform:scale(1)}}
@keyframes vgd-ft{0%,40%{opacity:0;transform:translateY(.33em)}46%,100%{opacity:1;transform:none}}

/* e: the home-health gauge fills, the maintenance team is one tap away */
.vg-e{width:15.33em}
.vg-e .vg-gauge{position:relative;display:block;height:6.67em;margin-top:.2em}
.vg-e .vg-tk{position:absolute;left:50%;top:5.67em;width:.4em;height:1.33em;margin-left:-.2em;border-radius:.33em;background:var(--ink);opacity:.14;transform-origin:50% 0}
.vg-e .vg-tk.on{opacity:1;animation-name:vge-tick}
.vg-e .vg-ndl{position:absolute;left:50%;top:1.67em;z-index:2;width:.3em;height:4em;margin-left:-.15em;border-radius:.33em;background:var(--tangerine);transform-origin:50% 100%;transform:rotate(48deg);animation-name:vge-needle}
.vg-e .vg-ndl::after{content:"";position:absolute;left:50%;bottom:-.47em;width:1em;height:1em;margin-left:-.5em;border-radius:50%;background:var(--ink)}
.vg-e .vg-val{display:flex;justify-content:space-between;align-items:baseline;margin-top:.33em;font-weight:500;font-size:1.07em;animation-name:vge-val}
.vg-e .vg-val small{font-weight:400;font-size:.75em;color:var(--muted)}
.vg-e .vg-act{position:relative;display:block;height:2.13em;margin-top:1em}
.vg-e .vg-act .vg-chip{position:absolute;left:0;top:0;height:2.13em;padding:0 .87em}
.vg-e .vg-act .a1{opacity:0;transform:translateY(-.33em);animation-name:vge-a1}
.vg-e .vg-act .a2{animation-name:vge-a2}
.vg-e .vg-ptr{animation-name:vge-cur}
@keyframes vge-tick{0%,10%{opacity:.14}14%,100%{opacity:1}}
@keyframes vge-needle{0%,10%{transform:rotate(-90deg)}44%,100%{transform:rotate(48deg)}}
@keyframes vge-val{0%,44%{opacity:0;transform:translateY(.33em)}49%,100%{opacity:1;transform:none}}
@keyframes vge-cur{0%,46%{opacity:0;transform:translate(15.3em,17.3em)}52%{opacity:1;transform:translate(15.3em,17.3em)}62%{transform:translate(6em,13.4em) scale(1)}65%{transform:translate(6em,13.4em) scale(.85)}68%{transform:translate(6em,13.4em) scale(1)}80%{opacity:1;transform:translate(6em,13.4em)}86%,100%{opacity:0;transform:translate(8.7em,16em)}}
@keyframes vge-a1{0%,66%{opacity:1;transform:none}71%,100%{opacity:0;transform:translateY(-.33em)}}
@keyframes vge-a2{0%,67%{opacity:0;transform:translateY(.33em)}72%,100%{opacity:1;transform:none}}

/* f: case study soon (a breathing placeholder; one ambient loop) */
.vg-f{width:14em;text-align:center}
.vg-f .vg-bar{margin:0 auto .67em;opacity:.45;animation:vgf-pulse var(--loop) var(--ease-inout) infinite}
.vg-f .vg-bar.h{height:3.33em;border-radius:.53em;width:100%}
.vg-f .vg-bar:nth-child(2){width:70%;animation-delay:.3s}
.vg-f .vg-bar:nth-child(3){width:50%;animation-delay:.6s}
.vg-f .vg-soon{display:block;font-size:.87em;color:var(--muted);margin-top:.33em}
@keyframes vgf-pulse{0%,100%{opacity:.45}50%{opacity:1}}

/* g: a prompt is typed and sent; the design-system Button comes back, not rebuilt */
.vg-g{width:20em}
.vg-g .vg-prompt{position:relative;display:block;font-size:1.07em;line-height:1.4;min-height:3.2em;padding-right:2.67em}
.vg-g .vg-wd:nth-child(1){animation-name:vgg-w1}
.vg-g .vg-wd:nth-child(2){animation-name:vgg-w2}
.vg-g .vg-wd:nth-child(3){animation-name:vgg-w3}
.vg-g .vg-wd:nth-child(4){animation-name:vgg-w4}
.vg-g .vg-wd:nth-child(5){animation-name:vgg-w5}
.vg-g .vg-wd:nth-child(6){animation-name:vgg-w6}
.vg-g .vg-wd:nth-child(7){animation-name:vgg-w7}
.vg-g .vg-wd:nth-child(8){animation-name:vgg-w8}
.vg-g .vg-wd:nth-child(9){animation-name:vgg-w9}
.vg-g .vg-wd:nth-child(10){animation-name:vgg-w10}
.vg-g .vg-wd:nth-child(11){animation-name:vgg-w11}
.vg-g .vg-w{display:inline-block;padding:0 .17em;margin:0 -.17em;border-radius:.3em;background:color-mix(in srgb,var(--case-g) 18%,transparent);color:color-mix(in srgb,var(--case-g) 60%,var(--ink))}
.vg-g .vg-cw{animation-name:vgg-cw}
.vg-g .vg-send{position:absolute;right:0;bottom:0;width:2.13em;height:2.13em;border-radius:50%;background:var(--ink);color:var(--white);display:grid;place-items:center;animation-name:vgg-send}
.vg-g .vg-send svg{width:1em;height:1em}
.vg-g .vg-res{display:flex;align-items:center;gap:.73em;margin-top:1em;padding-top:1em;box-shadow:0 -.07em 0 var(--line-soft);animation-name:vgg-res}
.vg-g .vg-btn{display:inline-flex;align-items:center;justify-content:center;height:1.87em;padding:0 1em;border-radius:.47em;background:var(--ink);color:var(--cream);font-size:.87em;font-weight:500}
.vg-g .vg-from{font-size:.83em;color:var(--muted)}
.vg-g .vg-res .vg-ck{margin-left:auto;animation-name:vgg-ck}
@keyframes vgg-w1{0%,8%{opacity:0}8.4%,100%{opacity:1}}
@keyframes vgg-w2{0%,10.4%{opacity:0}10.8%,100%{opacity:1}}
@keyframes vgg-w3{0%,12.8%{opacity:0}13.2%,100%{opacity:1}}
@keyframes vgg-w4{0%,15.2%{opacity:0}15.6%,100%{opacity:1}}
@keyframes vgg-w5{0%,17.6%{opacity:0}18%,100%{opacity:1}}
@keyframes vgg-w6{0%,20%{opacity:0}20.4%,100%{opacity:1}}
@keyframes vgg-w7{0%,22.4%{opacity:0}22.8%,100%{opacity:1}}
@keyframes vgg-w8{0%,24.8%{opacity:0}25.2%,100%{opacity:1}}
@keyframes vgg-w9{0%,27.2%{opacity:0}27.6%,100%{opacity:1}}
@keyframes vgg-w10{0%,29.6%{opacity:0}30%,100%{opacity:1}}
@keyframes vgg-w11{0%,32%{opacity:0}32.4%,100%{opacity:1}}
@keyframes vgg-cw{0%,6%{opacity:0}7%,49%{opacity:1}50%,100%{opacity:0}}
@keyframes vgg-send{0%,38%{transform:scale(1)}41%{transform:scale(.82)}44%,100%{transform:scale(1)}}
@keyframes vgg-res{0%,46%{opacity:0;transform:translateY(.47em)}52%,100%{opacity:1;transform:none}}
@keyframes vgg-ck{0%,56%{opacity:0;transform:scale(.6)}61%,100%{opacity:1;transform:scale(1)}}

/* wide card: copy column left, media right (Home Soon row, case Next project) */
@media(min-width:720px){
  .wk-wide{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:auto 1fr auto;column-gap:var(--s-5);min-height:280px}
  .wk-wide .wk-copy{grid-area:1 / 1}
  .wk-wide .wk-cap{grid-area:3 / 1}
  .wk-wide .wk-media{grid-area:1 / 2 / 4 / 3;min-height:0;align-items:center}
  .wk-wide .wk-tile{width:100%;aspect-ratio:16/10}
  .wk-wide .wk-copy{padding-right:0}
  .wk-wide .wk-media{margin-right:var(--s-8)}
}

@media(min-width:900px){
  .wk-grid-home{grid-template-columns:repeat(12,minmax(0,1fr));grid-template-rows:repeat(2,400px)}
  .wk-grid-home .wk-hero{grid-column:1 / 6;grid-row:1 / 3;padding:var(--s-6)}
  .wk-grid-home .case-h{grid-column:6 / 10}
  .wk-grid-home .case-c{grid-column:10 / 13}
  .wk-grid-home .case-d{grid-column:6 / 9;grid-row:2}
  .wk-grid-home .case-e{grid-column:9 / 13;grid-row:2}
  .wk-media{min-height:0}
  .wk-soon{grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* Work page: 2 x 2 grid of equal project cards */
@media(min-width:720px){.wk-grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}.wk-grid-2>.wk{min-height:520px}}

/* mini: the Work mega menu (three cards in the sheet) */
.wk-mini{gap:var(--s-3);padding:var(--s-4)}
.wk-mini .wk-go{top:var(--s-3);right:var(--s-3);width:32px;height:32px}
.wk-mini .wk-go svg{width:16px;height:16px}
.wk-mini .wk-word{font-size:var(--fs-title);letter-spacing:var(--ls-title)}
.wk-mini .wk-line{margin-top:var(--s-1);font-size:var(--fs-cap)}
.wk-mini .wk-media{min-height:0}

/* ---------- Tools shelf (about) ---------- */
.shelf{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4) var(--s-3)}
@media(min-width:560px){.shelf{grid-template-columns:repeat(6,minmax(0,1fr))}}
@media(min-width:900px){.shelf{grid-template-columns:repeat(3,max-content);gap:var(--s-2) var(--s-8);justify-content:start}.tool{padding-inline:0;min-width:120px}}
@media(min-width:1280px){.shelf{grid-template-columns:repeat(6,max-content)}}
.tool{position:relative;display:flex;flex-direction:column;align-items:center;gap:var(--s-3);padding:var(--s-4) var(--s-2);min-width:0;text-align:center}
.tool img{width:56px;height:56px;border-radius:var(--r-inner);box-shadow:var(--shadow-rest);transition:transform var(--dur-2) var(--ease)}
.tool:hover img{transform:translateY(var(--lift))}
.tool span{font-size:var(--fs-body);font-weight:500}
.tool small{display:block;font-size:var(--fs-cap);color:var(--muted);line-height:var(--lh-snug);max-width:16ch;margin-top:2px}
.tools-extra{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-top:var(--s-5)}

/* Whisper demo */
.demo{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--s-5);align-items:center;padding:var(--s-5);border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-rest)}
.keycap{position:relative;width:84px;height:84px;border-radius:var(--r-card);background:var(--white);box-shadow:0 8px 0 var(--ink),var(--edge);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;font-weight:700;font-size:var(--fs-title);letter-spacing:-.01em;color:var(--ink);transition:transform var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease),background var(--dur-1) var(--ease);user-select:none;-webkit-user-select:none;touch-action:none;-webkit-tap-highlight-color:transparent}
.keycap svg{width:14px;height:14px;color:var(--muted)}
.keycap.is-down{transform:translateY(6px);box-shadow:0 2px 0 var(--ink),var(--edge);background:var(--sun)}
.keycap-hint{display:block;margin-top:var(--s-4);text-align:center;font-size:var(--fs-cap);font-weight:500;color:var(--body)}
.demo-out{display:flex;flex-direction:column;gap:var(--s-3);min-width:0}
.wave{display:flex;align-items:center;gap:3px;height:28px}
.wave i{display:block;width:3px;height:6px;border-radius:var(--pill);background:var(--line-mid);transform-origin:center;transition:background var(--dur-2) var(--ease)}
.demo.is-live .wave i{background:var(--ink);animation:wave .8s var(--ease-inout) infinite alternate;animation-delay:calc(var(--i)*-.09s)}  /* runs only while the key is held */
@keyframes wave{from{transform:scaleY(.4)}to{transform:scaleY(3.2)}}
.transcript{min-height:1.6em;font-size:var(--fs-body);color:var(--ink);font-weight:500}
.transcript::after{content:"";display:inline-block;width:2px;height:1em;margin-left:2px;vertical-align:-2px;background:var(--ink);opacity:0}
.demo.is-live .transcript::after{opacity:1;animation:blink 1s steps(2) infinite}
.field{display:flex;align-items:center;gap:var(--s-2);min-height:44px;padding:var(--s-2) var(--s-4);border-radius:var(--r-inner);background:var(--cream);box-shadow:var(--edge);color:var(--muted);font-size:var(--fs-body);line-height:var(--lh-snug);transition:box-shadow var(--dur-2) var(--ease)}
.field .val{flex:1;min-width:0;overflow-wrap:anywhere;color:var(--ink)}
.field .badge{display:inline-flex;align-items:center;gap:4px;font-size:var(--fs-cap);font-weight:700;color:var(--ink);opacity:0;transform:translateY(4px);transition:opacity var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.field .badge svg{width:12px;height:12px}
.demo.is-pasted .field{box-shadow:inset 0 0 0 var(--stroke) var(--ink)}
.demo.is-pasted .field .badge{opacity:1;transform:none}
@media(max-width:560px){.demo{grid-template-columns:minmax(0,1fr);gap:var(--s-4);padding:var(--s-4)}.demo>div:first-child{display:flex;align-items:center;gap:var(--s-4)}.keycap{width:64px;height:64px;font-size:var(--fs-body)}.keycap-hint{margin-top:0;text-align:left}}

/* Whisper media: the film is one big clean frame (no browser chrome); the site link sits right under it */
.whisper-clip{position:relative;aspect-ratio:16/9;border-radius:var(--r-card);overflow:hidden;background:var(--cream);box-shadow:var(--shadow-overlay)}
.whisper-clip video{display:block;width:100%;height:100%;object-fit:cover}
.whisper-clip::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:var(--edge);pointer-events:none}  /* ring above the video */
/* pause / play: a round icon button on the film (WCAG pause control); behaviour in js/site.js */
.clip-toggle{position:absolute;top:var(--s-3);right:var(--s-3);z-index:1;display:grid;place-items:center;width:44px;height:44px;border-radius:var(--pill);background:var(--white);color:var(--ink);box-shadow:var(--shadow-rest);cursor:pointer;opacity:.9;transition:opacity var(--dur-1) var(--ease)}
.clip-toggle[hidden]{display:none}
.clip-toggle:is(:hover,:focus-visible){opacity:1}
.clip-toggle svg{width:16px;height:16px}
.clip-toggle .i-play,.clip-toggle.is-paused .i-pause{display:none}
.clip-toggle.is-paused .i-play{display:block}

/* ---------- Vibe Code: shared app-icon family + "More on the way" art (the bento itself: "Vibe Code bento" block at the end) ---------- */
/* .micro = small label (card category, menu column label): caption size, sentence case */
.micro{margin:0;font-size:var(--fs-cap);font-weight:500;line-height:var(--lh-snug);color:var(--muted)}

/* Icon family (Vibe Code cards + the Vibe Code mega menu): real app icons are images (Whisper, Hop, UI Kit);
   the rest are inline SVG glyphs on a two-stop gradient tile (--ic-a light, --ic-b deep). */
.app-ic{background:var(--ic-b);background:linear-gradient(145deg,var(--ic-a),var(--ic-b))}
.app-ic svg{display:block;width:100%;height:100%}
.app-ic .w{fill:var(--white)}
.app-ic .k{fill:var(--ink)}
.app-ic .s{fill:var(--sun)}
.app-ic .t{fill:var(--tangerine)}
.app-ic .m{fill:var(--mint)}
.app-ic .tl{fill:var(--teal)}
.app-ic .td{fill:var(--teal-deep)}
.app-ic .c{fill:var(--ic-b)}
.app-ic .rim{stroke:var(--white);stroke-width:2.5;paint-order:stroke}
.app-ic .ck{fill:none;stroke:var(--white);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
/* vivid two-stop tiles: light top-left, deeper bottom-right (Hop icon feel) */
.ic-frame{--ic-a:color-mix(in srgb,var(--ink) 70%,var(--pinpoint-blue));--ic-b:var(--ink)}
.ic-pin{--ic-a:color-mix(in srgb,var(--pinpoint-blue) 70%,var(--mint));--ic-b:color-mix(in srgb,var(--pinpoint-blue) 85%,var(--ink))}
.ic-tone{--ic-a:var(--mint);--ic-b:var(--teal)}
.ic-color{--ic-a:var(--sun);--ic-b:color-mix(in srgb,var(--sun) 80%,var(--tangerine))}
.ic-text{--ic-a:color-mix(in srgb,var(--tangerine) 55%,var(--sun));--ic-b:var(--tangerine)}
.tile-actions{display:flex;gap:var(--s-2);flex-wrap:wrap;align-items:center}

/* Pin demo */
.pinboard{position:relative;height:200px;border-radius:var(--r-inner);overflow:hidden;background:var(--white);box-shadow:var(--edge);cursor:crosshair;user-select:none;-webkit-user-select:none;-webkit-tap-highlight-color:transparent}
.pinboard:focus-visible{outline-offset:2px}
.fake-page{position:absolute;inset:var(--s-4) var(--s-4) var(--s-7);display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);gap:var(--s-3);pointer-events:none}
.fake-page .bar{border-radius:var(--pill);background:var(--line-soft);height:10px;margin-bottom:8px}
.fake-page .box{border-radius:var(--r-inner);background:var(--cream);box-shadow:var(--edge);flex:1}
.fake-page .col{display:flex;flex-direction:column;gap:6px}
.fake-page .w60{width:60%}.fake-page .w80{width:80%}.fake-page .w40{width:40%}.fake-page .acc{background:var(--mint)}
.pin{position:absolute;width:28px;height:28px;margin:-28px 0 0 -14px;border-radius:50% 50% 50% 4px;transform:rotate(-45deg) scale(0);background:var(--tangerine);box-shadow:0 0 0 2px var(--white),0 4px 10px -2px color-mix(in srgb,var(--ink) 38%,transparent);display:flex;align-items:center;justify-content:center;animation:pinIn var(--dur-2) var(--ease-out) forwards}
.pin span{transform:rotate(45deg);color:var(--white);font-size:11px;font-weight:700}
@keyframes pinIn{from{transform:rotate(-45deg) scale(0)}to{transform:rotate(-45deg) scale(1)}}
.pin-hint{position:absolute;inset-inline:0;bottom:var(--s-3);text-align:center;font-size:var(--fs-cap);font-weight:500;color:var(--muted);pointer-events:none;transition:opacity var(--dur-2) var(--ease)}
.pinboard.has-pins .pin-hint{opacity:0}

/* Momo Frame mock (placeholder until the real screenshot): one dark video-review window in the Vibe Code art frame.
   Player (16:9, letterbox bars around a 2.39:1 scene: soft sky, sun disc, two low hills, a small logo with note pin 1),
   frame counter on the top bar, round white play button; a notes panel beside it; a strip of six frame thumbnails;
   the timeline (current time, ticks, two note markers, the playhead = the card's one loop, duration). Sized in em,
   1em from the window width (--vb-w), so it scales with the frame and stays inside it. Text: white / ink only (>= 4.5:1). */
.fm{display:flex;flex-direction:column;gap:.5em;padding:.6em;font-size:clamp(8px,calc(var(--vb-w) / 25),13px);background:color-mix(in srgb,var(--white) 7%,var(--ink));color:var(--white)}
.fm-main{flex:1 1 auto;min-height:0;display:flex;gap:.5em}
.fm-player{position:relative;flex:none;height:100%;aspect-ratio:16/9;border-radius:.4em;overflow:hidden;background:var(--ink)}   /* the bars */
.fm-scene{position:absolute;left:0;right:0;top:50%;aspect-ratio:2.39;translate:0 -50%;overflow:hidden;background:linear-gradient(color-mix(in srgb,var(--case-d) 55%,var(--white)),color-mix(in srgb,var(--case-d) 18%,var(--white)))}
.fm-sun{position:absolute;left:22%;top:22%;width:11%;aspect-ratio:1;border-radius:var(--pill);background:color-mix(in srgb,var(--sun) 85%,var(--white))}
.fm-hill{position:absolute;left:-15%;width:80%;bottom:-55%;height:100%;border-radius:50%;background:color-mix(in srgb,var(--teal) 70%,var(--white))}
.fm-hill-b{left:40%;width:85%;bottom:-62%;background:color-mix(in srgb,var(--teal) 88%,var(--ink))}
.fm-logo{position:absolute;right:9%;bottom:16%;width:15%;height:20%;border-radius:.25em;background:var(--white)}
.fm-logo b{position:absolute;left:-.55em;top:-.65em;display:grid;place-items:center;width:1.3em;height:1.3em;border-radius:var(--pill);background:var(--tangerine);color:var(--ink);font-size:.8em;font-weight:700;font-style:normal;line-height:1;box-shadow:0 0 0 .15em var(--white)}
.fm-count{position:absolute;left:.4em;top:.15em;font-size:.7em;font-weight:500;line-height:1.3;color:var(--white);font-variant-numeric:tabular-nums}
.fm-btn{position:absolute;left:50%;top:50%;width:clamp(20px,2.6em,40px);aspect-ratio:1;translate:-50% -50%;border-radius:var(--pill);background:var(--white);box-shadow:var(--shadow-rest)}
.fm-btn::before{content:"";position:absolute;left:38%;top:30%;width:34%;height:40%;background:var(--ink);clip-path:polygon(0 0,100% 50%,0 100%)}
.fm-notes{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:.3em;padding:.45em;border-radius:.4em;background:color-mix(in srgb,var(--white) 12%,var(--ink))}
.fm-n{display:flex;align-items:center;gap:.35em;font-size:.75em;font-weight:500;line-height:1.3;color:color-mix(in srgb,var(--white) 75%,var(--ink));font-variant-numeric:tabular-nums}
.fm-n b{display:grid;place-items:center;width:1.4em;height:1.4em;border-radius:var(--pill);background:var(--tangerine);color:var(--ink);font-weight:700}
.fm-notes p{margin:0;max-width:none;font-size:.8em;font-weight:500;line-height:1.3;color:var(--white)}
.fm-strip{flex:none;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.25em;height:1.7em}
.fm-strip i{border-radius:.2em;opacity:.45;background:linear-gradient(transparent 58%,color-mix(in srgb,var(--teal) 70%,var(--white)) 58%),linear-gradient(color-mix(in srgb,var(--case-d) 55%,var(--white)),color-mix(in srgb,var(--case-d) 18%,var(--white)))}
.fm-strip i.is-on{opacity:1}
.fm-scrub{flex:none;display:flex;align-items:center;gap:.5em}
.fm-time{flex:none;font-size:.7em;font-weight:500;line-height:1;color:color-mix(in srgb,var(--white) 75%,var(--ink));font-variant-numeric:tabular-nums}
.fm-track{position:relative;flex:1;height:1.2em;border-radius:.3em;background:repeating-linear-gradient(90deg,color-mix(in srgb,var(--white) 22%,transparent) 0 1px,transparent 1px .5em) center/100% 40% no-repeat,color-mix(in srgb,var(--white) 6%,transparent)}
.fm-mark{position:absolute;left:var(--x,39%);top:50%;width:.55em;height:.55em;margin:-.275em 0 0 -.275em;border-radius:var(--pill);background:var(--tangerine)}
.fm-mark+.fm-mark{--x:68%}
.fm-head{position:absolute;left:39%;top:-.25em;bottom:-.25em;width:2px;margin-left:-1px;border-radius:var(--pill);background:var(--white)}

/* Color demo */
.swatches{display:grid;grid-template-columns:repeat(var(--n,10),minmax(0,1fr));gap:4px;min-height:72px}
.swatches i{display:block;border-radius:var(--r-inner);background:var(--sw);transition:background var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.swatches i:hover{transform:translateY(var(--lift))}
.swatches i.base{box-shadow:inset 0 0 0 2px var(--white),inset 0 0 0 4px var(--ink)}
.color-ctrl{display:flex;align-items:center;gap:var(--s-4);flex-wrap:wrap}
.color-ctrl label{font-size:var(--fs-cap);font-weight:500;color:var(--body)}
.hue{-webkit-appearance:none;appearance:none;flex:1;min-width:140px;height:10px;border-radius:var(--pill);background:linear-gradient(90deg,hsl(0 80% 60%),hsl(60 80% 60%),hsl(120 60% 55%),hsl(180 70% 50%),hsl(220 85% 60%),hsl(280 70% 60%),hsl(360 80% 60%));outline-offset:6px}
.hue::-webkit-slider-thumb{-webkit-appearance:none;width:22px;height:22px;border-radius:var(--pill);background:var(--white);box-shadow:var(--edge-out),0 4px 10px -4px var(--ink-50);cursor:var(--cursor-link)}
.hue::-moz-range-thumb{width:22px;height:22px;border-radius:var(--pill);background:var(--white);border:1px solid var(--line-soft);cursor:var(--cursor-link)}
.seg{display:inline-flex;padding:3px;border-radius:var(--pill);background:var(--white);box-shadow:var(--edge)}
.seg button{min-height:44px;padding:0 var(--s-4);border-radius:var(--pill);font-size:var(--fs-body);font-weight:500;color:var(--body);transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),transform var(--dur-1) var(--ease)}
.seg button:active{transform:scale(.97)}
.seg button[aria-pressed="true"]{background:var(--ink);color:var(--white)}
.hex{font-variant-numeric:tabular-nums;font-size:var(--fs-body);font-weight:500;color:var(--ink);min-width:7ch}

/* Text specimen */
.specimen{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--s-5);align-items:center;padding:var(--s-5);border-radius:var(--r-card);background:var(--white);box-shadow:var(--edge)}
.specimen .aa{font-size:4.5rem;font-weight:700;line-height:1;letter-spacing:-.06em;color:var(--ink)}
.specimen .aa em{font-style:normal;color:var(--tangerine)}
.specimen ul{display:flex;flex-direction:column;gap:var(--s-2);min-width:0}
.specimen li{display:flex;justify-content:space-between;gap:var(--s-3);font-size:var(--fs-cap);color:var(--muted);border-bottom:1px solid var(--line-soft);padding-bottom:var(--s-1)}
.specimen li b{font-weight:500;color:var(--ink)}
.specimen li:nth-child(1) b{font-size:1.1rem;letter-spacing:-.03em;font-weight:700}
.specimen li:nth-child(2) b{font-size:1rem}
.specimen li:nth-child(4) b{font-size:.8rem;color:var(--body)}

/* ---------- Writing page ---------- */
.filters{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-bottom:var(--s-6)}
.filters button{min-height:44px;padding:0 var(--s-4);border-radius:var(--pill);font-size:var(--fs-body);font-weight:500;color:var(--body);background:var(--white);box-shadow:var(--edge);transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease),transform var(--dur-1) var(--ease)}
.filters button:hover{color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.filters button:active{transform:scale(.97)}
.filters button[aria-pressed="true"]{background:var(--ink);color:var(--white);box-shadow:none}
/* .post/.thumb: Next note (articles) + the Writing grid (.post-card, below) */
.post{display:flex;flex-direction:column;gap:var(--s-4);min-width:0;transition:transform var(--dur-2) var(--ease)}
.post:hover{transform:translateY(var(--lift))}
.post.is-hidden{display:none}
.thumb{position:relative;aspect-ratio:4/3;border-radius:var(--r-inner);overflow:hidden;padding:var(--s-5);display:flex;flex-direction:column;justify-content:space-between;background:var(--cream);color:var(--ink)}
.thumb .t-n{position:relative;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--r-inner);font-size:var(--fs-cap);font-weight:700;background:var(--white);color:var(--ink)}
.thumb .t-title{position:relative;font-size:var(--fs-title);font-weight:700;line-height:var(--lh-snug);letter-spacing:var(--ls-title);max-width:16ch}
.post-body{display:flex;flex-direction:column;gap:var(--s-1);padding-inline:var(--s-1)}
.post-body h3{font-size:var(--fs-title);font-weight:700;letter-spacing:var(--ls-title);line-height:var(--lh-snug)}
.post-body p{color:var(--body);font-size:var(--fs-body)}
.post-meta{display:flex;align-items:center;gap:var(--s-2);font-size:var(--fs-cap);font-weight:500;color:var(--muted);margin-top:var(--s-1)}

/* ---------- Process (about) ---------- */
.process-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-7)}
@media(min-width:900px){.process-grid{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:var(--s-10)}}
.process-sticky{position:relative}
@media(min-width:900px){.process-sticky{position:sticky;top:clamp(6rem,14vh,9rem);align-self:start}}
.process-sticky .h2{margin-top:var(--s-4)}
.process-sticky .lead{margin-top:var(--s-4);font-size:var(--fs-body)}
.progress{display:none;position:relative;margin-top:var(--s-7);width:var(--stroke);height:160px;background:var(--line-mid)}
.progress i{position:absolute;inset:0;background:var(--ink);transform-origin:top;transform:scaleY(var(--p,0));transition:transform var(--dur-1) linear}
@media(min-width:900px){.progress{display:block}}
.steps{display:flex;flex-direction:column;gap:var(--s-4)}
.step{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--s-5);align-items:start;padding:var(--s-6);border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-rest);transition:opacity var(--dur-2) var(--ease),transform var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease)}
@media(min-width:900px){.step{opacity:.7;transform:scale(.985);padding:var(--s-7);min-height:30vh;align-content:center}.step.is-active{opacity:1;transform:none;box-shadow:var(--shadow-hover)}}
.step-num{--nsq:36px;transition:background var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}  /* + .nsq */
.step.is-active .step-num{background:var(--sun);transform:rotate(6deg)}
.step-body{display:flex;flex-direction:column;gap:var(--s-3);min-width:0}
.step p{color:var(--body);max-width:44ch}
.step .out{font-size:var(--fs-body);color:var(--ink);font-weight:500}
.glyph{width:72px;height:56px;position:relative;margin-bottom:var(--s-2)}
.glyph *{position:absolute}
.g-chat .b{height:22px;border-radius:var(--r-inner);background:var(--white);box-shadow:var(--edge)}
.g-chat .b1{left:0;top:4px;width:44px;border-bottom-left-radius:4px}
.g-chat .b2{right:0;top:30px;width:36px;background:var(--sun);box-shadow:none;border-bottom-right-radius:4px}
.step.is-active .g-chat .b1{animation:popIn var(--dur-2) var(--ease-out) both}
.step.is-active .g-chat .b2{animation:popIn var(--dur-2) var(--ease-out) both .2s}
.g-wire .x{width:30px;height:22px;border-radius:var(--r-inner);background:var(--white);box-shadow:var(--edge)}
.g-wire .x1{left:0;top:0}.g-wire .x2{left:38px;top:0}.g-wire .x3{left:0;top:30px}.g-wire .x4{left:38px;top:30px;background:var(--sun);box-shadow:none}
.step.is-active .g-wire .x{animation:popIn var(--dur-2) var(--ease-out) both}
.step.is-active .g-wire .x2{animation-delay:.1s}.step.is-active .g-wire .x3{animation-delay:.2s}.step.is-active .g-wire .x4{animation-delay:.3s}
.g-chip .c{height:16px;border-radius:var(--pill);box-shadow:var(--edge)}
.g-chip .c1{left:0;top:2px;width:40px;background:var(--white)}
.g-chip .c2{left:0;top:22px;width:56px;background:var(--sun)}
.g-chip .c3{left:0;top:42px;width:28px;background:var(--ink);box-shadow:none}
.step.is-active .g-chip .c{animation:slideIn var(--dur-2) var(--ease-out) both}
.step.is-active .g-chip .c2{animation-delay:.12s}.step.is-active .g-chip .c3{animation-delay:.24s}
@keyframes slideIn{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:none}}
.g-code .l{height:6px;border-radius:var(--pill);background:var(--line-mid);transform-origin:left}
.g-code .l1{left:0;top:4px;width:48px}.g-code .l2{left:12px;top:18px;width:34px;background:var(--sun)}.g-code .l3{left:12px;top:32px;width:52px;background:var(--ink)}.g-code .l4{left:0;top:46px;width:20px}
.g-code .caret{left:26px;top:44px;width:2px;height:10px;background:var(--ink);animation:blink 1s steps(2) infinite}
.step.is-active .g-code .l{animation:growX var(--dur-2) var(--ease-out) both}
.step.is-active .g-code .l2{animation-delay:.1s}.step.is-active .g-code .l3{animation-delay:.2s}.step.is-active .g-code .l4{animation-delay:.3s}
@keyframes growX{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* ---------- About ---------- */
.bio{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-6);align-items:center;position:relative}
@media(min-width:900px){.bio{grid-template-columns:minmax(0,4fr) minmax(0,8fr);gap:var(--s-9)}}
.bio-avatar{position:relative;width:min(100%,220px);justify-self:start}
@media(min-width:900px){.bio-avatar{width:min(100%,300px)}}
.bio-avatar img,.bio-avatar svg{display:block;height:auto;width:100%;border-radius:var(--r-card) var(--r-card) var(--pill) var(--pill);box-shadow:var(--shadow-overlay)}
.bio-avatar .sticker{position:absolute;right:-16px;bottom:12%;--rot:6deg}
.bio-copy{display:flex;flex-direction:column;gap:var(--s-4);min-width:0}
.bio-copy .lead{max-width:60ch}
.bio-copy p{color:var(--body);max-width:60ch}
.bio-copy .h1{max-width:16ch}
.facts-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-4);margin-top:var(--s-3)}
@media(min-width:640px){.facts-row{grid-template-columns:repeat(4,minmax(0,1fr))}}
.facts-row div{min-width:0;padding:var(--s-3) 0;border-top:1px solid var(--line-soft)}
.facts-row b{display:block;font-size:var(--fs-sub);font-weight:700;letter-spacing:var(--ls-display);line-height:var(--lh-tight)}
.facts-row div>span{font-size:var(--fs-cap);color:var(--body);font-weight:500}
.facts-row .stat-tiles>span{width:1.05em;height:1.05em}

/* Experience: big years, one editorial row per role (outlined year, solid for the current role) */
.years{border-bottom:1px solid var(--line-soft)}
.year-row{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,7fr) 96px;gap:var(--s-5);align-items:center;min-height:128px;padding:var(--s-4) var(--s-5);border-top:1px solid var(--line-mid);transition:background var(--dur-1) var(--ease)}
.year-row .yr{font-size:var(--fs-section);font-weight:700;letter-spacing:var(--ls-display);line-height:1;color:var(--muted);font-variant-numeric:tabular-nums;transition:color var(--dur-1) var(--ease)}
.year-row.is-now .yr{color:var(--ink)}
.year-row .jb{display:flex;flex-direction:column;gap:var(--s-1);min-width:0}
.year-row .ttl{font-size:var(--fs-title);font-weight:700;letter-spacing:var(--ls-title);color:var(--ink)}
.year-row .co{color:var(--body)}
.year-row img{justify-self:end;width:72px;height:72px;object-fit:contain;transition:transform var(--dur-2) var(--ease)}
.year-row:hover{background:var(--sun)}
.year-row:hover .yr{color:var(--ink)}
.year-row:hover img{transform:scale(1.08)}
/* current company: a small card in the shape of the Tools shelf items (icon box, name, site) */
.co-card{position:relative;justify-self:end;display:flex;flex-direction:column;align-items:center;min-width:96px;text-align:center;color:var(--ink)}
.co-card .co-ic{display:grid;place-items:center;width:64px;height:64px;padding:var(--s-2);border-radius:var(--r-inner);background:var(--white);box-shadow:var(--shadow-rest);transition:transform var(--dur-2) var(--ease)}
.year-row .co-card img{display:block;justify-self:center;width:40px;height:40px;object-fit:contain;transform:none}
.co-card small{position:absolute;top:calc(100% + var(--s-2));left:-2em;right:-2em;white-space:nowrap;display:flex;justify-content:center;align-items:center;gap:2px;font-size:var(--fs-cap);color:var(--ink);font-weight:500;opacity:0;transform:translateY(-4px);transition:opacity var(--dur-1) var(--ease),transform var(--dur-1) var(--ease)}
.co-card:hover small,.co-card:focus-visible small{opacity:1;transform:none}
@media(hover:none){.co-card small{opacity:1;transform:none}}
.co-card small svg{width:12px;height:12px;transition:transform var(--dur-1) var(--ease)}
.co-card:hover .co-ic,.co-card:focus-visible .co-ic{transform:translateY(var(--lift))}
.co-card:hover small svg,.co-card:focus-visible small svg{transform:translate(2px,-2px)}
@media(max-width:640px){.year-row .co-more{display:none}.year-row{min-height:168px;grid-template-columns:minmax(0,1fr) 56px;gap:var(--s-2) var(--s-4);padding-inline:var(--s-3)}.year-row .jb{grid-column:1}.year-row>img,.year-row>.co-card{grid-row:1 / span 2;grid-column:2}.year-row.is-now{grid-template-columns:minmax(0,1fr) auto}.co-card{min-width:0}.co-card .co-ic{width:56px;height:56px}.year-row .co-card img{width:34px;height:34px}.year-row img{width:56px;height:56px}}

/* Skill grid (about) */
.skill-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-5) var(--s-7)}
@media(min-width:720px){.skill-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1024px){.skill-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
.skill{padding-top:var(--s-4);border-top:1px solid var(--line-soft);min-width:0}
.skill h3{font-size:var(--fs-title);font-weight:700;letter-spacing:var(--ls-title);display:flex;align-items:center;gap:var(--s-3)}
.skill h3 i{--nsq:32px;transition:background var(--dur-1) var(--ease)}  /* + .nsq */
.skill:hover h3 i{background:var(--sun)}
.skill p{margin-top:var(--s-2);color:var(--body);font-size:var(--fs-body);max-width:36ch}

/* ---------- Contact ---------- */
.contact{position:relative;overflow:hidden}
.contact .container{position:relative;z-index:1}
.mega{font-size:var(--fs-page);font-weight:700;line-height:var(--lh-tight);letter-spacing:var(--ls-display);margin-top:var(--s-4);max-width:12ch}
.email{display:inline-flex;align-items:center;gap:var(--s-4);margin-top:var(--s-6);font-size:var(--fs-title);font-weight:500;letter-spacing:var(--ls-title);line-height:var(--lh-tight);overflow-wrap:anywhere;color:var(--ink);transition:color var(--dur-1) var(--ease);text-align:left;max-width:100%}
.email:hover>span:last-child{text-decoration:underline var(--stroke);text-underline-offset:6px}
.email .ic{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:52px;height:52px;border-radius:var(--pill);background:var(--sun);transition:background var(--dur-1) var(--ease),transform var(--dur-2) var(--ease-spring)}
@media(min-width:900px){.email{font-size:var(--fs-sub)}}
.email .ic svg{width:20px;height:20px}  /* inherits the chip colour: ink on sun, white on ink (owner pin 15 Oct: icon vanished on hover) */
.email:is(:hover,:focus-visible) .ic{background:var(--ink);color:var(--white);transform:rotate(-12deg) scale(1.08)}
.socials{display:flex;flex-wrap:wrap;gap:var(--s-3);margin-top:var(--s-6)}
.clock{margin-top:var(--s-6);font-size:var(--fs-body);color:var(--body)}
.clock b{font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
@media(max-width:899px){.contact .sq,.contact .ring{display:none}}

/* CTA strip (subpages): one sun card on the cream ground, its section only adds space below */
.strip-sec{padding-top:0}
.section-white+.strip-sec{padding-top:var(--section)}
.strip{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-5);align-items:center;padding:var(--s-6);border-radius:var(--r-card);background:var(--sun);position:relative;overflow:hidden}
.strip>*{position:relative;min-width:0}
.strip .h2{font-size:var(--fs-sub);max-width:18ch}
.strip p{color:var(--ink);margin-top:var(--s-3);max-width:44ch}
.strip-actions{display:flex;flex-wrap:wrap;gap:var(--s-3)}
@media(min-width:900px){.strip{grid-template-columns:minmax(0,1fr) auto;padding:var(--s-7)}}
/* Buttons on the sun strip: the primary hovers white (sun on sun would vanish) */
.strip .btn-ink:hover{background:var(--white);color:var(--ink)}

/* ---------- Still sheet: prefers-reduced-motion AND the footer "Motion: off" toggle (html[data-motion="off"]) ----------
   Every animation ends on its last frame at once (the resting styles are the finished frames), transitions are instant,
   reveals are visible, the typed caret stops; films and the typing are stopped by
   js/site.js. The same rules appear twice (media query / attribute), generated from one list: keep both in sync. A visitor
   who prefers reduced motion can still switch the toggle to on (html[data-motion="on"] wins over the media block).
   Pointer effects (grid spotlight) are off under reduced motion only. Focus rings untouched. */
@media(prefers-reduced-motion:reduce){
  html:not([data-motion="on"]) .grid-spot::before{display:none}
  html:not([data-motion="on"]){scroll-behavior:auto}
  html:not([data-motion="on"]) :is(*,*::before,*::after){animation-duration:.001ms!important;animation-iteration-count:1!important;animation-delay:0s!important;transition-duration:.001ms!important;transition-delay:0s!important}
  html:not([data-motion="on"]) [data-reveal],html:not([data-motion="on"]) [data-reveal-children]>*{opacity:1;transform:none}
  html:not([data-motion="on"]) .hero .display,html:not([data-motion="on"]) .hero-role,html:not([data-motion="on"]) .hero .kicker,html:not([data-motion="on"]) .hero .lead,html:not([data-motion="on"]) .hero-actions,html:not([data-motion="on"]) .avatar,html:not([data-motion="on"]) .avatar .sticker,html:not([data-motion="on"]) .avatar .doodle,html:not([data-motion="on"]) .avatar .doodle-label,html:not([data-motion="on"]) .bio-avatar .sticker{opacity:1;transform:none;animation:none}
  html:not([data-motion="on"]) .hero .name::after{transform:none;animation:none}
  html:not([data-motion="on"]) .hl{background-size:100% 42%}
  html:not([data-motion="on"]) .doodle path{stroke-dashoffset:0}
  html:not([data-motion="on"]) .float,html:not([data-motion="on"]) .float-slow,html:not([data-motion="on"]) .mesh::before,html:not([data-motion="on"]) .vg *,html:not([data-motion="on"]) .sk-vig *,html:not([data-motion="on"]) .vb-play,html:not([data-motion="on"]) .pp *{animation:none}
  html:not([data-motion="on"]) .step{opacity:1;transform:none}
  html:not([data-motion="on"]) .rotator-txt::after{animation:none}
  html:not([data-motion="on"]) .av-live.is-idle .av-glint,html:not([data-motion="on"]) .av-live.is-idle .av-spark,html:not([data-motion="on"]) .av-live.is-blink .av-face{animation:none}
  html:not([data-motion="on"]) .mega-sheet{transform:none}
  html:not([data-motion="on"]) .key-sheet{transition:none}
  html:not([data-motion="on"]) .transcript .wd.is-pop{animation:none}
  html:not([data-motion="on"]) :is(.post-lead,.post-card,.vb-link):is(:hover,:focus-visible,:focus-within){translate:none}
  html:not([data-motion="on"]) .vb-link:is(:hover,:focus-within) .vb-art>.vb-win{rotate:var(--vb-tilt);translate:none}
}
html[data-motion="off"]{scroll-behavior:auto}
html[data-motion="off"] :is(*,*::before,*::after){animation-duration:.001ms!important;animation-iteration-count:1!important;animation-delay:0s!important;transition-duration:.001ms!important;transition-delay:0s!important}
html[data-motion="off"] [data-reveal],html[data-motion="off"] [data-reveal-children]>*{opacity:1;transform:none}
html[data-motion="off"] .hero .display,html[data-motion="off"] .hero-role,html[data-motion="off"] .hero .kicker,html[data-motion="off"] .hero .lead,html[data-motion="off"] .hero-actions,html[data-motion="off"] .avatar,html[data-motion="off"] .avatar .sticker,html[data-motion="off"] .avatar .doodle,html[data-motion="off"] .avatar .doodle-label,html[data-motion="off"] .bio-avatar .sticker{opacity:1;transform:none;animation:none}
html[data-motion="off"] .hero .name::after{transform:none;animation:none}
html[data-motion="off"] .hl{background-size:100% 42%}
html[data-motion="off"] .doodle path{stroke-dashoffset:0}
html[data-motion="off"] .float,html[data-motion="off"] .float-slow,html[data-motion="off"] .mesh::before,html[data-motion="off"] .vg *,html[data-motion="off"] .sk-vig *,html[data-motion="off"] .vb-play,html[data-motion="off"] .pp *{animation:none}
html[data-motion="off"] .step{opacity:1;transform:none}
html[data-motion="off"] .rotator-txt::after{animation:none}
html[data-motion="off"] .av-live.is-idle .av-glint,html[data-motion="off"] .av-live.is-idle .av-spark,html[data-motion="off"] .av-live.is-blink .av-face{animation:none}
html[data-motion="off"] .mega-sheet{transform:none}
html[data-motion="off"] .key-sheet{transition:none}
html[data-motion="off"] .transcript .wd.is-pop{animation:none}
html[data-motion="off"] :is(.post-lead,.post-card,.vb-link):is(:hover,:focus-visible,:focus-within){translate:none}
html[data-motion="off"] .vb-link:is(:hover,:focus-within) .vb-art>.vb-win{rotate:var(--vb-tilt);translate:none}

/* ---------- Utilities ---------- */
.pt-0{padding-top:0}
.mt-5{margin-top:var(--s-5)}
.mt-7{margin-top:var(--s-7)}

/* ---------- Avatar idle twinkle (glasses) ---------- */
.av-glint{opacity:0;transform-box:fill-box;transform-origin:center;transform:translateX(0) rotate(28deg)}
.av-spark{opacity:0;transform-box:fill-box;transform-origin:center;transform:scale(0)}
.av-live.is-idle .av-glint{animation:av-glint 1.6s var(--ease) 1 both}   /* once per pointer rest, not a loop */
.av-live.is-idle .av-glint:nth-of-type(2){animation-delay:.1s}
.av-live.is-idle .av-spark{animation:av-spark 1.6s var(--ease) 1 both}
@keyframes av-glint{0%,8%{opacity:0;transform:translateX(0) rotate(28deg)}14%{opacity:.85}34%,100%{opacity:0;transform:translateX(88px) rotate(28deg)}}
@keyframes av-spark{0%,26%{opacity:0;transform:scale(0) rotate(0)}34%{opacity:1;transform:scale(1.15) rotate(20deg)}46%{opacity:1;transform:scale(.9) rotate(40deg)}56%,100%{opacity:0;transform:scale(0) rotate(60deg)}}
/* background shapes: pointer parallax only (JS on .av-bg); the three idle float loops were removed in the motion pass */

/* ---------- Momo Copy Review card (case page demo + static lineup preview) ---------- */
.tone-card{display:flex;flex-direction:column;gap:var(--s-3);padding:var(--s-5);border-radius:var(--r-inner);background:var(--white);box-shadow:var(--edge),var(--shadow-overlay);min-width:0}
.tone-card-head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2)}
.tone-row{padding:var(--s-3) var(--s-4);border-radius:var(--r-inner);transition:opacity var(--dur-2) var(--ease),background var(--dur-2) var(--ease)}
.tone-row p{max-width:none;color:var(--ink);line-height:var(--lh-body)}
.tone-label{display:block;font-size:var(--fs-cap);font-weight:500;color:var(--body);margin-bottom:var(--s-1)}
.tone-old{background:var(--tangerine-tint)}
.tone-old del{background:var(--tangerine-hl);text-decoration:line-through;text-decoration-color:var(--tangerine);text-decoration-thickness:2px}
.tone-new{background:var(--teal-tint)}
.tone-new button{font:inherit;color:inherit;margin:0;padding:0 .15em;border-radius:4px;background:transparent;cursor:pointer;transition:background var(--dur-1) var(--ease)}
.tone-new .add{background:var(--line-soft)}
.tone-new button:hover{background:var(--ink-20)}
.tone-new button[aria-pressed="true"]{background:var(--sun)}
.tone-key{margin-left:var(--s-2);padding:0 .3em;border-radius:4px;background:var(--line-soft);color:var(--ink)}
.tone-comment{display:block}
.tone-comment textarea{display:block;width:100%;min-height:64px;padding:var(--s-2) var(--s-3);border:0;border-radius:var(--r-inner);background:var(--cream);box-shadow:var(--edge);font:inherit;font-size:var(--fs-body);color:var(--ink);resize:vertical;transition:box-shadow var(--dur-1) var(--ease)}
.tone-comment textarea::placeholder{color:var(--muted)}
.tone-comment textarea:focus{outline:0;box-shadow:inset 0 0 0 var(--stroke) var(--ink)}
.tone-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--s-2) var(--s-3);margin:var(--s-2) calc(var(--s-5) * -1) calc(var(--s-5) * -1);padding:var(--s-3) var(--s-5);border-top:1px solid var(--line-soft);border-radius:0 0 var(--r-inner) var(--r-inner);background:var(--cream)}
.tone-count{font-size:var(--fs-body);color:var(--body);font-variant-numeric:tabular-nums}
.tone-hint{font-size:var(--fs-body);color:var(--muted);min-height:1.6em;max-width:none}
.tone-card.is-ok .tone-old{opacity:.45}
.tone-card.is-ok .tone-new{box-shadow:inset 0 0 0 var(--stroke) var(--ink)}
.tone-card.is-no .tone-new{opacity:.45}
.tone-card.is-no .tone-old{box-shadow:inset 0 0 0 var(--stroke) var(--tangerine)}
.tone-card [aria-pressed="true"].btn-ghost{background:var(--sun)}
.tone-row .tone-th{margin-top:var(--s-1);font-size:var(--fs-body);color:var(--body);line-height:var(--lh-body)}
.link-inline{color:var(--ink);font-weight:500;text-decoration:underline;text-underline-offset:3px}

/* ---------- Modes (public / hire / private) ---------- */
html:not([data-mode="hire"]):not([data-mode="private"]) [data-mode-min="hire"],
html:not([data-mode="private"]) [data-mode-min="private"]{display:none!important}
.mode-pill{min-height:44px}  /* + .btn .btn-ghost .btn-sm, in .footer-tools */
.av-live.is-blink .av-face{animation:avBlink var(--dur-2) var(--ease)}
@keyframes avBlink{50%{opacity:.35}}
.key-sheet{position:fixed;inset:0;z-index:90;display:grid;place-items:center;padding:var(--s-4);background:var(--ink-50);opacity:0;transition:opacity var(--dur-1) var(--ease)}
.key-sheet.is-on{opacity:1}
.key-card,.lock-form{display:grid;gap:var(--s-3);width:min(100%,360px);padding:var(--s-6);border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-overlay)}
.key-card b,.lock-form b{font-size:var(--fs-title);letter-spacing:var(--ls-title)}
.key-card p,.lock-form p{font-size:var(--fs-body);color:var(--body)}
.key-card input,.lock-form input{min-height:44px;padding:0 var(--s-3);border:0;border-radius:var(--r-inner);background:var(--cream);box-shadow:var(--edge);font:inherit;color:var(--ink)}
.key-card input:focus,.lock-form input:focus{outline:0;box-shadow:inset 0 0 0 var(--stroke) var(--ink)}
.key-card.is-wrong input,.lock-form.is-wrong input{box-shadow:inset 0 0 0 var(--stroke) var(--tangerine)}
.key-actions{display:flex;gap:var(--s-2)}
.lock-wrap{min-height:70vh;display:grid;place-items:center;padding:var(--s-10) var(--s-4) var(--s-8)}
/* public mode (the default before js/site.js sets data-mode): Writing sits right after the hero via flex order, no DOM move
   (a move after first paint was a 0.04 layout shift), so the order is hero → Writing → sun spotlight → skills (cream) → contact;
   contact goes white so no two cream bands stack. Hire / private: source order. */
html:not([data-mode="hire"]):not([data-mode="private"]) .page{display:flex;flex-direction:column}
html:not([data-mode="hire"]):not([data-mode="private"]) .page>*{order:2}
html:not([data-mode="hire"]):not([data-mode="private"]) .page>.hero{order:0}
html:not([data-mode="hire"]):not([data-mode="private"]) .page>[data-public-after]{order:1}
html:not([data-mode="hire"]):not([data-mode="private"]) .contact{background:var(--white)}

/* Momo Whisper demo: spoken Thai words pop in one at a time */
.transcript .wd{display:inline-block;margin-right:.3em}
.transcript .wd.is-pop{animation:wordPop var(--dur-2) var(--ease-out) both}
@keyframes wordPop{from{opacity:0;transform:translateY(6px) scale(.8)}to{opacity:1;transform:none}}

/* ============================================================
   Home: the v4 arrangement and block forms, in the v6 skin (soft edges, no ink outlines, one font, sun marker).
   Hero → Brands (hire, logo wall) → Selected work (hire) → Whisper spotlight (sun) → What I can do → Writing (white) → Contact (cream)
   ============================================================ */
/* ---------- Hero: copy left, the tall avatar card right with a 'that's me' arrow note and one sticker.
   Entrance (motion pass): ONE 300ms fade-up on the copy, an opacity fade on the avatar, the sun marker wipes in from 200ms,
   the sticker and note pop from 150 / 200ms, the arrow draws from 250ms: everything settled by ~750ms. Ambient: only the
   typed role line (its caret). The avatar looks at the pointer; its glint plays once when the pointer rests. ---------- */
.hero{position:relative;overflow:hidden;padding-top:calc(var(--nav-h) + var(--section));padding-bottom:var(--s-7)}
.hero.grid-spot{--spot:220px;--grid-cell:44px}
.hero-grid{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-6);align-items:center}
.hero-copy{display:flex;flex-direction:column;gap:var(--s-5);min-width:0}
.hero .display{max-width:11ch;isolation:isolate}
.hero .display .thai{display:block;font-size:var(--fs-sub);font-weight:500;letter-spacing:var(--ls-title);color:var(--body);margin-bottom:var(--s-2)}
.hero-role{font-size:var(--fs-sub);font-weight:500;letter-spacing:var(--ls-title);line-height:var(--lh-snug);color:var(--ink)}
.hero .lead{max-width:44ch}
.hero-actions{display:flex;flex-wrap:wrap;gap:var(--s-3)}
/* the headline + role line are the LCP element: they rise with transform only (opacity 1 from the first frame; Chrome never
   reports an element first painted at opacity 0). The small lines fade up with them. */
.hero .display,.hero-role{animation:riseIn var(--dur-2) var(--ease-out) both}
.hero .kicker,.hero .lead,.hero-actions{animation:fadeUp var(--dur-2) var(--ease-out) both}
@keyframes riseIn{from{transform:translateY(var(--reveal-y))}to{transform:none}}
@keyframes fadeUp{from{opacity:0;transform:translateY(var(--reveal-y))}to{opacity:1;transform:none}}
/* the name's sun marker (same look as .hl) wipes in after the letters */
.hero .name{position:relative;z-index:0;padding-inline:.04em;margin-inline:-.04em}
.hero .name::after{content:"";position:absolute;left:0;right:0;bottom:.04em;height:.36em;z-index:-1;background:var(--sun);transform:scaleX(0);transform-origin:left;animation:markIn .5s var(--ease-out) .2s forwards}
@keyframes markIn{to{transform:scaleX(1)}}
.avatar{position:relative;justify-self:center;width:100%;animation:avatarIn var(--dur-2) var(--ease-out) both}
@keyframes avatarIn{from{opacity:0}to{opacity:1}}
.avatar-frame{position:relative}
.avatar img{width:100%;height:auto;border-radius:var(--r-card);box-shadow:var(--shadow-rest)}
.avatar-desk{display:none}
.avatar-mobile{display:block}
.avatar .sticker{position:absolute;right:-12px;bottom:18%;--rot:6deg}
.avatar .doodle{left:-96px;top:44%;width:96px;height:70px}
.avatar .doodle-label{position:absolute;left:-150px;top:40%;transform:rotate(-8deg);white-space:nowrap}
/* decorations pop in once (no idle bob: motion pass) */
.avatar .sticker,.avatar .doodle,.avatar .doodle-label,.bio-avatar .sticker{animation:popIn var(--dur-2) var(--ease-out) var(--pop-d,0s) both}
.avatar .sticker{--pop-d:.15s}
.avatar .doodle,.avatar .doodle-label{--pop-d:.2s}
.bio-avatar .sticker{--pop-d:.3s}
@keyframes popIn{from{opacity:0;transform:translateY(6px) scale(.9) rotate(var(--rot,0deg))}to{opacity:1;transform:translateY(0) scale(1) rotate(var(--rot,0deg))}}
@media(max-width:899px){.avatar .doodle,.avatar .doodle-label{display:none}.avatar .sticker{right:var(--s-3);bottom:var(--s-3)}}
@media(min-width:900px){
  .hero{min-height:min(calc(100svh - 4.5rem),860px);display:flex;align-items:center;padding-bottom:var(--s-6)}
  .hero-grid{grid-template-columns:minmax(0,7fr) minmax(0,5fr);gap:var(--s-9);align-items:center}
  .avatar{justify-self:end;width:min(100%,330px);margin-right:var(--s-6)}
  .avatar-desk{display:block}
  .avatar-mobile{display:none}
  .avatar-desk svg{display:block;width:100%;height:auto;border-radius:var(--r-card) var(--r-card) 999px 999px;box-shadow:var(--shadow-hover)}   /* v6: soft shadow, no ink ring */
}

/* ---------- Section head row: heading left, a "see all" secondary button right ---------- */
.section-head-row{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-4);align-items:end;margin-bottom:var(--s-7)}
@media(min-width:900px){.section-head-row{grid-template-columns:minmax(0,1fr) auto;gap:var(--s-8)}}
.section-head-row .section-head{margin:0}
.section-head-row>.btn{justify-self:start}

/* ---------- Brands I've designed for (hire): still logo wall on the white band, no visible heading (the h2 is .sr) ---------- */
.clients{position:relative;padding-block:var(--s-7)}

/* ---------- Whisper spotlight: the sun block. Copy left (app head, headline, more tools), the film right ---------- */
.spotlight{position:relative;overflow:hidden;background:var(--sun);color:var(--ink)}
.spot-grid{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-7)}
@media(min-width:900px){.spot-grid{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:var(--s-9);align-items:center}}
.spot-copy{display:flex;flex-direction:column;gap:var(--s-4);min-width:0}
.spot-copy .h2{max-width:14ch}
.spot-copy p{color:var(--ink);max-width:48ch}
.spot-copy .credit{font-size:var(--fs-body);color:color-mix(in srgb,var(--ink) 78%,var(--sun))}
/* one action only (owner pin 14 Oct 2026): the ink pill to all side projects; Whisper's own site link lives on Vibe Code */
.spot-actions{margin-top:var(--s-2)}
.spot-visual{display:flex;flex-direction:column;align-items:flex-start;gap:var(--s-4);min-width:0}
.spot-visual .whisper-clip{width:100%}
.app-head{display:flex;align-items:center;gap:var(--s-3)}
.app-head img{width:48px;height:48px;border-radius:var(--r-inner);box-shadow:var(--shadow-rest);flex:0 0 auto}
.app-head .kind{font-size:var(--fs-cap);font-weight:500;color:color-mix(in srgb,var(--ink) 78%,var(--sun))}
.app-head .name-app{font-weight:700;font-size:var(--fs-title);letter-spacing:var(--ls-title)}
@media(max-width:899px){.spotlight .sq,.spotlight .ring{display:none}}

/* ---------- What I can do: skills bento (owner pick 15 Oct 2026, family.co pattern): white INFO cards on cream ----------
   Not links: no chip, no lift, no pointer. Colour lives ONLY in each card's small vignette tile (.sk-art = .mesh with a
   case hue at tile scale, or the sun). Vignettes are transform/opacity only. Home shows them in the card panel (.cs) below;
   .sk-grid / .sk / .sk-skill stay for the design-system page.
   PLAY ONCE (16 Oct 2026, docs/motion-spec.md "How a vignette behaves"): no loops and no loop owners in this section. Each card
   (data-play) gets .is-play from js/site.js when half of it scrolls in (80 ms stagger), plays its sk-* set ONE time (every set
   ENDS on the rest frame = the base style = the finished state, fill-mode both), the class comes off, and it replays on hover /
   focus / tap. Motion: off and reduced motion never add .is-play, so the rest frames show; nothing here is ever paused mid-frame. */
:root{--sk-ink-soft:color-mix(in srgb,var(--ink) 30%,transparent)}   /* dashed slots, tracks */
.sk-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-4)}
.sk{position:relative;display:flex;flex-direction:column;gap:var(--s-2);min-width:0;padding:var(--s-5);border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-rest);color:var(--ink)}
.sk-small{font-size:var(--fs-body);line-height:var(--lh-snug);color:var(--body)}
/* the vignette tile: the only colour on a skills card (.mesh + a hue class: a case hue at tile scale, or the sun) */
.sk-art{display:grid;place-items:center;height:120px;margin-bottom:var(--s-3);border-radius:var(--r-inner);background:var(--wk-bg)}
/* ---------- What I can do: card panel (owner pin 20 Oct 2026, elevenlabs.io/careers 'Life at ElevenLabs';
   docs/research/home-cardstack/). One pale cream panel on the white band. REST: the eight cards lie in a tilted fan (card 1 on
   top, expand chip), fanned by --tx --ty --rot --sc per card, squared up until the panel reveals (settle once). Fine pointer +
   Motion on: --px/--py on the stage move each card by its depth --k through the individual translate / rotate properties,
   hover lifts the pile (the reference's translateZ stagger as scale). OPEN (.is-open, js/site.js "Card panel"): every card
   takes the same row transform, --o = its offset from the active card (0 = centre, the row runs off the right edge), arrows
   beside the active card, close button top right, caption cross-fades. The stage height never changes, so nothing below
   moves. transform / opacity only, no loops; Motion off / reduced motion = instant state changes (still sheet). */
.cs{
  --cw:clamp(240px,26vw,320px);--cs-gap:var(--s-5);--fan:1;--zoom:1.4;
  position:relative;overflow:clip;padding-block:var(--s-7) var(--s-6);border-radius:var(--r-card);background:var(--cream);
  box-shadow:inset 0 0 0 1px var(--line-soft)
}
@media(min-width:1100px){.cs{--zoom:1.7}}
@media(max-width:599px){.cs{--cw:72vw;--cs-gap:var(--s-4);--fan:.6;--zoom:1.6;padding-block:var(--s-6) var(--s-5)}}
.cs-stage{position:relative;height:calc(var(--cw) * .8 + 2 * var(--s-6))}
.cs-card{
  --tx:0%;--ty:0%;--rot:-2deg;--sc:1;--k:1;--i:0;
  position:absolute;left:50%;top:50%;z-index:calc(8 - var(--i));width:var(--cw);aspect-ratio:5 / 4;
  margin:calc(var(--cw) * -.4) 0 0 calc(var(--cw) * -.5);border-radius:var(--r-inner);background:var(--white);
  box-shadow:0 0 0 5px var(--white),0 0 0 6px var(--line-soft),var(--shadow-rest);
  transform:translate(calc(var(--tx) * var(--fan)),var(--ty)) rotate(var(--rot)) scale(var(--sc));
  translate:calc(var(--px,0) * var(--k) * 10px) calc(var(--py,0) * var(--k) * 6px);
  rotate:calc(var(--px,0) * var(--k) * 2deg);
  transition:transform var(--dur-3) var(--ease-out) calc(var(--i) * 25ms),scale var(--dur-2) var(--ease-out);
  will-change:transform   /* the tilt (translate / rotate) is written per frame by js/site.js, so it has no CSS transition of its own */
}
.cs-card:nth-child(2){--i:1;--tx:16%;--ty:-4%;--rot:5deg;--sc:.94;--k:.7}
.cs-card:nth-child(3){--i:2;--tx:-16%;--ty:-3%;--rot:-6deg;--sc:.94;--k:.6}
.cs-card:nth-child(4){--i:3;--tx:29%;--ty:1%;--rot:9deg;--sc:.88;--k:.5}
.cs-card:nth-child(5){--i:4;--tx:-29%;--ty:2%;--rot:-9deg;--sc:.88;--k:.4}
.cs-card:nth-child(6){--i:5;--tx:40%;--ty:4%;--rot:12deg;--sc:.82;--k:.3}
.cs-card:nth-child(7){--i:6;--tx:-40%;--ty:5%;--rot:-12deg;--sc:.82;--k:.2}
html[data-motion="on"] .cs:not(.is-in) .cs-card{transform:translate(0%,4%) rotate(0deg) scale(.86)}
@media(hover:hover) and (pointer:fine){
  html[data-motion="on"] .cs:not(.is-open) .cs-stage:hover .cs-card{scale:calc(1 + var(--k) * .04)}
}
.cs.is-open .cs-card{will-change:auto;transform:translate(calc(var(--o,0) * (100% + var(--cs-gap))),0%) rotate(0deg) scale(1);translate:none;rotate:none;scale:none;cursor:pointer}
.cs.is-open .cs-stage{touch-action:pan-y}
.cs-card>.sk-art{position:relative;height:100%;margin:0;overflow:hidden;border-radius:inherit}
.cs-zoom{scale:var(--zoom)}
.cs-word{position:absolute;left:var(--s-3);bottom:var(--s-3);padding:var(--s-1) var(--s-3);border-radius:var(--pill);background:var(--white);box-shadow:var(--shadow-rest);font-size:var(--fs-cap);font-weight:700;color:var(--ink);white-space:nowrap}
.cs-expand{position:absolute;top:var(--s-3);right:var(--s-3);display:grid;place-items:center;width:36px;height:36px;border-radius:var(--pill);background:var(--white);box-shadow:var(--shadow-rest);color:var(--ink);transition:opacity var(--dur-1) var(--ease)}
.cs-expand svg{width:16px;height:16px}
.cs.is-open .cs-expand{opacity:0}

/* Home card panel: the Enterprise card is typography only (see below) */
.is-play /* sector tiles (owner pin 15 Oct): calm cream tile, ink line icon (24px, 1.75 stroke), one small case-hue dot */
.sk-tile{position:relative;display:grid;place-items:center;flex:none;width:48px;height:48px;border-radius:var(--r-inner);background:var(--cream);color:var(--ink)}
.sk-tile::after{content:"";position:absolute;top:6px;right:6px;width:8px;height:8px;border-radius:var(--pill);background:var(--sk-dot);box-shadow:0 0 0 2px var(--cream)}
.sk-tile svg{width:24px;height:24px;stroke-width:1.75}
@keyframes sk-rise{from{opacity:0;transform:translateY(8px) scale(.9)}to{opacity:1;transform:none}}
/* the open button covers the top card only (its focus ring hugs it); hidden while open */
.cs-open{position:absolute;left:50%;top:50%;z-index:20;width:var(--cw);aspect-ratio:5 / 4;margin:calc(var(--cw) * -.4) 0 0 calc(var(--cw) * -.5);border-radius:var(--r-inner);cursor:pointer;-webkit-tap-highlight-color:transparent}
.cs-open:focus-visible{outline-offset:8px}
.cs-arrow,.cs-close{position:absolute;z-index:30;display:grid;place-items:center;width:44px;height:44px;border-radius:var(--pill);background:var(--white);color:var(--ink);box-shadow:inset 0 0 0 1px var(--line-soft),var(--shadow-rest);transition:background var(--dur-1) var(--ease)}
.cs-arrow:hover,.cs-close:hover{background:var(--cream)}
.cs-arrow:active,.cs-close:active{scale:.97}
.cs-arrow svg,.cs-close svg{width:20px;height:20px}
.cs-arrow[hidden],.cs-close[hidden],.cs-open[hidden]{display:none}
.cs-arrow{top:50%;margin-top:-22px}
.cs-next{left:calc(50% + var(--cw) / 2 + var(--s-3))}
.cs-prev{right:calc(50% + var(--cw) / 2 + var(--s-3))}
.cs-close{top:var(--s-3);right:var(--s-3)}
@media(max-width:599px){.cs-next{left:calc(50% + var(--cw) / 2 - 22px)}.cs-prev{right:calc(50% + var(--cw) / 2 - 22px)}}
/* caption: title + up to two lines (+ n / 8 when open); all of it reserved so it never moves the page */
.cs-cap{display:flex;flex-direction:column;align-items:center;gap:var(--s-1);min-height:calc(var(--fs-title) * var(--lh-snug) + 3em * var(--lh-snug) + 2 * var(--s-1));margin-top:var(--s-4);padding-inline:var(--s-5);text-align:center;font-size:var(--fs-body);line-height:var(--lh-snug);color:var(--body);text-wrap:pretty;transition:opacity var(--dur-1) var(--ease)}
.cs-cap.is-swap{opacity:0}
.cs-cap-title{font-size:var(--fs-title);font-weight:700;letter-spacing:var(--ls-title);color:var(--ink)}
.cs-count{font-size:var(--fs-cap);font-weight:500;color:var(--muted);font-variant-numeric:tabular-nums}
.cs-count:empty{display:none}
/* six skills: one word + a tiny vignette + the full name. The base style of every piece IS the finished frame (rest); the
   sk-* sets below run once on .is-play (<= 6 s, the gears) and end exactly there. Easings: the two ambient tokens only. */
.sk-skill{gap:var(--s-1)}
.sk-word{font-size:var(--fs-title);font-weight:700;letter-spacing:var(--ls-title);line-height:var(--lh-snug)}
.sk-vig{position:relative;width:128px;height:64px}
/* optical centring in the tile: each drawing's visible box (resting frame) measured against the tile, offset by the difference (owner pin 15 Oct; tools/review/v6s-center.mjs) */
.vig-ux{translate:21px -1px}.vig-sys{translate:11px 1px}.vig-proto{translate:20px -3px}.vig-work{translate:7.4px 1.3px}.vig-tools{translate:20.75px -1px}.vig-qa{translate:1px 1px}
.sk-vig i{position:absolute;display:block}
/* UX/UI: a dashed wireframe box turns into a rounded card */
.vig-ux .v-wire,.vig-ux .v-card{left:0;top:6px;width:86px;height:54px}
.vig-ux .v-wire{border:1.5px dashed var(--sk-ink-soft);opacity:0}
.vig-ux .v-card{border-radius:var(--r-inner);background:var(--white);box-shadow:var(--shadow-rest)}
.is-play .vig-ux .v-wire{animation:sk-wire 2s var(--ease-inout) both}
.is-play .vig-ux .v-card{animation:sk-card 2s var(--ease-inout) both}
.vig-ux .v-card i{left:12px;height:6px;border-radius:var(--pill);background:var(--sk-ink-soft)}
.vig-ux .v-card i:first-child{top:14px;width:44px;background:var(--ink)}
.vig-ux .v-card i:last-child{top:28px;width:58px}
@keyframes sk-wire{0%,35%{opacity:1}70%,100%{opacity:0}}
@keyframes sk-card{0%,35%{opacity:0;transform:scale(.8)}70%,100%{opacity:1;transform:none}}
/* Systems: three tokens snap into their slots */
.vig-sys .v-slot,.vig-sys .v-tok{top:16px;width:30px;height:30px;border-radius:var(--r-inner)}
.vig-sys .v-slot{border:1.5px dashed var(--sk-ink-soft)}
.vig-sys :nth-child(1),.vig-sys :nth-child(4){left:0}
.vig-sys :nth-child(2),.vig-sys :nth-child(5){left:38px}
.vig-sys :nth-child(3),.vig-sys :nth-child(6){left:76px}
.vig-sys .v-tok{background:var(--white)}
.is-play .vig-sys .v-tok{animation:sk-snap 1.4s var(--ease-out) both}
.vig-sys .v-tok:nth-child(5){background:var(--ink);--fx:10px;--fy:-14px;--fr:14deg;animation-delay:.15s}
.vig-sys .v-tok:nth-child(6){background:var(--white);--fx:22px;--fy:10px;--fr:-18deg;animation-delay:.3s}
@keyframes sk-snap{0%,25%{transform:translate(var(--fx,-12px),var(--fy,12px)) rotate(var(--fr,-12deg))}100%{transform:none}}
/* Prototyping: a cursor taps a button */
.vig-proto .v-btn{left:0;top:16px;width:88px;height:32px;border-radius:var(--pill);background:var(--ink)}
.is-play .vig-proto .v-btn{animation:sk-press 2.2s var(--ease-inout) both}
.is-play .vig-proto .v-cur{animation:sk-cur 2.2s var(--ease-inout) both}
.vig-proto .v-btn::after{content:"";position:absolute;left:24px;right:24px;top:13px;height:6px;border-radius:var(--pill);background:var(--white)}
.vig-proto .v-cur{position:absolute;left:62px;top:30px;width:24px;height:24px;fill:var(--white);stroke:var(--ink);stroke-width:1.6;stroke-linejoin:round}
@keyframes sk-cur{0%,10%{transform:translate(34px,22px)}45%,65%,100%{transform:none}55%{transform:scale(.85)}}
@keyframes sk-press{0%,50%,62%,100%{transform:none}56%{transform:scale(.94)}}
/* Workshops: sticky notes pop onto the wall */
.vig-work .v-note{top:10px;width:34px;height:34px;border-radius:4px;box-shadow:var(--shadow-rest)}
.is-play .vig-work .v-note{animation:sk-pop var(--dur-3) var(--ease-out) both}
.vig-work .v-note:nth-child(1){left:0;background:var(--white);rotate:-6deg}
.vig-work .v-note:nth-child(2){left:40px;top:18px;background:var(--sun);rotate:4deg;animation-delay:.3s}
.vig-work .v-note:nth-child(3){left:80px;background:var(--white);rotate:-3deg;animation-delay:.6s}
@keyframes sk-pop{0%{transform:scale(0)}65%{transform:scale(1.08)}100%{transform:none}}
/* Tools: two meshing gears, generated by tools/build-gears.py (12 + 8 teeth, module 4, short rounded teeth: addendum 2.6,
   centres 41 apart on a 20deg line, the small gear's mesh phase baked into its path; 64-frame clearance test >= 1.1px).
   Play: one 6 s turn (owner 16 Oct: turn on enter, ease out to a stop), both on the same curve so they stay meshed: the big
   gear turns 6 teeth (180deg), the small one 6 of its 8 the other way (-270deg = 1.5x), and both land on the baked mesh pose. */
.vig-tools .v-gear{position:absolute;fill-rule:evenodd}
.vig-tools .v-gear-a{left:0;top:2px;width:56px;height:56px;fill:var(--ink)}
.vig-tools .v-gear-b{left:46.5px;top:24px;width:40px;height:40px;fill:var(--white)}
.is-play .vig-tools .v-gear-a{animation:sk-spin-a 6s var(--ease-inout) both}
.is-play .vig-tools .v-gear-b{animation:sk-spin-b 6s var(--ease-inout) both}
@keyframes sk-spin-a{to{transform:rotate(180deg)}}
@keyframes sk-spin-b{to{transform:rotate(-270deg)}}
/* QA & mentoring: each row gets its tick */
.vig-qa .v-row{left:0;width:104px;height:14px;border-radius:var(--pill);background:var(--white)}
.vig-qa .v-row:nth-child(1){top:4px}.vig-qa .v-row:nth-child(2){top:24px}.vig-qa .v-row:nth-child(3){top:44px}
.vig-qa .v-ok{right:-22px;top:-2px;display:grid;place-items:center;width:18px;height:18px;border-radius:var(--pill);background:var(--ink);color:var(--white)}
.is-play .vig-qa .v-ok{animation:sk-pop var(--dur-3) var(--ease-out) both}
.vig-qa .v-ok svg{width:12px;height:12px}
.vig-qa .v-row:nth-child(2) .v-ok{animation-delay:.35s}.vig-qa .v-row:nth-child(3) .v-ok{animation-delay:.7s}
.roles-note{margin-top:var(--s-6);font-size:var(--fs-body);color:var(--body);max-width:60ch}
.roles-note b{font-weight:500;color:var(--ink)}
/* design-system page info cards: two by two on phones, 4 of 12 columns on desktop */
@media(max-width:599px){
  .sk-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-3)}
  .sk-skill{padding:var(--s-3) var(--s-3) var(--s-4)}
  .sk-skill .sk-art{height:96px;margin-bottom:var(--s-2)}
}
@media(min-width:900px){
  .sk-grid{grid-template-columns:repeat(12,minmax(0,1fr))}
  .sk-skill{grid-column:span 4}
}

/* ---------- Writing: the latest note (cover + title) left, the next five as a hairline list right, same height ---------- */
.blog-split{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-6)}
@media(min-width:900px){.blog-split{grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:var(--s-8);align-items:stretch}}
.blog-split .post-lead{padding:0;border-radius:0;background:none;box-shadow:none}   /* home: no card (Writing page keeps its cover card) */
.blog-split .post-lead:is(:hover,:focus-visible){translate:0 var(--lift);box-shadow:none}
.blog-split .post-lead .post-body h3{font-size:var(--fs-title)}
.index{display:grid;grid-template-columns:minmax(0,1fr);gap:0 var(--s-8)}
.index a{display:grid;grid-template-columns:44px minmax(0,1fr) auto;gap:var(--s-4);align-items:center;padding:var(--s-4) 0;border-bottom:1px solid var(--line-mid);min-height:72px}
.index .n{transition:background var(--dur-1) var(--ease)}  /* + .nsq */
.index a:is(:hover,:focus-visible) .n{background:var(--sun)}
.index .rt{display:flex;flex-direction:column;gap:2px;min-width:0}
.index h3{font-size:var(--fs-body);font-weight:700;line-height:var(--lh-snug)}
.index a:is(:hover,:focus-visible) h3{text-decoration:underline var(--stroke);text-underline-offset:4px}
.index .rt span{font-size:var(--fs-cap);font-weight:500;color:var(--muted)}
.index .rm{font-size:var(--fs-cap);font-weight:500;color:var(--muted);white-space:nowrap;display:inline-flex;align-items:center;gap:var(--s-2)}
.index .rm svg{width:14px;height:14px;color:var(--ink);opacity:0;transform:translate(-4px,4px);transition:opacity var(--dur-1) var(--ease),transform var(--dur-1) var(--ease)}
.index a:is(:hover,:focus-visible) .rm svg{opacity:1;transform:none}
.index-fill{display:flex;flex-direction:column;border-top:1px solid var(--line-mid)}
.index-fill li{flex:1 1 auto;display:flex}   /* grow from content size, so every row gets the same extra space */
.index-fill a{flex:1}

/* ---------- Writing cards: .post-lead (newest note; Home keeps it bare, see .blog-split) and .post-card (Writing grid) ---------- */
.post-lead,.post-card{display:flex;flex-direction:column;gap:var(--s-4);padding:var(--s-4) var(--s-4) var(--s-5);border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-rest);color:var(--ink);
  transition:opacity var(--dur-3) var(--ease-out),transform var(--dur-3) var(--ease-out),translate var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease)}
.post-lead:is(:hover,:focus-visible),.post-card:is(:hover,:focus-visible){transform:none;translate:0 var(--lift);box-shadow:var(--shadow-hover)}
.post-lead .cover{border-radius:var(--r-inner)}
.post-lead .post-body{display:flex;flex-direction:column;align-items:flex-start;gap:var(--s-2);padding:0 var(--s-2)}
.post-lead .post-meta{margin:0;font-weight:500;font-size:var(--fs-cap)}
.post-lead .post-meta b{font-weight:700;color:var(--ink)}
.post-lead .post-body :is(h2,h3){font-size:var(--fs-sub);font-weight:700;line-height:var(--lh-tight);letter-spacing:var(--ls-display);text-wrap:balance}
.post-lead .post-body p{display:-webkit-box;overflow:hidden;-webkit-line-clamp:3;-webkit-box-orient:vertical;max-width:44ch;font-size:var(--fs-body)}
.post-foot{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-3) var(--s-4);margin-top:var(--s-2)}
.post-time{font-size:var(--fs-cap);font-weight:500;color:var(--muted)}
/* the affordance on a content card = the tertiary link (.link) in its foot; it underlines + nudges while the card is hovered */
:is(.post-lead,.post-card,.vb-link):is(:hover,:focus-within) .link{text-decoration-color:currentColor}
:is(.post-lead,.post-card,.vb-link):is(:hover,:focus-within) .link svg{transform:translateX(3px)}
/* .post-card base: the articles' Next note card + the Writing grid (overridden under .wgrid below) */
.post-card{flex:1;gap:var(--s-4);padding:var(--s-3) var(--s-3) var(--s-5);border-radius:var(--r-card)}
.post-card :is(.cover,.thumb){aspect-ratio:16/10;border-radius:var(--r-inner)}
.post-card .cover-ui{zoom:.64;right:-12%}   /* a crop, not a shrink: the UI stays readable and bleeds off the right edge, clear of the pen note */
@container (min-width:420px){.post-card .cover-ui{zoom:.78;right:-8%}}   /* 2-column cards are wider: a bigger crop */
.post-card .thumb{padding:var(--s-4) var(--s-5)}
.post-card .post-body{flex:1;display:flex;flex-direction:column;align-items:flex-start;gap:var(--s-2);padding:0 var(--s-2)}
.post-card .post-meta{margin:0;font-size:var(--fs-cap);font-weight:500;color:var(--muted)}
.post-card .post-body h2{font-size:var(--fs-title);font-weight:700;line-height:var(--lh-snug);letter-spacing:var(--ls-title);text-wrap:balance;display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.post-card .post-body p{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:var(--fs-body);color:var(--body)}
.post-card .post-foot{margin-top:auto;padding-top:var(--s-2)}

/* ---------- Writing page v7 (owner pick 20 Oct 2026, board direction B; docs/decisions.md "Writing page v7") ----------
   Filters (one scrolling row on phones) > ONE lead card (.wlead: text left, the cover bleeding to the card's right edge
   on the sun mesh; the only cover on the page that moves) > a tall editorial grid (.wgrid): square covers, a wide card
   every second row (.is-w3 at 3 columns, .is-w2 = full width at 2; the generator picks them so no row ends alone; any
   topic filter drops back to plain cells), phones = one white list of compact rows (thumb + number + title).
   Card = number + topic + minutes, title, one line, the arrow chip (.wk-go, the Work cards' affordance); no Read link.
   Covers v3 (.wcv-*): one family per topic group (tools/build-articles.py GROUPS, the same map as the filter chips), see
   "cover families" below. Static; hover = the card's lift only. */
.wfeed{display:flex;flex-direction:column;gap:var(--s-6)}
.wfeed .post-meta{flex-wrap:wrap;font-size:var(--fs-cap)}
.wfeed .post-meta .nsq{--nsq:28px;margin-right:var(--s-1)}
.wfeed .post-meta b{display:inline-flex;align-items:center;min-height:24px;padding:0 var(--s-2);border-radius:var(--pill);background:var(--white);box-shadow:var(--shadow-rest);font-size:var(--fs-cap)}   /* owner 20 Oct: white, not sun (it sat by the sun cover and blended in) */
@media(max-width:767px){
  /* one row of chips that scrolls sideways, edge to edge (the page gutter stays as its inner padding) */
  .filters{flex-wrap:nowrap;overflow-x:auto;margin-inline:calc(var(--gutter) * -1);padding:var(--s-1) var(--gutter);scrollbar-width:none;overscroll-behavior-x:contain}
  .filters::-webkit-scrollbar{display:none}
  .filters button{flex:none}
}

/* lead: one white card, no inner frame; the cover fills its right side (below the text on narrow screens) */
.wlead{gap:0;padding:0;overflow:hidden;isolation:isolate}
.wlead .post-body{gap:var(--s-3);padding:var(--s-5) var(--s-5) var(--s-6)}
.wfeed>.wlead .post-body h2{font-size:var(--fs-section)}
.wlead .post-body p{max-width:40ch}
.wlead .cover.wcv-hero{aspect-ratio:16/10;border-radius:0}
@media(min-width:900px){
  .wlead{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);align-items:stretch}
  .wlead .post-body{justify-content:center;padding:var(--s-7) var(--s-6) var(--s-7) var(--s-7)}
  .wlead .cover.wcv-hero{height:100%}
}

/* grid */
.wgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-5)}
.wgrid>li{display:flex;min-width:0;container-type:inline-size}
.wfeed :is(.post-lead,li).is-hidden{display:none}   /* topic filter (js/site.js) */
.wgrid .post-card{position:relative}
.wgrid .post-card .cover{aspect-ratio:1/1}
.wgrid .post-card .post-meta .nsq{transition:background var(--dur-1) var(--ease)}
.wgrid .post-card:is(:hover,:focus-visible) .post-meta .nsq{background:var(--sun)}
.wgrid .post-card:is(:hover,:focus-visible) .wk-go{background:var(--ink);color:var(--white)}
.wgrid .post-card:is(:hover,:focus-visible) .wk-go svg{transform:translateX(3px)}
@media(min-width:561px) and (max-width:899px){
  .wgrid .post-card .cover{aspect-ratio:5/4}   /* 2 columns: a little lower, or the page runs long */
  .wgrid:not(:has(>li.is-hidden))>li.is-w2{grid-column:1 / -1}
  .wgrid:not(:has(>li.is-hidden))>li.is-w2 .cover{aspect-ratio:5/2}
  .wgrid:not(:has(>li.is-hidden))>li.is-w2 .wcv-sheet{padding-right:52%}   /* a low frame: the line left, the UI right */
  }
@media(min-width:900px){
  .wgrid{grid-template-columns:repeat(3,minmax(0,1fr))}
  .wgrid:not(:has(>li.is-hidden))>li.is-w3{grid-column:span 2}
  /* as tall as its row's square covers: the cell is 2 columns + 1 gap wide (the li is the size container) */
  .wgrid:not(:has(>li.is-hidden))>li.is-w3 .cover{aspect-ratio:auto;height:calc((100cqw - var(--s-5)) / 2 - 2 * var(--s-3))}
  .wgrid:not(:has(>li.is-hidden))>li.is-w3 .wcv-title{font-size:var(--fs-section)}
}

/* cover families v3 (owner 20 Oct 2026: "the ElevenLabs direction, in OUR mood and tone"; docs/decisions.md "Writing covers
   v3"). Their traits, our palette: a soft mesh of the site's pale tints (never --case-*, never a deep ground), strong fine
   grain (no blend mode), ink text in light Silka, one crisp white UI piece. v3b (owner, same day): accents TONE-ON-TONE
   (--cv-acc = a deeper step of the cover's own hue: glow, chips, tick, highlighted row, marker, back card; sun only on the
   lead; a pill on a ground of its own hue is white), NO outlines (the .il window ring is switched off on covers; depth = soft shadow + tone), AI = a fine
   wave-contour pattern instead of blurred words. Each family says its topic: tools = the real tool, ai = a line of words
   on the pattern, process = a stack of working cards, craft = a snippet. Grounds: tools cool mint, ai butter, process airy
   cream, craft warm peach. Ink on all four >= 4.5:1 (measured). */
.cover:is(.wcv-tools,.wcv-ai,.wcv-process,.wcv-craft){--mesh-grain:.3;--il-ring:0 0 0 0 transparent}
/* tone: VIVID by default (owner 20 Oct: "a bit more vivid, match the other pages"; a lighter step of the site's hue-mint / hue-sun /
   hue-tan meshes, calmer than the rejected deep set). PALE backup = one switch: <html data-cover-tone="soft"> (block below),
   or git tag writing-covers-pale-20oct. --cv-acc = a deeper step of the same hue. */
.cover.mesh.wcv-tools{background:var(--cream);--m1:var(--sun-tint);--m2:var(--teal-tint);--m3:var(--tangerine-tint);--cv-acc:color-mix(in srgb,var(--teal) 28%,var(--sun-tint))}   /* owner 20 Oct: calm pale ground = the "More on the way" .hue-soft tile; no pattern. Earlier mint: tag writing-covers-pale-20oct / git 4546a7e */
.cover.mesh.wcv-ai{background:linear-gradient(170deg,color-mix(in srgb,var(--sun) 40%,var(--white)),color-mix(in srgb,var(--sun) 68%,var(--white)));--m1:color-mix(in srgb,var(--sun) 70%,transparent);--m2:color-mix(in srgb,var(--white) 55%,transparent);--m3:color-mix(in srgb,var(--sun-art) 45%,transparent);--cv-acc:color-mix(in srgb,var(--sun-art) 60%,var(--sun))}
.cover.mesh.wcv-process{background:linear-gradient(160deg,color-mix(in srgb,var(--pinpoint-blue) 9%,var(--white)),color-mix(in srgb,var(--pinpoint-blue) 22%,var(--white)));--m1:color-mix(in srgb,var(--pinpoint-blue) 20%,transparent);--m2:color-mix(in srgb,var(--white) 60%,transparent);--m3:color-mix(in srgb,var(--teal) 16%,transparent);--cv-acc:color-mix(in srgb,var(--pinpoint-blue) 32%,var(--white))}   /* owner 20 Oct: process must not look like tools: pale sky */
.cover.mesh.wcv-craft{background:linear-gradient(160deg,color-mix(in srgb,var(--tangerine) 30%,var(--white)),color-mix(in srgb,var(--tangerine) 50%,var(--white)));--m1:var(--tangerine-hl);--m2:color-mix(in srgb,var(--sun) 40%,transparent);--m3:color-mix(in srgb,var(--tangerine) 55%,transparent);--cv-acc:color-mix(in srgb,var(--tangerine) 58%,var(--white));--mark:var(--cv-acc)}
/* pale backup (the set the owner saw first, tag writing-covers-pale-20oct) */
html[data-cover-tone="soft"] .cover.mesh.wcv-tools{background:linear-gradient(165deg,var(--teal-tint),color-mix(in srgb,var(--mint) 24%,var(--white)));--m1:color-mix(in srgb,var(--mint) 30%,transparent);--m2:color-mix(in srgb,var(--teal) 14%,transparent);--m3:color-mix(in srgb,var(--mint) 40%,transparent);--cv-acc:color-mix(in srgb,var(--mint) 72%,var(--teal))}
html[data-cover-tone="soft"] .cover.mesh.wcv-ai{background:linear-gradient(170deg,var(--sun-tint),color-mix(in srgb,var(--sun) 26%,var(--white)));--m1:color-mix(in srgb,var(--sun) 38%,transparent);--m2:color-mix(in srgb,var(--white) 75%,transparent);--m3:color-mix(in srgb,var(--sun) 30%,transparent);--cv-acc:color-mix(in srgb,var(--sun) 62%,var(--white))}
html[data-cover-tone="soft"] .cover.mesh.wcv-process{background:linear-gradient(160deg,var(--white),var(--cream));--m1:var(--teal-tint);--m2:var(--tangerine-tint);--m3:var(--sun-tint);--cv-acc:color-mix(in srgb,var(--sun-art) 34%,var(--cream))}
html[data-cover-tone="soft"] .cover.mesh.wcv-craft{background:linear-gradient(160deg,var(--tangerine-tint),color-mix(in srgb,var(--tangerine-hl) 70%,var(--white)));--m1:color-mix(in srgb,var(--tangerine-hl) 80%,transparent);--m2:var(--sun-tint);--m3:color-mix(in srgb,var(--tangerine) 24%,transparent);--cv-acc:color-mix(in srgb,var(--tangerine) 42%,var(--white));--mark:var(--cv-acc)}
/* the light word on top (tools: the tool's name, big; process: the note's line, small) */
.wcv-title{position:absolute;inset:8% 14% auto;z-index:3;text-align:center;color:var(--ink);font-size:var(--fs-sub);font-weight:400;line-height:var(--lh-tight);letter-spacing:var(--ls-title);text-wrap:balance}
.wcv-process .wcv-title{font-size:var(--fs-body);line-height:var(--lh-snug)}
/* tools: the real window / app icons run off the bottom-right edge, a soft glow in the cover's own deeper mint (no line) */
/* Tools covers (grid + lead): the title sits one pad from the top, the window is centred in the space left under it, with a pad
   at the sides and bottom. js/site.js "Cover fit" measures the card (square, 5:4 or wide) and sets --fp (pad), --ft (title top, lower than the pad), --fy (the centre of
   the free space) and --fz (the window's scale: its size, capped, shrunk only if it would not fit). Without JS: centred. */
.cover:is(.wcv-tools,.cv-fit)>.cover-ui{left:50%;right:auto;top:var(--fy,50%);bottom:auto;translate:-50% -50%;zoom:var(--fz,var(--fz-max,.86))}
.cover:is(.wcv-tools,.cv-fit):not(.cover-mp,.cover-hop)>.cover-ui{width:max-content}
.cover:is(.wcv-tools,.cv-fit)>.wcv-title{top:var(--ft,10%);inset-inline:var(--fp,14%)}
.cover.wcv-hero{--fz-max:1}
/* the dotted tint sheet that peeks out behind a board / panel (.dot-back: mood board, layer panels, post-it notes) */
/* mood-board cover (06, owner pick M1, 20 Oct): a white board of drawn tiles on the pale-sky ground; positioned by js "Cover fit" like the Tools covers (.cv-fit) */
.mb{--mb-sh:0 0 40px -6px color-mix(in srgb,var(--cv-acc) 80%,transparent),var(--shadow-overlay);position:relative;width:300px;height:212px}
.dot-back{position:absolute;left:24px;top:24px;right:-16px;bottom:-16px;border-radius:16px;background:radial-gradient(circle,color-mix(in srgb,var(--white) 75%,transparent) 1.2px,transparent 1.7px) 0 0/9px 9px,color-mix(in srgb,var(--pinpoint-blue) 34%,var(--white))}
.mb-sheet{position:relative;display:grid;grid-template-columns:58px 1fr 1fr 1fr 34px 46px;grid-template-rows:repeat(4,1fr);grid-template-areas:"sm hero hero hero fog aa" "wd hero hero hero fog aa" "wd tex tex blob blob blob" "sw tex tex blob blob blob";gap:6px;width:100%;height:100%;box-sizing:border-box;padding:10px;border-radius:14px;background:var(--white);box-shadow:var(--mb-sh)}
.mb-ti{display:block;min-width:0;min-height:0;border-radius:6px;overflow:hidden}
.mb-ph{position:relative;display:block;width:100%;height:100%;overflow:hidden;border-radius:inherit}
.mb-ph svg{position:absolute;inset:0;display:block;width:100%;height:100%}
.mb-ph::after{content:"";position:absolute;inset:0;background:var(--grain) 0 0/120px auto;opacity:.45;pointer-events:none}
.mb-hills{background:linear-gradient(180deg,color-mix(in srgb,var(--pinpoint-blue) 26%,var(--white)) 10%,color-mix(in srgb,var(--sun) 40%,var(--white)) 78%)}
.mb-sun{fill:color-mix(in srgb,var(--sun) 75%,var(--white))}
.mb-h1{fill:color-mix(in srgb,var(--teal) 45%,var(--white))}
.mb-h2{fill:color-mix(in srgb,var(--teal) 72%,var(--ink))}
.mb-still{background:color-mix(in srgb,var(--tangerine) 14%,var(--white))}
.mb-table{fill:color-mix(in srgb,var(--tangerine) 34%,var(--white))}
.mb-arch{fill:color-mix(in srgb,var(--tangerine) 85%,var(--white))}
.mb-ball{fill:var(--ink)}
.mb-blobs{background:radial-gradient(60% 70% at 25% 30%,var(--tangerine-hl),transparent 70%),radial-gradient(55% 65% at 80% 25%,color-mix(in srgb,var(--sun) 70%,var(--white)),transparent 70%),radial-gradient(70% 70% at 65% 90%,color-mix(in srgb,var(--pinpoint-blue) 40%,var(--white)),transparent 72%),color-mix(in srgb,var(--tangerine) 22%,var(--white))}
.mb-fog{background:linear-gradient(180deg,color-mix(in srgb,var(--teal) 50%,var(--white)),color-mix(in srgb,var(--mint) 22%,var(--white)))}
.mb-moon{fill:color-mix(in srgb,var(--white) 80%,transparent)}
.mb-ridge{fill:color-mix(in srgb,var(--teal) 80%,var(--ink))}
.mb-sw{display:flex;flex-direction:column;gap:3px;width:100%;height:100%;box-sizing:border-box}
.mb-sw i{display:block;flex:1;border-radius:4px}
.mb-sw .s1{background:var(--teal)}.mb-sw .s2{background:var(--ink)}.mb-sw .s3{background:var(--tangerine-hl)}
.mb-aa,.mb-wd{display:grid;place-items:center;width:100%;height:100%;box-sizing:border-box;border-radius:inherit;background:var(--cream);color:var(--ink)}
.mb-aa b{font-size:26px;font-weight:600;letter-spacing:-.02em;line-height:1}
.mb-wd{display:flex;align-items:center;padding:7px 8px;font-size:14px;font-weight:600;line-height:1.15}
.mb-tex{position:relative;display:block;width:100%;height:100%;overflow:hidden;border-radius:inherit;background:color-mix(in srgb,var(--pinpoint-blue) 10%,var(--white))}
.mb-tex .wcv-pat{opacity:.5}
/* layer panels (09, owner pick N3 + struck-through unnamed layers) and four post-it vote notes (10, owner pick S1): glow shadow, dotted sheet behind */
.ly{--ly-sh:0 0 40px -6px color-mix(in srgb,var(--cv-acc) 80%,transparent),var(--shadow-overlay);position:relative}   /* the same shadow as the mood board (06): owner 20 Oct, one shadow colour for the cards */
.ly{width:320px;height:204px}
.ly-list{position:absolute;margin:0;padding:10px 0;list-style:none;border-radius:var(--il-r-md);background:var(--white);box-shadow:var(--ly-sh)}
.ly-list li{display:flex;align-items:center;gap:10px;height:30px;padding:0 18px 0 calc(18px + var(--lv,0) * 18px);font-size:15px;font-weight:500;color:var(--ink);white-space:nowrap}
.ly-dot{right:auto;bottom:auto}   /* each panel carries its own small dotted sheet, the same colour and dots as the mood board's (.dot-back); both are drawn before the panels */
.ly-dot-before{left:20px;top:20px;width:178px;height:156px}
.ly-dot-after{left:160px;top:84px;width:176px;height:140px}
.ly-gl{flex:none;width:14px;height:14px;fill:color-mix(in srgb,var(--ink) 38%,transparent)}
.ly-gl .gs{fill:none;stroke:color-mix(in srgb,var(--ink) 42%,transparent);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
.ly-before{left:0;top:0;width:162px}
.ly-before li{color:color-mix(in srgb,var(--ink) 45%,transparent)}
.ly-before li span{text-decoration:line-through;text-decoration-thickness:1.5px}
.ly-before .ly-gl{opacity:.6}
.ly-after{right:0;bottom:0;width:180px}
.ly-after .root{font-weight:600}
.stk-wrap{--stk-sh:0 1px 2px color-mix(in srgb,var(--ink) 8%,transparent),0 6px 12px -6px color-mix(in srgb,var(--ink) 20%,transparent),0 18px 28px -14px color-mix(in srgb,var(--ink) 30%,transparent);position:relative;width:232px;height:212px}
.stk{position:absolute;display:flex;flex-direction:column;justify-content:space-between;box-sizing:border-box;width:112px;height:100px;padding:12px 13px;border-radius:8px;background:var(--white);box-shadow:var(--stk-sh);font-size:16px;font-weight:600;line-height:1.15;color:var(--ink)}
.stk.win{background:var(--sun-tint)}
.stk.p1{left:0;top:0;rotate:-2deg}.stk.p2{left:116px;top:4px;rotate:1.5deg}
.stk.p3{left:4px;top:106px;rotate:1.5deg}.stk.p4{left:118px;top:110px;rotate:-2deg}
.stk-dots{display:inline-flex;gap:5px}
.stk-dots i{width:9px;height:9px;border-radius:50%;background:color-mix(in srgb,var(--ink) 12%,transparent)}
.stk-dots i.on{background:var(--teal)}
.stk-ck{position:absolute;top:-9px;right:-9px;display:grid;place-items:center;width:26px;height:26px;border-radius:50%;background:var(--sun);color:var(--ink);box-shadow:0 4px 8px -4px color-mix(in srgb,var(--ink) 40%,transparent)}
.stk-ck svg{width:14px;height:14px}
/* craft covers 02 / 08 / 13 / 14 as full-bleed pictures (owner picks 20 Oct): no sheet, no title. The picture is drawn on a 760x420 canvas in --u
   (one canvas px = the cover's short side / 333, container-type:size), centred: a square card shows its centre, a wide card more. */
.cover.cv-pic{container-type:size}
.pic{--u:calc(100cqmin / 333);--pic-sh:0 0 40px -6px color-mix(in srgb,var(--cv-acc) 80%,transparent),var(--shadow-overlay);position:absolute;left:50%;top:50%;width:calc(var(--u) * 760);height:calc(var(--u) * 420);translate:-50% -50%;color:var(--ink)}
.pic>*{position:absolute;box-sizing:border-box}
.pic-bg{left:calc(var(--u) * var(--x));top:calc(var(--u) * var(--y));width:calc(var(--u) * var(--s));height:calc(var(--u) * var(--s));border-radius:50%;background:color-mix(in srgb,var(--white) 30%,transparent)}
.pic-prod,.pic-clock{border-radius:calc(var(--u) * 24);background:var(--white);box-shadow:var(--pic-sh)}
.pic-prod{left:calc(var(--u) * 222);top:calc(var(--u) * 104);width:calc(var(--u) * 306);height:calc(var(--u) * 160);display:flex;align-items:center;gap:calc(var(--u) * 16);padding:calc(var(--u) * 16)}
.pic-lamp{display:grid;flex:none;place-items:center;width:calc(var(--u) * 120);height:calc(var(--u) * 120);border-radius:calc(var(--u) * 18);background:var(--tangerine-tint)}
.pic-lamp svg{width:calc(var(--u) * 92);height:calc(var(--u) * 92)}
.pic-lamp .sh{fill:var(--tangerine)}.pic-lamp .st{fill:var(--ink)}
.pic-txt{display:flex;flex-direction:column;gap:calc(var(--u) * 8);text-align:right}
.pic-txt b{font-size:calc(var(--u) * 20);font-weight:600;line-height:1.25}
.pic-txt em{font-size:calc(var(--u) * 22);font-style:normal;font-weight:700}
.pic-add{position:absolute;left:calc(var(--u) * 16);bottom:calc(var(--u) * 16);display:grid;place-items:center;width:calc(var(--u) * 44);height:calc(var(--u) * 44);border-radius:50%;background:var(--ink);color:var(--white)}
.pic-add svg{width:calc(var(--u) * 22);height:calc(var(--u) * 22)}
.pic-clock{left:calc(var(--u) * 346);top:calc(var(--u) * 286);width:calc(var(--u) * 210);height:calc(var(--u) * 116);display:flex;justify-content:flex-end;padding:calc(var(--u) * 20) calc(var(--u) * 22)}
.pic-clock b{font-size:calc(var(--u) * 40);font-weight:700;line-height:1;letter-spacing:-.01em}
/* 02: three project chips, one colour each */
.pic-chip{display:inline-flex;align-items:center;gap:calc(var(--u) * 12);height:calc(var(--u) * 60);padding:0 calc(var(--u) * 24) 0 calc(var(--u) * 18);border-radius:var(--pill);background:var(--white);box-shadow:var(--pic-sh);font-size:calc(var(--u) * 21);font-weight:600;white-space:nowrap}
.pic-chip i{width:calc(var(--u) * 22);height:calc(var(--u) * 22);border-radius:50%}
.pic-chip.c1{left:calc(var(--u) * 263);top:calc(var(--u) * 100)}.pic-chip.c1 i{background:var(--tangerine)}
.pic-chip.c2{left:calc(var(--u) * 297);top:calc(var(--u) * 180)}.pic-chip.c2 i{background:var(--sun)}
.pic-chip.c3{left:calc(var(--u) * 331);top:calc(var(--u) * 260)}.pic-chip.c3 i{background:var(--ink)}
/* 14: three design-token cards, staggered */
.pic-tk{display:flex;flex-direction:column;gap:calc(var(--u) * 12);width:calc(var(--u) * 118);height:calc(var(--u) * 150);padding:calc(var(--u) * 12);border-radius:calc(var(--u) * 20);background:var(--white);box-shadow:var(--pic-sh)}
.pic-tk>span{display:grid;flex:1;place-items:center;border-radius:calc(var(--u) * 12);background:var(--cream)}
.pic-tk b{padding:0 calc(var(--u) * 2);font-size:calc(var(--u) * 14);font-weight:600;line-height:1.1;white-space:nowrap}
.pic-tk.k1{left:calc(var(--u) * 222);top:calc(var(--u) * 119);width:calc(var(--u) * 140);rotate:-3deg}
.pic-tk.k1>span{background:var(--tangerine)}
.pic-tk.k2{left:calc(var(--u) * 346);top:calc(var(--u) * 153);rotate:2deg}
.pic-tk.k2>span{font-size:calc(var(--u) * 44);font-weight:700;letter-spacing:-.02em}
.pic-tk.k3{left:calc(var(--u) * 450);top:calc(var(--u) * 123);rotate:-2deg}
.pic-tk.k3 i{width:calc(var(--u) * 56);height:calc(var(--u) * 56);border-radius:calc(var(--u) * 26) calc(var(--u) * 6) calc(var(--u) * 6) calc(var(--u) * 6);background:var(--tangerine-hl)}
/* 08: two toasts, the clunky literal line struck and tilted behind, the clear one in front */
.pic-toast{display:flex;align-items:center;gap:calc(var(--u) * 14);width:calc(var(--u) * 268);padding:0 calc(var(--u) * 20);border-radius:calc(var(--u) * 20);background:var(--white);box-shadow:var(--pic-sh)}
.pic-toast i{flex:none;width:calc(var(--u) * 14);height:calc(var(--u) * 14);border-radius:50%;background:var(--tangerine)}
.pic-toast>span{display:flex;flex-direction:column;gap:calc(var(--u) * 2)}
.pic-toast b{font-size:calc(var(--u) * 26);font-weight:600;line-height:1.35;white-space:nowrap}
.pic-toast small{font-size:calc(var(--u) * 16);font-weight:500;line-height:1.2;color:color-mix(in srgb,var(--ink) 55%,transparent);white-space:nowrap}
.pic-toast.old{left:calc(var(--u) * 236);top:calc(var(--u) * 110);height:calc(var(--u) * 84);rotate:-3deg;box-shadow:0 1px 2px color-mix(in srgb,var(--ink) 8%,transparent),0 10px 22px -12px color-mix(in srgb,var(--ink) 28%,transparent)}
.pic-toast.old i{background:color-mix(in srgb,var(--ink) 20%,transparent)}
.pic-toast.old b{font-size:calc(var(--u) * 21);color:color-mix(in srgb,var(--ink) 50%,transparent);text-decoration:line-through;text-decoration-thickness:calc(var(--u) * 2)}
.pic-toast.old small{color:color-mix(in srgb,var(--ink) 40%,transparent)}
.pic-toast.now{left:calc(var(--u) * 258);top:calc(var(--u) * 210);height:calc(var(--u) * 100)}
/* lockup covers (GitHub, MCP, Figma plugins; owner 20 Oct): the ground + ONE small centred logo that carries its own name, no title.
   js/site.js "Cover fit" scales the whole lockup (about half the card, at most 60% of its height); --H is only the natural size. */
.cover.cv-lock>.cover-ui{color:var(--ink)}
.lk{--H:56px;display:inline-flex;align-items:center;white-space:nowrap}
.lk svg{display:block;flex:none}
.lk b{font-weight:600;letter-spacing:-.01em;line-height:1}
.lk-gh{gap:calc(var(--H)*.26)}
.lk-gh .m{width:var(--H);height:var(--H)}
.lk-gh .w{height:calc(var(--H)*.6);width:calc(var(--H)*.6*1020/291)}
.lk-mcp{gap:calc(var(--H)*.22)}
.lk-mcp .m{width:calc(var(--H)*.92);height:var(--H)}
.lk-mcp b{font-size:calc(var(--H)*.3);line-height:1.08}
.lk-hop{gap:calc(var(--H)*.26)}
.lk-hop .m{width:var(--H);height:var(--H);border-radius:calc(var(--H)*.22)}
.lk-hop b{font-size:calc(var(--H)*.74);font-weight:600;letter-spacing:-.02em}
.lk-fig{gap:calc(var(--H)*.24)}
.lk-fig .m{width:calc(var(--H)*.667);height:var(--H)}
.lk-fig b{font-size:calc(var(--H)*.8);font-weight:500;letter-spacing:-.02em}
/* the lead (.wcv-hero: Writing lead + Home Writing lead): the family ground, the cover word on top, the real window
   cropped by the bottom-right edge on a soft tone glow (drop-shadow: the Hop window is a cut-out screenshot); pen note +
   avatar stay left; its one loop is untouched */
.cover.wcv-hero .wcv-title{font-size:var(--fs-section)}
.cover.wcv-hero .hpr{filter:drop-shadow(0 0 32px color-mix(in srgb,var(--cv-acc) 70%,transparent)) drop-shadow(0 18px 28px color-mix(in srgb,var(--ink) 20%,transparent))}
.wgrid .wcv-tools :is(.ilw,.mp-tile){box-shadow:0 0 40px -6px color-mix(in srgb,var(--cv-acc) 80%,transparent),var(--shadow-overlay)}
/* the cover UIs' own yellow touches take the cover's accent (chips, the pick tick, the highlighted sheet row) */
.wgrid .cover:is(.wcv-tools,.wcv-process,.wcv-craft) :is(.cv-chip:not(.cv-chip+.cv-chip),.cv-pill,.cv-tick){background:var(--cv-acc)}
.wgrid .cover .cv-tick{box-shadow:none}
.wgrid .cover :is(.ilw-col small,.cv-lab){text-transform:none;letter-spacing:0}   /* site type = sentence case (the figures' small caps labels stay in the articles) */
.wgrid .cover .sh-rows .sh-on{background:color-mix(in srgb,var(--cv-acc) 45%,transparent);box-shadow:none}
/* process: the note's board / panel on a fan of two cards, the back one in the accent (sand) */
.wgrid .wcv-process:not(.cv-fit) .cover-ui{top:34%;translate:-50% 0;isolation:isolate}
.wgrid .wcv-process:not(.cv-fit) .cover-ui::before,.wgrid .wcv-process:not(.cv-fit) .cover-ui::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:var(--il-r-md);background:var(--white);box-shadow:var(--shadow-overlay)}
.wgrid .wcv-process:not(.cv-fit) .cover-ui::before{rotate:-8deg;translate:-7% 5%;background:var(--cv-acc)}
.wgrid .wcv-process:not(.cv-fit) .cover-ui::after{rotate:5deg;translate:6% 3%}
/* craft: ONE white snippet sheet off the bottom-right edge: a line with a deeper-peach marker (--mark), the note's UI under it */
.wcv-sheet{position:absolute;left:11%;top:12%;right:-8%;bottom:-10%;padding:7cqi 16cqi 0 7cqi;border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-overlay)}
.wcv-snip{display:block;font-size:var(--fs-title);font-weight:400;line-height:var(--lh-snug);letter-spacing:var(--ls-title);color:var(--ink);text-wrap:balance}
.wgrid .wcv-craft .cover-ui{left:20%;top:46%;translate:none;zoom:.8}
/* ai: a fine wave-contour pattern (ink, ~9 %, crisp, static; inline SVG, strokes stay 1 px at any size), a white pill + one light centred line */
:is(.wgrid,.art-media-cv) .wcv-ai,.cover.wcv-ai.wcv-hero{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s-3);padding:9%;text-align:center}   /* % of the cover width (cq units on the container itself would read the viewport) */
.wcv-pat{position:absolute;inset:0;opacity:.09;pointer-events:none;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400' preserveAspectRatio='none'%3E%3Cg fill='none' stroke='%23191A1E' stroke-width='1'%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 -35.5C-30 -31.4 0 -17.1 20 -11.3C40 -5.5 60 -1.1 80 -0.8C100 -0.5 120 -7.5 140 -9.5C160 -11.4 180 -10.0 200 -12.6C220 -15.1 240 -19.6 260 -24.7C280 -29.7 300 -41.5 320 -43.1C340 -44.7 360 -39.0 380 -34.4C400 -29.8 430 -18.7 440 -15.6'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 -9.1C-30 -4.5 0 13.0 20 18.7C40 24.3 60 25.4 80 24.7C100 24.1 120 17.4 140 14.8C160 12.1 180 13.0 200 9.0C220 5.0 240 -3.6 260 -9.2C280 -14.8 300 -24.7 320 -24.6C340 -24.5 360 -14.5 380 -8.6C400 -2.7 430 7.4 440 10.7'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 19.9C-30 24.7 0 43.7 20 48.6C40 53.5 60 51.1 80 49.4C100 47.6 120 41.6 140 38.1C160 34.5 180 33.7 200 28.2C220 22.8 240 10.9 260 5.5C280 0.1 300 -6.2 320 -4.0C340 -1.8 360 11.8 380 18.8C400 25.7 430 34.4 440 37.6'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 51.0C-30 55.4 0 74.1 20 77.8C40 81.4 60 75.9 80 72.9C100 70.0 120 64.6 140 60.0C160 55.4 180 51.9 200 45.3C220 38.7 240 24.8 260 20.5C280 16.1 300 14.8 320 19.3C340 23.8 360 39.8 380 47.4C400 55.1 430 62.1 440 65.0'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 83.4C-30 87.1 0 103.6 20 105.6C40 107.5 60 99.4 80 95.2C100 91.0 120 86.1 140 80.4C160 74.7 180 68.0 200 60.8C220 53.5 240 39.3 260 36.8C280 34.2 300 38.6 320 45.3C340 52.0 360 69.1 380 77.0C400 84.9 430 90.0 440 92.6'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 116.2C-30 118.7 0 131.4 20 131.4C40 131.3 60 121.4 80 116.0C100 110.6 120 105.9 140 99.1C160 92.3 180 82.5 200 75.2C220 67.9 240 55.6 260 55.4C280 55.2 300 65.4 320 74.0C340 82.6 360 99.3 380 107.0C400 114.6 430 117.9 440 120.1'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 148.2C-30 149.3 0 157.0 20 154.9C40 152.8 60 141.9 80 135.5C100 129.1 120 123.9 140 116.3C160 108.7 180 96.3 200 89.7C220 83.2 240 74.5 260 77.0C280 79.5 300 94.8 320 104.8C340 114.7 360 129.6 380 136.7C400 143.7 430 145.3 440 147.0'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 178.5C-30 178.1 0 180.2 20 176.1C40 171.9 60 161.1 80 153.8C100 146.5 120 140.5 140 132.4C160 124.3 180 110.3 200 105.3C220 100.2 240 96.7 260 102.0C280 107.3 300 126.4 320 137.0C340 147.6 360 159.6 380 165.6C400 171.6 430 171.8 440 173.0'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 206.3C-30 204.4 0 200.9 20 195.1C40 189.2 60 179.0 80 171.2C100 163.3 120 155.9 140 147.9C160 139.8 180 125.7 200 122.8C220 119.9 240 122.5 260 130.3C280 138.1 300 159.1 320 169.6C340 180.1 360 188.7 380 193.4C400 198.0 430 196.9 440 197.6'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 231.0C-30 227.9 0 219.5 20 212.3C40 205.2 60 196.1 80 188.0C100 179.8 120 171.0 140 163.5C160 156.0 180 143.4 200 143.1C220 142.7 240 151.5 260 161.3C280 171.1 300 192.0 320 201.7C340 211.4 360 216.4 380 219.5C400 222.6 430 220.4 440 220.5'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 252.5C-30 248.5 0 236.4 20 228.5C40 220.5 60 212.7 80 204.6C100 196.5 120 186.3 140 179.9C160 173.6 180 164.1 200 166.5C220 168.9 240 183.2 260 194.2C280 205.2 300 224.2 320 232.5C340 240.8 360 242.4 380 243.9C400 245.5 430 242.1 440 241.7'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 271.1C-30 266.6 0 252.3 20 244.1C40 235.8 60 229.1 80 221.5C100 213.8 120 202.7 140 198.0C160 193.2 180 188.2 200 193.2C220 198.2 240 216.7 260 228.1C280 239.4 300 254.8 320 261.2C340 267.7 360 266.6 380 266.6C400 266.6 430 262.1 440 261.2'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 287.4C-30 282.8 0 267.9 20 259.9C40 251.8 60 246.0 80 239.0C100 232.1 120 220.8 140 218.1C160 215.3 180 215.4 200 222.7C220 230.0 240 250.8 260 261.6C280 272.4 300 283.1 320 287.5C340 291.8 360 289.1 380 287.7C400 286.3 430 280.5 440 279.1'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 302.2C-30 298.0 0 283.9 20 276.5C40 269.1 60 263.6 80 257.7C100 251.7 120 241.1 140 240.6C160 240.0 180 245.5 200 254.4C220 263.2 240 284.2 260 293.7C280 303.2 300 308.9 320 311.2C340 313.5 360 310.0 380 307.5C400 304.9 430 297.8 440 295.9'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 316.6C-30 312.9 0 300.9 20 294.4C40 287.9 60 282.4 80 277.6C100 272.8 120 264.0 140 265.6C160 267.2 180 277.6 200 287.3C220 297.0 240 316.0 260 323.6C280 331.1 300 332.1 320 332.5C340 333.0 360 329.7 380 326.3C400 322.9 430 314.4 440 312.0'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 331.5C-30 328.5 0 319.2 20 313.8C40 308.3 60 302.5 80 299.0C100 295.5 120 289.3 140 292.8C160 296.4 180 310.7 200 320.3C220 329.9 240 345.3 260 350.5C280 355.8 300 353.0 320 352.0C340 351.0 360 348.7 380 344.7C400 340.7 430 330.8 440 328.0'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 347.7C-30 345.5 0 339.0 20 334.7C40 330.4 60 324.0 80 321.8C100 319.7 120 316.8 140 321.9C160 327.0 180 343.6 200 352.3C220 361.1 240 371.5 260 374.5C280 377.5 300 372.2 320 370.3C340 368.3 360 367.3 380 363.0C400 358.7 430 347.5 440 344.4'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 365.9C-30 364.4 0 360.4 20 357.1C40 353.8 60 346.9 80 346.1C100 345.2 120 346.0 140 352.1C160 358.2 180 375.2 200 382.5C220 389.8 240 394.8 260 395.7C280 396.7 300 390.4 320 388.1C340 385.7 360 385.9 380 381.5C400 377.2 430 365.2 440 361.9'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 386.2C-30 385.3 0 383.2 20 380.7C40 378.3 60 371.2 80 371.5C100 371.8 120 376.2 140 382.6C160 389.1 180 404.8 200 410.1C220 415.4 240 415.4 260 414.7C280 414.0 300 408.5 320 406.1C340 403.8 360 404.9 380 400.6C400 396.4 430 384.1 440 380.8'/%3E%3Cpath vector-effect='non-scaling-stroke' d='M-40 408.8C-30 408.2 0 406.9 20 405.1C40 403.2 60 396.5 80 397.8C100 399.0 120 406.5 140 412.7C160 418.9 180 431.7 200 434.9C220 438.2 240 433.9 260 432.3C280 430.6 300 427.0 320 425.0C340 423.1 360 424.4 380 420.5C400 416.5 430 404.5 440 401.4'/%3E%3C/g%3E%3C/svg%3E") 0 0/100% 100% no-repeat}
.wcv-word{position:relative;max-width:12ch;font-size:var(--fs-section);font-weight:400;line-height:var(--lh-tight);letter-spacing:var(--ls-title);color:var(--ink);text-wrap:balance}

/* phones: one white list of compact rows, thumb + number + title */
@media(max-width:560px){
  .wgrid{grid-template-columns:minmax(0,1fr);gap:0;padding:var(--s-2);border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-rest)}
  .wgrid>li+li{border-top:1px solid var(--line-soft)}
  .wgrid .post-card{display:grid;grid-template-columns:72px minmax(0,1fr);align-items:center;gap:var(--s-4);padding:var(--s-3) var(--s-2);border-radius:var(--r-inner);background:none;box-shadow:none}
  .wgrid .post-card:is(:hover,:focus-visible){translate:none;box-shadow:none}
  .wgrid .post-card .cover{width:72px;height:72px;border-radius:var(--r-inner)}
  .wgrid .cover:not(.cover-mp) .cover-ui{zoom:.2}
  .wgrid .cover.cv-lock .cover-ui{zoom:var(--fz,.2)}   /* a lockup thumb is scaled by js (70% of the thumb) */
  .wgrid .mp-ic b{display:none}
  .wgrid .cover:is(.wcv-tools,.wcv-process,.wcv-craft) .cover-ui{left:50%;top:50%;bottom:auto;translate:-50% -50%}   /* thumbs: the UI centred */
  .wgrid .wcv-ai{padding:8%}
  .wgrid :is(.wcv-title,.wcv-sheet){display:none}
  .wgrid .wcv-word{font-size:var(--fs-cap)}
  .wgrid .post-card .post-body{gap:var(--s-1);padding:0}
  .wgrid .post-card .post-body h2{font-size:var(--fs-body)}
  .wgrid .post-card .post-body p,.wgrid .wk-go{display:none}
}


/* === Vibe Code bento (owner pick 15 Oct 2026, option C; art-frame rule 16 Oct 2026, decisions.md "Vibe Code art frames") ===
   White cards on cream; colour ONLY in each card's art frame (.vb-art = .mesh with a hue class from the tool palette:
   sun, sky (case-d), lime (case-b), tangerine, mint, teal; neighbours never share a hue at 1, 2 or 3 columns;
   "More on the way" = the pale .hue-soft mesh).
   Layout: 3 columns = Whisper hero (column 1, rows 1-2) beside the two wide cards (Hop, Copy Review; rows 1-2 share one
   height), then two rows of three small cards. 2 columns = hero full width, then pairs. 1 column = stacked.
   Art frames (one rule, tokens below): small frame = --vb-ar; wide frame = the shared row height; hero = its own.
   Inside every frame ONE piece of art, same radius, overlay shadow and tilt (--vb-tilt). Real-UI screenshots (.vb-win)
   sit low (--vb-top = 20% of the frame of empty colour above) and bleed past the frame bottom; constructed mocks (Frame, Copy
   Review, More, Whisper film) sit fully inside as the largest 16:10 window (--vb-win-ar) that fits the insets: --vb-w,
   from container units, so they never clip at any width.
   Link cards: .vb-link + .vb-cover (lift on hover/focus). At most one loop per card (Whisper film, Frame playhead),
   paused offscreen (data-pause), static for reduced motion. */
.vb-grid{--vb-ar:16/10;--vb-win-ar:1.6;--vb-inset:var(--s-5);--vb-tilt:-4deg;
  --vb-top:20cqh;   /* screenshot windows sit low: an empty colour field of 20% of the frame above them (owner pin 19 Oct: half of the earlier 40%, so more of the plugin UI shows) */
  
  display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-4)}
@media(min-width:768px){
  .vb-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .vb-hero{grid-column:1 / -1}   /* 2 columns: the hero runs full width, the other eight pair up */
}
@media(min-width:1024px){
  .vb-grid{grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:minmax(0,1fr) minmax(0,1fr)}   /* hero rows share one height */
  .vb-hero{grid-column:auto;grid-row:span 2}
  .vb-wide{grid-column:span 2}
}
.vb{position:relative;display:flex;flex-direction:column;gap:var(--s-4);min-width:0;padding:var(--s-3);border-radius:var(--r-card);background:var(--white);box-shadow:var(--shadow-rest);isolation:isolate;
  transition:opacity var(--dur-3) var(--ease-out) calc(var(--d,0)*60ms),transform var(--dur-3) var(--ease-out) calc(var(--d,0)*60ms),translate var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease)}
.vb-link:is(:hover,:focus-within){translate:0 var(--lift);box-shadow:var(--shadow-hover)}
.vb-cover{position:absolute;inset:0;z-index:3;border-radius:inherit}
/* the art frame is its own stacking context (container-type), so its pause button sat UNDER the cover link and never got the click (owner 19 Oct): lift the frame above the cover, let every click on the art pass through to the link, and give the button back its own pointer events */
.vb-link .vb-art{z-index:4;pointer-events:none}
.vb-link .vb-art .clip-toggle{pointer-events:auto}
.vb-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* art frame: the only colour on the card; one piece of art centred in it with the same inset on every card */
.vb-art{position:relative;flex:none;display:grid;place-items:center;aspect-ratio:var(--vb-ar);container-type:size;overflow:hidden;border-radius:var(--r-inner);background:var(--wk-bg,var(--cream))}
.vb-art>*{--vb-w:min(calc(100cqw - 2 * var(--vb-inset)),calc((100cqh - 2 * var(--vb-inset)) * var(--vb-win-ar)))}
.vb-art>:is(.vb-win,.vb-mock,.vb-tone){width:var(--vb-w);rotate:var(--vb-tilt);transition:rotate var(--dur-2) var(--ease),translate var(--dur-2) var(--ease)}
.vb-art>:is(.vb-win,.vb-mock){aspect-ratio:var(--vb-win-ar);overflow:hidden;border-radius:var(--r-inner);box-shadow:var(--shadow-overlay)}
.vb-link:is(:hover,:focus-within) .vb-art>.vb-win{rotate:-2deg;translate:0 -4px}
.vb-win{position:relative;background:var(--white)}
/* real-UI screenshots (Hop, PinPoint, UI Kit, Color, Type): a 16:10 window at the frame width minus the side insets,
   starting --vb-top (20% of the frame height) below the frame top, so it sits low under an empty colour field and runs
   past the frame bottom (at least one inset; the frame crops it). The focus point (--pos) keeps each screenshot's title bar + first rows in view. */
.vb-art>.vb-win{align-self:start;width:calc(100cqw - 2 * var(--vb-inset));height:max(calc((100cqw - 2 * var(--vb-inset)) / var(--vb-win-ar)),calc(100cqh - var(--vb-top) + var(--vb-inset)));aspect-ratio:auto;margin-top:var(--vb-top)}
.vb-win>img{display:block;width:100%;height:100%;object-fit:cover;object-position:var(--pos,50% 0)}
.vb-tone{gap:.6em;padding:.9em;font-size:clamp(10px,calc(var(--vb-w) / 24),13px)}   /* em-sized from the window width, like the Frame mock */
.vb-tone .tone-row{padding:.6em .9em}
.vb-tone .tone-row p{font-size:1em;line-height:var(--lh-snug)}
.vb-tone .tone-label{margin-bottom:.15em;font-size:1em}
@container (max-height:260px){.vb-tone .tone-label{display:none}}   /* small frames: the colours carry before / after */
.vb-soon{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s-3);padding:var(--vb-inset);text-align:center}
.vb-soon p{margin:0;font-size:var(--fs-title);font-weight:700;line-height:var(--lh-snug);letter-spacing:var(--ls-title);text-wrap:balance}
.vb-soon .tag{background:var(--white);color:var(--ink)}

/* Frame: the playhead steps from note 1 to note 2 and back (the card's one loop) */
.vb-play{position:absolute;inset:0;animation:vb-scrub var(--loop) var(--ease-inout) infinite}
.is-paused .vb-play{animation-play-state:paused}
@keyframes vb-scrub{0%,30%{transform:none}50%,80%{transform:translateX(29%)}100%{transform:none}}

/* Whisper hero frame: 4:3 on phones, 2:1 full width at 2 columns, then the rest of its column beside the two wide cards. */
.vb-hero .vb-art{aspect-ratio:4/3}
@media(min-width:768px){.vb-hero .vb-art{aspect-ratio:2/1}}
@media(min-width:1024px){.vb-hero .vb-art{flex:1 1 auto;aspect-ratio:auto;min-height:0}.vb-hero .vb-body{flex:none}}
.vb-clip .clip-toggle{z-index:4;top:var(--s-2);right:var(--s-2)}
/* Clips. .vb-clip-full (Whisper, Hop, PinPoint; owner verdict
   19 Oct 2026 "video again": the live DOM scene + page camera were not as smooth as video) = the whole frame is the video: the
   card's own mesh is baked into the clip (tools/clips/<name>), the UI window sits on it and the camera zoom runs inside the
   file, so nothing is cropped into a box and no ground shows at the edges. Rendered at the 1440 frame ratio; object-fit:cover
   crops it in the other frames. Whisper carries a second, landscape render for the 2:1 / 4:3 frames below 1024: the hidden
   one is display:none, so it is never observed, loaded or played (js/site.js clips: play only in view). */
.vb-art>.vb-clip{position:relative;width:var(--vb-w);aspect-ratio:var(--vb-win-ar)}
.vb-clip video{display:block;width:100%;height:100%;object-fit:cover}
.vb-art>.vb-clip-full{position:absolute;inset:0;width:auto;aspect-ratio:auto;border-radius:0;box-shadow:none}
.vb-clip-full video{position:absolute;left:-1px;top:-1px;width:calc(100% + 2px);height:calc(100% + 2px)}   /* 1 px overscan: a fractional card width left a 1 px sliver of mesh on the right edge (owner 19 Oct) */
.vb-clip-full .v-wide{display:none}
@media(max-width:1023px){.vb-clip-full .v-tall{display:none}.vb-clip-full .v-wide{display:block}}

/* text */
.vb-body{flex:1 1 auto;display:flex;flex-direction:column;align-items:flex-start;padding:0 var(--s-3) var(--s-2)}
.vb-app{display:flex;align-items:center;gap:var(--s-3);max-width:none;font-size:var(--fs-cap);font-weight:500;line-height:var(--lh-snug);color:var(--muted)}
.vb-app b{display:block;font-weight:700;color:var(--ink)}
.vb-ic{flex:none;display:block;width:40px;height:40px;border-radius:var(--r-inner);overflow:hidden;box-shadow:var(--shadow-rest)}
.vb-ic-light{box-shadow:var(--edge-out),var(--shadow-rest)}  /* white icon on a white card */
.vb-word{margin-top:var(--s-4);font-size:var(--fs-sub);font-weight:700;line-height:var(--lh-tight);letter-spacing:var(--ls-display)}
.vb-hero .vb-word{font-size:var(--fs-section)}
.vb-line{max-width:42ch;margin-top:var(--s-2);font-size:var(--fs-body);line-height:var(--lh-snug);color:var(--body);text-wrap:pretty}
.vb-foot{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--s-5);margin-top:auto;padding-top:var(--s-2)}   /* links line up at the card bottom across a row */
.vb-alt{position:relative;z-index:4;display:inline-flex;align-items:center;gap:var(--s-1);min-height:44px;font-size:var(--fs-cap);font-weight:500;color:var(--body);text-decoration:underline var(--stroke) transparent;text-underline-offset:4px;transition:text-decoration-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.vb-alt:is(:hover,:focus-visible){color:var(--ink);text-decoration-color:currentColor}
.vb-alt svg{width:14px;height:14px}
.vb-note{display:inline-flex;align-items:center;min-height:44px;font-size:var(--fs-cap);font-weight:500;color:var(--muted)}

/* wide cards (3 columns): text left, art frame right at the shared row height (both wide frames identical) */
@media(min-width:1024px){
  .vb-wide{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);align-items:stretch}
  .vb-wide .vb-art{grid-column:2;grid-row:1;aspect-ratio:auto;min-height:0}
  .vb-wide .vb-body{grid-column:1;grid-row:1;padding:var(--s-4) var(--s-2) var(--s-2) var(--s-3)}
  .vb-wide .vb-word{margin-top:auto;padding-top:var(--s-4)}   /* app row on top, word + line + link at the bottom */
}


/* Enterprise experience card = typography only (owner 20 Oct: the sector tiles were not pretty): a big years figure and one label, white on the indigo mesh */
.cs-years{display:flex;flex-direction:column;align-items:center;gap:var(--s-2);text-align:center;color:var(--white)}
.cs-years b{font-size:clamp(3.25rem,5.2vw,4.5rem);font-weight:700;line-height:1;letter-spacing:var(--ls-display);font-variant-numeric:tabular-nums}
.cs-years-l{font-size:var(--fs-cap);font-weight:500;line-height:var(--lh-snug);opacity:.92}

/* COVER-LAYOUT:START (generated by tools/cover-editor, data in docs/cover-layout.json; do not hand edit) */
.cover.wcv-hero{container-type:inline-size}
/* COVER-LAYOUT:END */
