Files
agent-ui/frontend/src/components/transcript-debug/aquaticBackground/layers/PixelLife.vue
josedario87 220d595568 feat: voice mic, pixel life layer, enhanced transcript-debug UX
VoiceMicButton component, PixelLife aquatic layer, improved UserMessageBubble
with voice display, AgentBadge terminal switcher, ChatContainer voice integration,
FloatingTranscriptDebug ocean life enhancements, and terminal registry support.
Remove traefik config.
2026-02-20 12:12:53 -06:00

357 lines
12 KiB
Vue

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { useAquaticState } from '../useAquaticState'
const { activeEventModifiers } = useAquaticState()
const pixelSeeds = Array.from({ length: 15 }, () => Math.random())
// All swimming creatures are rare — only stationary ones always visible
const showSeahorse = ref(false)
const showOctopus = ref(false)
const showCrab = ref(false)
const showEel = ref(false)
const showPufferfish = ref(false)
const showShrimp = ref(false)
const showNautilus = ref(false)
const showSwordfish = ref(false)
const showStarfish = ref(false)
const showAnchor = ref(false)
const showSubmarine = ref(false)
const showDiver = ref(false)
let tickTimer: ReturnType<typeof setInterval> | null = null
function tickPixelLife() {
// Common creatures — low chance each tick
showSeahorse.value = Math.random() < 0.06
showOctopus.value = Math.random() < 0.05
showCrab.value = Math.random() < 0.06
showEel.value = Math.random() < 0.04
showPufferfish.value = Math.random() < 0.05
showShrimp.value = Math.random() < 0.06
showNautilus.value = Math.random() < 0.04
showSwordfish.value = Math.random() < 0.03
showStarfish.value = Math.random() < 0.05
// Very rare creatures
showAnchor.value = Math.random() < 0.01
showSubmarine.value = Math.random() < 0.008
showDiver.value = Math.random() < 0.015
}
onMounted(() => {
tickPixelLife()
tickTimer = setInterval(tickPixelLife, 60000)
})
onBeforeUnmount(() => {
if (tickTimer) clearInterval(tickTimer)
})
</script>
<template>
<div class="pixel-life">
<!-- Swimming creatures (all rare) -->
<i v-if="showSeahorse" class="px seahorse" :style="{ animationDelay: `-${pixelSeeds[0] * 160}s` }"></i>
<i v-if="showOctopus" class="px octopus" :style="{ animationDelay: `-${pixelSeeds[1] * 200}s` }"></i>
<i v-if="showCrab" class="px crab" :style="{ animationDelay: `-${pixelSeeds[2] * 120}s` }"></i>
<i v-if="showEel" class="px eel" :style="{ animationDelay: `-${pixelSeeds[3] * 70}s` }"></i>
<i v-if="showPufferfish" class="px pufferfish" :style="{ animationDelay: `-${pixelSeeds[4] * 140}s` }"></i>
<i v-if="showShrimp" class="px shrimp" :style="{ animationDelay: `-${pixelSeeds[5] * 50}s` }"></i>
<i v-if="showNautilus" class="px nautilus" :style="{ animationDelay: `-${pixelSeeds[6] * 240}s` }"></i>
<i v-if="showSwordfish" class="px swordfish" :style="{ animationDelay: `-${pixelSeeds[7] * 25}s` }"></i>
<i v-if="showStarfish" class="px starfish-walk" :style="{ animationDelay: `-${pixelSeeds[8] * 360}s` }"></i>
<!-- Stationary creatures (always visible) -->
<i class="px treasure"></i>
<i class="px sea-anemone"></i>
<i class="px clam"></i>
<!-- Very rare creatures -->
<i v-if="showAnchor" class="px anchor"></i>
<i v-if="showSubmarine" class="px submarine" :style="{ animationDelay: `-${pixelSeeds[11] * 320}s` }"></i>
<i v-if="showDiver" class="px diver" :style="{ animationDelay: `-${pixelSeeds[12] * 180}s` }"></i>
</div>
</template>
<style scoped>
/* ══════════════════════════════════════════════════════════════════════════
Pixel Life — box-shadow pixel art creatures for the main background
══════════════════════════════════════════════════════════════════════════ */
.pixel-life {
position: absolute;
inset: 0;
overflow: hidden;
pointer-events: none;
z-index: 8;
}
.px {
position: absolute;
width: 1px;
height: 1px;
background: transparent;
font-style: normal;
transform: scale(3);
transform-origin: center;
will-change: transform;
}
/* ── Keyframes ── */
@keyframes px-swim-left {
from { left: calc(100% + 20px); }
to { left: -20px; }
}
@keyframes px-swim-right {
from { left: -20px; }
to { left: calc(100% + 20px); }
}
@keyframes px-bob {
0%, 100% { transform: scale(3) translateY(0); }
50% { transform: scale(3) translateY(-4px); }
}
@keyframes px-sine {
0% { transform: scale(3) translateY(0); }
25% { transform: scale(3) translateY(-6px); }
50% { transform: scale(3) translateY(0); }
75% { transform: scale(3) translateY(6px); }
100% { transform: scale(3) translateY(0); }
}
@keyframes px-sink {
from { top: -10px; }
to { top: calc(100% + 10px); }
}
@keyframes px-puff {
0%, 100% { transform: scale(3); }
50% { transform: scale(4.5); }
}
@keyframes px-pulse-glow {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.7; }
}
@keyframes px-tentacle {
0%, 100% { transform: scale(3) translateY(0) skewX(0deg); }
25% { transform: scale(3) translateY(-2px) skewX(2deg); }
75% { transform: scale(3) translateY(2px) skewX(-2deg); }
}
@keyframes px-clam-open {
0%, 100% { transform: scale(3) scaleY(1); }
50% { transform: scale(3) scaleY(0.5); }
}
/* ── 1. Seahorse — yellow-orange, gentle bob, swims left ── */
.seahorse {
top: 40%;
animation:
px-swim-left 160s linear infinite,
px-bob 8s ease-in-out infinite;
box-shadow:
1px -2px #fbbf24, 2px -2px #fbbf24,
0 -1px #f59e0b, 1px -1px #f59e0b, 2px -1px #f59e0b,
0 0 #f59e0b, 1px 0 #d97706,
0 1px #d97706, 1px 1px #d97706,
0 2px #b45309, 1px 2px #b45309,
-1px 3px #b45309, 0 3px #92400e,
-1px 4px #92400e;
}
/* ── 2. Octopus — purple-red, 4 trailing tentacles, swims right ── */
.octopus {
top: 55%;
animation: px-swim-right 200s linear infinite;
box-shadow:
1px -1px #a855f7, 2px -1px #a855f7,
0 0 #9333ea, 1px 0 #9333ea, 2px 0 #9333ea, 3px 0 #a855f7,
0 1px #7c3aed, 1px 1px #7c3aed, 2px 1px #7c3aed, 3px 1px #7c3aed,
-1px 2px #6d28d9, 0 2px #7c3aed, 2px 2px #7c3aed, 3px 2px #6d28d9,
-1px 3px #5b21b6, 1px 3px #6d28d9, 3px 3px #5b21b6,
-2px 4px #4c1d95, 0 4px #5b21b6, 2px 4px #5b21b6, 4px 4px #4c1d95;
}
/* ── 3. Crab — red-orange, walking along bottom ── */
.crab {
top: 85%;
animation: px-swim-right 120s linear infinite;
box-shadow:
-2px -1px #dc2626, 4px -1px #dc2626,
-2px 0 #ef4444, -1px 0 #ef4444, 4px 0 #ef4444, 3px 0 #ef4444,
0 0 #b91c1c, 1px 0 #dc2626, 2px 0 #dc2626,
0 1px #991b1b, 1px 1px #b91c1c, 2px 1px #b91c1c,
-1px 2px #7f1d1d, 0 2px #991b1b, 2px 2px #991b1b, 3px 2px #7f1d1d;
}
/* ── 4. Eel — green-dark, sinuous, swims left ── */
.eel {
top: 45%;
animation:
px-swim-left 70s linear infinite,
px-sine 4s ease-in-out infinite;
box-shadow:
0 0 #16a34a, 1px 0 #15803d, 2px 0 #166534, 3px 0 #14532d,
4px 0 #166534, 5px 0 #15803d, 6px 0 #16a34a, 7px 0 #15803d,
1px 1px #22c55e, 2px 1px #22c55e, 3px 1px #22c55e, 5px 1px #22c55e, 6px 1px #22c55e,
0 -1px #fbbf24;
}
/* ── 5. Pufferfish — yellow, inflates via scale pulse ── */
.pufferfish {
top: 35%;
animation:
px-swim-left 140s linear infinite,
px-puff 10s ease-in-out infinite;
box-shadow:
0 -1px #fbbf24, 1px -1px #fbbf24,
-1px 0 #f59e0b, 0 0 #eab308, 1px 0 #eab308, 2px 0 #f59e0b,
-1px 1px #f59e0b, 0 1px #eab308, 1px 1px #eab308, 2px 1px #f59e0b,
0 2px #d97706, 1px 2px #d97706,
-2px 0 #ca8a04, 3px 0 #ca8a04, 0 -2px #ca8a04, 1px -2px #ca8a04,
0 0 #1e293b;
}
/* ── 6. Shrimp — pink-red, dart near bottom ── */
.shrimp {
top: 80%;
animation: px-swim-right 50s linear infinite;
box-shadow:
0 0 #fb7185, 1px 0 #f43f5e, 2px 0 #e11d48, 3px 0 #be123c,
0 1px #fda4af, 1px 1px #fb7185, 2px 1px #f43f5e,
-1px -1px rgba(251,113,133,0.6), -2px -2px rgba(251,113,133,0.3),
4px 0 #9f1239, 5px -1px #881337;
}
/* ── 7. Nautilus — cream-brown spiral shell, swims left ── */
.nautilus {
top: 50%;
animation:
px-swim-left 240s linear infinite,
px-bob 12s ease-in-out infinite;
box-shadow:
0 -1px #d4a574, 1px -1px #c2956a,
-1px 0 #d4a574, 0 0 #b08050, 1px 0 #a0714a, 2px 0 #c2956a,
-1px 1px #c2956a, 0 1px #8b6040, 1px 1px #a0714a, 2px 1px #b08050,
0 2px #c2956a, 1px 2px #d4a574,
-2px 1px #fef3c7, -2px 2px #fde68a;
}
/* ── 8. Swordfish — silver-blue, fast streak ── */
.swordfish {
top: 25%;
animation: px-swim-left 25s linear infinite;
box-shadow:
-3px 0 #94a3b8, -2px 0 #94a3b8,
-1px 0 #64748b, 0 0 #475569, 1px 0 #475569,
2px 0 #334155, 3px 0 #334155, 4px 0 #475569, 5px 0 #64748b,
1px 1px #94a3b8, 2px 1px #94a3b8, 3px 1px #94a3b8, 4px 1px #94a3b8,
2px -1px #334155, 3px -1px #334155,
6px -1px #475569, 6px 1px #475569;
}
/* ── 9. Starfish — orange, very slow crawl along floor ── */
.starfish-walk {
top: 88%;
animation: px-swim-right 360s linear infinite;
box-shadow:
0 0 #f97316, 1px 0 #ea580c,
0 -2px #fb923c, 1px -2px #fb923c,
-2px 0 #fb923c, 3px 0 #fb923c,
-1px 2px #fb923c, 2px 2px #fb923c,
0 -1px #f97316, 1px -1px #f97316,
-1px 0 #f97316, 2px 0 #f97316,
0 1px #ea580c, 1px 1px #ea580c,
-1px 1px #f97316, 2px 1px #f97316;
}
/* ── 10. Anchor — grey iron, sinks slowly (very rare) ── */
.anchor {
left: 70%;
animation: px-sink 100s linear forwards;
box-shadow:
0 -3px #6b7280, 1px -3px #6b7280,
-1px -2px #6b7280, 2px -2px #6b7280,
0 -2px #9ca3af, 1px -2px #9ca3af,
0 -1px #4b5563, 1px -1px #4b5563,
0 0 #4b5563, 1px 0 #4b5563,
0 1px #4b5563, 1px 1px #4b5563,
0 2px #374151, 1px 2px #374151,
-2px 2px #6b7280, -1px 2px #4b5563, 2px 2px #4b5563, 3px 2px #6b7280,
-2px 3px #374151, 3px 3px #374151,
-1px 3px #4b5563, 2px 3px #4b5563;
}
/* ── 11. Treasure — brown chest with gold gleam (stationary) ── */
.treasure {
top: 90%;
left: 25%;
animation: px-pulse-glow 10s ease-in-out infinite;
box-shadow:
0 -1px #92400e, 1px -1px #92400e, 2px -1px #92400e, 3px -1px #92400e,
-1px 0 #78350f, 0 0 #78350f, 1px 0 #92400e, 2px 0 #92400e, 3px 0 #78350f, 4px 0 #78350f,
-1px 1px #78350f, 0 1px #78350f, 1px 1px #92400e, 2px 1px #92400e, 3px 1px #78350f, 4px 1px #78350f,
1px 0 #fbbf24, 2px 0 #fbbf24,
1px -1px #fde68a;
}
/* ── 12. Submarine — grey with yellow light (very rare), swims right ── */
.submarine {
top: 30%;
animation: px-swim-right 320s linear infinite;
box-shadow:
3px -2px #6b7280, 3px -1px #6b7280,
0 0 #4b5563, 1px 0 #4b5563, 2px 0 #4b5563, 3px 0 #4b5563, 4px 0 #4b5563, 5px 0 #4b5563,
-1px 1px #374151, 0 1px #374151, 1px 1px #374151, 2px 1px #374151, 3px 1px #374151, 4px 1px #374151, 5px 1px #374151, 6px 1px #374151,
0 2px #4b5563, 1px 2px #4b5563, 2px 2px #4b5563, 3px 2px #4b5563, 4px 2px #4b5563, 5px 2px #4b5563,
1px 1px #fbbf24, 4px 1px #fbbf24,
-2px 0 #9ca3af, -2px 1px #9ca3af, -2px 2px #9ca3af;
}
/* ── 13. Diver — black suit, white mask, bubble trail (very rare) ── */
.diver {
top: 40%;
animation: px-swim-left 180s linear infinite;
box-shadow:
0 -1px #f8fafc, 1px -1px #f8fafc,
0 0 #1e293b, 1px 0 #1e293b,
0 1px #1e293b, 1px 1px #1e293b,
0 2px #0f172a, 1px 2px #0f172a,
-1px 3px #1e293b, 2px 3px #1e293b,
2px 0 #475569, 2px 1px #475569,
-1px -2px rgba(255,255,255,0.5), -2px -3px rgba(255,255,255,0.3), -3px -4px rgba(255,255,255,0.15);
}
/* ── 14. Sea Anemone — pink-purple, tentacle wave (stationary) ── */
.sea-anemone {
top: 92%;
left: 60%;
animation: px-tentacle 12s ease-in-out infinite;
box-shadow:
-1px -2px #e879f9, 0 -2px #d946ef, 1px -2px #c026d3, 2px -2px #e879f9,
-1px -1px #d946ef, 0 -1px #c026d3, 1px -1px #d946ef, 2px -1px #c026d3,
0 0 #a21caf, 1px 0 #a21caf,
0 1px #86198f, 1px 1px #86198f;
}
/* ── 15. Clam — grey shell, pearl gleam inside (stationary) ── */
.clam {
top: 90%;
left: 82%;
animation: px-clam-open 16s ease-in-out infinite;
box-shadow:
0 -1px #9ca3af, 1px -1px #9ca3af, 2px -1px #9ca3af,
-1px 0 #6b7280, 0 0 #6b7280, 1px 0 #6b7280, 2px 0 #6b7280, 3px 0 #6b7280,
-1px 1px #4b5563, 0 1px #4b5563, 1px 1px #4b5563, 2px 1px #4b5563, 3px 1px #4b5563,
0 2px #6b7280, 1px 2px #6b7280, 2px 2px #6b7280,
1px 0 #fef3c7;
}
</style>