/* Menu and logo micro-animations (first pass, to be reworked). Loaded before style.css,
   which sets --hl (highlight colour) and turns .nav-ind into a pill. */

/* logo: the hexagon draws itself on load and again on hover; the NP mark pops in, then tilts on hover */
.brand svg .hexp { stroke-dasharray: 1; animation: np-draw 1.4s cubic-bezier(.6, 0, .2, 1) backwards; }
.brand:hover svg .hexp { animation: np-redraw .9s cubic-bezier(.6, 0, .2, 1); }
.brand svg .markp { transform-box: fill-box; transform-origin: center; animation: np-pop .7s .6s cubic-bezier(.3, 1.6, .5, 1) backwards; transition: transform .45s cubic-bezier(.3, 1.6, .5, 1); }
.brand:hover svg .markp { transform: rotate(-10deg) scale(1.08); }
@keyframes np-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes np-redraw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes np-pop { from { opacity: 0; transform: scale(.5) rotate(-25deg); } }

/* hexagon portrait: the outline traces around the photo once */
.ring { stroke-dasharray: 1; animation: np-draw 1.8s .3s cubic-bezier(.6, 0, .2, 1) backwards; }

/* menu: a sliding underline that follows the pointer, springy on arrival */
.nav { position: relative; isolation: isolate; }
.nav-ind { position: absolute; left: 0; top: calc(var(--y, 0px) + var(--h, 0px) - 2px); height: 2px; width: 0; border-radius: 2px; background: var(--hl); pointer-events: none; z-index: -1; opacity: 0;
	transition: transform .45s cubic-bezier(.3, 1.35, .5, 1), width .45s cubic-bezier(.3, 1.35, .5, 1), opacity .25s; }
.nav-ind.still { transition: none; }
.nav a:not(.btn) { transition: color .2s, transform .25s; }
.nav a:not(.btn):hover { color: var(--hl); }
.nav a:not(.btn):active { transform: translateY(1px); }

/* call-to-action: an arrow slides in on hover (no lift), a small press on click */
.nav .btn { gap: 0; transition: transform .25s cubic-bezier(.3, 1.6, .5, 1), background-color .2s, box-shadow .25s; }
.nav .btn::after { content: ""; display: inline-block; max-width: 0; opacity: 0; overflow: hidden; transform: translateX(-6px); transition: max-width .3s, opacity .2s, transform .3s, margin .3s; }
.nav .btn:hover { box-shadow: 0 8px 18px -10px rgba(0, 0, 0, .5); }
.nav .btn:hover::after { max-width: 1.2em; opacity: 1; transform: none; margin-left: 8px; }
.nav .btn:active { transform: translateY(0) scale(.97); }

/* service cards: rise in on first view, icon strokes draw; on hover the strokes redraw and the coral accents pop */
.svc article.pre, [data-reveal] > .pre { opacity: 0; transform: translateY(24px); }
.svc article.in, [data-reveal] > .in { transition: opacity .7s calc(var(--i, 0) * 110ms), transform .8s calc(var(--i, 0) * 110ms) cubic-bezier(.2, .9, .3, 1); }
.ico .st { stroke-dasharray: 1; }
.svc article.in .ico .st { animation: np-draw 1.3s calc(var(--i, 0) * 110ms + .25s) cubic-bezier(.6, 0, .2, 1) backwards; }
.svc article:hover .ico .st { animation: np-redraw .9s cubic-bezier(.6, 0, .2, 1); }
.ico [stroke="none"] { transform-box: fill-box; transform-origin: center; }
.svc article:hover .ico [stroke="none"] { animation: np-pop-accent .7s .35s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes np-pop-accent { 45% { transform: scale(1.6); } }

/* logo intro only on the first page of a visit (brand.js sets .seen afterwards); hover still redraws */
.seen .brand:not(:hover) svg .hexp, .seen .brand svg .markp { animation: none; }

/* ── page transitions (transit.js): only the blue header block and its lines carry over; everything else fades.
   Cross-document View Transitions just keep the old and new frames from flashing in between. ── */
@media (prefers-reduced-motion: no-preference) { @view-transition { navigation: auto; } }
.top { view-transition-name: site-header; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .2s; }
[data-topo="hero"] > :not(.topo, .top), [data-topo="hero"] ~ * { transition: opacity .4s ease; }
html.leaving [data-topo="hero"] > :not(.topo, .top), html.leaving [data-topo="hero"] ~ * { opacity: 0; }
html.arriving [data-topo="hero"] > :not(.topo, .top), html.arriving [data-topo="hero"] ~ * { opacity: 0; animation: np-safety-show 0s 3s forwards; }
@keyframes np-safety-show { to { opacity: 1; } } /* if transit.js never runs, the content still shows after 3 s */

/* landing: the client strip scrolls (pauses on hover) */
.marquee .track > ul { animation: np-scroll 38s linear infinite; }
.marquee .track:hover > ul { animation-play-state: paused; }
@keyframes np-scroll { to { transform: translateX(-100%); } }
.seen 
/* FAQ chat: the question pops in, the answer bubble shows "•••" for a moment, then its text; hovering a pair makes the avatar nod */
.faq > .in h3 { animation: np-bubble .45s calc(var(--i, 0) * 110ms + .1s) cubic-bezier(.3, 1.5, .5, 1) backwards; }
.faq > .in p { animation: np-bubble .45s calc(var(--i, 0) * 110ms + .6s) cubic-bezier(.3, 1.5, .5, 1) backwards; }
.faq > .in p::after { animation: np-dots .36s steps(1) infinite, np-type-out 1.4s calc(var(--i, 0) * 110ms + .6s) both; }
@keyframes np-bubble { from { opacity: 0; transform: scale(.6); } }
@keyframes np-dots { 0% { content: "•"; } 33% { content: "••"; } 66% { content: "•••"; } }
@keyframes np-type-out { 0%, 70% { opacity: 1; } 100% { opacity: 0; } }
@keyframes np-nod { 30% { transform: rotate(-12deg) translateY(-3px); } 60% { transform: rotate(6deg); } }

/* portfolio: the filter pill slides like the menu's; cards rise in column by column while their screenshot wipes up;
   on hover a glow in the project colour follows the pointer, the hexagon spins, the chips tint one after the other
   and an accent bar draws along the bottom. Filtering glides the cards to their new places (a View Transition
   started in portfolio.html). */
.filters .pill { transition: transform .45s cubic-bezier(.3, 1.35, .5, 1), width .45s cubic-bezier(.3, 1.35, .5, 1), height .45s; }
.filters .pill.still { transition: none; }
.filters button { transition: color .25s, transform .2s; }
.filters button:active { transform: scale(.95); }
.works > .in { transition-delay: calc(var(--col, 0) * 120ms); }
.works > .in .img img { animation: np-wipe 1.1s calc(var(--col, 0) * 120ms + .15s) cubic-bezier(.6, 0, .2, 1) backwards; }
@keyframes np-wipe { from { clip-path: inset(100% 0 0 0); scale: 1.15; } }
.work { transition: transform .35s cubic-bezier(.2, .9, .3, 1), box-shadow .35s, border-color .35s; }
.work::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: 0; transition: opacity .35s;
	background: radial-gradient(380px circle at var(--mx, 50%) var(--my, 50%), color-mix(in srgb, var(--c) 18%, transparent), transparent 70%); }
.work::after { content: ""; position: absolute; inset: auto 0 0; height: 3px; background: var(--c); transform: scaleX(0); transform-origin: left; transition: transform .55s cubic-bezier(.6, 0, .2, 1); }
.work img { transition: transform .9s cubic-bezier(.2, .9, .3, 1); }
.work .hx { transition: rotate .7s cubic-bezier(.3, 1.4, .5, 1); }
.work .chips li { transition: background-color .3s calc(var(--k, 0) * 50ms), color .3s calc(var(--k, 0) * 50ms); }
.work .n { transition: color .3s; }
.work .visit .ic { transition: transform .3s cubic-bezier(.3, 1.6, .5, 1); }
@media (hover: hover) {
	.work:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--c) 50%, var(--line)); box-shadow: 0 22px 44px -24px color-mix(in srgb, var(--c) 60%, rgba(17, 25, 37, .6)); }
	.work:hover::before { opacity: 1; }
	.work:hover::after { transform: none; }
	.work:hover img { transform: scale(1.04); }
	.work:hover .hx { rotate: 1turn; }
	.work:hover .chips li { background: color-mix(in srgb, var(--c) 22%, transparent); color: var(--ink); }
	.work:hover .n { color: color-mix(in srgb, var(--c) 70%, var(--ink)); }
	.work:hover .visit .ic { transform: translateX(5px); }
}
.work:active { transform: translateY(-1px) scale(.99); }
.works > .work { view-transition-class: work; }
::view-transition-group(.work) { animation-duration: .55s; animation-timing-function: cubic-bezier(.3, 1.15, .5, 1); }
::view-transition-old(.work), ::view-transition-new(.work) { height: 100%; object-fit: cover; object-position: top left; }

@media (prefers-reduced-motion: reduce) {
	.work, .work *, .work::before, .work::after, .filters *,
	.marquee ul, [data-reveal] > *, .faq *, .faq p::before, .faq p::after, .ic, .lightbox, .lightbox button,
	.brand svg *, .ring, .nav-ind, .nav a, .nav .btn, .nav .btn::after, .ico *, .svc article, .svc article *, .svc article::before { animation: none !important; transition: none !important; }
}
