[hidden] { display: none !important; }
.world-scene { position: fixed; inset: 0; z-index: -2; overflow: hidden; pointer-events: none; }
body[data-world='original'] .world-scene { display: none; }
#world-stage { position: absolute; inset: 0; width: 100%; height: 100%; }
#world-companions { position: fixed; inset: 0; z-index: 18; pointer-events: none; overflow: hidden; }
.world-wanderer { position: absolute; top: 0; left: 0; width: var(--pet-size, 60px); height: var(--pet-size, 60px); padding: 0; border: 0; background: transparent; cursor: grab; pointer-events: auto; touch-action: none; user-select: none; will-change: transform; transition: opacity 320ms ease, visibility 0s linear 0s; }
.world-wanderer .pet-body { position: absolute; inset: 0; transform-origin: 50% 88%; will-change: transform; pointer-events: none; }
.world-wanderer .pet-shadow { position: absolute; left: 20%; right: 20%; bottom: -1%; height: 13%; border-radius: 50%; background: radial-gradient(closest-side, #000c, #0000); opacity: .3; pointer-events: none; }
.world-wanderer.is-home .pet-shadow { background: radial-gradient(closest-side, var(--accent, #f80) 0 55%, #0000); opacity: .5 !important; }
.world-wanderer .character-pose { position: absolute; inset: 0; display: block; width: 100%; height: 100%; background: var(--sprite) 0 0/200% 200% no-repeat; pointer-events: none; transform-origin: 50% 85%; filter: drop-shadow(0 3px 3px #0003); animation: companion-breathe 6s ease-in-out infinite; }
.world-wanderer .pose-ghost { opacity: 0; }
.character-pose[data-frame='1'] { background-position: 100% 0; }
.character-pose[data-frame='2'] { background-position: 0 100%; }
.character-pose[data-frame='3'] { background-position: 100% 100%; }
.world-wanderer.dragging { cursor: grabbing; z-index: 4; }
.world-wanderer.dragging .character-pose { animation-play-state: paused; }
.world-wanderer.dragging .pet-body { filter: drop-shadow(0 10px 8px #0004); }
.world-transforming .world-wanderer, .world-wanderer.pet-crossing-content { pointer-events: none; }
/* Crossing a reading area fades the companion out, then hides it from hit-testing once invisible. */
.world-wanderer.pet-crossing-content { opacity: 0; visibility: hidden; transition: opacity 320ms ease, visibility 0s linear 320ms; }
.world-wanderer:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
/* Gait, lean, squash and float are driven per companion in worlds.js; CSS only adds breathing. */
.world-wanderer [data-character='halloween'] { animation-duration: 4.5s; }
.world-wanderer [data-character='lego'], .world-wanderer [data-character='minecraft'], .world-wanderer [data-character='roblox'] { animation-timing-function: steps(3); }
@keyframes companion-breathe { 50% { transform: translateY(-1.5px) scale(1.012, .99); } }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
body:not([data-world='original']) { --bg: var(--paper); --text: var(--ink); }
body:not([data-world='original']) #app { padding-bottom: 110px; }
body:not([data-world='original']) .dock { position: fixed; bottom: max(14px, env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%); display: flex; gap: 3px; align-items: center; padding: 8px; background: var(--paper); color: var(--ink); border: 1px solid var(--line); border-radius: 50px; box-shadow: 0 5px 20px #0003; z-index: 30; max-width: calc(100% - 16px); }
body:not([data-world='original']) .dock a, body:not([data-world='original']) .dock button { display: grid; place-items: center; flex: 0 0 36px; width: 36px; height: 36px; padding: 8px; background: none; color: inherit; border: 0; border-radius: 50%; }
body:not([data-world='original']) .dock a:hover, body:not([data-world='original']) .dock button:hover { background: var(--ink); color: var(--paper); }
body:not([data-world='original']) .dock svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
body:not([data-world='original']) .dock a:nth-child(n+3):nth-child(-n+6) svg { fill: currentColor; stroke: none; }
body[data-world='minecraft'] .dock { background: #302f34; border-color: #d0d0d3; border-radius: 0; box-shadow: 0 3px #1b191e; }
body[data-world='minecraft'] .dock :is(a, button) { background: #77767a; color: #202124; border-radius: 0; box-shadow: inset 1px 1px #b9b8bd, inset -1px -1px #39383e; }
body[data-world='minecraft'] .dock :is(a, button):hover { background: #b2b0bb; color: #202124; }
body[data-world='minecraft'] .dock :is(a, button):focus-visible { outline: 2px solid #f1f1f3; outline-offset: -2px; }
body[data-world='lego'] .dock { border-radius: 4px; border-bottom: 5px solid #cf342f; }
body[data-world='mario'] .dock { border-bottom: 4px solid #db3644; }
body[data-world='superhero'] .dock { border: 3px solid var(--ink); border-radius: 4px; box-shadow: 4px 4px 0 var(--ink); }
body[data-world='halloween'] button.candle-row { appearance: none; background: none; color: inherit; border: 0; border-bottom: 6px double #a58e636b; width: 100%; padding: 12px 0 17px; display: flex; align-items: flex-end; cursor: pointer; }
body[data-world='halloween'] button.candle-row:focus-visible { outline: 1px solid #d4aa6d; outline-offset: 8px; }
body[data-world='halloween'] .candle-row > i { --out: 0; flex-shrink: 0; pointer-events: none; filter: brightness(calc(1 - var(--out) * .23)); }
body[data-world='halloween'] .candle-row > i::before { content: ''; position: absolute; width: 1px; height: 4px; left: 4px; top: -3px; background: #3e2a29; }
body[data-world='halloween'] .candle-row b { opacity: calc(1 - var(--out)); scale: calc(1 - var(--out) * .75) calc(1 - var(--out) * .94); rotate: calc(var(--out) * -30deg); transform-origin: 50% 100%; }
body[data-world='halloween'] .candle-row .is-extinguishing b { animation: none; }
body[data-world='halloween'] .candle-smoke { position: absolute; pointer-events: none; left: 2px; bottom: calc(100% + 2px); width: 9px; height: 28px; border-left: 1px solid #baafc38c; border-radius: 50%; opacity: 0; }
body[data-world='halloween'] .candle-row .is-out .candle-smoke { animation: candle-smoke-rise 1.8s ease-out both; }
body[data-world='halloween'] .candle-row .is-out .smoke-second { animation-delay: .22s; border-left: 0; border-right: 1px solid #baafc35c; }
body[data-world='halloween'] .haunted-frame > .photo { transition: opacity 1.1s ease; }
body[data-world='halloween'] .haunt-dark .haunted-frame > .photo { opacity: .22; }
body[data-world='halloween'] .haunt-dark .haunted-frame .spectral-figure { opacity: .78; transition: opacity 1.1s ease; }
@keyframes candle-smoke-rise { 0% { opacity: 0; transform: translate(0, 4px) scale(.4,.3); } 20% { opacity: .65; } 100% { opacity: 0; transform: translate(10px,-40px) scale(1.8,1.3) rotate(14deg); } }
.haunt-flight { position: fixed; inset: 0; z-index: 26; pointer-events: none; overflow: hidden; contain: strict; }
.haunt-flight canvas { display: block; width: 100%; height: 100%; }
body[data-world='halloween'] .colophon { flex-wrap: wrap; gap: 15px 25px; }
.haunt-bat-shadow { position: absolute; top: 0; left: 0; width: 94px; height: 30px; display: flex; align-items: center; margin: -15px 0 0 -47px; }
.haunt-bat-shadow b { width: 10px; height: 24px; background: #2c2135; border-radius: 40%; }
.haunt-bat-shadow i { width: 42px; height: 27px; background: #2c2135; clip-path: polygon(100% 50%,70% 0,0 15%,15% 100%,42% 75%,65% 100%,90% 65%); animation: bat-shadow-flap .22s ease-in-out infinite alternate; transform-origin: 100% 50%; }
.haunt-bat-shadow i:last-child { scale: -1 1; }
@keyframes bat-shadow-flap { to { transform: scaleY(.35); } }
.world-fold-layer { position: fixed; inset: 0; z-index: 1000; pointer-events: all; overflow: hidden; contain: strict; }
.world-fold-layer canvas, .world-fold-veil, .world-fold-tint { position: absolute; inset: 0; width: 100%; height: 100%; }
.world-fold-tint { opacity: 0; }
.world-fold-ring { position: absolute; top: 0; left: 0; border-radius: 50%; border: 1.5px solid var(--ring, #fff); box-shadow: 0 0 14px 2px var(--ring, #fff); opacity: 0; pointer-events: none; }
#world-effects, #world-play { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 17; pointer-events: none; }
body[data-world='original'] #world-play, body[data-world='original'] #world-effects { display: none; }
.world-play-drawing, .world-play-drawing * { user-select: none !important; -webkit-user-select: none !important; }
.world-play-drawing { cursor: crosshair; }
body[data-world='mario'] .kingdom-counters [data-coin-count] { display: inline-flex; align-items: center; gap: 6px; }
body[data-world='mario'] .coin-icon { display: inline-block; width: 11px; height: 15px; border-radius: 50%; background: #f7c63a; box-shadow: inset -2px 0 #be8913, 0 0 0 1.5px #8a5a10; }
body[data-world='mario'] .coin-pulse b { animation: coin-pulse .35s ease-out; }
@keyframes coin-pulse { 40% { transform: scale(1.35); color: #d72938; } }
/* Native fallback (no WebGL/capture): a CSS approximation of the gravity fold and pin-point aperture. */
::view-transition-old(root) { animation: portfolio-fold 900ms cubic-bezier(.55,0,.75,.2) 40ms both; transform-origin: 50% 58%; }
::view-transition-new(root) { animation: portfolio-reveal 600ms cubic-bezier(.7,0,.2,1) 740ms both; clip-path: circle(0 at 50% 58%); }
::view-transition-group(root) { animation-duration: 1380ms; perspective: 1300px; }
@keyframes portfolio-fold { 40% { transform: perspective(1300px) rotateX(14deg) scale(.9) rotate(8deg); filter: brightness(.9); } 100% { transform: perspective(1300px) rotateX(30deg) scale(.04) rotate(200deg); opacity: 0; filter: blur(3px); } }
@keyframes portfolio-reveal { from { clip-path: circle(2px at 50% 58%); } to { clip-path: circle(160vmax at 50% 58%); } }
@media(max-width: 540px) { body:not([data-world='original']) .dock { gap: 0; padding: 5px; } body:not([data-world='original']) .dock a, body:not([data-world='original']) .dock button { flex-basis: 30px; width: 30px; height: 34px; padding: 7px; } }
@media(prefers-reduced-motion: reduce) { html { scroll-behavior: auto !important; } .world-wanderer .character-pose { animation: none !important; } ::view-transition-old(root), ::view-transition-new(root) { animation: none !important; } }
@media(prefers-reduced-motion: reduce) { body[data-world='halloween'] .candle-row .is-out .candle-smoke { animation: none; opacity: .25; height: 12px; } }
/* Murim: ink text on a rice-paper strip; the original pale-on-pale header and index were hard to read. */
body[data-world='murim'] .sect-header > span { color: #24332b; text-shadow: 0 1px 0 #f2f0e2b3; }
body[data-world='murim'] .sect-index { color: #24332b; background: #f2f0e2e0; box-shadow: 0 0 0 1px #2c3b3326, 0 6px 18px #24332b1f; padding: 16px 8px; }
body[data-world='murim'] .sect-index a[aria-current] { color: #a3322b; }
@media (max-width: 760px) { body[data-world='murim'] .sect-index { padding: 6px 4px; box-shadow: 0 0 0 1px #2c3b3326; } }
body[data-world='mario'] .scenery-bump { animation: scenery-bump .28s cubic-bezier(.3,.7,.4,1); }
body[data-world='mario'] .scenery-empty { filter: saturate(.45) brightness(.82); }
@keyframes scenery-bump { 45% { translate: 0 -9px; } }
body[data-world='lego'] .brick-header .build-status-live { color: #0b3f86; font-weight: 700; animation: build-status .35s ease-out; }
@keyframes build-status { from { opacity: 0; transform: translateY(4px); } }
/* LEGO cover: the institution line and name sit over the 3D castle, so they get darker ink, more weight and a soft paper halo. */
body[data-world='lego'] .cover-title .institution { color: #13202f; font-weight: 700; font-size: 12px; letter-spacing: .04em; text-shadow: 0 0 1px #fff, 0 0 4px #fff, 0 0 9px #ffffffd9, 0 1px 0 #fff; }
body[data-world='lego'] .cover-title h1 { color: #161c24; text-shadow: 0 0 2px #ffffffb3, 0 0 14px #ffffff99; }
@media (max-width: 600px) { body[data-world='lego'] .cover-title .institution { font-size: 10px; } }
body[data-world='lego'] .cover-title .institution { -webkit-text-stroke: 2.5px #fff; paint-order: stroke fill; }
@media (max-width: 600px) { body[data-world='lego'] .cover-title .institution { font-size: 11px; -webkit-text-stroke: 3px #fff; line-height: 1.7; } }
