feat(ui): add fullscreen toggle button and include icon proposals

This commit is contained in:
2026-10-20 14:20:23 +08:00
parent 2c9dc6d2ee
commit f446c0ddbd
11 changed files with 683 additions and 9 deletions

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@ node_modules
dist
dist-ssr
*.local
.pi-cache/
# Editor directories and files
.vscode/*

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

View File

@@ -0,0 +1,176 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
<defs>
<!-- Deep obsidian radial background -->
<radialGradient id="bgA" cx="50%" cy="42%" r="68%">
<stop offset="0%" stop-color="#14231b" />
<stop offset="55%" stop-color="#0b130f" />
<stop offset="100%" stop-color="#09090b" />
</radialGradient>
<!-- Trunk & Stem Gradient -->
<linearGradient id="trunkGradA" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" stop-color="#047857" />
<stop offset="35%" stop-color="#059669" />
<stop offset="70%" stop-color="#10b981" />
<stop offset="100%" stop-color="#34d399" />
</linearGradient>
<!-- Top Willow Leaf Upper Surface -->
<linearGradient id="topLeafGradA" x1="0%" y1="20%" x2="100%" y2="60%">
<stop offset="0%" stop-color="#059669" />
<stop offset="25%" stop-color="#10b981" />
<stop offset="70%" stop-color="#34d399" />
<stop offset="100%" stop-color="#a7f3d0" />
</linearGradient>
<!-- Top Willow Leaf Shaded Underbelly -->
<linearGradient id="topLeafUnderA" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#047857" />
<stop offset="50%" stop-color="#059669" />
<stop offset="100%" stop-color="#10b981" />
</linearGradient>
<!-- Mid Leaf Gradient -->
<linearGradient id="midLeafGradA" x1="0%" y1="20%" x2="100%" y2="60%">
<stop offset="0%" stop-color="#047857" />
<stop offset="35%" stop-color="#10b981" />
<stop offset="75%" stop-color="#34d399" />
<stop offset="100%" stop-color="#6ee7b7" />
</linearGradient>
<!-- Dewdrop Gradient -->
<radialGradient id="dewDropGradA" cx="35%" cy="30%" r="65%">
<stop offset="0%" stop-color="#ffffff" />
<stop offset="40%" stop-color="#d1fae5" />
<stop offset="75%" stop-color="#34d399" />
<stop offset="100%" stop-color="#059669" />
</radialGradient>
<!-- Vein Filament Glow -->
<filter id="veinGlowA" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- Dew Drop Flare -->
<filter id="dewFlareA" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="5" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="auraA" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="12" result="blur" />
</filter>
</defs>
<!-- Canvas -->
<rect width="512" height="512" rx="128" fill="url(#bgA)" />
<!-- Botanical Ambient Rings & Aura -->
<circle cx="256" cy="256" r="195" fill="none" stroke="#059669" stroke-width="1.2" stroke-opacity="0.2" stroke-dasharray="6 8" />
<circle cx="256" cy="256" r="150" fill="none" stroke="#10b981" stroke-width="0.8" stroke-opacity="0.15" />
<circle cx="240" cy="230" r="130" fill="#10b981" fill-opacity="0.05" filter="url(#auraA)" />
<!-- BOTANICAL SERIF F -->
<g>
<!-- Base Root Serif (Organic flared roots seamlessly sculpted at trunk foot) -->
<path d="M 136 398
C 165 394, 185 382, 194 358
L 224 358
C 233 382, 253 394, 282 398
C 252 403, 230 400, 218 390
C 206 400, 172 403, 136 398 Z"
fill="url(#trunkGradA)" />
<!-- Main Trunk: Graceful Living Sprout Trunk with Seamless Classical Leaf Serif -->
<path d="M 194 360
C 192 290, 190 220, 188 155
C 186 138, 172 126, 142 122
C 138 121, 137 127, 140 129
C 152 138, 172 148, 186 156
L 190 124
C 194 118, 204 116, 216 118
C 224 120, 226 128, 224 140
C 220 216, 222 295, 224 360
Z"
fill="url(#trunkGradA)" />
<!-- Trunk Inner Vitality Sap Line -->
<path d="M 209 370 C 205 270, 203 190, 196 126"
fill="none"
stroke="#ecfdf5"
stroke-width="2.2"
stroke-linecap="round"
filter="url(#veinGlowA)" />
<!-- TOP BAR: Outstretched Wind-Swept Willow Leaf / Botanical Plume -->
<!-- Under-leaf layer for depth -->
<path d="M 208 120
C 255 98, 332 104, 405 146
C 342 176, 268 168, 212 144
Z"
fill="url(#topLeafUnderA)" />
<!-- Upper luminous leaf surface -->
<path d="M 208 120
C 250 94, 328 96, 405 146
C 338 162, 275 152, 212 136
Z"
fill="url(#topLeafGradA)" />
<!-- Top Leaf Master Rib / Vein Line -->
<path d="M 212 124 C 275 110, 342 118, 402 146"
fill="none"
stroke="#ecfdf5"
stroke-width="2.6"
stroke-linecap="round"
filter="url(#veinGlowA)" />
<!-- Top Leaf Delicate Lateral Veinlets -->
<path d="M 252 116 Q 272 106, 292 110" fill="none" stroke="#a7f3d0" stroke-width="1.3" stroke-linecap="round" opacity="0.75" />
<path d="M 292 117 Q 318 111, 342 120" fill="none" stroke="#a7f3d0" stroke-width="1.3" stroke-linecap="round" opacity="0.75" />
<path d="M 334 123 Q 360 122, 382 134" fill="none" stroke="#a7f3d0" stroke-width="1.2" stroke-linecap="round" opacity="0.75" />
<path d="M 270 124 Q 288 136, 310 142" fill="none" stroke="#10b981" stroke-width="1.2" stroke-linecap="round" opacity="0.5" />
<path d="M 312 130 Q 336 142, 360 148" fill="none" stroke="#10b981" stroke-width="1.2" stroke-linecap="round" opacity="0.5" />
<!-- Dewdrop at Top Leaf Apex -->
<g transform="translate(408, 147)">
<circle cx="0" cy="0" r="14" fill="#34d399" fill-opacity="0.3" filter="url(#dewFlareA)" />
<circle cx="0" cy="0" r="7.5" fill="url(#dewDropGradA)" />
<circle cx="-2" cy="-2" r="2.5" fill="#ffffff" />
<circle cx="2" cy="2" r="1" fill="#ffffff" fill-opacity="0.6" />
</g>
<!-- MIDDLE BAR: Secondary Willow Leaf Shoot -->
<path d="M 216 244
C 252 230, 298 230, 350 255
C 310 282, 260 278, 218 262
Z"
fill="url(#midLeafGradA)" />
<!-- Mid Leaf Master Rib -->
<path d="M 220 248 C 262 238, 305 240, 348 255"
fill="none"
stroke="#ecfdf5"
stroke-width="2"
stroke-linecap="round"
filter="url(#veinGlowA)" />
<!-- Mid Leaf Secondary Veinlets -->
<path d="M 252 243 Q 270 234, 288 237" fill="none" stroke="#a7f3d0" stroke-width="1.2" stroke-linecap="round" opacity="0.7" />
<path d="M 290 244 Q 312 240, 330 248" fill="none" stroke="#a7f3d0" stroke-width="1.1" stroke-linecap="round" opacity="0.7" />
<!-- Dewdrop at Mid Leaf Apex -->
<g transform="translate(354, 256)">
<circle cx="0" cy="0" r="10" fill="#34d399" fill-opacity="0.3" filter="url(#dewFlareA)" />
<circle cx="0" cy="0" r="5.5" fill="url(#dewDropGradA)" />
<circle cx="-1.5" cy="-1.5" r="1.8" fill="#ffffff" />
</g>
<!-- Tender dewdrop nestled along lower stem -->
<g transform="translate(204, 318)">
<circle cx="0" cy="0" r="4.5" fill="url(#dewDropGradA)" />
<circle cx="-1.2" cy="-1.2" r="1.5" fill="#ffffff" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

View File

@@ -0,0 +1,158 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
<defs>
<!-- Background Gradient -->
<radialGradient id="bgB" cx="48%" cy="46%" r="68%">
<stop offset="0%" stop-color="#122018" />
<stop offset="55%" stop-color="#0a120e" />
<stop offset="100%" stop-color="#09090b" />
</radialGradient>
<!-- Main Chassis Monolith Gradient -->
<linearGradient id="chassisGradB" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#10b981" />
<stop offset="35%" stop-color="#059669" />
<stop offset="70%" stop-color="#047857" />
<stop offset="100%" stop-color="#064e3b" />
</linearGradient>
<!-- Laser Track Inset Gradient -->
<linearGradient id="laserTrackGradB" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#34d399" />
<stop offset="50%" stop-color="#a7f3d0" />
<stop offset="100%" stop-color="#ecfdf5" />
</linearGradient>
<!-- Photonic Core White Hot -->
<linearGradient id="photonicWhite" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#6ee7b7" />
<stop offset="50%" stop-color="#ffffff" />
<stop offset="100%" stop-color="#ffffff" />
</linearGradient>
<!-- High-End Glassmorphism Neon Glow -->
<filter id="neonBloomB" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="12" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="laserGlowB" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="photonImpulseB" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- Deep Obsidian Canvas -->
<rect width="512" height="512" rx="128" fill="url(#bgB)" />
<!-- Ultra-Precision Optical Reticle / Collimator Grid -->
<g stroke="#10b981" fill="none" opacity="0.22">
<!-- Concentric Aperture Rings -->
<circle cx="256" cy="256" r="196" stroke-width="1.2" stroke-dasharray="4 8" />
<circle cx="256" cy="256" r="148" stroke-width="0.8" />
<circle cx="256" cy="256" r="88" stroke-width="0.6" stroke-dasharray="8 6" />
<!-- Crosshair Calibration Axis -->
<line x1="256" y1="48" x2="256" y2="70" stroke-width="2" />
<line x1="256" y1="442" x2="256" y2="464" stroke-width="2" />
<line x1="48" y1="256" x2="70" y2="256" stroke-width="2" />
<line x1="442" y1="256" x2="464" y2="256" stroke-width="2" />
<!-- 45-degree angle tick marks -->
<line x1="117" y1="117" x2="129" y2="129" stroke-width="1.5" />
<line x1="395" y1="117" x2="383" y2="129" stroke-width="1.5" />
<line x1="117" y1="395" x2="129" y2="383" stroke-width="1.5" />
<line x1="395" y1="395" x2="383" y2="383" stroke-width="1.5" />
<!-- Optical Horizontal Trajectory Guides -->
<line x1="120" y1="147" x2="425" y2="147" stroke-width="0.8" stroke-dasharray="4 4" opacity="0.6" />
<line x1="120" y1="262" x2="380" y2="262" stroke-width="0.8" stroke-dasharray="4 4" opacity="0.6" />
</g>
<!-- Ambient Optical Core Glow Behind F -->
<circle cx="256" cy="230" r="120" fill="#10b981" fill-opacity="0.08" filter="url(#neonBloomB)" />
<!-- UNIFIED MONOLITHIC CHASSIS (Seamless, Continuous F Architecture) -->
<g filter="url(#neonBloomB)">
<!--
Outer contour of the architectural F:
- Starts at top-left corner: (152, 120) with r=26
- Runs horizontally across top arm to (388, 120), rounded cap r=27 down to (388, 174)
- Returns left to inner top corner (212, 174), fillets down to (212, 235)
- Turns right into mid arm to (330, 235), rounded cap r=27 down to (330, 289)
- Returns left to inner mid corner (212, 289), fillets down to (212, 366)
- Bottom of stem rounded cap r=26 from (212, 392) to (152, 392)
- Runs up the left vertical edge back to (152, 120)
-->
<path d="M 178 120
L 388 120
A 27 27 0 0 1 415 147
A 27 27 0 0 1 388 174
L 220 174
A 12 12 0 0 0 208 186
L 208 223
A 12 12 0 0 0 220 235
L 332 235
A 27 27 0 0 1 359 262
A 27 27 0 0 1 332 289
L 220 289
A 12 12 0 0 0 208 301
L 208 366
A 28 28 0 0 1 180 394
A 28 28 0 0 1 152 366
L 152 148
A 28 28 0 0 1 180 120
Z"
fill="url(#chassisGradB)"
stroke="#34d399"
stroke-width="1.8"
stroke-opacity="0.6" />
</g>
<!-- RECESSED LASER TRACK CHANNELS (Subtle Inset Bevels) -->
<g opacity="0.3">
<!-- Vertical channel rim -->
<rect x="173" y="142" width="14" height="228" rx="7" fill="#047857" />
<!-- Top arm channel rim -->
<rect x="173" y="140" width="216" height="14" rx="7" fill="#047857" />
<!-- Mid arm channel rim -->
<rect x="173" y="255" width="158" height="14" rx="7" fill="#047857" />
</g>
<!-- PHOTONIC LASER RUNNERS (High-Luminance Speed Streams) -->
<!-- 1. Vertical Still Gazing Light Pillar Core -->
<rect x="176" y="145" width="8" height="222" rx="4" fill="url(#laserTrackGradB)" filter="url(#laserGlowB)" />
<rect x="178" y="165" width="4" height="180" rx="2" fill="#ffffff" />
<!-- 2. Top Stream Ray Photonic Beam -->
<rect x="176" y="143" width="210" height="8" rx="4" fill="url(#laserTrackGradB)" filter="url(#laserGlowB)" />
<rect x="200" y="145" width="180" height="4" rx="2" fill="url(#photonicWhite)" />
<!-- Leading Photon Impulse Ring at Top Tip -->
<g transform="translate(390, 147)" filter="url(#photonImpulseB)">
<circle cx="0" cy="0" r="16" fill="#34d399" fill-opacity="0.25" />
<circle cx="0" cy="0" r="8" fill="#a7f3d0" />
<circle cx="0" cy="0" r="3.5" fill="#ffffff" />
</g>
<!-- 3. Mid Stream Ray Photonic Beam -->
<rect x="176" y="258" width="152" height="8" rx="4" fill="url(#laserTrackGradB)" filter="url(#laserGlowB)" />
<rect x="195" y="260" width="128" height="4" rx="2" fill="url(#photonicWhite)" />
<!-- Leading Photon Dot at Mid Tip -->
<g transform="translate(332, 262)" filter="url(#photonImpulseB)">
<circle cx="0" cy="0" r="13" fill="#10b981" fill-opacity="0.25" />
<circle cx="0" cy="0" r="6.5" fill="#a7f3d0" />
<circle cx="0" cy="0" r="2.8" fill="#ffffff" />
</g>
<!-- Speed Calibration Dashes / Photonic Trailing Emitters -->
<line x1="422" y1="147" x2="442" y2="147" stroke="#6ee7b7" stroke-width="3" stroke-linecap="round" opacity="0.8" />
<line x1="448" y1="147" x2="455" y2="147" stroke="#34d399" stroke-width="2" stroke-linecap="round" opacity="0.5" />
<line x1="362" y1="262" x2="380" y2="262" stroke="#34d399" stroke-width="2.5" stroke-linecap="round" opacity="0.75" />
<line x1="386" y1="262" x2="391" y2="262" stroke="#10b981" stroke-width="1.8" stroke-linecap="round" opacity="0.4" />
</svg>

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

View File

@@ -0,0 +1,142 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
<defs>
<!-- Background Gradient -->
<radialGradient id="bgC" cx="48%" cy="42%" r="70%">
<stop offset="0%" stop-color="#14241c" />
<stop offset="55%" stop-color="#0a130f" />
<stop offset="100%" stop-color="#09090b" />
</radialGradient>
<!-- Fern Trunk & Spiral Ribbon Gradient -->
<linearGradient id="fernGradC" x1="0%" y1="100%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#047857" />
<stop offset="30%" stop-color="#059669" />
<stop offset="65%" stop-color="#10b981" />
<stop offset="85%" stop-color="#34d399" />
<stop offset="100%" stop-color="#a7f3d0" />
</linearGradient>
<!-- Middle Crossbar Frond Gradient -->
<linearGradient id="midFrondGradC" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#059669" />
<stop offset="50%" stop-color="#10b981" />
<stop offset="85%" stop-color="#34d399" />
<stop offset="100%" stop-color="#6ee7b7" />
</linearGradient>
<!-- Bio Spore Radial Glow -->
<radialGradient id="sporeGradC" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#ffffff" />
<stop offset="40%" stop-color="#a7f3d0" />
<stop offset="75%" stop-color="#34d399" />
<stop offset="100%" stop-color="#059669" />
</radialGradient>
<!-- Organic Bloom Filter -->
<filter id="fernGlowC" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="sporeFlareC" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- Deep Obsidian Canvas -->
<rect width="512" height="512" rx="128" fill="url(#bgC)" />
<!-- Fibonacci Golden Ratio Geometric Guide Watermark -->
<g stroke="#10b981" fill="none" opacity="0.14">
<circle cx="256" cy="256" r="195" stroke-width="1.2" stroke-dasharray="6 6" />
<path d="M 180 395 C 190 280, 240 130, 350 130 C 420 130, 420 220, 360 220 C 310 220, 310 170, 345 170" stroke-width="1.5" stroke-dasharray="3 5" />
<path d="M 120 395 A 270 270 0 0 1 390 125" stroke-width="0.8" />
</g>
<!-- Ambient Vitality Aura -->
<circle cx="280" cy="200" r="120" fill="#10b981" fill-opacity="0.06" filter="url(#fernGlowC)" />
<!-- GOLDEN SPIRAL FERN 'F' -->
<g filter="url(#fernGlowC)">
<!-- Main Trunk to Top Arm & Golden Spiral Crozier Coil -->
<path d="M 178 396
C 188 330, 196 260, 206 180
C 214 135, 248 112, 305 112
C 342 112, 380 120, 400 145
C 416 168, 412 198, 386 216
C 358 232, 324 220, 318 190
C 314 165, 336 148, 358 152
C 374 156, 380 172, 372 184
C 366 190, 356 188, 354 180
C 352 174, 358 170, 362 172
C 366 174, 364 180, 360 180
C 356 180, 344 172, 346 162
C 348 152, 362 144, 376 150
C 394 158, 396 184, 380 200
C 360 216, 332 210, 328 185
C 324 155, 350 134, 385 136
C 358 126, 318 126, 280 136
C 245 146, 230 175, 226 215
C 220 270, 214 335, 212 396
Z"
fill="url(#fernGradC)" />
<!-- Middle Frond Crossbar (Unfurling Young Pinna) -->
<path d="M 214 250
C 246 240, 285 240, 328 250
C 348 255, 356 266, 348 276
C 338 286, 318 284, 298 276
C 264 266, 235 272, 212 284
Z"
fill="url(#midFrondGradC)" />
<!-- Organic micro-buds along the spine -->
<path d="M 194 320 C 182 315, 178 305, 186 298 C 192 305, 196 312, 194 320 Z" fill="#10b981" />
<path d="M 198 260 C 186 255, 182 245, 190 238 C 196 245, 200 252, 198 260 Z" fill="#34d399" />
<path d="M 206 200 C 196 195, 194 185, 202 178 C 206 185, 210 192, 206 200 Z" fill="#6ee7b7" />
</g>
<!-- Luminous Central Golden Spiral Filament -->
<path d="M 195 390
C 202 315, 212 225, 226 170
C 238 128, 275 118, 318 120
C 362 122, 396 138, 396 170
C 396 202, 365 214, 338 198
C 324 188, 330 166, 348 162
C 362 158, 370 172, 362 180"
fill="none"
stroke="#ecfdf5"
stroke-width="2.5"
stroke-linecap="round"
filter="url(#sporeFlareC)" />
<!-- Mid Frond Center Vein -->
<path d="M 218 256 C 255 248, 295 248, 342 260"
fill="none"
stroke="#ecfdf5"
stroke-width="2"
stroke-linecap="round"
opacity="0.9" />
<!-- Golden Spiral Luminescent Spore Nodes -->
<g transform="translate(362, 174)" filter="url(#sporeFlareC)">
<circle cx="0" cy="0" r="10" fill="#34d399" fill-opacity="0.3" />
<circle cx="0" cy="0" r="5" fill="url(#sporeGradC)" />
<circle cx="-1.2" cy="-1.2" r="1.8" fill="#ffffff" />
</g>
<g transform="translate(398, 148)" filter="url(#sporeFlareC)">
<circle cx="0" cy="0" r="11" fill="#34d399" fill-opacity="0.3" />
<circle cx="0" cy="0" r="5.5" fill="url(#sporeGradC)" />
<circle cx="-1.5" cy="-1.5" r="2" fill="#ffffff" />
</g>
<g transform="translate(346, 262)" filter="url(#sporeFlareC)">
<circle cx="0" cy="0" r="9" fill="#10b981" fill-opacity="0.3" />
<circle cx="0" cy="0" r="4.5" fill="url(#sporeGradC)" />
<circle cx="-1" cy="-1" r="1.5" fill="#ffffff" />
</g>
<circle cx="206" cy="285" r="3.5" fill="url(#sporeGradC)" />
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View File

@@ -0,0 +1,166 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
<defs>
<!-- Background Gradient -->
<radialGradient id="bgD" cx="48%" cy="45%" r="68%">
<stop offset="0%" stop-color="#142118" />
<stop offset="55%" stop-color="#0a120e" />
<stop offset="100%" stop-color="#09090b" />
</radialGradient>
<!-- Cello Body Gradient -->
<linearGradient id="celloGradD" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#a7f3d0" />
<stop offset="20%" stop-color="#34d399" />
<stop offset="60%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- Upper Acoustic Soundbar Gradient -->
<linearGradient id="upperBarGradD" x1="210" y1="135" x2="395" y2="135" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10b981" />
<stop offset="45%" stop-color="#34d399" />
<stop offset="80%" stop-color="#a7f3d0" />
<stop offset="100%" stop-color="#ffffff" />
</linearGradient>
<!-- Harmonic String Laser Gradient (userSpaceOnUse ensures full horizontal rendering) -->
<linearGradient id="stringLaserGradD" x1="110" y1="256" x2="385" y2="256" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#059669" stop-opacity="0" />
<stop offset="15%" stop-color="#10b981" stop-opacity="0.9" />
<stop offset="40%" stop-color="#34d399" />
<stop offset="50%" stop-color="#ffffff" />
<stop offset="60%" stop-color="#34d399" />
<stop offset="85%" stop-color="#10b981" stop-opacity="0.9" />
<stop offset="100%" stop-color="#059669" stop-opacity="0" />
</linearGradient>
<!-- Acoustic Resonance Filters -->
<filter id="celloAcousticGlowD" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="9" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="stringLaserBloomD" x="-40%" y="-40%" width="180%" height="180%">
<feGaussianBlur stdDeviation="5" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="nodeFlareD" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- Deep Obsidian Canvas -->
<rect width="512" height="512" rx="128" fill="url(#bgD)" />
<!-- Acoustic Elliptical Sound Waves Radiating from Soundhole Waist -->
<g stroke="#10b981" fill="none" opacity="0.22">
<ellipse cx="256" cy="256" rx="205" ry="125" stroke-width="1.2" stroke-dasharray="4 6" />
<ellipse cx="256" cy="256" rx="160" ry="95" stroke-width="0.8" />
<ellipse cx="256" cy="256" rx="110" ry="65" stroke-width="0.6" stroke-dasharray="8 4" />
</g>
<!-- Harmonic String Vibrating Sine Waves (Acoustic Standing Waves) -->
<path d="M 100 256
Q 140 238 180 256
T 260 256
T 340 256
T 400 256"
fill="none"
stroke="#34d399"
stroke-width="1.8"
stroke-opacity="0.4" />
<path d="M 100 256
Q 140 274 180 256
T 260 256
T 340 256
T 400 256"
fill="none"
stroke="#10b981"
stroke-width="1.4"
stroke-opacity="0.3" />
<!-- UPPER ACOUSTIC SOUNDBAR (Top Horizontal Stroke of 'F') -->
<g filter="url(#celloAcousticGlowD)">
<path d="M 224 122
C 268 114, 335 114, 392 128
A 20 20 0 0 1 402 146
A 20 20 0 0 1 382 164
C 330 160, 268 156, 218 150
Z"
fill="url(#upperBarGradD)" />
</g>
<!-- Upper Bar Core Luminous Beam -->
<rect x="226" y="142.5" width="164" height="3" rx="1.5" fill="#ffffff" filter="url(#stringLaserBloomD)" />
<circle cx="395" cy="144" r="5.5" fill="#ffffff" filter="url(#nodeFlareD)" />
<!-- THE MASTER STRADIVARIUS CELLO f-HOLE -->
<g filter="url(#celloAcousticGlowD)">
<path d="
M 236 120
A 18 18 0 1 1 236 156
A 18 18 0 1 1 236 120
M 224 146
C 206 170, 196 198, 200 230
L 188 236
L 212 250
C 214 256, 214 262, 212 268
L 188 282
L 200 288
C 200 325, 186 355, 158 365
M 158 357
A 18 18 0 1 1 158 393
A 18 18 0 1 1 158 357
M 172 372
C 218 355, 236 315, 232 275
L 250 268
L 230 254
C 230 244, 232 238, 234 230
L 252 236
L 232 220
C 232 180, 250 152, 264 135
Z
"
fill="url(#celloGradD)"
stroke="#34d399"
stroke-width="1.6"
stroke-opacity="0.6" />
</g>
<!-- Luminous Acoustic Spine Ribbon running inside the f-Hole -->
<path d="M 236 138
C 214 175, 206 215, 212 256
C 218 300, 208 342, 158 375"
fill="none"
stroke="#ecfdf5"
stroke-width="3.2"
stroke-linecap="round"
filter="url(#nodeFlareD)" />
<!-- Upper and Lower Pearl Soundhole Core Flares -->
<circle cx="236" cy="138" r="6.5" fill="#ffffff" filter="url(#nodeFlareD)" />
<circle cx="158" cy="375" r="6.5" fill="#a7f3d0" filter="url(#nodeFlareD)" />
<!-- THE HARMONIC CELLO STRING (Middle Crossbar Laser Beam of 'F') -->
<g filter="url(#stringLaserBloomD)">
<!-- Primary high-voltage horizontal string -->
<rect x="110" y="253.5" width="275" height="5" rx="2.5" fill="url(#stringLaserGradD)" />
<rect x="150" y="254.5" width="200" height="3" rx="1.5" fill="#ffffff" />
</g>
<!-- Central Acoustic Waist Intersection Resonance Node (Lens Flare) -->
<g transform="translate(212, 256)" filter="url(#nodeFlareD)">
<circle cx="0" cy="0" r="18" fill="#34d399" fill-opacity="0.35" />
<circle cx="0" cy="0" r="8" fill="#ffffff" />
<circle cx="0" cy="0" r="3" fill="#ecfdf5" />
</g>
<!-- Right String Harmonic Terminal Node -->
<g transform="translate(355, 256)" filter="url(#nodeFlareD)">
<circle cx="0" cy="0" r="13" fill="#10b981" fill-opacity="0.35" />
<circle cx="0" cy="0" r="6" fill="#a7f3d0" />
<circle cx="0" cy="0" r="2.5" fill="#ffffff" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

View File

@@ -1,4 +1,4 @@
import { Settings as SettingsIcon } from 'lucide-react';
import { Maximize, Minimize, Settings as SettingsIcon } from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { FocusDisplay } from './components/FocusDisplay';
import { SettingsDrawer } from './components/SettingsDrawer';
@@ -23,8 +23,22 @@ export default function App() {
const [words, setWords] = useState<string[]>([]);
const [isSettingsOpen, setIsSettingsOpen] = useState<boolean>(false);
const [isUserActive, setIsUserActive] = useState<boolean>(true);
const [isFullscreen, setIsFullscreen] = useState<boolean>(() =>
typeof document !== 'undefined' ? Boolean(document.fullscreenElement) : false
);
const inactivityTimerRef = useRef<number | null>(null);
// Sync fullscreen state with document events
useEffect(() => {
const handleFullscreenChange = () => {
setIsFullscreen(Boolean(document.fullscreenElement));
};
document.addEventListener('fullscreenchange', handleFullscreenChange);
return () => {
document.removeEventListener('fullscreenchange', handleFullscreenChange);
};
}, []);
// Fast-path IndexedDB restore with silent background verification
useEffect(() => {
let isCancelled = false;
@@ -337,14 +351,31 @@ export default function App() {
{BOOK_TITLE}
</span>
{/* Quiet Gear Button */}
<button
onClick={() => setIsSettingsOpen(true)}
className="p-1.5 rounded-lg text-zinc-500 hover:text-zinc-200 transition-colors"
title="Settings [Esc]"
>
<SettingsIcon className="w-4 h-4" />
</button>
{/* Top Right Action Buttons */}
<div className="flex items-center gap-1">
{/* Fullscreen Toggle Button */}
<button
onClick={toggleFullscreen}
className="p-2 text-zinc-500 hover:text-zinc-200 transition-colors rounded-lg"
title="全屏 (F)"
aria-label={isFullscreen ? '退出全屏' : '进入全屏'}
>
{isFullscreen ? (
<Minimize className="w-4 h-4" />
) : (
<Maximize className="w-4 h-4" />
)}
</button>
{/* Quiet Gear Button */}
<button
onClick={() => setIsSettingsOpen(true)}
className="p-2 text-zinc-500 hover:text-zinc-200 transition-colors rounded-lg"
title="Settings [Esc]"
>
<SettingsIcon className="w-4 h-4" />
</button>
</div>
</header>
{/* Main RSVPs Central Stream (Instant 0ms display, zero loading mask) */}