|
56 | 56 | margin-bottom: 3rem; |
57 | 57 | } |
58 | 58 |
|
| 59 | + /* Wrapper handles the floating up and down motion */ |
| 60 | + .logo-wrapper { |
| 61 | + position: relative; |
| 62 | + width: 140px; |
| 63 | + height: 140px; |
| 64 | + margin: 0 auto 2.5rem; |
| 65 | + animation: float-pulse 5s ease-in-out infinite; |
| 66 | + transition: transform 0.3s ease; |
| 67 | + cursor: pointer; |
| 68 | + overflow: visible; |
| 69 | + } |
| 70 | + |
| 71 | + .logo-wrapper:hover { |
| 72 | + transform: scale(1.1); |
| 73 | + animation-play-state: paused; |
| 74 | + } |
| 75 | + |
| 76 | + /* Boundary specifically for the canvas so it doesn't block the page */ |
| 77 | + .canvas-boundary { |
| 78 | + position: absolute; |
| 79 | + top: -150px; left: -150px; |
| 80 | + width: 440px; height: 440px; |
| 81 | + pointer-events: none; |
| 82 | + overflow: hidden; |
| 83 | + z-index: 4; |
| 84 | + } |
| 85 | + |
| 86 | + /* Logo image handles the vibrant glowing box-shadow pulse */ |
59 | 87 | .hero img.logo { |
60 | 88 | width: 140px; |
61 | 89 | height: 140px; |
62 | 90 | border-radius: 20px; |
63 | 91 | border: 2px solid var(--clover-green); |
64 | | - margin-bottom: 2.5rem; |
| 92 | + margin-bottom: 0; |
65 | 93 | background-color: var(--card-bg); |
66 | | - animation: float-pulse 4s ease-in-out infinite; |
67 | | - transition: transform 0.3s ease, box-shadow 0.3s ease; |
| 94 | + position: absolute; |
| 95 | + top: 0; left: 0; |
| 96 | + z-index: 1; |
| 97 | + animation: glow-pulse 5s ease-in-out infinite; |
| 98 | + transition: box-shadow 0.3s ease; |
68 | 99 | } |
69 | 100 |
|
70 | | - .hero img.logo:hover { |
71 | | - transform: scale(1.1); |
72 | | - animation-play-state: paused; |
| 101 | + .logo-wrapper:hover img.logo { |
73 | 102 | box-shadow: 0 0 40px 5px rgba(46, 160, 67, 0.8), 0 0 80px 10px rgba(46, 160, 67, 0.4); |
74 | 103 | } |
75 | 104 |
|
| 105 | + /* Up and down floating motion */ |
76 | 106 | @keyframes float-pulse { |
| 107 | + 0% { transform: translateY(0); } |
| 108 | + 50% { transform: translateY(-10px); } |
| 109 | + 100% { transform: translateY(0); } |
| 110 | + } |
| 111 | + |
| 112 | + /* Vibrant glowing box-shadow pulse */ |
| 113 | + @keyframes glow-pulse { |
77 | 114 | 0% { |
78 | | - transform: translateY(0); |
79 | 115 | box-shadow: 0 5px 15px rgba(46, 160, 67, 0.3), 0 0 20px rgba(46, 160, 67, 0.2); |
80 | 116 | } |
81 | 117 | 50% { |
82 | | - transform: translateY(-10px); |
83 | 118 | box-shadow: 0 20px 30px rgba(46, 160, 67, 0.5), 0 0 40px 5px rgba(46, 160, 67, 0.6); |
84 | 119 | filter: brightness(1.2); |
85 | 120 | } |
86 | 121 | 100% { |
87 | | - transform: translateY(0); |
88 | 122 | box-shadow: 0 5px 15px rgba(46, 160, 67, 0.3), 0 0 20px rgba(46, 160, 67, 0.2); |
89 | 123 | } |
90 | 124 | } |
91 | 125 |
|
| 126 | + /* ORBITING LIGHT FRAME ANIMATION (SVG) */ |
| 127 | + .orbit-light { |
| 128 | + position: absolute; |
| 129 | + top: 0; left: 0; |
| 130 | + width: 140px; |
| 131 | + height: 140px; |
| 132 | + z-index: 2; |
| 133 | + pointer-events: none; |
| 134 | + overflow: visible; |
| 135 | + } |
| 136 | + |
| 137 | + .orbit-light rect { |
| 138 | + fill: none; |
| 139 | + stroke: #00ff00; |
| 140 | + stroke-width: 2.5; |
| 141 | + stroke-linecap: round; |
| 142 | + stroke-dasharray: 50 477; |
| 143 | + animation: orbit-frame 4s linear infinite; |
| 144 | + filter: drop-shadow(0 0 5px #00ff00) drop-shadow(0 0 10px #2ea043) drop-shadow(0 0 15px #2ea043); |
| 145 | + } |
| 146 | + |
| 147 | + @keyframes orbit-frame { |
| 148 | + to { |
| 149 | + stroke-dashoffset: -527; |
| 150 | + } |
| 151 | + } |
| 152 | + |
| 153 | + /* Canvas for Explosion */ |
| 154 | + #fx-canvas { |
| 155 | + display: block; |
| 156 | + background-color: transparent; |
| 157 | + width: 100%; |
| 158 | + height: 100%; |
| 159 | + } |
| 160 | + |
92 | 161 | .hero h1 { |
93 | 162 | font-size: 2.5rem; |
94 | 163 | background: linear-gradient(45deg, var(--text-color), var(--clover-green)); |
|
215 | 284 | font-size: 0.95rem; |
216 | 285 | } |
217 | 286 |
|
| 287 | + /* Spoiler Styling */ |
| 288 | + .dev-spoiler { |
| 289 | + background-color: var(--card-bg); |
| 290 | + border: 1px solid var(--border-color); |
| 291 | + border-radius: 8px; |
| 292 | + padding: 1rem 1.5rem; |
| 293 | + margin-top: 1.5rem; |
| 294 | + } |
| 295 | + |
| 296 | + .dev-spoiler summary { |
| 297 | + cursor: pointer; |
| 298 | + font-weight: 600; |
| 299 | + color: var(--text-color); |
| 300 | + display: flex; |
| 301 | + align-items: center; |
| 302 | + list-style: none; /* Remove default arrow */ |
| 303 | + transition: color 0.2s; |
| 304 | + } |
| 305 | + |
| 306 | + .dev-spoiler summary::-webkit-details-marker { |
| 307 | + display: none; /* Remove default arrow in Safari/Chrome */ |
| 308 | + } |
| 309 | + |
| 310 | + .dev-spoiler summary:hover { |
| 311 | + color: var(--accent-color); |
| 312 | + } |
| 313 | + |
| 314 | + .dev-spoiler summary .arrow { |
| 315 | + margin-right: 0.75rem; |
| 316 | + display: inline-block; |
| 317 | + transition: transform 0.2s ease; |
| 318 | + color: var(--clover-green); |
| 319 | + font-size: 1.2rem; |
| 320 | + } |
| 321 | + |
| 322 | + .dev-spoiler[open] summary .arrow { |
| 323 | + transform: rotate(90deg); /* Rotate arrow when open */ |
| 324 | + } |
| 325 | + |
| 326 | + /* Green Rounded Square Button Style for the Spoiler Note */ |
| 327 | + .dev-spoiler .spoiler-note { |
| 328 | + margin-left: auto; |
| 329 | + background-color: var(--accent-color); |
| 330 | + color: #ffffff; |
| 331 | + padding: 0.4rem 1rem; |
| 332 | + border-radius: 8px; /* Rounded square shape */ |
| 333 | + font-size: 0.85rem; |
| 334 | + font-weight: 600; |
| 335 | + text-transform: uppercase; |
| 336 | + letter-spacing: 0.5px; |
| 337 | + box-shadow: 0 0 10px rgba(46, 160, 67, 0.4); |
| 338 | + transition: background-color 0.2s, transform 0.2s; |
| 339 | + } |
| 340 | + |
| 341 | + .dev-spoiler summary:hover .spoiler-note { |
| 342 | + background-color: var(--accent-hover); |
| 343 | + transform: scale(1.05); |
| 344 | + } |
| 345 | + |
218 | 346 | /* Developers Grid */ |
219 | 347 | .devs-grid { |
220 | 348 | display: grid; |
221 | 349 | grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); |
222 | 350 | gap: 1rem; |
| 351 | + margin-top: 1.5rem; |
| 352 | + border-top: 1px solid var(--border-color); |
| 353 | + padding-top: 1.5rem; |
223 | 354 | } |
224 | 355 |
|
225 | 356 | .dev-card { |
226 | | - background-color: var(--card-bg); |
| 357 | + background-color: var(--bg-color); |
227 | 358 | border: 1px solid var(--border-color); |
228 | 359 | border-radius: 8px; |
229 | 360 | padding: 1rem 0.5rem; |
|
418 | 549 |
|
419 | 550 | <!-- Hero Section --> |
420 | 551 | <div class="hero"> |
421 | | - <img src="https://raw.githubusercontent.com/CloverHackyColor/CloverBootloader/refs/heads/master/Logo/Clover-Logo-Default-256x256%401x.png" alt="Clover Bootloader Logo" class="logo"> |
| 552 | + <div class="logo-wrapper" id="logo-wrapper"> |
| 553 | + <!-- Boundary Box for Canvas --> |
| 554 | + <div class="canvas-boundary"> |
| 555 | + <canvas id="fx-canvas"></canvas> |
| 556 | + </div> |
| 557 | + <!-- SVG Light Orbiting Exactly on the Frame --> |
| 558 | + <svg class="orbit-light" viewBox="0 0 140 140" xmlns="http://www.w3.org/2000/svg"> |
| 559 | + <!-- x=1, y=1, width=138, height=138 centers the 2.5px stroke exactly on the 2px border --> |
| 560 | + <rect x="1" y="1" width="138" height="138" rx="19" ry="19" /> |
| 561 | + </svg> |
| 562 | + <img src="https://raw.githubusercontent.com/CloverHackyColor/CloverBootloader/refs/heads/master/Logo/Clover-Logo-Default-256x256%401x.png" alt="Clover Bootloader Logo" class="logo"> |
| 563 | + </div> |
422 | 564 | <h1>The Clover UEFI Bootloader</h1> |
423 | 565 | <p class="subtitle">A legacy of macOS booting, firmware emulation, and Hackintosh innovation.</p> |
424 | 566 |
|
@@ -492,9 +634,17 @@ <h3>Present - Active Maintenance</h3> |
492 | 634 | <h2 class="section-title">The Developers</h2> |
493 | 635 | <p class="section-text">Clover was created by Slice, with help from a dedicated community of contributors over the years.</p> |
494 | 636 |
|
495 | | - <div class="devs-grid" id="devs-grid"> |
496 | | - <!-- Developers injected here --> |
497 | | - </div> |
| 637 | + <!-- Spoiler Wrapper (Closed by default) --> |
| 638 | + <details class="dev-spoiler" id="dev-spoiler-container"> |
| 639 | + <summary> |
| 640 | + <span class="arrow">▶</span> |
| 641 | + Click to view all contributors |
| 642 | + <span class="spoiler-note">See Dev's names</span> |
| 643 | + </summary> |
| 644 | + <div class="devs-grid" id="devs-grid"> |
| 645 | + <!-- Developers injected here by JS --> |
| 646 | + </div> |
| 647 | + </details> |
498 | 648 | </div> |
499 | 649 |
|
500 | 650 | <!-- Credits Section --> |
@@ -573,6 +723,136 @@ <h2 class="section-title">Latest Releases</h2> |
573 | 723 | // Set current year |
574 | 724 | document.getElementById('year').textContent = new Date().getFullYear(); |
575 | 725 |
|
| 726 | + // --- LOGO EXPLOSION LOGIC (SINGLE EXPLOSION) --- |
| 727 | + const canvas = document.getElementById('fx-canvas'); |
| 728 | + const ctx = canvas.getContext('2d'); |
| 729 | + |
| 730 | + canvas.width = 440; |
| 731 | + canvas.height = 440; |
| 732 | + const cx = canvas.width / 2; |
| 733 | + const cy = canvas.height / 2; |
| 734 | + |
| 735 | + let particles = []; |
| 736 | + let glow = 0; |
| 737 | + let isAnimating = false; |
| 738 | + |
| 739 | + class Particle { |
| 740 | + constructor(type) { |
| 741 | + this.x = cx; |
| 742 | + this.y = cy; |
| 743 | + const angle = Math.random() * Math.PI * 2; |
| 744 | + const speed = Math.random() * 3 + 1; // Slower outward speed |
| 745 | + this.vx = Math.cos(angle) * speed; |
| 746 | + this.vy = Math.sin(angle) * speed; |
| 747 | + this.life = 1; |
| 748 | + this.decay = Math.random() * 0.008 + 0.004; // Slower decay (lasts longer) |
| 749 | + this.type = type; |
| 750 | + |
| 751 | + // Different sizes and colors based on type (Removed pure white) |
| 752 | + if (type === 'heart') { |
| 753 | + this.size = Math.random() * 6 + 4; |
| 754 | + this.color = ['#00ff00', '#2ea043', '#3fb950'][Math.floor(Math.random()*3)]; |
| 755 | + } else if (type === 'spark') { |
| 756 | + this.size = Math.random() * 8 + 4; |
| 757 | + this.color = ['#aaffd0', '#7affc0', '#00ff00'][Math.floor(Math.random()*3)]; |
| 758 | + } else { // 'dot' |
| 759 | + this.size = Math.random() * 3 + 1; |
| 760 | + this.color = '#3fb950'; |
| 761 | + } |
| 762 | + } |
| 763 | + update() { |
| 764 | + this.x += this.vx; |
| 765 | + this.y += this.vy; |
| 766 | + this.vx *= 0.98; // Air resistance |
| 767 | + this.vy *= 0.98; |
| 768 | + this.vy += 0.03; // Very slow gravity |
| 769 | + this.life -= this.decay; |
| 770 | + } |
| 771 | + draw() { |
| 772 | + const s = this.size * Math.max(0, this.life); |
| 773 | + ctx.globalAlpha = Math.max(0, this.life); |
| 774 | + ctx.fillStyle = this.color; |
| 775 | + ctx.shadowBlur = 15; |
| 776 | + ctx.shadowColor = this.color; |
| 777 | + |
| 778 | + if (this.type === 'heart') { |
| 779 | + // Draw a heart shape centered at x, y |
| 780 | + ctx.beginPath(); |
| 781 | + ctx.moveTo(this.x, this.y + s * 0.75); |
| 782 | + ctx.bezierCurveTo(this.x - s, this.y + s * 0.25, this.x - s, this.y - s * 0.5, this.x, this.y - s * 0.25); |
| 783 | + ctx.bezierCurveTo(this.x + s, this.y - s * 0.5, this.x + s, this.y + s * 0.25, this.x, this.y + s * 0.75); |
| 784 | + ctx.closePath(); |
| 785 | + ctx.fill(); |
| 786 | + } else if (this.type === 'spark') { |
| 787 | + // Draw a 4-point sparkle star centered at x, y |
| 788 | + ctx.beginPath(); |
| 789 | + ctx.moveTo(this.x, this.y - s); |
| 790 | + ctx.lineTo(this.x + s * 0.2, this.y - s * 0.2); |
| 791 | + ctx.lineTo(this.x + s, this.y); |
| 792 | + ctx.lineTo(this.x + s * 0.2, this.y + s * 0.2); |
| 793 | + ctx.lineTo(this.x, this.y + s); |
| 794 | + ctx.lineTo(this.x - s * 0.2, this.y + s * 0.2); |
| 795 | + ctx.lineTo(this.x - s, this.y); |
| 796 | + ctx.lineTo(this.x - s * 0.2, this.y - s * 0.2); |
| 797 | + ctx.closePath(); |
| 798 | + ctx.fill(); |
| 799 | + } else { |
| 800 | + // Draw a circle |
| 801 | + ctx.beginPath(); |
| 802 | + ctx.arc(this.x, this.y, s, 0, Math.PI * 2); |
| 803 | + ctx.fill(); |
| 804 | + } |
| 805 | + } |
| 806 | + } |
| 807 | + |
| 808 | + function triggerExplosion() { |
| 809 | + glow = 1; // Trigger green glow |
| 810 | + |
| 811 | + // Spawn a beautiful mix of hearts, sparks, and dots (FULL COUNT RESTORED) |
| 812 | + for(let i=0; i<60; i++) particles.push(new Particle('heart')); |
| 813 | + for(let i=0; i<80; i++) particles.push(new Particle('spark')); |
| 814 | + for(let i=0; i<40; i++) particles.push(new Particle('dot')); |
| 815 | + |
| 816 | + // Start the animation loop if it isn't already running |
| 817 | + if (!isAnimating) { |
| 818 | + isAnimating = true; |
| 819 | + animate(); |
| 820 | + } |
| 821 | + } |
| 822 | + |
| 823 | + function animate() { |
| 824 | + ctx.clearRect(0, 0, canvas.width, canvas.height); |
| 825 | + ctx.globalCompositeOperation = 'lighter'; // Additive glow blending |
| 826 | + |
| 827 | + // Draw Soft Radial Green Glow |
| 828 | + if (glow > 0) { |
| 829 | + ctx.globalAlpha = glow; |
| 830 | + const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, 150); |
| 831 | + grad.addColorStop(0, 'rgba(0, 255, 0, 0.9)'); |
| 832 | + grad.addColorStop(0.4, 'rgba(46, 160, 67, 0.5)'); |
| 833 | + grad.addColorStop(1, 'rgba(0, 0, 0, 0)'); |
| 834 | + ctx.fillStyle = grad; |
| 835 | + ctx.fillRect(0, 0, canvas.width, canvas.height); |
| 836 | + glow -= 0.04; |
| 837 | + } |
| 838 | + |
| 839 | + // Draw Particles |
| 840 | + particles = particles.filter(p => p.life > 0); |
| 841 | + particles.forEach(p => { p.update(); p.draw(); }); |
| 842 | + |
| 843 | + if (particles.length > 0 || glow > 0) { |
| 844 | + requestAnimationFrame(animate); |
| 845 | + } else { |
| 846 | + ctx.clearRect(0, 0, canvas.width, canvas.height); |
| 847 | + isAnimating = false; // Animation finished |
| 848 | + } |
| 849 | + } |
| 850 | + |
| 851 | + // Trigger the single explosion after one full turn (4 seconds) |
| 852 | + setTimeout(() => { |
| 853 | + triggerExplosion(); |
| 854 | + }, 4000); |
| 855 | + |
576 | 856 | // --- DATA ARRAYS --- |
577 | 857 |
|
578 | 858 | const developers = [ |
|
0 commit comments