Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AsciiFish | Creative ASCII Aquarium</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=Outfit:wght@300;400;500;600;700;800;900&family=Space+Grotesk:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/dist/confetti.browser.min.js"></script> | |
| <style> | |
| :root { | |
| --bg-deep: #040e19; | |
| --bg-surface: #0a1d2e; | |
| --bg-panel: #0e253a; | |
| --bg-panel-hover: #13304d; | |
| --border-subtle: #1a3a5c; | |
| --border-bright: #2a5080; | |
| --border-glow: rgba(40, 167, 200, 0.25); | |
| --text-primary: #d8e8f2; | |
| --text-secondary: #7a9ab8; | |
| --text-muted: #4a6a88; | |
| --accent: #28c7dd; | |
| --accent-dim: #1a9aaa; | |
| --accent-glow: rgba(40, 199, 221, 0.3); | |
| --fish-body: #ff8844; | |
| --fish-body-dim: #cc6622; | |
| --fish-pattern: #ffee55; | |
| --fish-eye: #ffffff; | |
| --fish-outline: #1a0a00; | |
| --success: #2ecc71; | |
| --error: #e74c3c; | |
| --bubbles: rgba(40, 199, 221, 0.15); | |
| --surface: rgba(255, 255, 255, 0.03); | |
| } | |
| [data-theme="sunset"] { | |
| --bg-deep: #120612; | |
| --bg-surface: #1a0a1e; | |
| --bg-panel: #241030; | |
| --bg-panel-hover: #301840; | |
| --border-subtle: #4a2060; | |
| --border-bright: #7a40a0; | |
| --accent: #ff7eb3; | |
| --accent-dim: #cc4a88; | |
| --bubbles: rgba(255, 126, 179, 0.2); | |
| } | |
| [data-theme="abyss"] { | |
| --bg-deep: #020205; | |
| --bg-surface: #050510; | |
| --bg-panel: #080818; | |
| --bg-panel-hover: #0d0d28; | |
| --border-subtle: #1a1a45; | |
| --border-bright: #2a2a70; | |
| --accent: #00ffaa; | |
| --accent-dim: #00cc88; | |
| --bubbles: rgba(0, 255, 170, 0.15); | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| html { | |
| scroll-behavior: smooth; | |
| } | |
| body { | |
| font-family: 'Outfit', system-ui, sans-serif; | |
| background: var(--bg-deep); | |
| color: var(--text-primary); | |
| min-height: 100vh; | |
| overflow-x: hidden; | |
| transition: background 0.6s ease; | |
| } | |
| /* === BACKGROUND === */ | |
| .ocean-bg { | |
| position: fixed; | |
| inset: 0; | |
| z-index: 0; | |
| overflow: hidden; | |
| } | |
| .ocean-bg::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: | |
| radial-gradient(ellipse 80% 50% at 20% 10%, rgba(40, 199, 221, 0.06) 0%, transparent 60%), | |
| radial-gradient(ellipse 60% 40% at 80% 90%, rgba(40, 199, 221, 0.04) 0%, transparent 50%), | |
| radial-gradient(ellipse 50% 30% at 50% 50%, rgba(40, 167, 200, 0.03) 0%, transparent 50%); | |
| animation: oceanDrift 20s ease-in-out infinite alternate; | |
| } | |
| @keyframes oceanDrift { | |
| 0% { transform: translate(0, 0) scale(1); } | |
| 100% { transform: translate(30px, -20px) scale(1.05); } | |
| } | |
| /* Light rays */ | |
| .light-rays { | |
| position: absolute; | |
| inset: 0; | |
| overflow: hidden; | |
| pointer-events: none; | |
| } | |
| .light-ray { | |
| position: absolute; | |
| top: -10%; | |
| width: 3px; | |
| height: 120%; | |
| background: linear-gradient(180deg, rgba(255, 255, 255, 0.04) 0%, transparent 70%); | |
| transform-origin: top center; | |
| animation: lightRaySway 8s ease-in-out infinite alternate; | |
| } | |
| .light-ray:nth-child(1) { left: 10%; animation-delay: 0s; animation-duration: 10s; } | |
| .light-ray:nth-child(2) { left: 25%; animation-delay: -2s; animation-duration: 12s; opacity: 0.6; } | |
| .light-ray:nth-child(3) { left: 45%; animation-delay: -4s; animation-duration: 9s; opacity: 0.4; } | |
| .light-ray:nth-child(4) { left: 65%; animation-delay: -1s; animation-duration: 11s; opacity: 0.5; } | |
| .light-ray:nth-child(5) { left: 82%; animation-delay: -3s; animation-duration: 13s; opacity: 0.3; } | |
| @keyframes lightRaySway { | |
| 0% { transform: rotate(-8deg); opacity: 0.04; } | |
| 100% { transform: rotate(8deg); opacity: 0.08; } | |
| } | |
| /* Floating particles */ | |
| .particles { | |
| position: absolute; | |
| inset: 0; | |
| overflow: hidden; | |
| pointer-events: none; | |
| } | |
| .particle { | |
| position: absolute; | |
| width: 3px; | |
| height: 3px; | |
| border-radius: 50%; | |
| background: var(--accent); | |
| opacity: 0; | |
| animation: particleFloat linear infinite; | |
| } | |
| @keyframes particleFloat { | |
| 0% { opacity: 0; transform: translateY(100vh) scale(0); } | |
| 10% { opacity: 0.6; } | |
| 90% { opacity: 0.6; } | |
| 100% { opacity: 0; transform: translateY(-10vh) scale(1); } | |
| } | |
| /* === LAYOUT === */ | |
| .app-container { | |
| position: relative; | |
| z-index: 1; | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| } | |
| /* === HEADER === */ | |
| .site-header { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 12px 24px; | |
| margin-bottom: 24px; | |
| background: var(--surface); | |
| border: 1px solid var(--border-subtle); | |
| border-radius: 20px; | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| } | |
| .brand { | |
| display: flex; | |
| align-items: center; | |
| gap: 14px; | |
| } | |
| .brand-icon { | |
| width: 48px; | |
| height: 48px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| border-radius: 14px; | |
| background: linear-gradient(135deg, var(--accent-dim), var(--accent)); | |
| font-size: 1.4rem; | |
| color: #000; | |
| box-shadow: 0 4px 20px var(--accent-glow); | |
| transition: transform 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .brand:hover .brand-icon { | |
| transform: rotate(8deg) scale(1.1); | |
| box-shadow: 0 6px 30px var(--accent-glow); | |
| } | |
| .brand h1 { | |
| font-family: 'Space Grotesk', sans-serif; | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| letter-spacing: -0.5px; | |
| background: linear-gradient(135deg, var(--text-primary), var(--accent)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| } | |
| .brand p { | |
| font-size: 0.72rem; | |
| color: var(--text-muted); | |
| margin-top: 1px; | |
| letter-spacing: 0.5px; | |
| } | |
| .header-actions { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .header-btn { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 12px; | |
| border: 1px solid var(--border-subtle); | |
| background: var(--bg-panel); | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 0.9rem; | |
| transition: all 0.25s ease; | |
| } | |
| .header-btn:hover { | |
| background: var(--bg-panel-hover); | |
| color: var(--accent); | |
| border-color: var(--border-bright); | |
| transform: translateY(-2px); | |
| } | |
| .header-btn:active { | |
| transform: translateY(0); | |
| } | |
| /* AnyCoder Link */ | |
| .anycoder-badge { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| padding: 6px 16px; | |
| background: rgba(40, 199, 221, 0.08); | |
| border: 1px solid rgba(40, 199, 221, 0.2); | |
| border-radius: 100px; | |
| color: var(--accent); | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| text-decoration: none; | |
| transition: all 0.3s ease; | |
| margin-right: 8px; | |
| } | |
| .anycoder-badge:hover { | |
| background: rgba(40, 199, 221, 0.15); | |
| border-color: var(--accent); | |
| box-shadow: 0 0 20px rgba(40, 199, 221, 0.15); | |
| } | |
| /* === MAIN GRID === */ | |
| .main-grid { | |
| display: grid; | |
| grid-template-columns: 360px 1fr; | |
| gap: 24px; | |
| align-items: start; | |
| } | |
| @media (max-width: 1100px) { | |
| .main-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| /* === PANELS === */ | |
| .panel { | |
| background: var(--surface); | |
| border: 1px solid var(--border-subtle); | |
| border-radius: 24px; | |
| overflow: hidden; | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| transition: box-shadow 0.4s ease; | |
| } | |
| .panel:hover { | |
| box-shadow: 0 0 40px rgba(0, 0, 0, 0.3); | |
| } | |
| .panel-header { | |
| padding: 20px 24px 16px; | |
| border-bottom: 1px solid var(--border-subtle); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| } | |
| .panel-title { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| font-family: 'Space Grotesk', sans-serif; | |
| font-weight: 600; | |
| font-size: 0.95rem; | |
| color: var(--text-primary); | |
| } | |
| .panel-title i { | |
| width: 32px; | |
| height: 32px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| border-radius: 10px; | |
| background: rgba(40, 199, 221, 0.1); | |
| color: var(--accent); | |
| font-size: 0.85rem; | |
| } | |
| .panel-body { | |
| padding: 20px 24px; | |
| } | |
| .panel-body.compact { | |
| padding: 12px 20px; | |
| } | |
| /* === SECTION === */ | |
| .section { | |
| margin-bottom: 24px; | |
| } | |
| .section:last-child { | |
| margin-bottom: 0; | |
| } | |
| .section-label { | |
| font-size: 0.72rem; | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| letter-spacing: 1.5px; | |
| color: var(--text-muted); | |
| margin-bottom: 14px; | |
| } | |
| /* === SPECIES BUTTONS === */ | |
| .species-grid { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 8px; | |
| } | |
| .species-btn { | |
| position: relative; | |
| padding: 10px 6px; | |
| border-radius: 14px; | |
| border: 1.5px solid var(--border-subtle); | |
| background: var(--bg-panel); | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .species-btn:hover { | |
| background: var(--bg-panel-hover); | |
| border-color: var(--border-bright); | |
| transform: translateY(-3px); | |
| color: var(--text-primary); | |
| } | |
| .species-btn.active { | |
| background: rgba(40, 199, 221, 0.08); | |
| border-color: var(--accent); | |
| color: var(--accent); | |
| box-shadow: 0 0 20px var(--accent-glow); | |
| } | |
| .species-btn .species-icon { | |
| font-size: 1.3rem; | |
| transition: transform 0.3s ease; | |
| } | |
| .species-btn:hover .species-icon { | |
| transform: scale(1.2); | |
| } | |
| .species-btn .species-name { | |
| font-size: 0.65rem; | |
| font-weight: 600; | |
| letter-spacing: 0.3px; | |
| } | |
| .species-btn.active .species-name { | |
| font-weight: 700; | |
| } | |
| /* === SLIDER === */ | |
| .slider-wrap { | |
| margin-bottom: 18px; | |
| } | |
| .slider-header { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| margin-bottom: 8px; | |
| } | |
| .slider-label { | |
| font-size: 0.82rem; | |
| font-weight: 500; | |
| color: var(--text-secondary); | |
| } | |
| .slider-value { | |
| font-family: 'Fira Code', monospace; | |
| font-size: 0.78rem; | |
| font-weight: 600; | |
| color: var(--accent); | |
| background: rgba(40, 199, 221, 0.08); | |
| padding: 3px 10px; | |
| border-radius: 8px; | |
| min-width: 36px; | |
| text-align: center; | |
| } | |
| .slider { | |
| -webkit-appearance: none; | |
| appearance: none; | |
| width: 100%; | |
| height: 5px; | |
| border-radius: 10px; | |
| background: var(--border-subtle); | |
| outline: none; | |
| cursor: pointer; | |
| transition: background 0.3s ease; | |
| } | |
| .slider:hover { | |
| background: var(--border-bright); | |
| } | |
| .slider::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| appearance: none; | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: var(--accent); | |
| border: 3px solid var(--bg-panel); | |
| cursor: pointer; | |
| transition: transform 0.2s ease, box-shadow 0.2s ease; | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); | |
| } | |
| .slider::-webkit-slider-thumb:hover { | |
| transform: scale(1.25); | |
| box-shadow: 0 0 16px var(--accent-glow); | |
| } | |
| .slider::-moz-range-thumb { | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: var(--accent); | |
| border: 3px solid var(--bg-panel); | |
| cursor: pointer; | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); | |
| } | |
| /* === COLOR PICKER === */ | |
| .color-grid { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 6px; | |
| } | |
| .color-swatch { | |
| width: 34px; | |
| height: 34px; | |
| border-radius: 10px; | |
| border: 2px solid transparent; | |
| cursor: pointer; | |
| transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .color-swatch::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: inherit; | |
| box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); | |
| } | |
| .color-swatch:hover { | |
| transform: scale(1.2) translateY(-2px); | |
| } | |
| .color-swatch.active { | |
| border-color: var(--text-primary); | |
| box-shadow: 0 0 0 3px var(--bg-panel), 0 0 15px rgba(0, 0, 0, 0.3); | |
| transform: scale(1.1); | |
| } | |
| .color-picker-wrap { | |
| position: relative; | |
| width: 34px; | |
| height: 34px; | |
| border-radius: 10px; | |
| overflow: hidden; | |
| border: 2px dashed var(--border-bright); | |
| cursor: pointer; | |
| transition: all 0.25s ease; | |
| } | |
| .color-picker-wrap:hover { | |
| border-color: var(--accent); | |
| transform: scale(1.15); | |
| } | |
| .color-picker-wrap input[type="color"] { | |
| position: absolute; | |
| inset: -10px; | |
| width: calc(100% + 20px); | |
| height: calc(100% + 20px); | |
| opacity: 0; | |
| cursor: pointer; | |
| } | |
| .color-picker-wrap::before { | |
| content: '+'; | |
| position: absolute; | |
| inset: 0; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: var(--text-muted); | |
| font-weight: 700; | |
| font-size: 1.1rem; | |
| } | |
| /* === TOGGLE === */ | |
| .toggle-row { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 10px 0; | |
| border-bottom: 1px solid rgba(255, 255, 255, 0.04); | |
| } | |
| .toggle-row:last-child { | |
| border-bottom: none; | |
| } | |
| .toggle-info { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .toggle-info i { | |
| width: 30px; | |
| height: 30px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| border-radius: 8px; | |
| background: rgba(255, 255, 255, 0.04); | |
| color: var(--text-muted); | |
| font-size: 0.8rem; | |
| } | |
| .toggle-info span { | |
| font-size: 0.85rem; | |
| color: var(--text-secondary); | |
| } | |
| .toggle-switch { | |
| width: 44px; | |
| height: 24px; | |
| border-radius: 12px; | |
| background: var(--border-subtle); | |
| position: relative; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| border: 1px solid var(--border-subtle); | |
| } | |
| .toggle-switch::after { | |
| content: ''; | |
| position: absolute; | |
| top: 2px; | |
| left: 2px; | |
| width: 18px; | |
| height: 18px; | |
| border-radius: 50%; | |
| background: var(--text-muted); | |
| transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); | |
| } | |
| .toggle-switch.on { | |
| background: rgba(40, 199, 221, 0.15); | |
| border-color: var(--accent-dim); | |
| } | |
| .toggle-switch.on::after { | |
| left: 22px; | |
| background: var(--accent); | |
| box-shadow: 0 2px 8px var(--accent-glow); | |
| } | |
| /* === CHOICE CHIPS === */ | |
| .chip-group { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 6px; | |
| } | |
| .chip { | |
| padding: 7px 14px; | |
| border-radius: 10px; | |
| border: 1.5px solid var(--border-subtle); | |
| background: var(--bg-panel); | |
| color: var(--text-muted); | |
| font-size: 0.78rem; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| } | |
| .chip:hover { | |
| border-color: var(--border-bright); | |
| color: var(--text-secondary); | |
| } | |
| .chip.active { | |
| background: rgba(40, 199, 221, 0.1); | |
| border-color: var(--accent); | |
| color: var(--accent); | |
| } | |
| /* === SELECT === */ | |
| .custom-select { | |
| width: 100%; | |
| padding: 10px 14px; | |
| border-radius: 12px; | |
| border: 1.5px solid var(--border-subtle); | |
| background: var(--bg-panel); | |
| color: var(--text-primary); | |
| font-family: 'Outfit', sans-serif; | |
| font-size: 0.85rem; | |
| cursor: pointer; | |
| appearance: none; | |
| background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%237a9ab8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); | |
| background-repeat: no-repeat; | |
| background-position: right 14px center; | |
| padding-right: 36px; | |
| transition: all 0.25s ease; | |
| } | |
| .custom-select:focus { | |
| outline: none; | |
| border-color: var(--accent); | |
| box-shadow: 0 0 0 3px rgba(40, 199, 221, 0.1); | |
| } | |
| /* === DISPLAY === */ | |
| .display-area { | |
| position: relative; | |
| min-height: 480px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 40px; | |
| overflow: hidden; | |
| } | |
| .display-bg { | |
| position: absolute; | |
| inset: 0; | |
| border-radius: 24px; | |
| overflow: hidden; | |
| } | |
| .display-bg::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: | |
| radial-gradient(ellipse at 30% 20%, rgba(40, 199, 221, 0.06) 0%, transparent 50%), | |
| radial-gradient(ellipse at 70% 80%, rgba(40, 199, 221, 0.03) 0%, transparent 50%); | |
| } | |
| .caustics { | |
| position: absolute; | |
| inset: 0; | |
| opacity: 0.03; | |
| background-image: | |
| radial-gradient(ellipse at 20% 30%, var(--accent) 0%, transparent 40%), | |
| radial-gradient(ellipse at 80% 70%, var(--accent) 0%, transparent 40%), | |
| radial-gradient(ellipse at 50% 50%, var(--accent) 0%, transparent 50%); | |
| animation: causticShift 12s ease-in-out infinite alternate; | |
| pointer-events: none; | |
| } | |
| @keyframes causticShift { | |
| 0% { transform: scale(1) rotate(0deg); } | |
| 100% { transform: scale(1.15) rotate(3deg); } | |
| } | |
| /* Bubbles */ | |
| .bubble-layer { | |
| position: absolute; | |
| inset: 0; | |
| pointer-events: none; | |
| overflow: hidden; | |
| } | |
| .bubble { | |
| position: absolute; | |
| border-radius: 50%; | |
| background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.03)); | |
| border: 1px solid rgba(255, 255, 255, 0.05); | |
| animation: bubbleRise linear infinite; | |
| } | |
| .bubble:nth-child(1) { width: 8px; height: 8px; left: 10%; animation-duration: 8s; animation-delay: 0s; } | |
| .bubble:nth-child(2) { width: 12px; height: 12px; left: 25%; animation-duration: 11s; animation-delay: 2s; } | |
| .bubble:nth-child(3) { width: 6px; height: 6px; left: 40%; animation-duration: 7s; animation-delay: 4s; } | |
| .bubble:nth-child(4) { width: 15px; height: 15px; left: 55%; animation-duration: 13s; animation-delay: 1s; } | |
| .bubble:nth-child(5) { width: 5px; height: 5px; left: 70%; animation-duration: 9s; animation-delay: 3s; } | |
| .bubble:nth-child(6) { width: 10px; height: 10px; left: 85%; animation-duration: 10s; animation-delay: 5s; } | |
| @keyframes bubbleRise { | |
| 0% { bottom: -20px; opacity: 0; transform: translateX(0); } | |
| 10% { opacity: 0.4; } | |
| 90% { opacity: 0.4; } | |
| 100% { bottom: 105%; opacity: 0; transform: translateX(15px); } | |
| } | |
| /* === ASCII OUTPUT === */ | |
| .ascii-output { | |
| position: relative; | |
| z-index: 2; | |
| font-family: 'Fira Code', monospace; | |
| font-size: 13px; | |
| line-height: 1.1; | |
| letter-spacing: 0.5px; | |
| text-align: center; | |
| white-space: pre; | |
| overflow-x: auto; | |
| padding: 24px; | |
| border-radius: 20px; | |
| background: rgba(0, 0, 0, 0.25); | |
| border: 1px solid rgba(255, 255, 255, 0.05); | |
| backdrop-filter: blur(10px); | |
| -webkit-backdrop-filter: blur(10px); | |
| max-width: 100%; | |
| color: var(--fish-body); | |
| transition: all 0.4s ease; | |
| box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2); | |
| } | |
| .ascii-output.swim { | |
| animation: fishFloat 3s ease-in-out infinite; | |
| } | |
| @keyframes fishFloat { | |
| 0%, 100% { transform: translateY(0); } | |
| 50% { transform: translateY(-8px); } | |
| } | |
| /* === TOOLBAR === */ | |
| .toolbar { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| padding: 20px 24px; | |
| border-top: 1px solid var(--border-subtle); | |
| background: rgba(0, 0, 0, 0.1); | |
| flex-wrap: wrap; | |
| } | |
| .btn { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 8px; | |
| padding: 10px 20px; | |
| border-radius: 12px; | |
| border: 1.5px solid var(--border-subtle); | |
| background: var(--bg-panel); | |
| color: var(--text-secondary); | |
| font-family: 'Outfit', sans-serif; | |
| font-size: 0.82rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| white-space: nowrap; | |
| } | |
| .btn:hover { | |
| background: var(--bg-panel-hover); | |
| border-color: var(--border-bright); | |
| color: var(--text-primary); | |
| transform: translateY(-2px); | |
| } | |
| .btn:active { | |
| transform: translateY(0); | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, var(--accent-dim), var(--accent)); | |
| color: #000; | |
| border-color: transparent; | |
| box-shadow: 0 4px 16px var(--accent-glow); | |
| } | |
| .btn-primary:hover { | |
| box-shadow: 0 6px 24px rgba(40, 199, 221, 0.4); | |
| color: #000; | |
| } | |
| .btn-danger { | |
| border-color: var(--error); | |
| color: var(--error); | |
| } | |
| .btn-danger:hover { | |
| background: rgba(231, 76, 60, 0.1); | |
| } | |
| /* === TOAST === */ | |
| .toast { | |
| position: fixed; | |
| bottom: 30px; | |
| right: 30px; | |
| padding: 14px 24px; | |
| border-radius: 14px; | |
| background: var(--bg-panel); | |
| border: 1px solid var(--border-bright); | |
| color: var(--text-primary); | |
| font-size: 0.9rem; | |
| font-weight: 500; | |
| z-index: 1000; | |
| transform: translateY(100px); | |
| opacity: 0; | |
| transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .toast.show { | |
| transform: translateY(0); | |
| opacity: 1; | |
| } | |
| .toast i { | |
| color: var(--success); | |
| font-size: 1.1rem; | |
| } | |
| /* === WATERMARK === */ | |
| .watermark { | |
| position: absolute; | |
| bottom: 12px; | |
| right: 18px; | |
| font-size: 0.65rem; | |
| color: rgba(255, 255, 255, 0.06); | |
| pointer-events: none; | |
| z-index: 1; | |
| letter-spacing: 1px; | |
| } | |
| /* === THEME DROPDOWN === */ | |
| .theme-dropdown { | |
| position: relative; | |
| } | |
| .theme-menu { | |
| position: absolute; | |
| top: calc(100% + 8px); | |
| right: 0; | |
| width: 160px; | |
| background: var(--bg-panel); | |
| border: 1px solid var(--border-bright); | |
| border-radius: 14px; | |
| padding: 8px; | |
| z-index: 100; | |
| box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5); | |
| opacity: 0; | |
| visibility: hidden; | |
| transform: translateY(-8px); | |
| transition: all 0.25s ease; | |
| } | |
| .theme-menu.open { | |
| opacity: 1; | |
| visibility: visible; | |
| transform: translateY(0); | |
| } | |
| .theme-option { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| padding: 10px 12px; | |
| border-radius: 10px; | |
| cursor: pointer; | |
| font-size: 0.85rem; | |
| color: var(--text-secondary); | |
| transition: all 0.2s ease; | |
| } | |
| .theme-option:hover { | |
| background: rgba(40, 199, 221, 0.08); | |
| color: var(--text-primary); | |
| } | |
| .theme-option.active { | |
| color: var(--accent); | |
| } | |
| .theme-dot { | |
| width: 14px; | |
| height: 14px; | |
| border-radius: 50%; | |
| border: 2px solid var(--border-subtle); | |
| } | |
| /* === RESPONSIVE === */ | |
| @media (max-width: 640px) { | |
| .site-header { | |
| flex-wrap: wrap; | |
| gap: 10px; | |
| } | |
| .species-grid { | |
| grid-template-columns: repeat(3, 1fr); | |
| } | |
| .display-area { | |
| padding: 20px; | |
| min-height: 340px; | |
| } | |
| .ascii-output { | |
| font-size: 10px; | |
| } | |
| .toolbar { | |
| padding: 16px; | |
| } | |
| .btn { | |
| padding: 8px 14px; | |
| font-size: 0.75rem; | |
| } | |
| } | |
| /* === SCROLLBAR === */ | |
| ::-webkit-scrollbar { | |
| width: 6px; | |
| height: 6px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: var(--border-subtle); | |
| border-radius: 3px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: var(--border-bright); | |
| } | |
| /* === ANIMATED ENTRANCE === */ | |
| .panel { | |
| opacity: 0; | |
| transform: translateY(20px); | |
| animation: panelEnter 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards; | |
| } | |
| .panel:nth-child(1) { animation-delay: 0.1s; } | |
| .panel:nth-child(2) { animation-delay: 0.2s; } | |
| @keyframes panelEnter { | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| /* === MOBILE HEADER FIX === */ | |
| @media (max-width: 640px) { | |
| .anycoder-badge { | |
| font-size: 0.65rem; | |
| padding: 4px 10px; | |
| } | |
| .brand h1 { | |
| font-size: 1.1rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body data-theme="ocean"> | |
| <div class="ocean-bg"> | |
| <div class="light-rays"> | |
| <div class="light-ray"></div> | |
| <div class="light-ray"></div> | |
| <div class="light-ray"></div> | |
| <div class="light-ray"></div> | |
| <div class="light-ray"></div> | |
| </div> | |
| <div class="particles" id="particles"></div> | |
| </div> | |
| <div class="app-container"> | |
| <!-- Header --> | |
| <header class="site-header"> | |
| <div class="brand"> | |
| <div class="brand-icon"><i class="fas fa-fish"></i></div> | |
| <div> | |
| <h1>AsciiFish</h1> | |
| <p>Creative ASCII Aquarium</p> | |
| </div> | |
| </div> | |
| <div class="header-actions"> | |
| <a class="anycoder-badge" href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" rel="noopener noreferrer"> | |
| <i class="fas fa-code" style="font-size:0.65rem;"></i> Built with anycoder | |
| </a> | |
| <div class="theme-dropdown"> | |
| <button class="header-btn" onclick="toggleThemeMenu()" title="Theme"> | |
| <i class="fas fa-palette"></i> | |
| </button> | |
| <div class="theme-menu" id="themeMenu"> | |
| <div class="theme-option active" onclick="setTheme('ocean', this)"> | |
| <div class="theme-dot" style="background: #28c7dd;"></div> Ocean | |
| </div> | |
| <div class="theme-option" onclick="setTheme('sunset', this)"> | |
| <div class="theme-dot" style="background: #ff7eb3;"></div> Sunset | |
| </div> | |
| <div class="theme-option" onclick="setTheme('abyss', this)"> | |
| <div class="theme-dot" style="background: #00ffaa;"></div> Abyss | |
| </div> | |
| </div> | |
| </div> | |
| <button class="header-btn" onclick="toggleMute()" title="Toggle Sound"> | |
| <i class="fas fa-volume-up" id="muteIcon"></i> | |
| </button> | |
| <button class="header-btn" onclick="toggleFullscreen()" title="Fullscreen"> | |
| <i class="fas fa-expand"></i> | |
| </button> | |
| </div> | |
| </header> | |
| <div class="main-grid"> | |
| <!-- Controls --> | |
| <div class="panel" id="controlsPanel"> | |
| <div class="panel-header"> | |
| <div class="panel-title"> | |
| <i class="fas fa-sliders-h"></i> Fish Editor | |
| </div> | |
| <button class="header-btn" onclick="randomize()" title="Randomize"> | |
| <i class="fas fa-dice"></i> | |
| </button> | |
| </div> | |
| <div class="panel-body"> | |
| <!-- Species --> | |
| <div class="section"> | |
| <div class="section-label">Species</div> | |
| <div class="species-grid" id="speciesGrid"> | |
| <button class="species-btn active" data-species="clownfish" onclick="selectSpecies(this)"> | |
| <span class="species-icon"><i class="fas fa-fish"></i></span> | |
| <span class="species-name">Clownfish</span> | |
| </button> | |
| <button class="species-btn" data-species="goldfish" onclick="selectSpecies(this)"> | |
| <span class="species-icon"><i class="fas fa-fish-fins"></i></span> | |
| <span class="species-name">Goldfish</span> | |
| </button> | |
| <button class="species-btn" data-species="betta" onclick="selectSpecies(this)"> | |
| <span class="species-icon"><i class="fas fa-crown"></i></span> | |
| <span class="species-name">Betta</span> | |
| </button> | |
| <button class="species-btn" data-species="shark" onclick="selectSpecies(this)"> | |
| <span class="species-icon"><i class="fas fa-water"></i></span> | |
| <span class="species-name">Shark</span> | |
| </button> | |
| <button class="species-btn" data-species="angler" onclick="selectSpecies(this)"> | |
| <span class="species-icon"><i class="fas fa-lightbulb"></i></span> | |
| <span class="species-name">Angler</span> | |
| </button> | |
| <button class="species-btn" data-species="ray" onclick="selectSpecies(this)"> | |
| <span class="species-icon"><i class="fas fa-fan"></i></span> | |
| <span class="species-name">Ray</span> | |
| </button> | |
| <button class="species-btn" data-species="jelly" onclick="selectSpecies(this)"> | |
| <span class="species-icon"><i class="fas fa-umbrella"></i></span> | |
| <span class="species-name">Jellyfish</span> | |
| </button> | |
| <button class="species-btn" data-species="whale" onclick="selectSpecies(this)"> | |
| <span class="species-icon"><i class="fas fa-gem"></i></span> | |
| <span class="species-name">Whale</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Dimensions --> | |
| <div class="section"> | |
| <div class="section-label">Dimensions</div> | |
| <div class="slider-wrap"> | |
| <div class="slider-header"> | |
| <span class="slider-label">Length</span> | |
| <span class="slider-value" id="lengthVal">18</span> | |
| </div> | |
| <input type="range" class="slider" id="lengthSlider" min="8" max="40" value="18" oninput="onInput('length', this.value)"> | |
| </div> | |
| <div class="slider-wrap"> | |
| <div class="slider-header"> | |
| <span class="slider-label">Height</span> | |
| <span class="slider-value" id="heightVal">5</span> | |
| </div> | |
| <input type="range" class="slider" id="heightSlider" min="3" max="12" value="5" oninput="onInput('height', this.value)"> | |
| </div> | |
| </div> | |
| <!-- Colors --> | |
| <div class="section"> | |
| <div class |