html, body { margin: 0; height: 100%; overflow: hidden; background: #0e2a63; } #scene { position: fixed; inset: 0; width: 100%; height: 100%; display: block; } #title-overlay { position: fixed; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; pointer-events: none; z-index: 10; opacity: 1; transform: translateY(0); transition: opacity 1.8s ease, transform 1.8s cubic-bezier(0.55, 0, 0.55, 1); } #title-overlay.hidden { opacity: 0; transform: translateY(-48px); } /* Once the intro is dismissed the overlay only fades (no display:none, so the exit animation can play). But the spent start button keeps .ready, i.e. pointer-events: auto, leaving an invisible button on top that swallows clicks on the scene behind it (e.g. the bench / cassette collection). Drop its pointer-events the instant the overlay hides — it still fades out in place, so there's no layout jump. */ #title-overlay.hidden #start-btn { pointer-events: none; } #title { font-family: "Baloo 2", sans-serif; font-weight: 800; font-size: clamp(3.5rem, 11vw, 8rem); color: #ffffff; margin: 0; letter-spacing: 0.06em; text-shadow: 0 3px 0 rgba(173, 211, 255, 0.55), 0 8px 28px rgba(13, 47, 110, 0.5), 0 2px 6px rgba(13, 47, 110, 0.35); animation: title-in 1.6s cubic-bezier(0.22, 1, 0.36, 1) both, title-bob 5.5s ease-in-out 1.6s infinite alternate; } /* The transform-based entrance lives on the wrapper, NOT on #subtitle: an element with backdrop-filter loses its blur the moment it also carries a transform (and title-in's `both` fill left one on permanently), which is what wiped the glass during the intro. A 2D transform on an ancestor is not a backdrop root, so the pill's blur survives. */ .subtitle-wrap { margin-top: 1.1rem; animation: subtitle-slide 1.6s cubic-bezier(0.22, 1, 0.36, 1) 0.5s both; } #subtitle { font-family: "Baloo 2", sans-serif; font-weight: 600; font-size: clamp(0.95rem, 2.2vw, 1.3rem); color: rgba(255, 255, 255, 0.95); margin: 0; letter-spacing: 0.14em; text-transform: lowercase; padding: 0.45em 1.4em; border-radius: 999px; background: rgba(255, 255, 255, 0.14); border: 1px solid rgba(255, 255, 255, 0.3); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); /* opacity-only fade — opacity on the element itself does not break its own backdrop-filter, unlike a transform would */ animation: subtitle-fade 1.6s cubic-bezier(0.22, 1, 0.36, 1) 0.5s both; } @keyframes title-in { from { opacity: 0; transform: translateY(28px) scale(0.96); } to { opacity: 1; transform: translateY(0) scale(1); } } @keyframes subtitle-slide { from { transform: translateY(28px) scale(0.96); } to { transform: translateY(0) scale(1); } } @keyframes subtitle-fade { from { opacity: 0; } to { opacity: 1; } } #start-btn { margin-top: 2.4rem; pointer-events: none; /* the overlay ignores pointers; we opt in once ready */ cursor: pointer; font-family: "Baloo 2", sans-serif; font-weight: 700; font-size: clamp(0.95rem, 2.2vw, 1.25rem); letter-spacing: 0.12em; text-transform: lowercase; color: #ffffff; padding: 0.7em 1.9em; border-radius: 999px; background: rgba(255, 255, 255, 0.16); border: 1px solid rgba(255, 255, 255, 0.4); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); /* fades in via opacity only (a transform here would kill the backdrop blur, per the subtitle note above); the glow uses box-shadow, also transform-free */ opacity: 0; transition: opacity 0.8s ease, background 0.2s ease, border-color 0.2s ease; } #start-btn.ready { opacity: 1; pointer-events: auto; animation: start-glow 2.6s ease-in-out 0.6s infinite; } #start-btn:hover { background: rgba(255, 255, 255, 0.3); border-color: rgba(255, 255, 255, 0.7); } #start-btn:active { background: rgba(255, 255, 255, 0.4); } @keyframes start-glow { 0%, 100% { box-shadow: 0 0 0 0 rgba(173, 211, 255, 0); } 50% { box-shadow: 0 0 22px 2px rgba(173, 211, 255, 0.5); } } /* Global mute toggle, top-right. z-index above the modals (max 20) so it stays clickable while a tape plays. No transform on this backdrop-filter element. */ .mute-btn { position: fixed; top: 1rem; right: 1rem; z-index: 50; width: 2.6rem; height: 2.6rem; display: flex; align-items: center; justify-content: center; border-radius: 999px; color: #ffffff; background: rgba(18, 28, 58, 0.34); border: 1px solid rgba(255, 255, 255, 0.32); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); cursor: pointer; transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease; } .mute-btn:hover { background: rgba(18, 28, 58, 0.55); border-color: rgba(255, 255, 255, 0.6); } .mute-btn.muted { color: rgba(255, 255, 255, 0.55); } .mute-btn .mute-slash { display: none; } .mute-btn.muted .mute-waves { display: none; } .mute-btn.muted .mute-slash { display: inline; } @keyframes title-bob { from { transform: translateY(0); } to { transform: translateY(-12px); } } .hover-label { position: fixed; left: 0; top: 0; transform: translate(-50%, -118%); pointer-events: none; z-index: 8; opacity: 0; transition: opacity 0.18s ease; } .hover-label.visible { opacity: 1; } /* the lamp label sits to the LEFT of the pole (which runs up the right edge), vertically centred on the anchor, with its tail pointing right at the post */ #lamp-label { transform: translate(calc(-100% - 14px), -50%); } #lamp-label span::after { left: auto; right: -5px; bottom: auto; top: 50%; transform: translateY(-50%) rotate(45deg); } .hover-label span { position: relative; display: inline-block; font-family: "Baloo 2", sans-serif; font-weight: 800; font-size: clamp(1rem, 1.8vw, 1.3rem); color: #3a2c14; background: #ffd84a; padding: 0.4em 1.1em; border-radius: 999px; box-shadow: 0 6px 20px rgba(18, 44, 96, 0.28); white-space: nowrap; } .hover-label span::after { content: ""; position: absolute; left: 50%; bottom: -5px; width: 12px; height: 12px; background: #ffd84a; border-radius: 2px; transform: translateX(-50%) rotate(45deg); z-index: -1; } .hover-label.visible span { animation: label-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both, label-bob 2s ease-in-out 0.45s infinite alternate; } @keyframes label-pop { from { opacity: 0; transform: scale(0.55) translateY(12px); } to { opacity: 1; transform: scale(1) translateY(0); } } @keyframes label-bob { from { transform: translateY(0) rotate(-1.2deg); } to { transform: translateY(-7px) rotate(1.2deg); } } /* --- vending machine modal: machine control panel -------------------------- */ #machine-modal { position: fixed; top: 50%; right: 5vw; transform: translateY(-50%); transform-origin: 100% 0%; width: min(390px, 86vw); box-sizing: border-box; background: linear-gradient(165deg, #8ed0f4, #6db8e0 70%, #5fabd6); border: 3px solid #4f9cc8; border-radius: 20px; box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.55), inset 0 -3px 8px rgba(31, 79, 116, 0.35), 0 24px 70px rgba(15, 40, 90, 0.4); padding: 22px 20px 18px; font-family: "DotGothic16", "Baloo 2", monospace; color: #1d2a40; z-index: 20; } #machine-modal.hidden { display: none; } /* "play while waiting" nudge — a frosted pill below the card, shown only while the machine is brewing. Clicking it whisks you off to the garden mini-game. */ #play-while-waiting { position: absolute; top: calc(100% + 16px); left: 50%; transform: translateX(-50%); display: inline-flex; align-items: center; gap: 9px; white-space: nowrap; padding: 9px 17px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.18); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: #fff; font-family: "Baloo 2", sans-serif; font-weight: 600; font-size: 0.9rem; cursor: pointer; text-shadow: 0 1px 3px rgba(15, 40, 90, 0.45); box-shadow: 0 8px 24px rgba(15, 40, 90, 0.28); transition: background 0.18s ease, transform 0.18s ease; animation: pww-in 0.4s ease; } #play-while-waiting svg { flex: none; opacity: 0.95; } #play-while-waiting:hover { background: rgba(255, 255, 255, 0.32); transform: translateX(-50%) translateY(-2px); } #play-while-waiting.hidden { display: none; } @keyframes pww-in { from { opacity: 0; transform: translateX(-50%) translateY(8px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } } /* anime panel entrance: a thin slash from the corner that springs open */ #machine-modal.opening { animation: modal-in 0.55s cubic-bezier(0.25, 0.9, 0.35, 1.2) both; } @keyframes modal-in { 0% { transform: translateY(-50%) scale(0.04, 0.04) skewX(-10deg); opacity: 0; } 35% { transform: translateY(-50%) scale(1.06, 0.07) skewX(-7deg); opacity: 1; } 62% { transform: translateY(-50%) scale(0.99, 1.06) skewX(2.5deg); } 80% { transform: translateY(-50%) scale(1.01, 0.98) skewX(-1deg); } 100% { transform: translateY(-50%) scale(1, 1) skewX(0deg); } } #machine-modal.closing { animation: modal-out 0.3s ease-in both; } @keyframes modal-out { 0% { transform: translateY(-50%) scale(1, 1); opacity: 1; } 45% { transform: translateY(-50%) scale(1.04, 0.06) skewX(-6deg); opacity: 1; } 100% { transform: translateY(-50%) scale(0.03, 0.03) skewX(-10deg); opacity: 0; } } #modal-close { position: absolute; top: 12px; right: 14px; width: 32px; height: 32px; border-radius: 50%; border: 2px solid #16243c; background: #2b3a55; color: #cfe0f0; font-size: 1.05rem; line-height: 1; cursor: pointer; z-index: 2; } #modal-close:hover { background: #16243c; } /* --- LED screen ------------------------------------------------------------ */ #led-screen { position: relative; background: #0b120d; border: 2px solid #14241a; border-radius: 12px; box-shadow: inset 0 0 22px rgba(0, 0, 0, 0.85); padding: 14px 14px 12px; overflow: hidden; } #led-screen::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: repeating-linear-gradient( to bottom, transparent 0 2px, rgba(0, 0, 0, 0.22) 2px 3px ); border-radius: inherit; } .led-title { margin: 0; font-family: "DotGothic16", monospace; font-size: 1.3rem; letter-spacing: 0.1em; color: #5dff8d; text-shadow: 0 0 8px rgba(93, 255, 141, 0.7), 0 0 2px rgba(93, 255, 141, 0.9); animation: led-flicker 4s steps(1) infinite; } .led-cursor { animation: blink 1.1s steps(1) infinite; } .led-sub { margin: 4px 0 0; font-family: "DotGothic16", monospace; font-size: 0.78rem; letter-spacing: 0.12em; color: #3fd470; opacity: 0.8; } @keyframes led-flicker { 0%, 93%, 100% { opacity: 1; } 94% { opacity: 0.75; } 95% { opacity: 1; } 97% { opacity: 0.85; } 98% { opacity: 1; } } #prompt-input { width: 100%; box-sizing: border-box; margin-top: 12px; font-family: "DotGothic16", monospace; font-size: 1rem; letter-spacing: 0.04em; color: #5dff8d; caret-color: #5dff8d; text-shadow: 0 0 6px rgba(93, 255, 141, 0.5); padding: 10px 12px; border-radius: 8px; border: 1px dashed rgba(93, 255, 141, 0.35); background: rgba(0, 0, 0, 0.3); resize: none; outline: none; } #prompt-input::placeholder { color: rgba(93, 255, 141, 0.3); text-shadow: none; } #prompt-input:focus { border: 1px solid rgba(93, 255, 141, 0.8); } #prompt-input:disabled { opacity: 0.5; } /* tape-length slider — green-on-LED to match the dot-matrix screen */ #length-row { display: flex; align-items: center; gap: 10px; margin-top: 12px; font-family: "DotGothic16", monospace; } .len-label { flex: none; font-size: 0.74rem; letter-spacing: 0.12em; color: #3fd470; opacity: 0.85; } #length-value { flex: none; min-width: 34px; text-align: right; font-size: 0.84rem; letter-spacing: 0.06em; color: #5dff8d; text-shadow: 0 0 6px rgba(93, 255, 141, 0.5); } #length-slider { flex: 1; -webkit-appearance: none; appearance: none; height: 6px; border-radius: 3px; background: rgba(93, 255, 141, 0.18); border: 1px solid rgba(93, 255, 141, 0.25); outline: none; cursor: pointer; } #length-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border-radius: 50%; background: #5dff8d; box-shadow: 0 0 8px rgba(93, 255, 141, 0.85); border: none; cursor: pointer; } #length-slider::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: #5dff8d; box-shadow: 0 0 8px rgba(93, 255, 141, 0.85); border: none; cursor: pointer; } #length-slider:disabled { opacity: 0.45; cursor: default; } #prompt-input.shake { animation: shake 0.4s ease; } @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-6px); } 50% { transform: translateX(6px); } 75% { transform: translateX(-4px); } } #generating { margin-top: 14px; text-align: center; } .led-status { margin: 10px 0 4px; font-family: "DotGothic16", monospace; font-size: 0.95rem; letter-spacing: 0.1em; color: #5dff8d; text-shadow: 0 0 8px rgba(93, 255, 141, 0.7); } .dots { animation: blink 1.4s steps(1) infinite; } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.15; } } /* cozy loader: a little row of plants that sprout, bloom, and loop while the beat brews — green-on-LED to match the machine's dot-matrix screen. */ .grow-loader { position: relative; display: flex; gap: 13px; justify-content: center; align-items: flex-end; height: 40px; } /* a soft soil line the sprouts rise from */ .grow-loader::after { content: ""; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%); width: 118px; height: 3px; border-radius: 2px; background: linear-gradient(#2aa85a, #115f30); box-shadow: 0 0 6px rgba(93, 255, 141, 0.25); } /* brew progress — fills in whole 30s-chunk steps as the backend stitches them (e.g. a 1 min tape jumps to 50% when the first chunk lands). */ #brew-bar { position: relative; width: 80%; max-width: 230px; height: 6px; margin: 16px auto 0; border-radius: 3px; background: rgba(93, 255, 141, 0.15); border: 1px solid rgba(93, 255, 141, 0.25); overflow: hidden; } #brew-bar-fill { display: block; width: 0%; height: 100%; border-radius: 3px; background: #5dff8d; box-shadow: 0 0 8px rgba(93, 255, 141, 0.6); transition: width 0.3s ease; } .sprout { position: relative; width: 18px; height: 34px; transform-origin: 50% 100%; animation: sprout-grow 2.8s ease-in-out infinite; } .sprout:nth-child(2) { animation-delay: 0.4s; } .sprout:nth-child(3) { animation-delay: 0.8s; } .sprout:nth-child(4) { animation-delay: 1.2s; } .sprout .stem { position: absolute; left: 50%; bottom: 0; width: 2px; height: 22px; margin-left: -1px; border-radius: 2px; background: linear-gradient(#5dff8d, #1f8f4a); box-shadow: 0 0 6px rgba(93, 255, 141, 0.5); } .sprout .leaf { position: absolute; bottom: 9px; width: 7px; height: 4px; background: #43e07f; box-shadow: 0 0 4px rgba(93, 255, 141, 0.4); } .sprout .leaf.l { right: 50%; border-radius: 60% 0 60% 0; transform: rotate(22deg); transform-origin: right center; } .sprout .leaf.r { left: 50%; border-radius: 0 60% 0 60%; transform: rotate(-22deg); transform-origin: left center; } /* a 5-dot flower head: pale centre + four green petals via box-shadow */ .sprout .bloom { position: absolute; left: 50%; bottom: 19px; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: #d9ffe7; box-shadow: 0 -4px 0 #5dff8d, 0 4px 0 #5dff8d, -4px 0 0 #5dff8d, 4px 0 0 #5dff8d, 0 0 8px rgba(93, 255, 141, 0.8); } @keyframes sprout-grow { 0% { transform: scale(0); opacity: 0; } 12% { opacity: 1; } 50% { transform: scale(1.08); } 62% { transform: scale(1); } 88% { transform: scale(1); opacity: 1; } 100% { transform: scale(1); opacity: 0; } } /* --- coin slot + red button -------------------------------------------------- */ #controls-row { margin-top: 16px; display: flex; align-items: center; gap: 14px; } #coin-slot-area { position: relative; flex: none; width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: linear-gradient(#5fabd6, #4f9cc8); border: 2px solid #3f86ad; border-radius: 10px; box-shadow: inset 0 2px 4px rgba(255, 255, 255, 0.35), inset 0 -3px 5px rgba(31, 79, 116, 0.4); perspective: 300px; } #coin-slot { width: 10px; height: 40px; background: #0e1116; border-radius: 5px; box-shadow: inset 0 0 5px #000, 0 1px 0 rgba(255, 255, 255, 0.4); } #wado-coin { position: absolute; width: 46px; height: 46px; left: 50%; top: 50%; margin: -23px 0 0 -23px; opacity: 0; pointer-events: none; filter: drop-shadow(0 3px 4px rgba(20, 30, 50, 0.45)); } .wado-kanji { font-family: "Hiragino Mincho ProN", "Yu Mincho", serif; font-size: 21px; fill: #5d431d; } .inserting #wado-coin { animation: coin-insert 1.15s ease-in-out forwards; } @keyframes coin-insert { 0% { opacity: 0; transform: translate(-58px, 16px) rotate(-30deg) scale(0.3); } 18% { opacity: 1; transform: translate(-40px, -8px) rotate(-10deg) scale(1.25); } 42% { opacity: 1; transform: translate(0, -16px) rotate(0deg) scale(1.1); } 60% { opacity: 1; transform: translate(0, -16px) rotateY(80deg) scale(1); } 78% { opacity: 1; transform: translate(0, 6px) rotateY(80deg) scale(0.95); } 100% { opacity: 0; transform: translate(0, 26px) rotateY(80deg) scale(0.9); } } .inserting #coin-slot { animation: slot-flash 0.35s ease 0.95s; } @keyframes slot-flash { 50% { box-shadow: inset 0 0 5px #000, 0 0 12px rgba(93, 255, 141, 0.9); } } #coin-button { flex: 1; padding: 16px 10px; border-radius: 12px; border: 2px solid #a32119; background: linear-gradient(#ff6a5e, #e03a30 55%, #c52d24); color: #fff; font-family: "DotGothic16", monospace; font-size: 1.2rem; letter-spacing: 0.12em; text-shadow: 0 2px 3px rgba(0, 0, 0, 0.45); cursor: pointer; box-shadow: 0 5px 0 #8f1d18, inset 0 2px 3px rgba(255, 255, 255, 0.4); } #coin-button:active { transform: translateY(3px); box-shadow: 0 2px 0 #8f1d18, inset 0 2px 3px rgba(255, 255, 255, 0.4); } #coin-button:disabled { cursor: default; filter: saturate(0.7) brightness(0.92); } #cassette-stage { margin-top: 16px; } #cassette { background: linear-gradient(#3a4254, #2c3344); border-radius: 14px; padding-bottom: 4px; box-shadow: inset 0 2px 6px rgba(255, 255, 255, 0.12), 0 8px 22px rgba(15, 40, 90, 0.3); animation: cassette-out 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both; } @keyframes cassette-out { from { transform: translateY(56px) scale(0.92); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } } .cassette-label { background: #f6f1e3; border: 2px solid #e0d6bd; border-radius: 8px; margin: 12px 14px 10px; padding: 8px 10px; text-align: center; font-weight: 800; font-size: 0.95rem; color: #4a3b2c; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .reels { display: flex; align-items: center; padding: 0 28px 12px; } .reel { width: 34px; height: 34px; border-radius: 50%; border: 5px dashed #cfd6e4; background: #1d232f; box-sizing: border-box; } #cassette.playing .reel, .cassette-card.playing .reel { animation: reel-spin 2.4s linear infinite; } @keyframes reel-spin { to { transform: rotate(360deg); } } .tape-window { flex: 1; height: 16px; margin: 0 12px; background: #1d232f; border-radius: 8px; } #player { display: flex; align-items: center; gap: 10px; margin-top: 14px; } #play-btn, #np-toggle, #deck-play { width: 44px; height: 44px; flex: none; border-radius: 50%; border: none; background: #ffd84a; color: #3a2c14; font-size: 1rem; cursor: pointer; box-shadow: 0 3px 0 #d9ab1e; } #play-btn:active, #np-toggle:active, #deck-play:active { transform: translateY(2px); box-shadow: 0 1px 0 #d9ab1e; } #progress { flex: 1; height: 8px; border-radius: 4px; background: rgba(13, 26, 43, 0.4); cursor: pointer; overflow: hidden; } #progress-fill { height: 100%; width: 0%; border-radius: 4px; background: linear-gradient(90deg, #5dff8d, #2ea65a); box-shadow: 0 0 6px rgba(93, 255, 141, 0.6); } #time { font-family: "DotGothic16", monospace; font-size: 0.85rem; color: #16213a; min-width: 38px; text-align: right; } #again-btn { margin-top: 14px; width: 100%; padding: 11px; border-radius: 12px; border: 2px solid #16213a; background: linear-gradient(#3a4c6e, #2b3a55); color: #cfe0f0; font-family: "DotGothic16", monospace; font-size: 1rem; letter-spacing: 0.12em; cursor: pointer; box-shadow: 0 4px 0 #16213a, inset 0 2px 2px rgba(255, 255, 255, 0.18); } #again-btn:hover { background: linear-gradient(#465a80, #324466); } #again-btn:active { transform: translateY(2px); box-shadow: 0 2px 0 #16213a, inset 0 2px 2px rgba(255, 255, 255, 0.18); } #error-msg { font-family: "DotGothic16", monospace; color: #ff6b5e; text-shadow: 0 0 8px rgba(255, 107, 94, 0.7); font-size: 0.88rem; letter-spacing: 0.08em; margin: 10px 0 0; text-align: center; } #error-msg.hidden, #controls-row.hidden, #prompt-input.hidden, #length-row.hidden, #generating.hidden, #cassette-stage.hidden { display: none; } /* --- now playing pill ------------------------------------------------------ */ #now-playing { position: fixed; left: 18px; bottom: 18px; z-index: 15; display: flex; align-items: center; gap: 10px; padding: 8px 18px 8px 8px; background: rgba(255, 255, 255, 0.92); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); border-radius: 999px; box-shadow: 0 8px 24px rgba(15, 40, 90, 0.25); font-family: "Baloo 2", sans-serif; font-weight: 700; font-size: 0.95rem; color: #2b3a55; transition: opacity 0.3s ease, transform 0.3s ease; } #now-playing.hidden { opacity: 0; transform: translateY(12px); pointer-events: none; } #now-playing #np-toggle { width: 36px; height: 36px; font-size: 0.85rem; } #np-title { max-width: 230px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* --- cassette collection: carousel ------------------------------------------ */ #collection-panel { position: fixed; top: 6vh; left: 50%; transform: translateX(-50%); width: min(780px, 94vw); z-index: 18; text-align: center; transition: opacity 0.35s ease, transform 0.35s ease; } #collection-panel.hidden { opacity: 0; transform: translate(-50%, -18px); pointer-events: none; } #collection-heading { margin: 0; } #collection-heading span { display: inline-block; font-family: "Baloo 2", sans-serif; font-weight: 800; font-size: clamp(1.1rem, 2.2vw, 1.5rem); color: #3a2c14; background: #ffd84a; padding: 0.4em 1.3em; border-radius: 999px; box-shadow: 0 8px 24px rgba(18, 44, 96, 0.3); } #collection-close { position: absolute; top: -6px; right: 0; width: 36px; height: 36px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.22); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: #fff; font-size: 1.15rem; line-height: 1; cursor: pointer; text-shadow: 0 1px 3px rgba(15, 40, 90, 0.4); } #collection-close:hover { background: rgba(255, 255, 255, 0.38); } #collection-status { margin: 26px 0 0; font-family: "Baloo 2", sans-serif; font-weight: 700; font-size: 1.05rem; color: #fff; text-shadow: 0 2px 8px rgba(15, 40, 90, 0.45); } #collection-status.hidden { display: none; } #carousel-row { display: flex; align-items: center; gap: 10px; margin-top: 16px; } .caro-btn { flex: none; position: relative; z-index: 2; width: 40px; height: 40px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.22); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: #fff; font-size: 1.5rem; line-height: 1; padding-bottom: 4px; cursor: pointer; text-shadow: 0 1px 3px rgba(15, 40, 90, 0.4); } .caro-btn:hover { background: rgba(255, 255, 255, 0.38); } .caro-btn:disabled { opacity: 0.32; cursor: default; } .caro-btn:disabled:hover { background: rgba(255, 255, 255, 0.22); } #carousel { position: relative; flex: 1; height: 232px; perspective: 1200px; overflow: hidden; } .cassette-card { position: absolute; left: 50%; top: 50%; width: 184px; box-sizing: border-box; cursor: pointer; border: none; padding: 0 0 4px; font-family: "Baloo 2", sans-serif; background: linear-gradient(var(--shell1, #3a4254), var(--shell2, #2c3344)); border-radius: 14px; box-shadow: inset 0 2px 6px rgba(255, 255, 255, 0.14), 0 10px 24px rgba(15, 40, 90, 0.32); transform-origin: center center; transform: translate(-50%, -50%) scale(0.5); /* pre-layout: centred + small */ opacity: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; transition: transform 0.44s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.44s ease, box-shadow 0.25s ease, filter 0.2s ease; will-change: transform, opacity; } .cassette-card:hover { filter: brightness(1.08); } .cassette-card.selected { box-shadow: 0 0 0 3px #ffd84a, inset 0 2px 6px rgba(255, 255, 255, 0.16), 0 16px 34px rgba(15, 40, 90, 0.46); } .cassette-card .cassette-label { margin: 10px 12px 8px; padding: 6px 8px; font-size: 0.85rem; } .cassette-card .reels { padding: 0 22px 10px; } .cassette-card .reel { width: 28px; height: 28px; border-width: 4px; } .cassette-card .tape-window { height: 13px; margin: 0 10px; } /* --- tape deck: glass pill player -------------------------------------------- */ #tape-deck { position: fixed; bottom: 26px; left: 50%; transform: translateX(-50%); z-index: 18; display: flex; align-items: center; gap: 13px; width: min(620px, 92vw); box-sizing: border-box; padding: 9px 10px; border-radius: 999px; background: rgba(255, 255, 255, 0.16); border: 1px solid rgba(255, 255, 255, 0.42); backdrop-filter: blur(16px) saturate(1.35); -webkit-backdrop-filter: blur(16px) saturate(1.35); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 16px 44px rgba(15, 40, 90, 0.38); font-family: "Baloo 2", sans-serif; transition: opacity 0.35s ease, transform 0.35s ease; } #tape-deck.hidden { opacity: 0; transform: translate(-50%, 18px); pointer-events: none; } #deck-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; } #deck-title { font-weight: 800; font-size: 0.98rem; color: #fff; text-shadow: 0 1px 4px rgba(15, 40, 90, 0.45); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-right: 6px; } #deck-progress { height: 8px; border-radius: 4px; background: rgba(13, 26, 43, 0.35); cursor: pointer; overflow: hidden; } #deck-fill { height: 100%; width: 0%; border-radius: 4px; background: linear-gradient(90deg, #ffd84a, #e8a13c); box-shadow: 0 0 8px rgba(255, 216, 74, 0.65); } #deck-time { flex: none; font-family: "DotGothic16", monospace; font-size: 0.85rem; color: #fff; text-shadow: 0 1px 3px rgba(15, 40, 90, 0.45); min-width: 38px; text-align: right; } #deck-cassette { flex: none; position: relative; width: 64px; height: 42px; border-radius: 8px; background: linear-gradient(var(--shell1, #3a4254), var(--shell2, #2c3344)); box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.2), 0 3px 10px rgba(15, 40, 90, 0.3); display: flex; align-items: flex-end; justify-content: center; gap: 12px; padding-bottom: 6px; box-sizing: border-box; } #deck-cassette::before { content: ""; position: absolute; top: 5px; left: 7px; right: 7px; height: 12px; background: #f6f1e3; border: 1px solid #e0d6bd; border-radius: 3px; box-sizing: border-box; } .mini-reel { width: 15px; height: 15px; border-radius: 50%; border: 3px dashed #cfd6e4; background: #1d232f; box-sizing: border-box; } #tape-deck.playing .mini-reel { animation: reel-spin 2.4s linear infinite; } #deck-loop { flex: none; width: 44px; height: 44px; border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 1px solid rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.22); color: #fff; cursor: pointer; box-sizing: border-box; transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease; } #deck-loop:hover { background: rgba(255, 255, 255, 0.4); } /* lit up = this tape loops; off = roll through the whole shelf */ #deck-loop.on { background: #ffd84a; border-color: #ffd84a; color: #3a2c14; box-shadow: 0 0 10px rgba(255, 216, 74, 0.7); } #deck-loop:active { transform: translateY(1px); } #deck-download { flex: none; width: 44px; height: 44px; border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 1px solid rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.22); color: #fff; cursor: pointer; text-decoration: none; box-sizing: border-box; transition: background 0.15s ease; } #deck-download:hover { background: rgba(255, 255, 255, 0.4); } #deck-download.disabled { opacity: 0.4; pointer-events: none; } /* --- game boy modal --------------------------------------------------------- */ #gameboy-modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 19; } /* display:none (like #machine-modal) — an opacity fade here would let the inner .gb-shell snap back to full opacity as .closing is removed, causing a flicker. */ #gameboy-modal.hidden { display: none; } #gameboy-modal.opening .gb-shell { animation: gb-pop 0.42s cubic-bezier(0.34, 1.56, 0.64, 1) both; } #gameboy-modal.closing .gb-shell { animation: gb-drop 0.28s ease both; } @keyframes gb-pop { from { opacity: 0; transform: translateY(26px) scale(0.85); } to { opacity: 1; transform: translateY(0) scale(1); } } @keyframes gb-drop { to { opacity: 0; transform: translateY(20px) scale(0.92); } } #gameboy-close { position: absolute; top: -14px; right: -14px; z-index: 2; width: 36px; height: 36px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.22); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: #fff; font-size: 1.15rem; line-height: 1; cursor: pointer; text-shadow: 0 1px 3px rgba(15, 40, 90, 0.4); } #gameboy-close:hover { background: rgba(255, 255, 255, 0.38); } .gb-shell { width: min(330px, 86vw); padding: 22px 22px 26px; background: linear-gradient(160deg, #d3d0c6, #b7b4a9); border-radius: 16px 16px 64px 16px; box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.6), inset 0 -6px 14px rgba(0, 0, 0, 0.18), 0 24px 60px rgba(15, 40, 90, 0.45); font-family: "Baloo 2", sans-serif; } .gb-screen-frame { background: linear-gradient(160deg, #585d56, #3f443d); border-radius: 10px 10px 30px 10px; padding: 14px 26px 22px; box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.5); } .gb-power { display: flex; align-items: center; gap: 7px; margin: 0 0 8px 2px; font-size: 0.52rem; letter-spacing: 0.14em; font-weight: 700; color: #c4c8d0; } .gb-power i { width: 8px; height: 8px; border-radius: 50%; background: #d9534f; box-shadow: 0 0 6px #ff6a64; } .gb-screen { position: relative; aspect-ratio: 10 / 9; border-radius: 4px; overflow: hidden; box-shadow: inset 0 0 0 2px #1d2540, inset 0 2px 10px rgba(0, 0, 0, 0.35); } #gb-canvas { display: block; width: 100%; height: 100%; image-rendering: pixelated; image-rendering: crisp-edges; } /* faint scanlines for retro feel — subtle so the colour reads */ .gb-screen::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: repeating-linear-gradient( 0deg, rgba(0, 0, 0, 0.07) 0 1px, transparent 1px 3px ); } .gb-caption { margin: 9px 2px 0; min-height: 14px; display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-family: "DotGothic16", monospace; transition: filter 0.15s ease; } .gb-caption .gb-seed { font-size: 0.72rem; letter-spacing: 0.06em; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35); } .gb-caption .gb-hint { font-size: 0.5rem; letter-spacing: 0.03em; color: #6a6f86; } .gb-caption.gb-flash { animation: gb-flash 0.3s ease; } @keyframes gb-flash { 0% { filter: brightness(1.9); } 100% { filter: brightness(1); } } .gb-logo { margin: 12px 0 14px; text-align: center; font-weight: 800; font-style: italic; font-size: 1.05rem; color: #2c3550; } .gb-logo span { color: #8c2d52; margin-left: 2px; } .gb-controls { display: flex; align-items: center; justify-content: space-between; padding: 0 6px; } .gb-dpad { position: relative; width: 56px; height: 56px; } .gb-pad-v, .gb-pad-h { position: absolute; background: #2b2f2b; border-radius: 4px; box-shadow: inset 0 2px 3px rgba(255, 255, 255, 0.12); } .gb-pad-v { left: 19px; top: 0; width: 18px; height: 56px; } .gb-pad-h { top: 19px; left: 0; width: 56px; height: 18px; } /* transparent click targets over each arm of the d-pad */ .gb-pad-hit { position: absolute; z-index: 2; margin: 0; padding: 0; border: 0; background: transparent; cursor: pointer; -webkit-tap-highlight-color: transparent; } .gb-pad-hit:active { background: rgba(255, 255, 255, 0.14); border-radius: 3px; } .gb-up { left: 19px; top: 0; width: 18px; height: 19px; } .gb-down { left: 19px; top: 37px; width: 18px; height: 19px; } .gb-left { left: 0; top: 19px; width: 19px; height: 18px; } .gb-right { left: 37px; top: 19px; width: 19px; height: 18px; } .gb-ab { display: flex; gap: 14px; transform: rotate(-18deg); } .gb-btn { width: 40px; height: 40px; border-radius: 50%; border: 0; padding: 0; cursor: pointer; font-family: inherit; background: radial-gradient(circle at 35% 30%, #a8406b, #7a1f45); color: #f2d6e2; font-weight: 800; font-size: 0.95rem; display: flex; align-items: center; justify-content: center; box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3), inset 0 2px 3px rgba(255, 255, 255, 0.25); -webkit-tap-highlight-color: transparent; transition: transform 0.06s ease, box-shadow 0.06s ease; } .gb-btn:active { transform: translateY(2px); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), inset 0 2px 3px rgba(255, 255, 255, 0.25); } .gb-startsel { display: flex; justify-content: center; gap: 18px; margin-top: 18px; } .gb-startsel .gb-ss { width: 34px; height: 11px; border: 0; padding: 0; cursor: pointer; border-radius: 999px; background: #6b7280; transform: rotate(-22deg); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); -webkit-tap-highlight-color: transparent; transition: background 0.1s ease; } .gb-startsel .gb-ss:active { background: #565d6b; } .gb-speaker { display: flex; gap: 6px; justify-content: flex-end; margin: 16px 10px 0 0; transform: rotate(-22deg); } .gb-speaker i { width: 4px; height: 26px; border-radius: 999px; background: rgba(0, 0, 0, 0.22); }