:root{--site-header-height:76px}
html{scroll-padding-top:calc(var(--site-header-height) + 78px)}
.navigation button{font:inherit;color:inherit;background:none;border:0;padding:12px 0;min-height:44px}
.navigation button:hover{color:var(--orange)}
.navigation-backdrop{position:fixed;inset:0 0 auto;height:var(--site-header-height);z-index:18;background:#080d17ed;border-bottom:1px solid #e9e6e112;opacity:var(--dock-progress,0);pointer-events:none}
.has-traveling-header .navigation{position:fixed;z-index:21;top:16px;transition:none}
.has-traveling-header .hero-copy{position:fixed;z-index:20;transform-origin:0 0;will-change:transform}
.has-traveling-header .hero-copy p{opacity:var(--byline-opacity,1);transform-origin:0 0;white-space:nowrap}
.has-traveling-header .studio-cat{position:fixed;z-index:20;transform-origin:0 0;translate:-50% -50%;transform:var(--dock-transform,none);will-change:transform}
/* The invitation is original outlined lettering, sized beneath the cat. */
.cat-hint{margin:0;padding:0;width:185px;height:auto;background:none;border:0;filter:none;opacity:0;visibility:hidden;pointer-events:none;transform:translateX(-50%) scale(.8) rotate(var(--cue-tilt-from,0deg));transform-origin:50% 15%;transition:opacity .14s,transform .26s cubic-bezier(.2,.8,.25,1)}
.cat-hint img{display:block;width:100%;height:auto}
.cat-hint::before,.cat-hint::after{display:none}
.has-traveling-header .cat-hint{position:fixed;z-index:22;top:282px;left:74%}
.has-traveling-header:not(.is-compact) .studio-cat[data-cue-ready=true]:hover~.cat-hint,.has-traveling-header:not(.is-compact) .studio-cat[data-cue-ready=true]:focus-visible~.cat-hint,.has-traveling-header .studio-cat[data-cue-ready=true][data-charging=true]~.cat-hint{visibility:visible!important;opacity:var(--cue-dock-opacity,1);transform:translateX(-50%) scale(1) rotate(var(--cue-tilt,0deg))}
.has-traveling-header:not(.is-compact):not(.is-playing) .studio-cat[data-invite-open=true]~.cat-hint{visibility:visible!important;opacity:var(--cue-dock-opacity,1);transform:translateX(-50%) scale(1) rotate(var(--cue-tilt,0deg))}
.is-playing .cat-hint{display:none}
.is-docking .cat-hint{visibility:hidden!important}
.is-playing .navigation-backdrop{opacity:0}
@media(max-width:699px){
 :root{--site-header-height:64px}
 html:has(.space-stage.is-compact){--site-header-height:112px}
 .has-traveling-header .navigation{top:10px;left:25px;right:25px}
 .navigation-links{gap:20px}
 .navigation button{padding:12px 0}
 .has-traveling-header.is-compact .navigation{top:64px;left:25px;right:25px;min-height:44px}
 .has-traveling-header.is-compact .navigation-links{margin-left:0;gap:24px}
 .has-traveling-header .cat-hint{left:50%;top:368px;width:160px}
}
@media(prefers-reduced-motion:reduce){.has-traveling-header .hero-copy,.has-traveling-header .studio-cat{will-change:auto}}

/* Controls are actions, while descriptions and store copy remain selectable. */
button,.project-store-link,[role=button]{-webkit-user-select:none;user-select:none}
@media(max-width:699px) and (prefers-reduced-motion:no-preference){.has-traveling-header .navigation{transition:top .3s ease}}

/* The header names the section it has covered; that section's own heading
   has faded beneath it (navigation.js). */
.navigation-links a[aria-current]{text-decoration:underline;text-decoration-color:var(--teal);text-decoration-thickness:1px;text-underline-offset:9px}
#projects-heading,#about-heading{transition:opacity .12s linear}
@media(prefers-reduced-motion:reduce){#projects-heading,#about-heading{transition:none}}
/* The sky stays reachable from the small header (local-sky.js opens the same panel). */
.navigation .nav-sky{display:none;align-items:center;cursor:pointer}
.has-traveling-header.is-compact:not(.is-playing):not([data-sky=fallback]) .nav-sky{display:inline-flex}
@media(max-width:699px){
 .has-traveling-header.is-compact .navigation-links{gap:clamp(10px,3.6vw,24px)}
}
@media(max-width:359px){.has-traveling-header .navigation,.has-traveling-header.is-compact .navigation{left:16px;right:16px}}

/* ---- Phone tabs ---------------------------------------------------------------
   They have a row to themselves, so they use it: larger type,
   spread across the row, each at least a 44 px target. */
@media(max-width:699px){
 .navigation-links,.has-traveling-header.is-compact .navigation-links{margin-left:0;width:100%;justify-content:space-between;gap:6px;font-size:clamp(14px,4.1vw,16px)}
 .navigation-links a,.navigation-links button{min-width:44px;justify-content:center}
}
/* The smudge highlight (data-highlight="smudge" on <html>): a soft elliptical patch of the cat's colours
   behind each tab. The default is the text-masked highlight below. */
/* Cat colours. On hover, on keyboard focus and for the section the header
   has covered, a soft patch of the cat's own colours spreads out from under
   the tab (orange, gold, green and blue).
   Nothing shows at rest. One gradient; only opacity and scale change. */
html[data-highlight=smudge] .navigation-links a,html[data-highlight=smudge] .navigation-links button{position:relative;isolation:isolate}
html[data-highlight=smudge] .navigation-links a::before,html[data-highlight=smudge] .navigation-links button::before{content:"";position:absolute;z-index:-1;left:50%;top:50%;width:calc(100% + 52px);height:58px;translate:-50% -50%;border-radius:50%;pointer-events:none;opacity:0;transform:scale(.5);background:radial-gradient(closest-side,#eab94d2b,#fe520140 30%,#a5f0932b 56%,#01a1ff24 80%,#01a1ff00);transition:opacity .2s ease,transform .34s cubic-bezier(.2,.8,.25,1)}
html[data-highlight=smudge] .navigation-links a:focus-visible::before,html[data-highlight=smudge] .navigation-links button:focus-visible::before,html[data-highlight=smudge] .navigation-links a[aria-current]::before{opacity:1;transform:none}
@media(hover:hover){html[data-highlight=smudge] .navigation-links a:hover::before,html[data-highlight=smudge] .navigation-links button:hover::before{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){html[data-highlight=smudge] .navigation-links a::before,html[data-highlight=smudge] .navigation-links button::before{transition:none}}
/* ---- The highlight lives in the letters --------------------------------------
   On hover, keyboard focus, press and for the section the header has covered, the
   tab's own letters take a soft holographic gradient (the cat's orange, gold, green
   and blue with a touch of violet), clipped to the glyphs with background-clip: text,
   and a very light glow that hugs the glyph shapes. Nothing is drawn behind or around
   the words. Under reduced motion it is static. Keyboard focus also keeps a thin ring. */
html:not([data-highlight=smudge]) .navigation-links a,html:not([data-highlight=smudge]) .navigation-links button{--holo:linear-gradient(100deg,#ff9a62 0%,#eab94d 26%,#a5f093 52%,#62c9ff 78%,#c4a9ff 100%);-webkit-tap-highlight-color:transparent}
html:not([data-highlight=smudge]) .navigation-links :is(a,button):is(:focus-visible,:active),html:not([data-highlight=smudge]) .navigation-links a[aria-current]{background-image:var(--holo);background-size:220% 100%;background-position:0 0;-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent;filter:drop-shadow(0 0 3px #7fd0ff3d)}
@media(hover:hover),(any-hover:hover){html:not([data-highlight=smudge]) .navigation-links :is(a,button):hover{background-image:var(--holo);background-size:220% 100%;background-position:0 0;-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent;filter:drop-shadow(0 0 3px #7fd0ff3d)}}
html:not([data-highlight=smudge]) .navigation-links :is(a,button):active{filter:drop-shadow(0 0 4px #a5f09357)}
html:not([data-highlight=smudge]) .navigation-links :is(a,button):focus-visible{outline:1.5px solid var(--teal);outline-offset:3px;border-radius:2px}
@media(prefers-reduced-motion:no-preference){
 html:not([data-highlight=smudge]) .navigation-links :is(a,button):is(:focus-visible,:active){animation:holo-drift 2.6s ease-in-out infinite alternate}
 @media(hover:hover),(any-hover:hover){html:not([data-highlight=smudge]) .navigation-links :is(a,button):hover{animation:holo-drift 2.6s ease-in-out infinite alternate}}
 @keyframes holo-drift{to{background-position:100% 0}}
}


/* ---- The comic cue -----------------------------------------------------------
   data-cue-look on #cat-hint: "comic" (pow.svg: halftone burst, hard shadow,
   slanted capitals; pops in with an overshoot and a tilt) or "classic"
   (rally.svg). On a phone the cue is large and sits on
   the cat's lower half, inside the visible screen. */
.cat-hint[data-cue-look=comic] .cue-look-classic,.cat-hint:not([data-cue-look=comic]) .cue-look-comic{display:none}
.cat-hint[data-cue-look=comic]{--cue-tilt:-3deg;--cue-tilt-from:-18deg;width:240px;transform-origin:50% 50%;transform:translateX(-50%) scale(.3) rotate(var(--cue-tilt-from));transition:opacity .1s,transform .42s cubic-bezier(.2,1.9,.4,1);filter:drop-shadow(0 6px 18px #0008)}
@media(max-width:699px){
 /* Anchored at the cat's lower right, below its mouth and chin (the cat is 265 px square
   from y 193; its eyes, nose and mouth end near y 384), spilling into the space beside
   and below it. The cue stays clear of that face box at 390 and 320 px wide. */
 .has-traveling-header .cat-hint[data-cue-look=comic]{--cue-w:min(64vw,250px);width:var(--cue-w);left:calc(100vw - var(--cue-w) / 2 - 6px);top:calc(398px + var(--safe-top))}
}
@media(prefers-reduced-motion:reduce){
 .cat-hint[data-cue-look=comic]{--cue-tilt-from:-3deg;transform:translateX(-50%) scale(1) rotate(-3deg);transition:opacity .01s}
}

/* ---- Brand first ---------------------------------------------------------------
   At rest the name and tagline come first, the links row after them, with the
   sky's slot at the left end of that row. The row rises with the shrinking
   title (--nav-y, set by navigation.js from the same progress) and keeps the
   same horizontal places throughout: the slot is reserved by ::before, so the
   links do not close up when the sky button leaves. --safe-top is the phone's
   status area (viewport-fit=cover); the scene runs behind it. */
@media(max-width:699px){
 :root{--site-header-height:calc(64px + var(--safe-top))}
 html:has(.space-stage.is-compact){--site-header-height:calc(112px + var(--safe-top))}
 .has-traveling-header .navigation,.has-traveling-header.is-compact .navigation{top:var(--nav-y,calc(var(--safe-top) + 138px))}
 .space-stage.has-traveling-header .navigation{transition:opacity .35s ease}
 .has-traveling-header:not([data-sky-place=links-row]) .navigation-links::before{content:"";flex:none;width:var(--sky-slot,76px)}
 .space-stage.is-playing .navigation{pointer-events:none}
 .has-traveling-header .cat-hint{top:calc(368px + var(--safe-top))}
}
/* A finger leaves no hover behind: the orange hover colour must not stick after a tap. */
@media(hover:none) and (any-hover:none){
 html:not([data-highlight=smudge]) .navigation-links a:not([aria-current]):not(:focus-visible):not(:active):hover,html:not([data-highlight=smudge]) .navigation-links button:not(:focus-visible):not(:active):hover{color:var(--ink)}
 html:not([data-highlight=smudge]) .navigation-links .nav-sky:not(:focus-visible):not(:active):hover{color:#8e9ca9}
}
/* High-contrast / forced colours remove backgrounds, which would leave transparent letters empty:
   the tabs keep their system text colour and just show the focus ring and underline. */
@media(forced-colors:active){
 html:not([data-highlight=smudge]) .navigation-links :is(a,button){background:none!important;-webkit-text-fill-color:currentColor!important;color:LinkText!important;filter:none!important;animation:none!important}
}

/* Moving between sections (section-flow.js): the section takes focus without a ring, its heading settles in. */
.projects-section[tabindex="-1"]:focus,.about-section[tabindex="-1"]:focus{outline:none}
@media(prefers-reduced-motion:no-preference){.section-arrive{animation:section-settle 720ms cubic-bezier(.2,.8,.25,1) both}@keyframes section-settle{from{opacity:.45;transform:translateY(14px)}to{opacity:1;transform:none}}}

/* The top row is the page's own places (See your sky, Projects, About); Discord and Instagram stand
   together, with their marks, in About and the footer. data-header-discord="on" on <html> puts the word
   in the top row. The link stays in the page either way. */
@media(min-width:700px){html:not([data-header-discord=on]) .navigation-links .nav-discord{display:none}}
/* On a phone the row keeps its measure: the three entries keep their places (See your sky
   immediately left of Projects), and the place at the right end is left empty. */
@media(max-width:699px){html:not([data-header-discord=on]) .navigation-links .nav-discord{visibility:hidden;pointer-events:none}}
/* When the Posts link is shown, on a phone it takes the place at the right end of the row. */
@media(max-width:699px){html:not([data-header-discord=on]) .navigation-links:has(.nav-posts:not([hidden])) .nav-discord{display:none}}

/* The header row starts at the page's margin and its links sit at its right end, so the row's empty
   stretch lies over the small cat. Once the header has shrunk the small cat is the upper layer there,
   so it takes its own taps; the row still takes the rest. */
@media(min-width:700px){.has-traveling-header.is-compact .studio-cat{z-index:22}}

@media(min-width:700px){.navigation-links a{min-width:44px;justify-content:center}}
