mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-13 12:36:15 -08:00
chore(website): add support section with SVG illustration and footer watermark
- Introduced a new SVG illustration for supporting open-source software. - Added a footer watermark image to enhance the visual design of the footer. - Created a new SupportSection component to encourage user contributions with links to GitHub Stars, GitHub Sponsors, and Ko-fi. - Updated the Hero component to include a mascot image and social links for GitHub, Telegram, and Ko-fi. - Enhanced the FeatureGrid and Footer components with improved styling and layout adjustments. - Updated blog post metadata for better formatting and added a disclaimer in the SupportSection. - Improved global CSS styles for buttons and animations to create a more engaging user experience. Entire-Checkpoint: b7a1c2f08179
This commit is contained in:
1 parent
59581bd890
commit
d19ae82e72
15 files changed
+806
-29
No files matched your search
@@ -0,0 +1,95 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600" viewBox="0 0 600 600" role="img" aria-label="Blog corner playlist signal mark">
|
||||
<defs>
|
||||
<linearGradient id="tealStroke" x1="360" y1="120" x2="600" y2="420" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#20a8a8" stop-opacity="0.78"/>
|
||||
<stop offset="1" stop-color="#20a8a8" stop-opacity="0.16"/>
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient id="neutralStroke" x1="340" y1="140" x2="600" y2="460" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c7ced2" stop-opacity="0.14"/>
|
||||
<stop offset="1" stop-color="#3c474a" stop-opacity="0.18"/>
|
||||
</linearGradient>
|
||||
|
||||
<filter id="microGlow" x="-40%" y="-40%" width="180%" height="180%" color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="1.25" result="b"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="b"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- Weighted to top-right; airy; rotates well -->
|
||||
<g id="layer-motif" filter="url(#microGlow)" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
<!-- Hint of a "player/playlist card" (no UI text, just geometry) -->
|
||||
<g id="playlist-card">
|
||||
<path d="M410 128
|
||||
C402 128, 396 134, 396 142
|
||||
L396 242
|
||||
C396 250, 402 256, 410 256
|
||||
L544 256
|
||||
C552 256, 558 250, 558 242
|
||||
L558 142
|
||||
C558 134, 552 128, 544 128
|
||||
Z"
|
||||
stroke="url(#neutralStroke)" stroke-width="2.2" stroke-opacity="0.7"/>
|
||||
|
||||
<!-- Minimal "list rows" (very low contrast) -->
|
||||
<path d="M422 166 H534" stroke="#c7ced2" stroke-opacity="0.10" stroke-width="2"/>
|
||||
<path d="M422 192 H514" stroke="#c7ced2" stroke-opacity="0.08" stroke-width="2"/>
|
||||
<path d="M422 218 H528" stroke="#c7ced2" stroke-opacity="0.09" stroke-width="2"/>
|
||||
|
||||
<!-- A small play-indicator wedge, abstract -->
|
||||
<path d="M416 156 L416 176 L432 166 Z"
|
||||
stroke="#20a8a8" stroke-opacity="0.00" fill="#20a8a8" fill-opacity="0.12"/>
|
||||
</g>
|
||||
|
||||
<!-- "Antenna pin" (more like a signal marker than a tower) -->
|
||||
<g id="signal-pin">
|
||||
<path d="M520 270 L520 318" stroke="url(#tealStroke)" stroke-width="3" stroke-opacity="0.45"/>
|
||||
<circle cx="520" cy="258" r="6" fill="#20a8a8" fill-opacity="0.26"/>
|
||||
<path d="M505 328 L520 318 L535 328" stroke="#3c474a" stroke-opacity="0.30" stroke-width="5"/>
|
||||
<path d="M505 328 L520 318 L535 328" stroke="#20a8a8" stroke-opacity="0.12" stroke-width="2"/>
|
||||
</g>
|
||||
|
||||
<!-- Signal sweep arcs (corner-friendly) -->
|
||||
<g id="signal-sweep">
|
||||
<path d="M470 86
|
||||
C545 120, 590 190, 598 278"
|
||||
stroke="url(#tealStroke)" stroke-width="2.6" stroke-opacity="0.34"/>
|
||||
<path d="M492 112
|
||||
C548 140, 580 196, 586 266"
|
||||
stroke="#c7ced2" stroke-width="2" stroke-opacity="0.10"/>
|
||||
<path d="M448 64
|
||||
C545 106, 600 196, 608 312"
|
||||
stroke="#20a8a8" stroke-width="2" stroke-opacity="0.16"/>
|
||||
</g>
|
||||
|
||||
<!-- One thin connector line (ties card → pin) -->
|
||||
<g id="connector">
|
||||
<path d="M468 252 C480 270, 495 288, 520 318"
|
||||
stroke="#3c474a" stroke-opacity="0.28" stroke-width="2"/>
|
||||
<path d="M468 252 C480 270, 495 288, 520 318"
|
||||
stroke="#20a8a8" stroke-opacity="0.09" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- Sparse “stars” / points -->
|
||||
<g id="points" fill="none">
|
||||
<circle cx="576" cy="110" r="2.1" fill="#20a8a8" fill-opacity="0.18"/>
|
||||
<circle cx="548" cy="70" r="1.6" fill="#c7ced2" fill-opacity="0.10"/>
|
||||
<circle cx="592" cy="170" r="1.7" fill="#c7ced2" fill-opacity="0.09"/>
|
||||
<circle cx="560" cy="236" r="1.8" fill="#20a8a8" fill-opacity="0.13"/>
|
||||
<circle cx="430" cy="286" r="1.6" fill="#c7ced2" fill-opacity="0.08"/>
|
||||
|
||||
<!-- Tiny diamond point -->
|
||||
<path d="M548 312 l6 6 l-6 6 l-6-6 Z" fill="#20a8a8" fill-opacity="0.08"/>
|
||||
</g>
|
||||
|
||||
<!-- Subtle corner framing stroke (very airy, helps “corner” feel) -->
|
||||
<g id="corner-frame">
|
||||
<path d="M600 88 C560 92, 540 104, 520 132" stroke="#3c474a" stroke-opacity="0.16" stroke-width="2"/>
|
||||
<path d="M600 120 C566 124, 546 136, 532 156" stroke="#20a8a8" stroke-opacity="0.08" stroke-width="2"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
@@ -0,0 +1,50 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="120" viewBox="0 0 400 120" role="img" aria-label="Footer broadcast pattern strip light (tileable)">
|
||||
<defs>
|
||||
<filter id="microGlow" x="-40%" y="-40%" width="180%" height="180%" color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="0.8" result="b"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="b"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- Very minimal rails -->
|
||||
<g id="layer-rails" fill="none" stroke-linecap="round">
|
||||
<path d="M0 24 H400" stroke="#3c474a" stroke-opacity="0.14" stroke-width="1"/>
|
||||
<path d="M0 96 H400" stroke="#3c474a" stroke-opacity="0.12" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- Few ticks -->
|
||||
<g id="layer-ticks" fill="none" stroke-linecap="round">
|
||||
<g stroke="#c7ced2" stroke-opacity="0.07" stroke-width="1">
|
||||
<path d="M0 24 V32"/><path d="M80 24 V32"/><path d="M160 24 V32"/><path d="M240 24 V32"/><path d="M320 24 V32"/><path d="M400 24 V32"/>
|
||||
<path d="M40 96 V88"/><path d="M200 96 V88"/><path d="M360 96 V88"/>
|
||||
</g>
|
||||
|
||||
<!-- Single tiny wave notch -->
|
||||
<path d="M170 62 c8 -6 16 -6 24 0 c8 6 16 6 24 0"
|
||||
stroke="#20a8a8" stroke-opacity="0.07" stroke-width="1.5" fill="none" filter="url(#microGlow)"/>
|
||||
</g>
|
||||
|
||||
<!-- One small dial hint -->
|
||||
<g id="layer-dial" fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#microGlow)">
|
||||
<g transform="translate(340 60)">
|
||||
<circle cx="0" cy="0" r="9" stroke="#3c474a" stroke-opacity="0.16" stroke-width="1.2"/>
|
||||
<path d="M0 -9 V-12" stroke="#c7ced2" stroke-opacity="0.07" stroke-width="1"/>
|
||||
<circle cx="0" cy="0" r="2" fill="#20a8a8" fill-opacity="0.07"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Short dashed connector -->
|
||||
<g id="layer-connector" fill="none" stroke-linecap="round">
|
||||
<path d="M70 60 H130" stroke="#c7ced2" stroke-opacity="0.06" stroke-width="1" stroke-dasharray="3 7"/>
|
||||
</g>
|
||||
|
||||
<!-- Sparse dots -->
|
||||
<g id="layer-dots">
|
||||
<circle cx="220" cy="24" r="1.0" fill="#20a8a8" fill-opacity="0.06"/>
|
||||
<circle cx="120" cy="96" r="1.0" fill="#c7ced2" fill-opacity="0.05"/>
|
||||
<circle cx="280" cy="78" r="0.9" fill="#3c474a" fill-opacity="0.12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,158 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="800" viewBox="0 0 1920 800" role="img" aria-label="Ambient broadcast waves background motif">
|
||||
<defs>
|
||||
<!-- Core palette -->
|
||||
<linearGradient id="tealFade" x1="1400" y1="80" x2="780" y2="720" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#20a8a8" stop-opacity="0.22"/>
|
||||
<stop offset="0.55" stop-color="#20a8a8" stop-opacity="0.07"/>
|
||||
<stop offset="1" stop-color="#20a8a8" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
|
||||
<radialGradient id="ringFade" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(1535 400) rotate(90) scale(420 740)">
|
||||
<stop offset="0" stop-color="#20a8a8" stop-opacity="0.10"/>
|
||||
<stop offset="0.6" stop-color="#20a8a8" stop-opacity="0.04"/>
|
||||
<stop offset="1" stop-color="#20a8a8" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
|
||||
<linearGradient id="scanFade" x1="0" y1="0" x2="0" y2="800" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c7ced2" stop-opacity="0.00"/>
|
||||
<stop offset="0.45" stop-color="#c7ced2" stop-opacity="0.06"/>
|
||||
<stop offset="1" stop-color="#c7ced2" stop-opacity="0.00"/>
|
||||
</linearGradient>
|
||||
|
||||
<!-- Subtle glow (kept restrained for 5–20% overall opacity usage) -->
|
||||
<filter id="softGlow" x="-30%" y="-30%" width="160%" height="160%" color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="2.2" result="blur"/>
|
||||
<feColorMatrix in="blur" type="matrix"
|
||||
values="1 0 0 0 0
|
||||
0 1 0 0 0
|
||||
0 0 1 0 0
|
||||
0 0 0 0.55 0" result="glow"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="glow"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<filter id="microGlow" x="-40%" y="-40%" width="180%" height="180%" color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="1.1" result="b"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="b"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- Transparent background: no rect fill -->
|
||||
|
||||
<!-- Layer: scanline bands (subtle, keeps text readability) -->
|
||||
<g id="layer-scanlines" opacity="0.55">
|
||||
<!-- Wide soft bands -->
|
||||
<path d="M0 158H1920v38H0z" fill="url(#scanFade)" opacity="0.22"/>
|
||||
<path d="M0 298H1920v26H0z" fill="url(#scanFade)" opacity="0.16"/>
|
||||
<path d="M0 460H1920v30H0z" fill="url(#scanFade)" opacity="0.14"/>
|
||||
<path d="M0 610H1920v42H0z" fill="url(#scanFade)" opacity="0.18"/>
|
||||
|
||||
<!-- Thin scanline-inspired hairlines -->
|
||||
<g opacity="0.16" fill="#c7ced2">
|
||||
<rect x="0" y="214" width="1920" height="1"/>
|
||||
<rect x="0" y="238" width="1920" height="1"/>
|
||||
<rect x="0" y="512" width="1920" height="1"/>
|
||||
<rect x="0" y="536" width="1920" height="1"/>
|
||||
<rect x="0" y="684" width="1920" height="1"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Layer: broadcast wave arcs (asymmetric weight on right) -->
|
||||
<g id="layer-waves" filter="url(#softGlow)">
|
||||
<g fill="none" stroke="url(#tealFade)" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- Primary sweeping arcs -->
|
||||
<path d="M1040 120
|
||||
C1320 90, 1560 150, 1750 280
|
||||
C1900 382, 1940 520, 1815 640
|
||||
C1690 760, 1450 780, 1240 710"
|
||||
stroke-width="2.2" opacity="0.62"/>
|
||||
<path d="M980 170
|
||||
C1250 130, 1500 190, 1700 318
|
||||
C1860 420, 1895 540, 1782 642
|
||||
C1668 745, 1450 760, 1260 704"
|
||||
stroke-width="1.6" opacity="0.48"/>
|
||||
<path d="M1140 70
|
||||
C1440 35, 1720 120, 1890 290
|
||||
C2020 420, 1990 585, 1840 690
|
||||
C1690 796, 1405 805, 1185 710"
|
||||
stroke-width="1.2" opacity="0.34"/>
|
||||
|
||||
<!-- Secondary inner arcs for layered depth -->
|
||||
<path d="M1245 235
|
||||
C1440 205, 1605 255, 1730 350
|
||||
C1830 426, 1850 520, 1770 595
|
||||
C1690 670, 1520 682, 1375 630"
|
||||
stroke-width="1.4" opacity="0.42"/>
|
||||
<path d="M1315 300
|
||||
C1490 280, 1625 330, 1715 402
|
||||
C1795 466, 1800 532, 1735 585
|
||||
C1670 638, 1535 640, 1425 604"
|
||||
stroke-width="1.1" opacity="0.30"/>
|
||||
</g>
|
||||
|
||||
<!-- Low-contrast charcoal support curve (adds CRT geometry without stealing focus) -->
|
||||
<path id="support-curve"
|
||||
d="M720 690
|
||||
C980 610, 1180 560, 1400 520
|
||||
C1560 492, 1730 480, 1920 490"
|
||||
fill="none" stroke="#0c1114" stroke-opacity="0.35" stroke-width="2" stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
<!-- Layer: radial rings (right side, very restrained) -->
|
||||
<g id="layer-rings" opacity="0.9">
|
||||
<g fill="none" stroke="url(#ringFade)" stroke-width="1.2" filter="url(#microGlow)">
|
||||
<circle cx="1535" cy="400" r="118" opacity="0.36"/>
|
||||
<circle cx="1535" cy="400" r="178" opacity="0.26"/>
|
||||
<circle cx="1535" cy="400" r="248" opacity="0.18"/>
|
||||
<circle cx="1535" cy="400" r="320" opacity="0.12"/>
|
||||
</g>
|
||||
|
||||
<!-- Offset subtle ring cluster for asymmetry -->
|
||||
<g fill="none" stroke="#20a8a8" stroke-opacity="0.10" stroke-width="1" filter="url(#microGlow)">
|
||||
<ellipse cx="1705" cy="290" rx="92" ry="62" opacity="0.35"/>
|
||||
<ellipse cx="1705" cy="290" rx="140" ry="96" opacity="0.22"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Layer: nodes & dots (kept sparse) -->
|
||||
<g id="layer-nodes" filter="url(#microGlow)">
|
||||
<!-- Main node cluster -->
|
||||
<g>
|
||||
<circle cx="1688" cy="402" r="3.2" fill="#20a8a8" fill-opacity="0.38"/>
|
||||
<circle cx="1622" cy="520" r="2.6" fill="#20a8a8" fill-opacity="0.28"/>
|
||||
<circle cx="1748" cy="312" r="2.4" fill="#20a8a8" fill-opacity="0.24"/>
|
||||
<circle cx="1586" cy="350" r="1.9" fill="#c7ced2" fill-opacity="0.18"/>
|
||||
<circle cx="1765" cy="520" r="1.8" fill="#c7ced2" fill-opacity="0.14"/>
|
||||
</g>
|
||||
|
||||
<!-- A few distant dots to balance without clutter -->
|
||||
<g opacity="0.55">
|
||||
<circle cx="1140" cy="250" r="1.6" fill="#20a8a8" fill-opacity="0.16"/>
|
||||
<circle cx="980" cy="560" r="1.5" fill="#c7ced2" fill-opacity="0.10"/>
|
||||
<circle cx="860" cy="340" r="1.4" fill="#20a8a8" fill-opacity="0.12"/>
|
||||
</g>
|
||||
|
||||
<!-- Thin connector hints (barely there) -->
|
||||
<g fill="none" stroke="#20a8a8" stroke-opacity="0.10" stroke-width="1" stroke-linecap="round">
|
||||
<path d="M1688 402 L1622 520" opacity="0.35"/>
|
||||
<path d="M1688 402 L1748 312" opacity="0.25"/>
|
||||
<path d="M1622 520 L1765 520" opacity="0.18"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Layer: left-side negative-space soft vignette (improves text readability) -->
|
||||
<g id="layer-negative-space">
|
||||
<linearGradient id="leftVignette" x1="0" y1="0" x2="700" y2="0" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#0b0f12" stop-opacity="0.26"/>
|
||||
<stop offset="0.75" stop-color="#0b0f12" stop-opacity="0.10"/>
|
||||
<stop offset="1" stop-color="#0b0f12" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<rect x="0" y="0" width="760" height="800" fill="url(#leftVignette)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
@@ -0,0 +1,56 @@
|
||||
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>support-open-source-signal-isometric</title>
|
||||
<desc>Isometric architectural core representing the structural support of open-source software.</desc>
|
||||
|
||||
<!-- Central Isometric Core (The Engine) -->
|
||||
<g id="isometric-core" transform="translate(400, 420)">
|
||||
<!-- Bottom Plate -->
|
||||
<path d="M-120 0 L0 60 L120 0 L0 -60 Z" fill="#1a1f21" stroke="#3c474a" stroke-width="2" />
|
||||
|
||||
<!-- Vertical Pillars (Structure) -->
|
||||
<g stroke="#3c474a" stroke-width="2" stroke-linecap="round">
|
||||
<path d="M-80 -20 V-100" />
|
||||
<path d="M80 -20 V-100" />
|
||||
<path d="M0 20 V-60" />
|
||||
</g>
|
||||
|
||||
<!-- The Floating Heart-Core (The Pulse) -->
|
||||
<g id="core-pulse" transform="translate(0, -90)">
|
||||
<!-- Isometric Cube/Diamond Representation -->
|
||||
<path d="M-40 0 L0 20 L40 0 L0 -20 Z" fill="#20a8a8" fill-opacity="0.2" stroke="#20a8a8" stroke-width="3">
|
||||
<animate attributeName="fill-opacity" values="0.2;0.5;0.2" dur="3s" repeatCount="indefinite" />
|
||||
</path>
|
||||
<path d="M-40 0 V30 L0 50 V20 Z" fill="#20a8a8" fill-opacity="0.1" stroke="#20a8a8" stroke-width="2" />
|
||||
<path d="M40 0 V30 L0 50 V20 Z" fill="#20a8a8" fill-opacity="0.05" stroke="#20a8a8" stroke-width="2" />
|
||||
|
||||
<!-- Internal Heart Motif (Simplified for Isometric) -->
|
||||
<path d="M-10 -5 Q0 -15 10 -5 L0 10 Z" fill="#4fd1d1" opacity="0.8">
|
||||
<animate attributeName="opacity" values="0.8;0.3;0.8" dur="1.5s" repeatCount="indefinite" />
|
||||
</path>
|
||||
</g>
|
||||
|
||||
<!-- Converging "Support" Streams -->
|
||||
<g id="data-streams" stroke="#20a8a8" stroke-width="1.5" opacity="0.4">
|
||||
<path d="M-200 -100 L-100 -50" stroke-dasharray="4 8" />
|
||||
<path d="M200 -100 L100 -50" stroke-dasharray="4 8" />
|
||||
<path d="M-150 100 L-80 50" />
|
||||
<path d="M150 100 L80 50" />
|
||||
|
||||
<!-- Stream End Nodes -->
|
||||
<circle cx="-100" cy="-50" r="3" fill="#20a8a8" />
|
||||
<circle cx="100" cy="-50" r="3" fill="#20a8a8" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Framing Elements -->
|
||||
<g id="frames" stroke="#3c474a" stroke-width="1" opacity="0.2">
|
||||
<circle cx="400" cy="400" r="280" />
|
||||
<path d="M200 200 L150 150 M600 200 L650 150 M200 600 L150 650 M600 600 L650 650" />
|
||||
</g>
|
||||
|
||||
<!-- Accent Highlights -->
|
||||
<circle cx="400" cy="330" r="4" fill="#4fd1d1" opacity="0.6">
|
||||
<animate attributeName="r" values="4;6;4" dur="3s" repeatCount="indefinite" />
|
||||
</circle>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 266 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 573 KiB |
@@ -69,7 +69,7 @@ const carouselFeatures = [
|
||||
<section id="features" class="relative py-28">
|
||||
<hr class="section-divider mb-28" />
|
||||
|
||||
<div class="mx-auto max-w-6xl px-6">
|
||||
<div class="relative z-10 mx-auto max-w-6xl px-6">
|
||||
<!-- Editorial header: left-aligned -->
|
||||
<div class="max-w-xl">
|
||||
<span class="font-mono text-xs uppercase tracking-[0.2em] text-accent-500">
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
import footerWatermark from '../assets/footer-watermark.png';
|
||||
|
||||
const socialLinks = [
|
||||
{
|
||||
label: 'GitHub',
|
||||
@@ -13,7 +15,7 @@ const socialLinks = [
|
||||
{
|
||||
label: 'Bluesky',
|
||||
href: 'https://bsky.app/profile/4gray.bsky.social',
|
||||
icon: 'M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm3.5 14.5c-1.5 0-2.7-.8-3.5-2-.8 1.2-2 2-3.5 2C6.6 16.5 5 14.9 5 13c0-3 3.5-6.5 7-9.5 3.5 3 7 6.5 7 9.5 0 1.9-1.6 3.5-3.5 3.5z',
|
||||
icon: 'M13.202 10.857c2.752 2.066 5.711 6.254 6.798 8.502 1.087-2.248 4.046-6.436 6.798-8.502 1.985-1.49 5.202-2.644 5.202 1.026 0 .733-.42 6.157-.667 7.038-.857 3.061-3.978 3.842-6.755 3.37 4.854.826 6.089 3.562 3.422 6.299-5.065 5.197-7.279-1.304-7.847-2.97-.104-.305-.153-.448-.153-.327 0-.121-.049.021-.153.327-.567 1.666-2.782 8.166-7.847 2.97-2.667-2.736-1.432-5.473 3.422-6.299-2.777.473-5.899-.308-6.755-3.37-.246-.881-.667-6.305-.667-7.038 0-3.67 3.217-2.517 5.202-1.026Z',
|
||||
},
|
||||
{
|
||||
label: 'Sponsor',
|
||||
@@ -23,8 +25,21 @@ const socialLinks = [
|
||||
];
|
||||
---
|
||||
|
||||
<footer class="border-t border-dashed border-surface-700/60">
|
||||
<div class="mx-auto max-w-6xl px-6 py-16">
|
||||
<footer class="relative overflow-hidden border-t border-dashed border-surface-700/60">
|
||||
<div class="pointer-events-none absolute inset-0">
|
||||
<div class="absolute -bottom-32 -right-16 h-[28rem] w-[28rem] rounded-full bg-accent-500/[0.07] blur-3xl"></div>
|
||||
<div class="absolute -bottom-24 right-2 h-[23rem] w-[23rem]">
|
||||
<img
|
||||
src={footerWatermark.src}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="footer-watermark h-full w-full object-contain opacity-[0.075] grayscale"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative z-10 mx-auto max-w-6xl px-6 py-16">
|
||||
<div class="flex flex-col items-center gap-10 md:flex-row md:justify-between">
|
||||
<!-- Logo & description -->
|
||||
<div class="text-center md:text-left">
|
||||
@@ -71,3 +86,29 @@ const socialLinks = [
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
.footer-watermark {
|
||||
transform: rotate(-14deg) scale(1.06);
|
||||
filter: drop-shadow(0 18px 30px rgba(0, 0, 0, 0.45));
|
||||
mix-blend-mode: screen;
|
||||
animation: footerMarkFloat 11s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes footerMarkFloat {
|
||||
0%, 100% {
|
||||
transform: rotate(-14deg) translate3d(0, 0, 0) scale(1.06);
|
||||
opacity: 0.065;
|
||||
}
|
||||
50% {
|
||||
transform: rotate(-11deg) translate3d(-12px, -10px, 0) scale(1.1);
|
||||
opacity: 0.09;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.footer-watermark {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,57 @@
|
||||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import heroImg from '../assets/screenshots/hero-dark.png';
|
||||
import mascotImg from '../assets/illustrations/iptvnator-1-mascot.png';
|
||||
|
||||
const heroSocialLinks = [
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/4gray/iptvnator',
|
||||
icon: 'M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z',
|
||||
},
|
||||
{
|
||||
label: 'Telegram',
|
||||
href: 'https://t.me/iptvnator',
|
||||
icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69.01-.03.01-.14-.07-.2-.08-.06-.19-.04-.27-.02-.12.03-1.99 1.27-5.62 3.72-.53.36-1.01.54-1.44.53-.47-.01-1.38-.27-2.06-.49-.83-.27-1.49-.42-1.43-.88.03-.24.37-.49 1.02-.74 3.99-1.74 6.65-2.89 7.99-3.44 3.81-1.58 4.6-1.86 5.12-1.87.11 0 .37.03.54.17.14.12.18.28.2.45-.01.06.01.24 0 .38z',
|
||||
},
|
||||
{
|
||||
label: 'GitHub Sponsors',
|
||||
href: 'https://github.com/sponsors/4gray',
|
||||
icon: 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z',
|
||||
},
|
||||
{
|
||||
label: 'Ko-fi',
|
||||
href: 'https://ko-fi.com/4gray',
|
||||
icon: 'M4 5h12a4 4 0 0 1 0 8h-1v2.5A4.5 4.5 0 0 1 10.5 20h-1A4.5 4.5 0 0 1 5 15.5V13H4a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2Zm11 6h1a2 2 0 0 0 0-4h-1v4Z',
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<section class="relative overflow-hidden pt-36 pb-24 sm:pt-44 sm:pb-32">
|
||||
<!-- Ambient glow -->
|
||||
<div class="pointer-events-none absolute top-0 left-1/2 h-[600px] w-[900px] -translate-x-1/2 -translate-y-1/3 rounded-full bg-accent-500/[0.06] blur-[120px]"></div>
|
||||
<div class="pointer-events-none absolute inset-x-0 top-8 z-0 overflow-hidden opacity-35 mix-blend-screen">
|
||||
<img
|
||||
src="/iptvnator/illustrations/hero-ambient-broadcast-waves.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx-auto h-[18rem] w-full min-w-[1100px] object-cover md:h-[22rem] lg:h-[26rem]"
|
||||
loading="eager"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="relative mx-auto max-w-6xl px-6">
|
||||
<div class="pointer-events-none absolute -top-4 -right-12 z-0 hidden w-[18rem] opacity-75 blur-[0.2px] md:block lg:w-[22rem] xl:w-[25rem]">
|
||||
<div class="absolute inset-0 rounded-full bg-accent-500/[0.16] blur-3xl"></div>
|
||||
<Image
|
||||
src={mascotImg}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
width={520}
|
||||
class="relative w-full object-contain saturate-110 animate-glow-pulse"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Top section: editorial intro -->
|
||||
<div class="mx-auto max-w-3xl text-center">
|
||||
<!-- Mono label -->
|
||||
@@ -90,6 +134,24 @@ import heroImg from '../assets/screenshots/hero-dark.png';
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex flex-wrap items-center justify-center gap-2.5">
|
||||
{heroSocialLinks.map((link) => (
|
||||
<a
|
||||
href={link.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="group inline-flex items-center gap-2 rounded-full border border-dashed border-surface-700/70 bg-surface-900/40 px-3 py-1.5 text-[11px] font-mono uppercase tracking-[0.08em] text-surface-400 transition-all duration-300 hover:border-accent-500/40 hover:bg-accent-500/[0.06] hover:text-accent-300"
|
||||
aria-label={link.label}
|
||||
title={link.label}
|
||||
>
|
||||
<svg class="h-3.5 w-3.5 text-surface-500 transition-colors duration-300 group-hover:text-accent-300" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d={link.icon} />
|
||||
</svg>
|
||||
<span>{link.label}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hero screenshot with window chrome frame -->
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
const supportLinks = [
|
||||
{
|
||||
label: 'Give a Star',
|
||||
href: 'https://github.com/4gray/iptvnator/stargazers',
|
||||
description: 'The fastest way to help visibility',
|
||||
icon: 'M12 2.5l2.94 5.96 6.58.96-4.76 4.64 1.12 6.56L12 17.53 6.12 20.62l1.12-6.56-4.76-4.64 6.58-.96L12 2.5z',
|
||||
},
|
||||
{
|
||||
label: 'GitHub Sponsors',
|
||||
href: 'https://github.com/sponsors/4gray',
|
||||
description: 'Monthly support keeps development steady',
|
||||
icon: 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z',
|
||||
},
|
||||
{
|
||||
label: 'Ko-fi',
|
||||
href: 'https://ko-fi.com/4gray',
|
||||
description: 'One-time donations are always appreciated',
|
||||
icon: 'M3 6.5A2.5 2.5 0 0 1 5.5 4h10A2.5 2.5 0 0 1 18 6.5V8h1.5A2.5 2.5 0 0 1 22 10.5v1A2.5 2.5 0 0 1 19.5 14H18v1.5A4.5 4.5 0 0 1 13.5 20h-6A4.5 4.5 0 0 1 3 15.5v-9zm15 5.5h1.5a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5H18V12z',
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<section class="relative py-28">
|
||||
<hr class="section-divider mb-24" />
|
||||
|
||||
<div class="pointer-events-none absolute inset-x-0 top-12 mx-auto h-56 w-[42rem] rounded-full bg-accent-500/[0.05] blur-3xl"></div>
|
||||
|
||||
<div class="relative mx-auto max-w-6xl px-6">
|
||||
<div class="grid gap-6 lg:grid-cols-[1.15fr_0.85fr]">
|
||||
<div class="card-dotted relative overflow-hidden rounded-2xl bg-surface-900/35">
|
||||
<div class="pointer-events-none absolute -top-12 -right-14 hidden h-52 w-52 opacity-35 mix-blend-screen md:block">
|
||||
<img
|
||||
src="/iptvnator/illustrations/support-open-source-signal.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="h-full w-full object-contain"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span class="font-mono text-xs uppercase tracking-[0.2em] text-accent-500">Support</span>
|
||||
<h2 class="mt-4 font-display text-3xl font-bold tracking-tight text-surface-50 sm:text-4xl">
|
||||
IPTVnator stays <em class="font-medium text-accent-400" style="font-style: italic;">open source</em>
|
||||
</h2>
|
||||
<p class="mt-5 max-w-2xl text-base leading-relaxed text-surface-300 md:pr-24">
|
||||
IPTVnator was built as an open-source project and will remain one. If it helps you, your support keeps the
|
||||
project healthy and the motivation high for continued improvements, fixes, and long-term maintenance.
|
||||
</p>
|
||||
|
||||
<div class="mt-8 grid gap-3 sm:grid-cols-3">
|
||||
{supportLinks.map((item) => (
|
||||
<a
|
||||
href={item.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="group flex h-full flex-col rounded-xl border border-dashed border-surface-700/70 bg-surface-950/50 p-4 transition-all duration-300 hover:border-accent-500/40 hover:bg-accent-500/[0.06]"
|
||||
>
|
||||
<div class="flex min-h-[3rem] items-center gap-3 text-surface-200">
|
||||
<span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border border-accent-500/25 bg-accent-500/10">
|
||||
<svg class="h-5 w-5 text-accent-300 transition-transform duration-300 group-hover:scale-110" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d={item.icon} />
|
||||
</svg>
|
||||
</span>
|
||||
<span class="text-sm font-semibold text-surface-100">{item.label}</span>
|
||||
</div>
|
||||
<p class="mt-3 text-sm leading-relaxed text-surface-400">{item.description}</p>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="card-dotted rounded-2xl bg-surface-900/25">
|
||||
<span class="font-mono text-xs uppercase tracking-[0.2em] text-accent-500">Disclaimer</span>
|
||||
<p class="mt-4 text-sm leading-relaxed text-surface-300">
|
||||
IPTVnator is a media player application. It does not provide, host, or sell any digital media content,
|
||||
playlists, channels, or EPG data.
|
||||
</p>
|
||||
<p class="mt-3 text-sm leading-relaxed text-surface-400">
|
||||
Any channel names, logos, metadata, or playlists shown in screenshots are for demonstration purposes only.
|
||||
You are responsible for the sources you use and for complying with local laws and rights.
|
||||
</p>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1,10 +1,13 @@
|
||||
---
|
||||
title: 'Understanding the Electronic Program Guide'
|
||||
description: 'Learn how IPTVnator uses XMLTV data to display current and upcoming programs alongside your live TV channels.'
|
||||
title: Understanding the Electronic Program Guide
|
||||
description: Learn how IPTVnator uses XMLTV data to display current and upcoming programs alongside your live TV channels.
|
||||
pubDate: 2026-02-15
|
||||
author: '4gray'
|
||||
heroImage: '/iptvnator/blog/epg.png'
|
||||
tags: ['tutorial', 'epg']
|
||||
author: 4gray
|
||||
heroImage: /iptvnator/blog/epg.png
|
||||
tags:
|
||||
- tutorial
|
||||
- epg
|
||||
draft: false
|
||||
---
|
||||
|
||||
One of the most useful features in IPTVnator is the built-in Electronic Program Guide (EPG). Here is how it works and how to set it up.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
---
|
||||
title: 'Introducing the IPTVnator Website'
|
||||
description: 'We are excited to launch the official IPTVnator website and developer blog. Stay tuned for release notes, tutorials, and roadmap updates.'
|
||||
title: Introducing the IPTVnator Website
|
||||
description: We are excited to launch the official IPTVnator website and developer blog. Stay tuned for release notes, tutorials, and roadmap updates.
|
||||
pubDate: 2026-02-14
|
||||
author: '4gray'
|
||||
heroImage: '/iptvnator/blog/player.png'
|
||||
tags: ['announcement']
|
||||
author: 4gray
|
||||
heroImage: /iptvnator/blog/player.png
|
||||
tags:
|
||||
- announcement
|
||||
draft: false
|
||||
---
|
||||
|
||||
We are excited to launch the official IPTVnator website and developer blog!
|
||||
|
||||
@@ -24,11 +24,23 @@ const formattedUpdatedDate = updatedDate?.toLocaleDateString('en-US', {
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
});
|
||||
|
||||
const AUTHOR_AVATAR_URL = 'https://avatars.githubusercontent.com/u/1503032';
|
||||
---
|
||||
|
||||
<BaseLayout title={`${title} | IPTVnator Blog`} description={description}>
|
||||
<article class="pt-36 pb-24">
|
||||
<div class="mx-auto max-w-3xl px-6">
|
||||
<div class="relative mx-auto max-w-3xl px-6">
|
||||
<div class="pointer-events-none absolute -top-16 -right-14 hidden w-44 rotate-[-8deg] opacity-30 mix-blend-screen md:block lg:w-52">
|
||||
<img
|
||||
src="/iptvnator/illustrations/blog-corner-signal-mark.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="w-full object-contain"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Back link -->
|
||||
<a
|
||||
href="/iptvnator/blog/"
|
||||
@@ -67,9 +79,12 @@ const formattedUpdatedDate = updatedDate?.toLocaleDateString('en-US', {
|
||||
<p class="mt-4 text-lg text-surface-400">{description}</p>
|
||||
|
||||
<div class="mt-6 flex items-center gap-3">
|
||||
<div class="flex h-8 w-8 items-center justify-center rounded-full border border-dashed border-accent-500/30 bg-accent-500/10 font-mono text-sm font-bold text-accent-400">
|
||||
{author.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
<img
|
||||
src={AUTHOR_AVATAR_URL}
|
||||
alt={`${author} avatar`}
|
||||
class="h-8 w-8 rounded-full border border-dashed border-accent-500/30 object-cover"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div>
|
||||
<div class="text-sm font-medium text-surface-100">{author}</div>
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ import Hero from '../components/Hero.astro';
|
||||
import FeatureGrid from '../components/FeatureGrid.astro';
|
||||
import ScreenshotShowcase from '../components/ScreenshotShowcase.astro';
|
||||
import DownloadCTA from '../components/DownloadCTA.astro';
|
||||
import SupportSection from '../components/SupportSection.astro';
|
||||
import FeaturedBlogPost from '../components/FeaturedBlogPost.astro';
|
||||
import BlogPostCard from '../components/BlogPostCard.astro';
|
||||
|
||||
@@ -24,6 +25,7 @@ const [featuredPost, ...otherPosts] = posts;
|
||||
<FeatureGrid />
|
||||
<ScreenshotShowcase />
|
||||
<DownloadCTA />
|
||||
<SupportSection />
|
||||
|
||||
<!-- Recent Blog Posts -->
|
||||
{
|
||||
|
||||
@@ -68,16 +68,21 @@
|
||||
/* ── TV-effect download button ── */
|
||||
.btn-tv {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
overflow: hidden;
|
||||
isolation: isolate;
|
||||
border: 1px solid rgba(32, 168, 168, 0.3);
|
||||
background: linear-gradient(135deg, rgba(32, 168, 168, 0.12) 0%, rgba(32, 168, 168, 0.06) 50%, rgba(32, 168, 168, 0.1) 100%);
|
||||
background-size: 180% 180%;
|
||||
background-position: 0% 50%;
|
||||
box-shadow:
|
||||
0 0 20px rgba(32, 168, 168, 0.15),
|
||||
0 0 40px rgba(32, 168, 168, 0.05),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.06),
|
||||
inset 0 0 20px rgba(32, 168, 168, 0.03);
|
||||
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
animation: tvIdleGlow 2.1s ease-in-out infinite, tvSurfaceShift 2.8s linear infinite, tvButtonJitter 1.2s steps(2, end) infinite;
|
||||
will-change: transform, box-shadow, background-position;
|
||||
}
|
||||
|
||||
.btn-tv::before {
|
||||
@@ -85,7 +90,7 @@
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
opacity: 0.34;
|
||||
background: repeating-linear-gradient(
|
||||
0deg,
|
||||
transparent,
|
||||
@@ -95,6 +100,29 @@
|
||||
);
|
||||
transition: opacity 0.3s ease;
|
||||
pointer-events: none;
|
||||
animation: tvHorizontalRoll 2.2s linear infinite;
|
||||
}
|
||||
|
||||
.btn-tv::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
opacity: 0.22;
|
||||
pointer-events: none;
|
||||
mix-blend-mode: screen;
|
||||
background-image:
|
||||
linear-gradient(180deg, rgba(32, 168, 168, 0) 0%, rgba(32, 168, 168, 0.1) 48%, rgba(32, 168, 168, 0) 100%),
|
||||
repeating-linear-gradient(
|
||||
0deg,
|
||||
transparent 0px,
|
||||
transparent 5px,
|
||||
rgba(180, 255, 255, 0.045) 6px,
|
||||
transparent 7px
|
||||
);
|
||||
background-size: 100% 100%, 100% 12px;
|
||||
background-position: 0 0, 0 0;
|
||||
animation: tvInterferenceShift 0.45s steps(14) infinite, tvNoSignalBurst 3.6s steps(1, end) infinite;
|
||||
}
|
||||
|
||||
/* TV scanline sweep overlay */
|
||||
@@ -102,7 +130,7 @@
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 2;
|
||||
opacity: 0;
|
||||
opacity: 0.75;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s ease;
|
||||
@@ -122,7 +150,7 @@
|
||||
rgba(32, 168, 168, 0.08) 60%,
|
||||
transparent
|
||||
);
|
||||
animation: tvScan 3s linear infinite;
|
||||
animation: tvScan 1.1s linear infinite;
|
||||
}
|
||||
|
||||
/* Static noise overlay */
|
||||
@@ -130,12 +158,36 @@
|
||||
position: absolute;
|
||||
inset: -50%;
|
||||
z-index: 3;
|
||||
opacity: 0;
|
||||
opacity: 0.08;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.4'/%3E%3C/svg%3E");
|
||||
background-size: 128px 128px;
|
||||
background-position: 0 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s ease;
|
||||
mix-blend-mode: overlay;
|
||||
animation: tvNoiseDrift 0.55s steps(24) infinite;
|
||||
}
|
||||
|
||||
.btn-tv .tv-noise::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 48%;
|
||||
left: -38%;
|
||||
width: 34%;
|
||||
height: 1px;
|
||||
border-radius: 9999px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent 0%,
|
||||
rgba(32, 168, 168, 0.5) 40%,
|
||||
rgba(155, 255, 255, 0.8) 50%,
|
||||
rgba(32, 168, 168, 0.5) 60%,
|
||||
transparent 100%
|
||||
);
|
||||
box-shadow: 0 0 10px rgba(32, 168, 168, 0.35);
|
||||
opacity: 0.95;
|
||||
height: 2px;
|
||||
animation: tvNoiseLineX 1.15s linear infinite;
|
||||
}
|
||||
|
||||
/* CRT vignette corners */
|
||||
@@ -155,16 +207,20 @@
|
||||
border-color: rgba(32, 168, 168, 0.5);
|
||||
background: linear-gradient(135deg, rgba(32, 168, 168, 0.18) 0%, rgba(32, 168, 168, 0.08) 50%, rgba(32, 168, 168, 0.15) 100%);
|
||||
box-shadow:
|
||||
0 0 30px rgba(32, 168, 168, 0.3),
|
||||
0 0 60px rgba(32, 168, 168, 0.1),
|
||||
0 0 100px rgba(32, 168, 168, 0.05),
|
||||
0 0 44px rgba(32, 168, 168, 0.45),
|
||||
0 0 100px rgba(32, 168, 168, 0.22),
|
||||
0 0 130px rgba(32, 168, 168, 0.12),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.08),
|
||||
inset 0 0 30px rgba(32, 168, 168, 0.06);
|
||||
transform: scale(1.02);
|
||||
transform: translateY(-2px) scale(1.055);
|
||||
}
|
||||
|
||||
.btn-tv:hover::before {
|
||||
opacity: 1;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.btn-tv:hover::after {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.btn-tv:hover .tv-scanline {
|
||||
@@ -172,8 +228,13 @@
|
||||
}
|
||||
|
||||
.btn-tv:hover .tv-noise {
|
||||
opacity: 0.04;
|
||||
animation: tvFlicker 0.15s infinite;
|
||||
opacity: 0.16;
|
||||
animation: tvNoiseDrift 0.35s steps(30) infinite, tvFlicker 0.08s infinite;
|
||||
}
|
||||
|
||||
.btn-tv:hover .tv-noise::after {
|
||||
opacity: 1;
|
||||
animation-duration: 0.65s;
|
||||
}
|
||||
|
||||
.btn-tv:hover .tv-vignette {
|
||||
@@ -188,6 +249,10 @@
|
||||
animation: tvTextGlitch 4s infinite;
|
||||
}
|
||||
|
||||
.btn-tv .btn-tv-text {
|
||||
animation: tvSubpixelDrift 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes tvTextGlitch {
|
||||
0%, 93%, 100% {
|
||||
text-shadow:
|
||||
@@ -216,6 +281,137 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvIdleGlow {
|
||||
0%, 100% {
|
||||
box-shadow:
|
||||
0 0 18px rgba(32, 168, 168, 0.14),
|
||||
0 0 36px rgba(32, 168, 168, 0.04),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.05),
|
||||
inset 0 0 18px rgba(32, 168, 168, 0.02);
|
||||
}
|
||||
50% {
|
||||
box-shadow:
|
||||
0 0 24px rgba(32, 168, 168, 0.2),
|
||||
0 0 48px rgba(32, 168, 168, 0.07),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.07),
|
||||
inset 0 0 24px rgba(32, 168, 168, 0.04);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvSurfaceShift {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvButtonJitter {
|
||||
0%, 100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
20% {
|
||||
transform: translate3d(0.4px, -0.3px, 0);
|
||||
}
|
||||
40% {
|
||||
transform: translate3d(-0.5px, 0.2px, 0);
|
||||
}
|
||||
60% {
|
||||
transform: translate3d(0.3px, 0.1px, 0);
|
||||
}
|
||||
80% {
|
||||
transform: translate3d(-0.2px, -0.2px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvNoiseDrift {
|
||||
0% {
|
||||
transform: translate3d(-1%, -0.5%, 0) scale(1);
|
||||
background-position: 0 0;
|
||||
}
|
||||
50% {
|
||||
transform: translate3d(1%, 0.8%, 0) scale(1.015);
|
||||
background-position: 22px -18px;
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(-0.5%, -0.2%, 0) scale(1);
|
||||
background-position: 44px -8px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvNoiseLineX {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(420%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvHorizontalRoll {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvInterferenceShift {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
background-position: 0 0, 0 0;
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
background-position: 0 0, 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvNoSignalBurst {
|
||||
0%, 60%, 100% {
|
||||
filter: contrast(1) brightness(1);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
61% {
|
||||
filter: contrast(2.1) brightness(1.35) saturate(1.15);
|
||||
transform: translate3d(1.3%, -0.5%, 0);
|
||||
}
|
||||
62% {
|
||||
filter: contrast(0.72) brightness(0.8) saturate(0.9);
|
||||
transform: translate3d(-1.4%, 0.4%, 0);
|
||||
}
|
||||
63% {
|
||||
filter: contrast(1.6) brightness(1.2) saturate(1.1);
|
||||
transform: translate3d(0.6%, -0.2%, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tvSubpixelDrift {
|
||||
0%, 100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
text-shadow:
|
||||
0 0 rgba(32, 168, 168, 0),
|
||||
0 0 rgba(255, 110, 110, 0);
|
||||
}
|
||||
45% {
|
||||
transform: translate3d(0.1px, 0, 0);
|
||||
text-shadow:
|
||||
0.5px 0 rgba(32, 168, 168, 0.2),
|
||||
-0.5px 0 rgba(255, 110, 110, 0.08);
|
||||
}
|
||||
55% {
|
||||
transform: translate3d(-0.1px, 0, 0);
|
||||
text-shadow:
|
||||
0.4px 0 rgba(32, 168, 168, 0.16),
|
||||
-0.4px 0 rgba(255, 110, 110, 0.06);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Carousel infinite marquee ── */
|
||||
.carousel-track {
|
||||
animation: marquee 40s linear infinite;
|
||||
@@ -236,5 +432,16 @@
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.btn-tv,
|
||||
.btn-tv::before,
|
||||
.btn-tv::after,
|
||||
.btn-tv .tv-noise,
|
||||
.btn-tv .tv-noise::after,
|
||||
.btn-tv .tv-scanline::after,
|
||||
.btn-tv .btn-tv-text,
|
||||
.btn-tv:hover .btn-tv-text {
|
||||
animation-duration: 16s !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user