/* =====================================================================
   Shell (every page): frosted bottom pill nav, ring cursor, page
   transitions. Loaded after site.css on About/Craft, and with b.css on
   Work and case pages.
   ===================================================================== */
@view-transition { navigation: auto; }
:root {
  --b-blue: #0047ba; --b-ink: #121010; --b-cream: #f1ebe1; --b-amber: #e7834c;
  --b-serif: "Instrument Serif", Georgia, serif; --b-sans: Inter, system-ui, sans-serif;
  --b-out: cubic-bezier(.2,.7,.2,1); --b-io: cubic-bezier(.7,0,.2,1);
}

/* the old top nav is replaced by the menu below everywhere */
.nav { display: none !important; }

/* ---------- menu (separate from the progress tracker) ----------
   Three variants share one markup: html[data-nav="a|b|c"].
   a: quiet words at the top that condense into a small pill on scroll (default)
   b: a thin line at the bottom that opens into the menu on hover / tap
   c: name top-left, words top-right, hide on scroll down, return on scroll up */
.menu { position: fixed; z-index: 100; font: 400 21px/1 var(--b-serif); color: var(--fg, #f4f1ea); view-transition-name: site-menu; }
.menu a, .menu button { color: inherit; text-decoration: none; background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }
.menu .m-links { display: flex; align-items: center; }
.menu .m-links a { position: relative; padding: 8px 12px; opacity: .72; transition: opacity .25s ease; }
.menu .m-links a:hover, .menu .m-links a:focus-visible, .menu .m-links a[aria-current="page"] { opacity: 1; }
.menu .m-links a[aria-current="page"] { font-style: italic; }
/* hand-drawn pencil underline, same hand as the About doodles: draws itself on the current page, quickly on hover */
.menu .m-mark { position: absolute; left: 8px; right: 8px; bottom: -1px; width: calc(100% - 16px); height: 9px; overflow: visible; pointer-events: none; color: var(--b-amber); }
.menu .m-mark path { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1 2; stroke-dashoffset: 1.02; vector-effect: non-scaling-stroke; transition: stroke-dashoffset .6s cubic-bezier(.6,.1,.2,1); }
.menu .m-links a:hover .m-mark path, .menu .m-links a:focus-visible .m-mark path { stroke-dashoffset: 0; }
.menu .m-links a[aria-current="page"] .m-mark path { transition-duration: 1.4s; transition-delay: .35s; }
.menu.drawn .m-links a[aria-current="page"] .m-mark path { stroke-dashoffset: 0; }
.menu .m-name { display: none; }
.menu .m-line { display: none; }
.menu :focus-visible { outline: 2px solid currentColor; outline-offset: 2px; border-radius: 999px; }

/* a: the three words, in the current tone's foreground; slides up on scroll down, returns on a slight scroll up */
html[data-nav="a"] .menu, html:not([data-nav]) .menu { left: 50%; top: 12px; transform: translateX(-50%); padding: 4px 6px; color: var(--fg, #f4f1ea); transition: transform .55s var(--b-out), color .9s var(--b-io); }
html[data-nav="a"] .menu.away, html:not([data-nav]) .menu.away { transform: translate(-50%, calc(-100% - 20px)); }


/* ---------- progress tracker (case only, quiet, not interactive) ---------- */
.tracker { position: fixed; left: 50%; bottom: 20px; z-index: 99; display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 16px 0 14px; border-radius: 999px; color: #f4f1ea; background: rgba(18,16,16,.5); -webkit-backdrop-filter: blur(16px) saturate(1.3); backdrop-filter: blur(16px) saturate(1.3); box-shadow: 0 0 0 1px rgba(255,255,255,.08) inset; font: 500 12px/1 var(--b-sans); pointer-events: none; overflow: hidden; transform: translateX(-50%); opacity: 0; transition: opacity .5s ease; white-space: nowrap; }
.tracker.on { opacity: 1; }
.tracker.on.hush { opacity: 0; }
.tracker .t-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--b-amber); }
.tracker [data-t-label] { display: inline-block; font: italic 400 17px/1 var(--b-serif); }
.tracker [data-t-label].swap { animation: t-lab .5s var(--b-out); }
@keyframes t-lab { from { opacity: 0; transform: translateY(6px); filter: blur(4px); } }
.tracker [data-t-count] { opacity: .55; font-variant-numeric: tabular-nums; }
.tracker .t-prog { position: absolute; left: 0; bottom: 0; height: 2px; width: 100%; background: var(--b-amber); transform-origin: 0 50%; transform: scaleX(var(--prog, 0)); }
@media (max-width: 860px) {
  .tracker { bottom: 14px; }
  .menu { font-size: 19px; }
}

/* ---------- cursor: ring, frosted pill over cards ---------- */
.has-cursor, .has-cursor a, .has-cursor button { cursor: none; }
.has-cursor input[type="range"] { cursor: ew-resize; }
.cursor { position: fixed; left: 0; top: 0; z-index: 200; pointer-events: none; opacity: 0; transition: opacity .3s ease; }
.cursor.on { opacity: 1; }
.cursor .c-dot, .cursor .c-pill { position: absolute; left: 0; top: 0; }
.cursor .c-dot { width: 14px; height: 14px; color: var(--cc, #e7834c); transform: translate(-50%, -50%); transition: opacity .25s ease, transform .35s var(--b-out), color .3s ease; }
.cursor .c-dot svg { display: block; width: 100%; height: 100%; overflow: visible; }
.cursor .c-dot path { fill: currentColor; }
/* "View case study": no frame, the site's italic serif and an arrow in the same hand as the nav underline, both drawing on as it appears.
   A tight halo in the card's own colour (--halo, from b.js) keeps it legible over any picture. */
.cursor .c-pill { display: flex; align-items: center; gap: 8px; white-space: nowrap; color: #f4f1ea; font: italic 400 25px/1 var(--b-serif); letter-spacing: -.005em; --ink-w: 2.1; text-shadow: 0 0 1px var(--halo, #121010), 0 0 3px var(--halo, #121010), 0 0 7px var(--halo, #121010), 0 0 14px var(--halo, #121010), 0 0 26px var(--halo, #121010); filter: drop-shadow(0 0 2px var(--halo, #121010)) drop-shadow(0 0 6px var(--halo, #121010)); opacity: 0; transform: translate(-50%, -50%) scale(.92); transition: opacity .3s var(--b-out), transform .4s var(--b-out); }
.cursor .c-arr { width: 38px; height: 17px; overflow: visible; margin-top: -2px; }
.cursor .c-pill .ink-m { stroke-dasharray: 1 2; stroke-dashoffset: 1.02; transition: stroke-dashoffset 0s; }
.cursor[data-mode="case"] .c-pill .ink-m { stroke-dashoffset: 0; transition: stroke-dashoffset .38s cubic-bezier(.6,.1,.2,1) calc(.08s + var(--d, 0s)); }
.cursor[data-mode="case"] .c-pill { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.cursor[data-mode="case"] .c-dot { opacity: 0; transform: translate(-50%, -50%) scale(0); }
.cursor[data-mode="link"] .c-dot { transform: translate(-50%, -50%) scale(2.2); }
.cursor.down .c-dot { transform: translate(-50%, -50%) scale(.8); }

/* ---------- page transitions ---------- */
/* a shared-element move: the key visual's parts and the wordmark travel; everything else leaves first, then the new page arrives */
::view-transition-old(root) { animation: b-root-out .24s var(--b-io) both; }
::view-transition-new(root) { animation: b-root-in .55s var(--b-out) .34s both; }
/* the title never moves or scales: the leaving one fades out where it is, the arriving one sharpens in place once the morph has landed */
::view-transition-group(kv-cap-out), ::view-transition-group(kv-cap-in) { animation: none; }
::view-transition-old(kv-cap-out) { animation: b-fade-out .15s linear both; }
::view-transition-new(kv-cap-in) { animation: b-cap-in .5s var(--b-out) .84s both; }
@keyframes b-cap-in { from { opacity: 0; filter: blur(12px); transform: translateY(12px); } }
::view-transition-group(site-menu) { animation-duration: .3s; }
::view-transition-group(kv-field), ::view-transition-group(kv-phone), ::view-transition-group(kv-card), ::view-transition-group(kv-badge) { animation-duration: .95s; animation-timing-function: var(--b-io); }
::view-transition-group(kv-phone) { animation-delay: .03s; }
::view-transition-group(kv-card) { animation-duration: 1.05s; animation-delay: .06s; }
::view-transition-group(kv-badge) { animation-duration: 1.1s; animation-delay: .1s; }
::view-transition-old(kv-field), ::view-transition-new(kv-field) { height: 100%; width: 100%; }
::view-transition-old(kv-field) { animation: b-fade-out .3s ease both; }
::view-transition-new(kv-field) { animation: b-fade-in .3s ease both; }
.vt-on .tl-sh { opacity: 0 !important; transition: none !important; }
.kv .sa-tier { transition: opacity .6s var(--b-out); }
/* the case hero is the phone alone: the card's extra layers fade out where they are and fade back in on the way home; they never travel */
::view-transition-group(kv-card), ::view-transition-group(kv-badge), ::view-transition-group(kv-t1), ::view-transition-group(kv-t2) { animation: none; }
::view-transition-old(kv-card), ::view-transition-old(kv-badge), ::view-transition-old(kv-t1), ::view-transition-old(kv-t2) { animation: b-fade-out .18s ease-out both; }
::view-transition-new(kv-card), ::view-transition-new(kv-badge), ::view-transition-new(kv-t1), ::view-transition-new(kv-t2) { animation: b-fade-in .35s ease-out .55s both; }
/* the phone keeps its source image in flight and hands over at the end (a case hero may be a video still loading) */
::view-transition-old(kv-phone), ::view-transition-new(kv-phone) { height: 100%; width: 100%; object-fit: cover; }
::view-transition-old(kv-phone) { animation: b-hold-out .95s linear both; }
::view-transition-new(kv-phone) { animation: b-hold-in .95s linear both; }
/* the new phone is opaque before the old one starts to go, so the two never wash out together */
@keyframes b-hold-out { 0%, 80% { opacity: 1; } 100% { opacity: 0; } }
@keyframes b-hold-in { 0%, 60% { opacity: 0; } 78%, 100% { opacity: 1; } }
@keyframes b-root-out { to { opacity: 0; filter: blur(8px); transform: scale(.985); } }
@keyframes b-root-in { from { opacity: 0; filter: blur(8px); } }
@keyframes b-fade-out { to { opacity: 0; } }
@keyframes b-fade-in { from { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
  .menu, .menu .m-links, .tracker, .cursor .c-dot, .cursor .c-pill { transition: none !important; }
  .tracker [data-t-label].swap { animation: none; }
}

/* ---------- blur-to-sharp headline reveal (shared flavour) ---------- */
.js [data-split] .w { display: inline-block; opacity: 0; transform: translateY(.28em); filter: blur(12px); transition: opacity .8s var(--b-out), transform .9s var(--b-out), filter .8s var(--b-out); transition-delay: calc(var(--d, 0s) + var(--i) * 55ms); }
.js [data-split].in .w { opacity: 1; transform: none; filter: blur(0); }
/* About keeps its own design; reveals just arrive a little softer */
html.js body.about [data-r] { filter: blur(8px); transition: opacity var(--d-3) var(--e-out), transform var(--d-3) var(--e-out), filter var(--d-3) var(--e-out); transition-delay: var(--d, 0s); }
html.js body.about [data-r].in { filter: none; }
body.about { transition: --bgc 1.2s var(--b-io), --fg 1.2s var(--b-io); }
@media (prefers-reduced-motion: reduce) {
  .js [data-split] .w, html.js body.about [data-r] { opacity: 1 !important; transform: none !important; filter: none !important; transition: none !important; }
  .menu .m-mark path { stroke-dashoffset: 0 !important; transition: none !important; }
  .menu .m-links a:not([aria-current]) .m-mark { display: none; }
}

/* ---------- ink (see Ink in b.js): the original path becomes the reveal mask ---------- */
.ink-m { fill: none !important; stroke-linecap: round; stroke-linejoin: round; }
svg[data-ink], svg.doodle, svg.m-mark, svg.ring { --ink-w: 2.5; }

.menu .m-links a[aria-current] .m-mark path { transition-duration: 1.4s; transition-delay: .35s; }
.menu.drawn .m-links a[aria-current] .m-mark path { stroke-dashoffset: 0; }

/* ---------- Craft: not a page yet; it says so on hover or focus and goes nowhere ---------- */
.menu .m-links .m-soon { position: relative; padding: 8px 12px; opacity: .72; cursor: default; transition: opacity .25s ease; }
.menu .m-links .m-soon:focus-visible, .menu .m-links .m-soon.show { opacity: 1; }
@media (hover: hover) { .menu .m-links .m-soon:hover { opacity: 1; } .menu .m-soon:hover .m-s { opacity: .8; transform: translate(-50%, 0); } }
.menu .m-soon .m-s { position: absolute; left: 50%; top: calc(100% - 2px); transform: translate(-50%, -4px); white-space: nowrap; font: italic 400 15px/1 var(--b-serif); opacity: 0; pointer-events: none; transition: opacity .25s ease, transform .35s var(--b-out); }
.menu .m-soon:focus-visible .m-s, .menu .m-soon.show .m-s { opacity: .8; transform: translate(-50%, 0); }

/* ---------- home: a small hand-inked asterisk, first in the nav, same hand and ink as the underline; it redraws on hover ---------- */
.menu .m-links a.m-home { display: inline-flex; align-items: center; padding: 8px 10px; }
.m-star { flex: none; width: .72em; height: .72em; overflow: visible; --ink-w: 1.9; margin-top: -.08em; }
.m-star path { fill: none; stroke: currentColor; stroke-linecap: round; }
.m-star .ink-m { stroke-dasharray: 1 2; stroke-dashoffset: 0; }
.m-home:hover .m-star .ink-m, .m-home:focus-visible .m-star .ink-m { animation: hk-draw .45s cubic-bezier(.6,.1,.2,1) both; animation-delay: var(--d, 0s); }
@keyframes hk-draw { from { stroke-dashoffset: 1.02; } to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) { .m-star .ink-m { animation: none !important; } }
/* during a page transition nothing re-blurs the backdrop behind it */
html:active-view-transition .tracker, html:active-view-transition .menu .m-links { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }

/* arriving through the card-to-case morph: the wordmark is already whole */
.vt-whole[data-rv], .vt-whole [data-rv], .vt-whole [data-split] .w { opacity: 1 !important; filter: none !important; transform: none !important; transition: none !important; animation: none !important; }
