From 26e489f0bf06557ff35db57cc49b62645de4b53b Mon Sep 17 00:00:00 2001 From: sakrecoer Date: Fri, 31 Jul 2026 00:27:45 +0200 Subject: [PATCH] did all this shit without even commiting once ffs --- .gitignore | 4 + archetypes/default.md | 5 + fetch-and-convert.sh | 41 + hugo.toml | 15 + themes/one-pager/assets/css/style.css | 1519 +++++++++++++++++ themes/one-pager/assets/js/scripts.js | 870 ++++++++++ themes/one-pager/layouts/index.html | 180 ++ themes/one-pager/layouts/partials/footer.html | 55 + themes/one-pager/layouts/partials/header.html | 85 + themes/one-pager/layouts/partials/seo.html | 148 ++ .../one-pager/static/images/videoposter.png | Bin 0 -> 31431 bytes video-poster.svg | 56 + 12 files changed, 2978 insertions(+) create mode 100644 .gitignore create mode 100644 archetypes/default.md create mode 100755 fetch-and-convert.sh create mode 100644 hugo.toml create mode 100644 themes/one-pager/assets/css/style.css create mode 100644 themes/one-pager/assets/js/scripts.js create mode 100644 themes/one-pager/layouts/index.html create mode 100644 themes/one-pager/layouts/partials/footer.html create mode 100644 themes/one-pager/layouts/partials/header.html create mode 100644 themes/one-pager/layouts/partials/seo.html create mode 100644 themes/one-pager/static/images/videoposter.png create mode 100644 video-poster.svg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d7f4147 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +public +resources +.hugo_build.lock +data diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..25b6752 --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +date = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' ++++ diff --git a/fetch-and-convert.sh b/fetch-and-convert.sh new file mode 100755 index 0000000..b0b2e7a --- /dev/null +++ b/fetch-and-convert.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Configuration +PUBKEY="setto@basspistol.org" +RELAY="wss://basspistol.org" +DATA_DIR="data" + +# Clean up old JSON files (optional) +# rm -f data/*/*.json + +# Define kind mappings +declare -A KINDS +KINDS[0]="profile/profile" +KINDS[30023]="longform/blog" +KINDS[36787]="music/tracks" +KINDS[20]="pictures/photos" +KINDS[22]="videos/videos" + +# Fetch each kind +for kind in "${!KINDS[@]}"; do + output="${KINDS[$kind]}" + echo "Fetching kind $kind..." + + # Create directory if it doesn't exist + mkdir -p "$DATA_DIR/$(dirname "$output")" + + # Fetch and convert to JSON + nak req -k "$kind" -a "$PUBKEY" "$RELAY" | jq -s '.' > "$DATA_DIR/$output.json" + + # Remove any existing .jsonl file in the same directory + rm -f "$DATA_DIR/$(dirname "$output")"/*.jsonl + + echo "Saved to $DATA_DIR/$output.json" +done + +echo "All data fetched and converted!" +echo "JSONL files have been removed." + +echo "Building website" + +hugo build diff --git a/hugo.toml b/hugo.toml new file mode 100644 index 0000000..7140f3d --- /dev/null +++ b/hugo.toml @@ -0,0 +1,15 @@ +baseURL = "https://setto.basspistol.com" +locale = "en-us" +title = "Settolino Malandrino" +theme = "one-pager" +disableKinds = ["sitemap", "taxonomy", "term"] + +[params] + sitename = "My Site" + description = "Set, Party, Gang εΎ’ setto γ‚»γƒƒγƒˆ" + headerImage = "/images/header.jpg" + +[permalinks] + page = "/:contentbasename/" + + diff --git a/themes/one-pager/assets/css/style.css b/themes/one-pager/assets/css/style.css new file mode 100644 index 0000000..cae7aea --- /dev/null +++ b/themes/one-pager/assets/css/style.css @@ -0,0 +1,1519 @@ +/* Import Poppins font */ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700;900&display=swap'); + +:root { + --bg-primary: #0a0a0a; + --bg-secondary: #1a1a1a; + --text-primary: #f5f0eb; + --text-secondary: #d0c8c0; + --accent-yellow: #ffd700; + --accent-grey: #8a8a8a; + --accent-black: #ffffff; + --border-color: #ffd700; + --shadow-color: rgba(255, 215, 0, 0.1); + --card-bg: #141414; + --nav-bg: rgba(255, 215, 0, 0.1); + --tag-bg: #2a2a2a; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Poppins', -apple-system, BlinkMacSystemFont, sans-serif; + line-height: 1.6; + color: var(--text-primary); + background: var(--bg-primary); + transition: background-color 0.4s ease, color 0.4s ease; +} + + +.main-header { + min-height: 100vh !important; + height: 100vh !important; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 4rem 2rem; + position: relative; + background: var(--bg-primary); + border-bottom: 4px solid var(--accent-yellow); + transition: background-color 0.4s ease; + overflow: hidden; + flex-shrink: 0; +} + +/* Combined overlay: dark gradient + cyberpunk pattern */ +.main-header::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 0; + pointer-events: none; + background: + /* Dark overlay for readability */ + linear-gradient( + to bottom, + rgba(0, 0, 0, 0.5) 0%, + rgba(0, 0, 0, 0.25) 40%, + rgba(0, 0, 0, 0.25) 60%, + rgba(0, 0, 0, 0.5) 100% + ), + /* Cyberpunk pattern */ + repeating-linear-gradient( + 33deg, + transparent, + transparent 50px, + var(--accent-yellow) 50px, + var(--accent-yellow) 51px + ); + opacity: 0.6; +} + +[data-theme="dark"] .main-header::before { + background: + /* Darker overlay for dark mode */ + linear-gradient( + to bottom, + rgba(0, 0, 0, 0.7) 0%, + rgba(0, 0, 0, 0.4) 40%, + rgba(0, 0, 0, 0.4) 60%, + rgba(0, 0, 0, 0.7) 100% + ), + repeating-linear-gradient( + 33deg, + transparent, + transparent 50px, + var(--accent-yellow) 50px, + var(--accent-yellow) 51px + ); + opacity: 0.7; +} + +/* Decorative '>' character */ +.main-header::after { + content: '>'; + position: absolute; + bottom: 40px; + right: 40px; + z-index: 1; + font-family: 'Poppins', sans-serif; + font-weight: 900; + font-size: 4rem; + color: var(--accent-yellow); + opacity: 0.15; + pointer-events: none; +} + +/* Content sits above overlay */ +.header-content { + max-width: 1200px; + margin: 0 auto; + width: 100%; + position: relative; + z-index: 1; +} + +/* Profile layout */ +.header-profile { + display: flex; + align-items: center; + gap: 3rem; + justify-content: center; + flex-wrap: wrap; +} + +/* Profile picture */ +.profile-picture { + width: 180px; + height: 180px; + border-radius: 0; + border: 4px solid var(--accent-yellow); + object-fit: cover; + box-shadow: 12px 12px 0 var(--accent-yellow); + transition: all 0.3s ease; + border-radius: 100%; +} + +.profile-picture:hover { + transform: scale(1.02); + box-shadow: 16px 16px 0 var(--accent-yellow); + +} + +/* Header text container */ +.header-text { + text-align: left; + flex: 1; + min-width: 280px; +} + +/* Main title */ +.main-header h1 { + font-family: 'Poppins', sans-serif; + font-weight: 900; + font-size: 7rem; + letter-spacing: -2px; + line-height: 1.1; + color: var(--accent-yellow); + text-transform: uppercase; + margin-bottom: 0.5rem; + text-shadow: + 0 2px 20px rgba(0, 0, 0, 0.6), + 0 4px 8px rgba(0, 0, 0, 0.4), + 4px 4px 0 var(--accent-grey); + transition: all 0.3s ease; +} + + + +.main-header h1:hover { + text-shadow: + 0 2px 30px rgba(255, 215, 0, 0.3), + 0 4px 8px rgba(0, 0, 0, 0.5), + 6px 6px 0 var(--accent-yellow); + transform: translate(-2px, -2px); +} + +/* About text */ +.profile-about { + font-size: 1.1rem; + font-weight: 700; + margin: 1rem 0 1.5rem 0; + line-height: 1.8; + + color: var(--text-secondary); + border-left: 4px solid var(--accent-yellow); + padding: 0.5rem 1rem 1.5rem 1.5rem; + letter-spacing: 0.5px; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-radius: 0 8px 8px 0; +} + +[data-theme="dark"] .profile-about { + background: rgba(0, 0, 0, 0.4); + color: #f0ece8; +} + +.profile-about code { + background: var(--accent-yellow); + color: var(--bg-primary); + padding: 0.5rem; + + font-weight: 700; + font-size: 1.2rem; + font-family: 'Poppins', sans-serif; + letter-spacing: 1px; +} + +/* Tagline */ +.tagline { + font-size: 2rem; + font-weight: 700; + margin-top: 0.5rem; + letter-spacing: -0.5px; + text-transform: uppercase; + color: var(--text-primary); + text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); +} + +[data-theme="dark"] .tagline { + color: #f0ece8; + text-shadow: 0 2px 10px rgba(0, 0, 0, 0.6); +} + + + +[data-theme="dark"] .profile-nip05, +[data-theme="dark"] .profile-lud16 { + color: #f0ece8; + background: rgba(0, 0, 0, 0.5); + border-color: var(--accent-yellow); +} + +/* Main Navigation - NO SKEW on text */ +.main-nav { + margin-top: 3rem; + display: flex; + justify-content: center; + gap: 2rem; + flex-wrap: wrap; + position: relative; + z-index: 1; +} + +.main-nav a { + color: var(--text-primary); + text-decoration: none; + padding: 0.8rem 2rem; + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: 0.8rem; + letter-spacing: 4px; + text-transform: uppercase; + transition: all 0.3s ease; + border: 2px solid var(--accent-yellow); + background: rgba(0, 0, 0, 0.3); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); +} + +[data-theme="dark"] .main-nav a { + background: rgba(0, 0, 0, 0.5); + color: #f0ece8; +} + +.main-nav a:hover { + transform: scale(1.05); + background: var(--accent-yellow); + color: var(--accent-black); + box-shadow: 8px 8px 0 var(--accent-grey); + backdrop-filter: none; + -webkit-backdrop-filter: none; +} + +.main-nav a span { + display: inline-block; +} + +/* ============ END HEADER STYLES ============ */ + +/* Sticky Navigation - NO SKEW */ +.sticky-nav { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 999; + background: var(--bg-primary); + border-bottom: 3px solid var(--accent-yellow); + padding: 0.8rem 2rem; + transform: translateY(-100%); + transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.4s ease; + box-shadow: 0 4px 20px var(--shadow-color); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +.sticky-nav.visible { + transform: translateY(0); +} + +.sticky-nav .nav-container { + max-width: 1200px; + margin: 0 auto; + display: flex; + justify-content: space-between; + align-items: center; + gap: 2rem; + flex-wrap: wrap; +} + +.sticky-nav .nav-brand { + font-family: 'Poppins', sans-serif; + font-weight: 900; + font-size: 1.2rem; + letter-spacing: -1px; + color: var(--text-primary); + text-decoration: none; + text-transform: uppercase; +} + +.sticky-nav .nav-brand span { + color: var(--accent-yellow); +} + +.sticky-nav .nav-links { + display: flex; + gap: 1.5rem; + flex-wrap: wrap; + align-items: center; +} + +.sticky-nav .nav-links a { + color: var(--text-primary); + text-decoration: none; + font-family: 'Poppins', sans-serif; + font-weight: 600; + font-size: 0.75rem; + letter-spacing: 3px; + text-transform: uppercase; + padding: 0.4rem 0.8rem; + transition: all 0.3s ease; + border: 2px solid transparent; +} + +.sticky-nav .nav-links a:hover { + color: var(--accent-yellow); + border-color: var(--accent-yellow); + transform: scale(1.05); +} + +.sticky-nav .nav-links a span { + display: inline-block; +} + +.sticky-nav .nav-links { + color: var(--accent-black); + padding: 0.4rem 1rem; + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: 0.7rem; + letter-spacing: 3px; + cursor: pointer; + transition: all 0.3s ease; + text-transform: uppercase; +} + +.sticky-nav .nav-links .theme-toggle-small:hover { + transform: scale(1.05); + background: var(--accent-black); + color: var(--accent-yellow); + border-color: var(--accent-yellow); +} + +.sticky-nav .nav-links .theme-toggle-small span { + display: inline-block; +} + + +/* Sections */ +.section { + padding: 5rem 2rem; + max-width: 1200px; + margin: 0 auto; + border-bottom: 2px solid var(--accent-grey); + position: relative; +} + +.section:last-child { + border-bottom: none; +} +.section p { + margin-bottom: 2rem; +} + +.section h2 { + font-family: 'Poppins', sans-serif; + font-weight: 900; + font-size: 2.8rem; + letter-spacing: -2px; + margin-bottom: 2rem; + color: var(--text-primary); + text-align: left; + position: relative; + padding-bottom: 1rem; + text-transform: uppercase; +} + +.section h2::before { + content: '// '; + color: var(--accent-yellow); +} + +.section h2::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 80px; + height: 4px; + background: var(--accent-yellow); +} + +/* Blog Grid - KEEP SKEW ON CARDS */ +.blog-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2.5rem; +} + +.blog-card { + background: var(--card-bg); + border: 2px solid var(--accent-grey); + overflow: hidden; + transition: all 0.3s ease; + position: relative; + transform: skewX(-2deg); + box-shadow: 8px 8px 0 var(--accent-grey); +} + +.blog-card:hover { + transform: skewX(0deg) translate(-4px, -4px); + box-shadow: 12px 12px 0 var(--accent-yellow); +} + +.blog-header-image { + width: 100%; + height: 220px; + object-fit: cover; + border-bottom: 3px solid var(--accent-yellow); + filter: grayscale(30%); + transition: all 0.3s ease; +} + +.blog-card:hover .blog-header-image { + filter: grayscale(0%); +} + +.blog-content { + padding: 1.8rem; +} + +.blog-content h3 { + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: 1.4rem; + letter-spacing: -1px; + margin-bottom: 0.5rem; + color: var(--text-primary); +} + +.blog-meta { + color: var(--accent-grey); + font-size: 0.8rem; + font-weight: 400; + margin-bottom: 1rem; + letter-spacing: 1px; +} + +.blog-description { + color: var(--text-secondary); + margin-bottom: 1rem; + font-weight: 400; + font-size: 0.95rem; +} + +.blog-tags { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin: 0.5rem 0 1.2rem 0; +} + +button { + border-radius: 8px; +} + +/* Read More button - NO SKEW */ +.read-more-toggle { + background: var(--accent-yellow); + color: #0a0a0a !important; /* Force black */ + border: 2px solid var(--accent-grey); + padding: 0.6rem 1.5rem; + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: 0.7rem; + letter-spacing: 3px; + text-transform: uppercase; + cursor: pointer; + transition: all 0.3s ease; +} + +.read-more-toggle:hover { + background: var(--accent-black); + color: var(--accent-yellow) !important; /* Yellow on hover */ + border-color: var(--accent-yellow); + transform: scale(1.05); +} + +.read-more-toggle span { + display: inline-block; +} + +.blog-full-content { + margin-top: 1.5rem; + padding: 1.5rem; + background: var(--bg-secondary); + border-left: 4px solid var(--accent-yellow); + color: var(--text-secondary); + font-weight: 400; + font-size: 0.95rem; +} + +.blog-full-content img { + max-width: 100%; + height: auto; + margin: 0.5rem 0; + border: 2px solid var(--accent-grey); +} + +/* Music Grid - KEEP SKEW ON CARDS */ +.music-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); + gap: 2.5rem; +} + +.music-card { + background: var(--card-bg); + border: 2px solid var(--accent-grey); + padding: 1.8rem; + transition: all 0.3s ease; + transform: skewX(-2deg); + box-shadow: 8px 8px 0 var(--accent-grey); +} + +.music-card:hover { + transform: skewX(0deg) translate(-4px, -4px); + box-shadow: 12px 12px 0 var(--accent-yellow); +} + +.music-image { + width: 100%; + height: 200px; + object-fit: cover; + border: 2px solid var(--accent-grey); + margin-bottom: 1rem; + filter: grayscale(30%); + transition: all 0.3s ease; +} + +.music-card:hover .music-image { + filter: grayscale(0%); +} + +.music-card h4 { + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: 1.3rem; + letter-spacing: -1px; + margin-bottom: 0.3rem; + color: var(--text-primary); +} + +.music-artist { + color: var(--accent-yellow); + font-weight: 600; + font-size: 0.9rem; + letter-spacing: 2px; +} + +.music-album { + color: var(--accent-grey); + font-weight: 400; + font-size: 0.85rem; + margin-bottom: 1rem; +} + +.music-card audio { + width: 100%; + margin: 1rem 0; + border: 2px solid var(--accent-grey); +} + +.music-details { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin: 0.5rem 0; +} + +.music-details span { + background: var(--tag-bg); + padding: 0.3rem 0.8rem; + font-weight: 600; + font-size: 0.7rem; + letter-spacing: 2px; + color: var(--text-secondary); + border: 1px solid var(--accent-grey); +} + +.music-tags { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin: 0.5rem 0; +} + +/* Tags - NO SKEW */ +.tag { + background: var(--tag-bg); + padding: 0.3rem 0.8rem; + font-weight: 700; + font-size: 0.65rem; + letter-spacing: 2px; + text-transform: uppercase; + color: var(--text-secondary); + border: 1px solid var(--accent-grey); +} + +.tag span { + display: inline-block; +} + +/* Lyrics button - NO SKEW */ +.lyrics-toggle { + background: var(--accent-yellow); + color: #0a0a0a !important; /* Force black */ + border: 2px solid var(--accent-grey); + padding: 0.6rem 1.5rem; + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: 0.7rem; + letter-spacing: 3px; + text-transform: uppercase; + cursor: pointer; + transition: all 0.3s ease; + margin-top: 0.8rem; +} + +.lyrics-toggle:hover { + background: var(--accent-black); + color: #0a0a0a !important; /* Yellow on hover */ + border-color: var(--accent-yellow); + transform: scale(1.05); +} + +.lyrics-toggle span { + display: inline-block; +} + +.lyrics { + margin-top: 1rem; + padding: 1.5rem; + background: var(--bg-secondary); + border-left: 4px solid var(--accent-yellow); + color: var(--text-secondary); + font-weight: 400; + font-size: 0.9rem; + white-space: pre-wrap; +} + +/* Photo Grid - KEEP SKEW ON CARDS */ +.photo-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 2rem; +} + +.photo-item { + position: relative; + overflow: hidden; + border: 2px solid var(--accent-grey); + transition: all 0.3s ease; + transform: skewX(-2deg); + box-shadow: 8px 8px 0 var(--accent-grey); + background: var(--card-bg); +} + +.photo-item:hover { + transform: skewX(0deg) translate(-4px, -4px); + box-shadow: 12px 12px 0 var(--accent-yellow); +} + +.photo-item img { + width: 100%; + height: 320px; + object-fit: cover; + cursor: pointer; + filter: grayscale(30%); + transition: all 0.3s ease; + display: block; +} + +.photo-item:hover img { + filter: grayscale(0%); +} + +/* Photo date on main page */ +.photo-date { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 0.8rem 1.2rem; + background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); + color: white; + font-family: 'Poppins', sans-serif; + font-weight: 400; + font-size: 0.75rem; + letter-spacing: 2px; + opacity: 0; + transition: opacity 0.3s ease; +} + +.photo-item:hover .photo-date { + opacity: 1; +} + +/* Video Grid - KEEP SKEW ON CARDS */ +.video-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); + gap: 2.5rem; +} + +.video-item { + background: var(--card-bg); + border: 2px solid var(--accent-grey); + overflow: hidden; + transition: all 0.3s ease; + transform: skewX(-2deg); + box-shadow: 8px 8px 0 var(--accent-grey); +} + +.video-item:hover { + transform: skewX(0deg) translate(-4px, -4px); + box-shadow: 12px 12px 0 var(--accent-yellow); +} + +.video-item video { + width: 100%; + background: var(--accent-black); + display: block; + border-bottom: 3px solid var(--accent-yellow); +} + +.video-info { + padding: 1.5rem; +} + +.video-caption { + color: var(--text-primary); + font-family: 'Poppins', sans-serif; + font-weight: 600; + font-size: 1rem; + margin-bottom: 0.5rem; +} + +.video-meta { + display: flex; + flex-wrap: wrap; + gap: 1rem; + font-weight: 400; + font-size: 0.7rem; + letter-spacing: 2px; + color: var(--accent-grey); +} + +.video-meta span { + background: var(--tag-bg); + padding: 0.3rem 0.8rem; + border: 1px solid var(--accent-grey); +} + +/* Custom Lightbox - NO SKEW */ +.custom-lightbox { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.92); + z-index: 9999; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + animation: fadeIn 0.3s ease; +} + +.custom-lightbox.active { + display: flex; + align-items: center; + justify-content: center; +} + +.custom-lightbox-content { + max-width: 90%; + max-height: 85vh; + position: relative; + display: flex; + flex-direction: column; + align-items: center; + animation: zoomIn 0.3s ease; +} + +.custom-lightbox-content img { + max-width: 100%; + max-height: 75vh; + object-fit: contain; + border: 3px solid var(--accent-yellow); + box-shadow: 0 0 40px rgba(255, 215, 0, 0.2); +} + +.custom-lightbox-caption { + margin-top: 1rem; + padding: 0.8rem 1.5rem; + background: rgba(0, 0, 0, 0.7); + border-left: 4px solid var(--accent-yellow); + color: white; + font-family: 'Poppins', sans-serif; + font-weight: 400; + font-size: 0.95rem; + text-align: center; + max-width: 80%; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +.custom-lightbox-caption .lightbox-meta { + display: block; + font-size: 0.75rem; + color: var(--accent-yellow); + letter-spacing: 2px; + margin-top: 0.3rem; +} + +.custom-lightbox-close { + position: fixed; + top: 20px; + right: 30px; + font-size: 2.5rem; + color: white; + cursor: pointer; + font-family: 'Poppins', sans-serif; + transition: all 0.3s ease; + z-index: 10000; +} + +.custom-lightbox-close:hover { + color: var(--accent-yellow); + transform: scale(1.2); +} + +.custom-lightbox-prev, +.custom-lightbox-next { + position: fixed; + top: 50%; + transform: translateY(-50%); + background: rgba(0, 0, 0, 0.5); + color: white; + border: 2px solid var(--accent-yellow); + padding: 1rem 1.5rem; + font-size: 1.5rem; + cursor: pointer; + font-family: 'Poppins', sans-serif; + transition: all 0.3s ease; + z-index: 10000; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +.custom-lightbox-prev { + left: 20px; +} + +.custom-lightbox-next { + right: 20px; +} + +.custom-lightbox-prev:hover, +.custom-lightbox-next:hover { + background: var(--accent-yellow); + color: var(--accent-black); + transform: translateY(-50%) scale(1.1); +} + +.custom-lightbox-counter { + position: fixed; + bottom: 20px; + right: 30px; + color: white; + font-family: 'Poppins', sans-serif; + font-weight: 600; + font-size: 0.8rem; + letter-spacing: 3px; + color: var(--accent-yellow); + z-index: 10000; +} + +/* Responsive sticky nav */ +@media (max-width: 768px) { + .sticky-nav { + padding: 0.6rem 1rem; + } + + .sticky-nav .nav-container { + flex-direction: column; + gap: 0.8rem; + align-items: center; + } + + .sticky-nav .nav-links { + justify-content: center; + gap: 0.8rem; + } + + .sticky-nav .nav-links a { + font-size: 0.65rem; + letter-spacing: 2px; + padding: 0.3rem 0.6rem; + } + + .sticky-nav .nav-brand { + font-size: 1rem; + } +} + +@media (max-width: 480px) { + .sticky-nav .nav-links { + gap: 0.5rem; + } + + .sticky-nav .nav-links a { + font-size: 0.55rem; + letter-spacing: 1px; + padding: 0.2rem 0.5rem; + } +} + +/* Responsive Design */ +@media (max-width: 1024px) { + .main-header h1 { + font-size: 3.5rem; + } + + .section h2 { + font-size: 2.2rem; + } +} + +@media (max-width: 768px) { + .theme-toggle { + top: 10px; + right: 10px; + padding: 8px 16px; + font-size: 0.6rem; + } + + .header-profile { + flex-direction: column; + text-align: center; + gap: 1.5rem; + } + + .header-text { + text-align: center; + } + + .profile-about { + margin-left: auto; + margin-right: auto; + border-left: none; + border-top: 4px solid var(--accent-yellow); + padding: 1rem; + text-align: center; + } + + .profile-links { + justify-content: center; + } + + .main-header h1 { + font-size: 2.8rem; + letter-spacing: -1px; + } + + .main-header h1:hover { + text-shadow: 3px 3px 0 var(--accent-yellow); + } + + .profile-picture { + width: 140px; + height: 140px; + } + + .section { + padding: 3rem 1rem; + } + + .section h2 { + font-size: 1.8rem; + letter-spacing: -1px; + text-align: center; + } + + .section h2::after { + left: 50%; + transform: translateX(-50%); + } + + .blog-grid, + .music-grid, + .photo-grid, + .video-grid { + grid-template-columns: 1fr; + } + + .main-nav { + flex-direction: column; + align-items: center; + gap: 1rem; + } + + .main-nav a { + width: 100%; + max-width: 300px; + text-align: center; + } + + .photo-item img { + height: 250px; + } + + .blog-card, + .music-card, + .photo-item, + .video-item { + transform: skewX(0deg); + box-shadow: 4px 4px 0 var(--accent-grey); + } + + .blog-card:hover, + .music-card:hover, + .photo-item:hover, + .video-item:hover { + transform: translate(-2px, -2px); + box-shadow: 6px 6px 0 var(--accent-yellow); + } + + .custom-lightbox-prev, + .custom-lightbox-next { + padding: 0.8rem 1rem; + font-size: 1rem; + top: 50%; + } + + .custom-lightbox-prev { + left: 10px; + } + + .custom-lightbox-next { + right: 10px; + } + + .custom-lightbox-caption { + font-size: 0.8rem; + max-width: 90%; + } + + .custom-lightbox-close { + top: 10px; + right: 15px; + font-size: 2rem; + } +} + +@media (max-width: 480px) { + .main-header { + padding: 2rem 1rem; + min-height: 90vh; + } + + .main-header h1 { + font-size: 2rem; + letter-spacing: 0px; + } + + .main-header::after { + font-size: 2rem; + bottom: 20px; + right: 20px; + } + + .section h2 { + font-size: 1.4rem; + } + + .profile-picture { + width: 100px; + height: 100px; + } + + .profile-about { + font-size: 0.9rem; + } + + .blog-card, + .music-card, + .photo-item, + .video-item { + transform: skewX(0deg); + box-shadow: 4px 4px 0 var(--accent-grey); + } + + .photo-item img { + height: 200px; + } + + .main-nav a { + font-size: 0.7rem; + padding: 0.6rem 1.5rem; + letter-spacing: 2px; + } +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes zoomIn { + from { transform: scale(0.8); opacity: 0; } + to { transform: scale(1); opacity: 1; } +} + +/* Refresh/Randomize buttons */ +.refresh-button { + background: var(--bg-primary); + color: var(--accent-yellow) !important; /* Force black */ + border: 2px solid var(--accent-yellow); + padding: 0.5rem 1.5rem; + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: 0.7rem; + letter-spacing: 3px; + text-transform: uppercase; + cursor: pointer; + transition: all 0.3s ease; +} + +.refresh-button:hover { + transform: scale(1.05); + background: var(--accent-yellow); + color: var(--bg-primary) !important; /* Yellow on hover */ + border-color: var(--accent-yellow); +} + +.refresh-button span { + display: inline-block; +} + +/* ============ CYBERPUNK FOOTER ============ */ + +.site-footer { + background: var(--bg-primary); + border-top: 4px solid var(--accent-yellow); + padding: 3rem 2rem 2rem; + margin-top: 3rem; + position: relative; + overflow: hidden; + transition: background-color 0.4s ease, border-color 0.4s ease; +} + +/* Cyberpunk grid overlay */ +.site-footer::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: + repeating-linear-gradient( + 33deg, + transparent, + transparent 50px, + var(--accent-yellow) 50px, + var(--accent-yellow) 51px + ); + opacity: 0.03; + pointer-events: none; + z-index: 0; +} + +/* Top decorative line with scanline effect */ +.site-footer::after { + content: ''; + position: absolute; + top: -2px; + left: 0; + right: 0; + height: 4px; + background: repeating-linear-gradient( + 90deg, + var(--accent-yellow) 0px, + var(--accent-yellow) 20px, + transparent 20px, + transparent 25px + ); + opacity: 0.6; + z-index: 1; +} + +/* Glow line */ +.site-footer .footer-glow { + position: absolute; + top: -4px; + left: 10%; + right: 10%; + height: 2px; + background: var(--accent-yellow); + box-shadow: 0 0 30px var(--accent-yellow); + opacity: 0.3; + z-index: 1; +} + +.footer-content { + max-width: 1200px; + margin: 0 auto; + display: flex; + justify-content: space-between; + align-items: flex-start; + flex-wrap: wrap; + gap: 2rem; + position: relative; + z-index: 1; +} + +/* Left column */ +.footer-left { + display: flex; + flex-direction: column; + gap: 1rem; + flex: 1; + min-width: 200px; +} + +.footer-brand { + font-family: 'Poppins', sans-serif; + font-weight: 900; + font-size: 1.8rem; + letter-spacing: -2px; + color: var(--text-primary); + text-transform: uppercase; + position: relative; + display: inline-block; +} + +.footer-brand .copyleft { + color: var(--accent-yellow); + font-weight: 900; +} + +.footer-brand .year { + font-weight: 300; + color: var(--accent-grey); + font-size: 1.2rem; +} + +.footer-brand::after { + content: ''; + position: absolute; + bottom: -4px; + left: 0; + width: 40px; + height: 3px; + background: var(--accent-yellow); + transform: skewX(-33deg); +} + +.footer-tagline { + font-family: 'Poppins', sans-serif; + font-weight: 300; + font-size: 0.8rem; + color: var(--accent-grey); + letter-spacing: 4px; + text-transform: uppercase; + margin-top: 0.5rem; + opacity: 0.8; +} + +.footer-tagline span { + color: var(--accent-yellow); + font-weight: 600; +} + +.footer-statement { + font-family: 'Poppins', sans-serif; + font-weight: 400; + font-size: 0.85rem; + color: var(--text-secondary); + letter-spacing: 1px; + border-left: 3px solid var(--accent-yellow); + padding-left: 1rem; +} + +/* Right column */ +.footer-right { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 0.8rem; + flex: 1; + min-width: 200px; +} + +.footer-meta-item { + font-family: 'Poppins', sans-serif; + font-weight: 300; + font-size: 0.75rem; + color: var(--accent-grey); + letter-spacing: 1px; + display: flex; + align-items: center; + gap: 0.5rem; + transition: all 0.3s ease; +} + +.footer-meta-item:hover { + color: var(--text-primary); +} + +.footer-meta-item .icon { + font-size: 1rem; + display: inline-block; + width: 1.5rem; + text-align: center; +} + +.footer-meta-item .label { + color: var(--accent-grey); + font-weight: 400; + text-transform: uppercase; + font-size: 0.6rem; + letter-spacing: 2px; + opacity: 0.6; +} + +.footer-meta-item .value { + font-weight: 500; + color: var(--text-primary); +} + +.footer-meta-item a { + color: var(--accent-yellow); + text-decoration: none; + font-weight: 500; + transition: all 0.3s ease; + border-bottom: 1px solid transparent; + padding-bottom: 1px; +} + +.footer-meta-item a:hover { + color: var(--text-primary); + border-bottom-color: var(--accent-yellow); +} + +/* Bottom bar */ +.footer-bottom { + max-width: 1200px; + margin: 1.5rem auto 0; + padding-top: 1.5rem; + border-top: 1px solid rgba(138, 138, 138, 0.2); + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 1rem; + position: relative; + z-index: 1; +} + +.footer-bottom-text { + font-family: 'Poppins', sans-serif; + font-weight: 300; + font-size: 0.6rem; + color: var(--accent-grey); + letter-spacing: 3px; + text-transform: uppercase; + opacity: 0.5; +} + +.footer-bottom-text span { + color: var(--accent-yellow); + opacity: 1; +} + +.footer-social { + display: flex; + gap: 1.5rem; +} + +.footer-social a { + color: var(--accent-grey); + text-decoration: none; + font-family: 'Poppins', sans-serif; + font-weight: 600; + font-size: 0.65rem; + letter-spacing: 2px; + text-transform: uppercase; + transition: all 0.3s ease; + border: 1px solid transparent; + padding: 0.2rem 0.6rem; +} + +.footer-social a:hover { + color: var(--accent-yellow); + border-color: var(--accent-yellow); + transform: scale(1.05); +} + +/* Responsive footer */ +@media (max-width: 768px) { + .site-footer { + padding: 2rem 1.5rem 1.5rem; + } + + .footer-content { + flex-direction: column; + align-items: stretch; + gap: 1.5rem; + } + + .footer-right { + align-items: flex-start; + } + + .footer-brand { + font-size: 1.5rem; + } + + .footer-bottom { + flex-direction: column; + text-align: center; + gap: 0.8rem; + } + + .footer-social { + justify-content: center; + } + + .footer-meta-item { + font-size: 0.65rem; + } +} + +@media (max-width: 480px) { + .site-footer { + padding: 1.5rem 1rem 1rem; + } + + .footer-brand { + font-size: 1.2rem; + letter-spacing: -1px; + } + + .footer-tagline { + font-size: 0.6rem; + letter-spacing: 2px; + } + + .footer-statement { + font-size: 0.7rem; + padding-left: 0.8rem; + } + + .footer-meta-item { + font-size: 0.55rem; + flex-wrap: wrap; + } + + .footer-bottom-text { + font-size: 0.5rem; + letter-spacing: 2px; + } +} + +/* ============ END CYBERPUNK FOOTER ============ */ diff --git a/themes/one-pager/assets/js/scripts.js b/themes/one-pager/assets/js/scripts.js new file mode 100644 index 0000000..f42a1c2 --- /dev/null +++ b/themes/one-pager/assets/js/scripts.js @@ -0,0 +1,870 @@ +document.addEventListener('DOMContentLoaded', function() { + // Sticky Navigation + const stickyNav = document.getElementById('stickyNav'); + const mainHeader = document.querySelector('.main-header'); + const themeToggle = document.getElementById('themeToggle'); + const themeToggleSmall = document.getElementById('themeToggleSmall'); + let lastScrollY = window.scrollY; + let ticking = false; + + // Function to update sticky nav visibility + function updateStickyNav() { + const scrollY = window.scrollY; + const headerHeight = mainHeader ? mainHeader.offsetHeight : 400; + + if (scrollY > headerHeight - 100) { + stickyNav.classList.add('visible'); + if (themeToggle) { + themeToggle.classList.add('hidden'); + } + } else { + stickyNav.classList.remove('visible'); + if (themeToggle) { + themeToggle.classList.remove('hidden'); + } + } + lastScrollY = scrollY; + } + + // Throttled scroll listener + window.addEventListener('scroll', function() { + if (!ticking) { + window.requestAnimationFrame(function() { + updateStickyNav(); + ticking = false; + }); + ticking = true; + } + }); + + // Initial check + setTimeout(updateStickyNav, 100); + + + + + // Read More toggle for blog posts + const readMoreButtons = document.querySelectorAll('.read-more-toggle'); + + readMoreButtons.forEach(button => { + button.addEventListener('click', function() { + const content = this.nextElementSibling; + if (content.style.display === 'none') { + content.style.display = 'block'; + this.innerHTML = 'Read Less'; + } else { + content.style.display = 'none'; + this.innerHTML = 'Read More'; + } + }); + }); + + + // Smooth scrolling for navigation links (both main nav and sticky nav) + document.querySelectorAll('nav a').forEach(link => { + link.addEventListener('click', function(e) { + e.preventDefault(); + const targetId = this.getAttribute('href'); + const targetElement = document.querySelector(targetId); + if (targetElement) { + // Calculate offset for sticky nav + const navHeight = stickyNav.offsetHeight; + const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - navHeight - 20; + + window.scrollTo({ + top: targetPosition, + behavior: 'smooth' + }); + } + }); + }); + + // ============ CUSTOM LIGHTBOX ============ + const lightbox = document.getElementById('customLightbox'); + const lightboxImage = document.getElementById('lightboxImage'); + const lightboxCaption = document.getElementById('lightboxCaption'); + const lightboxMeta = document.getElementById('lightboxMeta'); + const lightboxCounter = document.getElementById('lightboxCounter'); + const lightboxClose = document.getElementById('lightboxClose'); + const lightboxPrev = document.getElementById('lightboxPrev'); + const lightboxNext = document.getElementById('lightboxNext'); + + let currentPhotos = []; + let currentIndex = 0; + + // Get all photo items + const photoItems = document.querySelectorAll('.photo-item'); + + // Build photo array + photoItems.forEach(item => { + const image = item.querySelector('img'); + const date = item.dataset.date || ''; + const pubkey = item.dataset.pubkey || ''; + const alt = item.dataset.alt || ''; + + if (image) { + currentPhotos.push({ + url: image.src, + alt: alt, + date: date, + pubkey: pubkey + }); + } + }); + + // Open lightbox + function openLightbox(index) { + if (index < 0) index = currentPhotos.length - 1; + if (index >= currentPhotos.length) index = 0; + currentIndex = index; + + const photo = currentPhotos[currentIndex]; + lightboxImage.src = photo.url; + lightboxImage.alt = photo.alt; + lightboxCaption.textContent = photo.alt; + lightboxMeta.textContent = `πŸ“… ${photo.date} | πŸ–ŠοΈ ${photo.pubkey}`; + lightboxCounter.textContent = `${currentIndex + 1} / ${currentPhotos.length}`; + + lightbox.classList.add('active'); + document.body.style.overflow = 'hidden'; + } + + // Close lightbox + function closeLightbox() { + lightbox.classList.remove('active'); + document.body.style.overflow = ''; + } + + // Navigate + function prevPhoto() { + openLightbox(currentIndex - 1); + } + + function nextPhoto() { + openLightbox(currentIndex + 1); + } + + // Event listeners for photo clicks + photoItems.forEach((item, index) => { + const img = item.querySelector('img'); + if (img) { + img.addEventListener('click', function(e) { + e.preventDefault(); + openLightbox(index); + }); + } + }); + + // Event listeners for lightbox controls + lightboxClose.addEventListener('click', closeLightbox); + lightboxPrev.addEventListener('click', prevPhoto); + lightboxNext.addEventListener('click', nextPhoto); + + // Keyboard controls + document.addEventListener('keydown', function(e) { + if (!lightbox.classList.contains('active')) return; + + if (e.key === 'Escape') { + closeLightbox(); + } else if (e.key === 'ArrowLeft') { + prevPhoto(); + } else if (e.key === 'ArrowRight') { + nextPhoto(); + } + }); + + // Click outside image to close + lightbox.addEventListener('click', function(e) { + if (e.target === lightbox) { + closeLightbox(); + } + }); +}); + +// No external lightbox library needed anymore! +console.log('Custom lightbox initialized successfully!'); + +// Artist filter list +const allowedArtists = [ + 'εΎ’ Setto γ‚»γƒƒγƒˆ', +'Settoshi Tonami', +'Sethy Bowoy' +]; + +// Function to check if a track is by an allowed artist +function isAllowedArtist(artist) { + if (!artist) return false; + // Normalize the artist name for comparison (remove extra spaces, lowercase) + const normalizedArtist = artist.trim().toLowerCase(); + + return allowedArtists.some(allowed => { + // Normalize the allowed artist name too + const normalizedAllowed = allowed.trim().toLowerCase(); + // Check if the artist name contains the allowed artist name or vice versa + return normalizedArtist.includes(normalizedAllowed) || + normalizedAllowed.includes(normalizedArtist); + }); +} + +// Render music tracks (randomized, 6 at a time, filtered by artist) +function renderMusicTracks(tracks, containerId) { + const container = document.getElementById(containerId); + if (!container) return; + + // Filter tracks by artist + const filteredTracks = tracks.filter(track => { + // Extract artist from tags + let artist = ''; + if (track.tags) { + track.tags.forEach(tag => { + if (tag[0] === 'artist') { + artist = tag[1]; + } + }); + } + return isAllowedArtist(artist); + }); + + // Check if we have any filtered tracks + if (filteredTracks.length === 0) { + container.innerHTML = '

No tracks found for the selected artists.

'; + return; + } + + // Shuffle and get first 6 + const shuffled = filteredTracks.sort(() => 0.5 - Math.random()); + const selected = shuffled.slice(0, 6); + + // Clear container + container.innerHTML = ''; + + // Render each track (same as before) + selected.forEach(track => { + // Extract data from tags + let title = '', url = '', image = '', artist = '', album = '', + trackNumber = '', duration = '', released = '', language = '', + tags = [], alt = '', content = ''; + + // Parse tags + if (track.tags) { + track.tags.forEach(tag => { + if (tag[0] === 'title') title = tag[1]; + else if (tag[0] === 'url') url = tag[1]; + else if (tag[0] === 'image') image = tag[1]; + else if (tag[0] === 'artist') artist = tag[1]; + else if (tag[0] === 'album') album = tag[1]; + else if (tag[0] === 'track_number') trackNumber = tag[1]; + else if (tag[0] === 'duration') duration = tag[1]; + else if (tag[0] === 'released') released = tag[1]; + else if (tag[0] === 'language') language = tag[1]; + else if (tag[0] === 't') tags.push(tag[1]); + else if (tag[0] === 'alt') alt = tag[1]; + }); + } + + content = track.content || ''; + + // Create music card HTML + const card = document.createElement('div'); + card.className = 'music-card'; + + let cardHTML = ` + ${image ? `${title}` : ''} +
+

${title || 'Untitled'}

+ ${artist ? `

${artist}

` : ''} + ${album ? `

${album}

` : ''} +
+ ${url ? `` : ''} +
+ ${trackNumber ? `Track ${trackNumber}` : ''} + ${duration ? `${duration}s` : ''} + ${released ? `${released}` : ''} + ${language ? `${language}` : ''} +
+
+ ${tags.map(t => `${t}`).join('')} +
+ ${content ? ` + + + ` : ''} + `; + + card.innerHTML = cardHTML; + container.appendChild(card); + }); + + // Re-initialize event listeners for new buttons + initMusicEventListeners(); +} + +// Initialize music event listeners +function initMusicEventListeners() { + // Lyrics toggle + document.querySelectorAll('.lyrics-toggle').forEach(button => { + button.removeEventListener('click', handleLyricsToggle); + button.addEventListener('click', handleLyricsToggle); + }); +} + +function handleLyricsToggle() { + const lyrics = this.nextElementSibling; + if (lyrics && lyrics.classList.contains('lyrics')) { + if (lyrics.style.display === 'none') { + lyrics.style.display = 'block'; + this.innerHTML = 'Hide Info'; + } else { + lyrics.style.display = 'none'; + this.innerHTML = 'Show Info'; + } + } +} + +// Refresh music (randomize) +function refreshMusic() { + if (window.allMusicData) { + renderMusicTracks(window.allMusicData, 'musicGrid'); + } +} + +// Call this when page loads +document.addEventListener('DOMContentLoaded', function() { + if (window.allMusicData && window.allMusicData.length > 0) { + renderMusicTracks(window.allMusicData, 'musicGrid'); + } +}); + +// ============ CUSTOM BLURHASH DECODER ============ +// Based on the official blurhash implementation, but compact + +const Blurhash = { + // Base83 character set + chars: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+,;<=>?@[]^_`{|}~', + + // Decode base83 to integer + decode83: function(str) { + let value = 0; + for (let i = 0; i < str.length; i++) { + const c = str[i]; + const digit = this.chars.indexOf(c); + if (digit === -1) { + throw new Error('Invalid base83 character: ' + c); + } + value = value * 83 + digit; + } + return value; + }, + + // Decode blurhash to pixel data + decode: function(blurhash, width, height, punch = 1) { + // Parse metadata + const sizeFlag = this.decode83(blurhash[0]); + const numX = (sizeFlag % 9) + 1; + const numY = Math.floor(sizeFlag / 9) + 1; + + // Calculate maximum AC component value + const maxAC = this.decode83(blurhash[1]) + 1; + + // Decode DC component + const dcValue = this.decode83(blurhash.slice(2, 6)); + const dc = this.decodeDC(dcValue); + + // Decode AC components + const ac = []; + let acIndex = 6; + for (let y = 0; y < numY; y++) { + for (let x = 0; x < numX; x++) { + if (x === 0 && y === 0) continue; + const encoded = this.decode83(blurhash.slice(acIndex, acIndex + 2)); + acIndex += 2; + const acValue = this.decodeAC(encoded, maxAC * punch); + ac.push({ x, y, value: acValue }); + } + } + + // Render pixels + const pixels = new Uint8ClampedArray(width * height * 4); + const size = width * height; + + // Pre-calculate cos values for performance + const cosX = []; + const cosY = []; + for (let x = 0; x < width; x++) { + cosX[x] = Math.cos(Math.PI * x / width); + } + for (let y = 0; y < height; y++) { + cosY[y] = Math.cos(Math.PI * y / height); + } + + for (let i = 0; i < size; i++) { + const x = i % width; + const y = Math.floor(i / width); + let r = dc[0]; + let g = dc[1]; + let b = dc[2]; + + for (const acVal of ac) { + const basis = cosX[x] * cosY[y]; + const value = acVal.value; + r += value[0] * basis; + g += value[1] * basis; + b += value[2] * basis; + } + + const index = i * 4; + pixels[index] = this.clamp(r + 128); + pixels[index + 1] = this.clamp(g + 128); + pixels[index + 2] = this.clamp(b + 128); + pixels[index + 3] = 255; + } + + return pixels; + }, + + // Decode DC component + decodeDC: function(value) { + return [ + this.signPow((value >> 16) & 0x3ff, 2), + this.signPow((value >> 8) & 0xff, 2), + this.signPow(value & 0xff, 2) + ]; + }, + + // Decode AC component + decodeAC: function(value, maxVal) { + const quantR = Math.floor(value / (19 * 19)); + const quantG = Math.floor((value / 19) % 19); + const quantB = value % 19; + return [ + this.signPow((quantR - 9) / 9, 2) * maxVal, + this.signPow((quantG - 9) / 9, 2) * maxVal, + this.signPow((quantB - 9) / 9, 2) * maxVal + ]; + }, + + // Sign power function + signPow: function(val, exp) { + return Math.sign(val) * Math.pow(Math.abs(val), exp); + }, + + // Clamp value to 0-255 + clamp: function(value) { + return Math.min(255, Math.max(0, value)); + }, + + // Render blurhash to canvas + renderToCanvas: function(blurhash, canvas, punch = 1) { + if (!blurhash) return false; + + try { + const width = canvas.width; + const height = canvas.height; + const pixels = this.decode(blurhash, width, height, punch); + const ctx = canvas.getContext('2d'); + const imageData = ctx.createImageData(width, height); + imageData.data.set(pixels); + ctx.putImageData(imageData, 0, 0); + return true; + } catch (e) { + console.warn('Failed to decode blurhash:', e); + return false; + } + }, + + // Get blurhash as data URL + toDataURL: function(blurhash, width = 64, height = 64, punch = 1) { + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + const success = this.renderToCanvas(blurhash, canvas, punch); + return success ? canvas.toDataURL('image/png') : null; + } +}; + +// ============ RANDOMIZED GALLERIES ============ + +// Function to shuffle array (Fisher-Yates) +function shuffleArray(array) { + const shuffled = [...array]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + return shuffled; +} + +// Render random pictures (6 max) + +function renderRandomPictures(picturesData, containerId) { + const container = document.getElementById(containerId); + if (!container) return; + + // Shuffle and get first 6 + const shuffled = shuffleArray(picturesData); + const selected = shuffled.slice(0, 6); + + // Clear container + container.innerHTML = ''; + + // Render each picture + selected.forEach(picture => { + // Parse imeta tag to get image URL + let imageUrl = ''; + let alt = picture.content || ''; + + if (picture.tags) { + picture.tags.forEach(tag => { + if (tag[0] === 'imeta') { + const imetaStr = tag[1]; + // Extract URL + const urlMatch = imetaStr.match(/url ([^\s]+)/); + if (urlMatch) { + imageUrl = urlMatch[1]; + } + // Extract alt + const altMatch = imetaStr.match(/alt ([^\s]+)/); + if (altMatch) { + alt = altMatch[1]; + } + } + }); + } + + // Create picture item + const item = document.createElement('div'); + item.className = 'photo-item'; + item.dataset.image = imageUrl; + item.dataset.alt = alt; + + const date = new Date(picture.created_at * 1000); + const dateStr = date.toLocaleDateString('en-US', { + year: 'numeric', + month: 'short', + day: 'numeric' + }); + + item.innerHTML = ` + ${imageUrl ? ` + ${alt} + ` : ''} +
+ πŸ“… ${dateStr} +
+ `; + + container.appendChild(item); + }); + + // Re-initialize the custom lightbox for new images + initCustomLightbox(); +} + +// Initialize custom lightbox (call this after any DOM updates) +function initCustomLightbox() { + const lightbox = document.getElementById('customLightbox'); + if (!lightbox) return; + + const lightboxImage = document.getElementById('lightboxImage'); + const lightboxCaption = document.getElementById('lightboxCaption'); + const lightboxMeta = document.getElementById('lightboxMeta'); + const lightboxCounter = document.getElementById('lightboxCounter'); + const lightboxClose = document.getElementById('lightboxClose'); + const lightboxPrev = document.getElementById('lightboxPrev'); + const lightboxNext = document.getElementById('lightboxNext'); + + // Get all photo items + const photoItems = document.querySelectorAll('.photo-item'); + + // Build photo array + let currentPhotos = []; + photoItems.forEach(item => { + const image = item.querySelector('img'); + const date = item.dataset.date || ''; + const pubkey = item.dataset.pubkey || ''; + const alt = item.dataset.alt || ''; + + if (image) { + currentPhotos.push({ + url: image.src, + alt: alt, + date: date, + pubkey: pubkey + }); + } + }); + + let currentIndex = 0; + + // Remove old event listeners by cloning and replacing + const newLightboxImage = lightboxImage.cloneNode(true); + const newLightboxCaption = lightboxCaption.cloneNode(true); + const newLightboxMeta = lightboxMeta.cloneNode(true); + const newLightboxCounter = lightboxCounter.cloneNode(true); + const newLightboxClose = lightboxClose.cloneNode(true); + const newLightboxPrev = lightboxPrev.cloneNode(true); + const newLightboxNext = lightboxNext.cloneNode(true); + + lightboxImage.parentNode.replaceChild(newLightboxImage, lightboxImage); + lightboxCaption.parentNode.replaceChild(newLightboxCaption, lightboxCaption); + lightboxMeta.parentNode.replaceChild(newLightboxMeta, lightboxMeta); + lightboxCounter.parentNode.replaceChild(newLightboxCounter, lightboxCounter); + lightboxClose.parentNode.replaceChild(newLightboxClose, lightboxClose); + lightboxPrev.parentNode.replaceChild(newLightboxPrev, lightboxPrev); + lightboxNext.parentNode.replaceChild(newLightboxNext, lightboxNext); + + // Update references + const newImage = document.getElementById('lightboxImage'); + const newCaption = document.getElementById('lightboxCaption'); + const newMeta = document.getElementById('lightboxMeta'); + const newCounter = document.getElementById('lightboxCounter'); + const newClose = document.getElementById('lightboxClose'); + const newPrev = document.getElementById('lightboxPrev'); + const newNext = document.getElementById('lightboxNext'); + + // Open lightbox + function openLightbox(index) { + if (index < 0) index = currentPhotos.length - 1; + if (index >= currentPhotos.length) index = 0; + currentIndex = index; + + const photo = currentPhotos[currentIndex]; + newImage.src = photo.url; + newImage.alt = photo.alt; + newCaption.textContent = photo.alt; + newMeta.textContent = `πŸ“… ${photo.date} | πŸ–ŠοΈ ${photo.pubkey}`; + newCounter.textContent = `${currentIndex + 1} / ${currentPhotos.length}`; + + lightbox.classList.add('active'); + document.body.style.overflow = 'hidden'; + } + + // Close lightbox + function closeLightbox() { + lightbox.classList.remove('active'); + document.body.style.overflow = ''; + } + + // Navigate + function prevPhoto() { + openLightbox(currentIndex - 1); + } + + function nextPhoto() { + openLightbox(currentIndex + 1); + } + + // Event listeners for photo clicks + photoItems.forEach((item, index) => { + const img = item.querySelector('img'); + if (img) { + // Remove old listener by cloning + const newImg = img.cloneNode(true); + img.parentNode.replaceChild(newImg, img); + newImg.addEventListener('click', function(e) { + e.preventDefault(); + openLightbox(index); + }); + } + }); + + // Event listeners for lightbox controls + newClose.addEventListener('click', closeLightbox); + newPrev.addEventListener('click', prevPhoto); + newNext.addEventListener('click', nextPhoto); + + // Keyboard controls + document.removeEventListener('keydown', handleLightboxKeydown); + document.addEventListener('keydown', handleLightboxKeydown); + + function handleLightboxKeydown(e) { + if (!lightbox.classList.contains('active')) return; + + if (e.key === 'Escape') { + closeLightbox(); + } else if (e.key === 'ArrowLeft') { + prevPhoto(); + } else if (e.key === 'ArrowRight') { + nextPhoto(); + } + } + + // Click outside image to close + lightbox.removeEventListener('click', handleLightboxClick); + lightbox.addEventListener('click', handleLightboxClick); + + function handleLightboxClick(e) { + if (e.target === lightbox) { + closeLightbox(); + } + } +} + +// Update the DOMContentLoaded event listener +document.addEventListener('DOMContentLoaded', function() { + // ... (your existing code for theme toggle, sticky nav, etc.) ... + + // Initialize Music (if you already have this) + if (window.allMusicData && window.allMusicData.length > 0) { + renderMusicTracks(window.allMusicData, 'musicGrid'); + } + + // Initialize Pictures + if (window.allPicturesData && window.allPicturesData.length > 0) { + renderRandomPictures(window.allPicturesData, 'photoGrid'); + } else { + // If no data, still initialize lightbox for static content + initCustomLightbox(); + } + + // Initialize Videos + if (window.allVideosData && window.allVideosData.length > 0) { + renderRandomVideos(window.allVideosData, 'videoGrid'); + } +}); + +// Refresh functions +function refreshMusic() { + if (window.allMusicData) { + renderMusicTracks(window.allMusicData, 'musicGrid'); + } +} + +function refreshPictures() { + if (window.allPicturesData) { + renderRandomPictures(window.allPicturesData, 'photoGrid'); + } +} + +function refreshVideos() { + if (window.allVideosData) { + renderRandomVideos(window.allVideosData, 'videoGrid'); + } +} + +// Render random videos (2 max) +function renderRandomVideos(videosData, containerId) { + const container = document.getElementById(containerId); + if (!container) return; + + // Shuffle and get first 2 + const shuffled = shuffleArray(videosData); + const selected = shuffled.slice(0, 2); + + // Clear container + container.innerHTML = ''; + + // Static poster image + const posterImage = '/images/videoposter.png'; + + + let html = ''; + + selected.forEach(video => { + let videoUrl = ''; + let mimeType = 'video/mp4'; + let alt = video.content || ''; + let dim = ''; + let isVertical = false; + + if (video.tags) { + video.tags.forEach(tag => { + if (tag[0] === 'imeta') { + const imetaStr = tag[1]; + const urlMatch = imetaStr.match(/url ([^\s]+)/); + if (urlMatch) videoUrl = urlMatch[1]; + + const mimeMatch = imetaStr.match(/m ([^\s]+)/); + if (mimeMatch) mimeType = mimeMatch[1]; + + const altMatch = imetaStr.match(/alt ([^\s]+)/); + if (altMatch) alt = altMatch[1]; + + const dimMatch = imetaStr.match(/dim ([^\s]+)/); + if (dimMatch) { + dim = dimMatch[1]; + const [width, height] = dim.split('x').map(Number); + if (height > width) isVertical = true; + } + } + }); + } + + const date = new Date(video.created_at * 1000); + const dateStr = date.toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric' + }); + + const wrapperStyle = isVertical + ? 'style="position:relative;padding-bottom:177.78%;height:0;overflow:hidden;background:var(--accent-black);"' + : ''; + + const videoStyle = isVertical + ? 'style="position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;"' + : 'style="width:100%;"'; + + html += ` +
+ ${videoUrl ? ` +
+ +
+ ` : ''} +
+

${alt}

+
+ πŸ“… ${dateStr} + ${dim ? `πŸ“ ${dim}` : ''} +
+
+
+ `; + }); + + container.innerHTML = html; +} + +// ============ INITIALIZATION ============ + +document.addEventListener('DOMContentLoaded', function() { + // ... (your existing code for theme toggle, sticky nav, etc.) ... + + // Initialize Music (if you already have this) + if (window.allMusicData && window.allMusicData.length > 0) { + renderMusicTracks(window.allMusicData, 'musicGrid'); + } + + // Initialize Pictures + if (window.allPicturesData && window.allPicturesData.length > 0) { + renderRandomPictures(window.allPicturesData, 'photoGrid'); + } + + // Initialize Videos + if (window.allVideosData && window.allVideosData.length > 0) { + renderRandomVideos(window.allVideosData, 'videoGrid'); + } +}); + +// Refresh functions for randomize buttons +function refreshMusic() { + if (window.allMusicData) { + renderMusicTracks(window.allMusicData, 'musicGrid'); + } +} + +function refreshPictures() { + if (window.allPicturesData) { + renderRandomPictures(window.allPicturesData, 'photoGrid'); + } +} + +function refreshVideos() { + if (window.allVideosData) { + renderRandomVideos(window.allVideosData, 'videoGrid'); + } +} diff --git a/themes/one-pager/layouts/index.html b/themes/one-pager/layouts/index.html new file mode 100644 index 0000000..27f4a9a --- /dev/null +++ b/themes/one-pager/layouts/index.html @@ -0,0 +1,180 @@ + + + + + + + {{ partial "seo.html" . }} + + + + + + + + + + {{ $style := resources.Get "css/style.css" | resources.Minify | fingerprint }} + + + + + + {{ partial "header.html" . }} + +
+ +
+

Now Log

+
+ {{ $blogPosts := slice }} + {{ range $path, $entries := hugo.Data.longform }} + {{ range $entries }} + {{ $blogPosts = $blogPosts | append . }} + {{ end }} + {{ end }} + + {{ $sortedPosts := sort $blogPosts "created_at" "desc" }} + {{ range first 2 $sortedPosts }} + {{ $title := "" }} + {{ $summary := "" }} + {{ $image := "" }} + {{ $tags := slice }} + {{ $d := "" }} + {{ $createdAt := int .created_at }} + + {{ range .tags }} + {{ if eq (index . 0) "title" }} + {{ $title = index . 1 }} + {{ else if eq (index . 0) "summary" }} + {{ $summary = index . 1 }} + {{ else if eq (index . 0) "image" }} + {{ $image = index . 1 }} + {{ else if eq (index . 0) "t" }} + {{ $tags = $tags | append (index . 1) }} + {{ else if eq (index . 0) "d" }} + {{ $d = index . 1 }} + {{ end }} + {{ end }} + +
+ {{ if $image }} + {{ $title }} + {{ end }} +
+

{{ $title }}

+

+ {{ dateFormat "January 2, 2006" (time (int .created_at)) }} +

+ {{ if $summary }} +

{{ $summary }}

+ {{ end }} +
+ {{ range $tags }} + {{ . }} + {{ end }} +
+ + +
+
+ {{ end }} +
+
+ + +
+

Music Traxxx

+
+ +
+
+ {{ $allMusic := slice }} + {{ range $path, $entries := hugo.Data.music }} + {{ range $entries }} + {{ $allMusic = $allMusic | append . }} + {{ end }} + {{ end }} + + {{ $musicData := jsonify $allMusic }} + +
+
+ + +
+

Pix & Doodles

+
+ +
+
+ {{ $allPictures := slice }} + {{ range $path, $entries := hugo.Data.pictures }} + {{ range $entries }} + {{ $allPictures = $allPictures | append . }} + {{ end }} + {{ end }} + + + {{ $picturesData := jsonify $allPictures }} + +
+
+ + +
+

Vidz

+
+ +
+
+ {{ $allVideos := slice }} + {{ range $path, $entries := hugo.Data.videos }} + {{ range $entries }} + {{ $allVideos = $allVideos | append . }} + {{ end }} + {{ end }} + + + {{ $videosData := jsonify $allVideos }} + +
+
+
+ + + {{ partial "footer.html" . }} + + +
+ βœ• + + +
+ +
+ + +
+
+
1 / 1
+
+ + {{ $js := resources.Get "js/scripts.js" | resources.Minify | fingerprint }} + + + diff --git a/themes/one-pager/layouts/partials/footer.html b/themes/one-pager/layouts/partials/footer.html new file mode 100644 index 0000000..584955f --- /dev/null +++ b/themes/one-pager/layouts/partials/footer.html @@ -0,0 +1,55 @@ + diff --git a/themes/one-pager/layouts/partials/header.html b/themes/one-pager/layouts/partials/header.html new file mode 100644 index 0000000..efe909f --- /dev/null +++ b/themes/one-pager/layouts/partials/header.html @@ -0,0 +1,85 @@ +{{ $displayName := "" }} +{{ $name := "" }} +{{ $picture := "" }} +{{ $banner := "" }} +{{ $about := "" }} +{{ $website := "" }} +{{ $nip05 := "" }} +{{ $lud16 := "" }} + +{{ range hugo.Data.profile }} + {{ range . }} + {{ range .tags }} + {{ if eq (index . 0) "display_name" }} + {{ $displayName = index . 1 }} + {{ else if eq (index . 0) "name" }} + {{ $name = index . 1 }} + {{ else if eq (index . 0) "picture" }} + {{ $picture = index . 1 }} + {{ else if eq (index . 0) "banner" }} + {{ $banner = index . 1 }} + {{ else if eq (index . 0) "about" }} + {{ $about = index . 1 }} + {{ else if eq (index . 0) "website" }} + {{ $website = index . 1 }} + {{ else if eq (index . 0) "nip05" }} + {{ $nip05 = index . 1 }} + {{ else if eq (index . 0) "lud16" }} + {{ $lud16 = index . 1 }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} + + +{{ if not $displayName }} + {{ $displayName = $name }} +{{ end }} + + + + + + +
+ + {{ if $banner }} +
+ +
+ {{ end }} + + + + +
+ +
+
+ {{ if $picture }} + {{ $displayName }} + {{ end }} +
+ + {{ if $about }} +

{{ if $displayName }}{{ $displayName }}{{ else }}{{ .Site.Title }}{{ end }}

{{ $about | markdownify }}
+ {{ else }} +
{{ .Site.Params.description }}
+ {{ end }} +
+
+
+ +
diff --git a/themes/one-pager/layouts/partials/seo.html b/themes/one-pager/layouts/partials/seo.html new file mode 100644 index 0000000..b20bcf0 --- /dev/null +++ b/themes/one-pager/layouts/partials/seo.html @@ -0,0 +1,148 @@ + + + +{{/* Get profile data */}} +{{ $displayName := "" }} +{{ $name := "" }} +{{ $picture := "" }} +{{ $about := "" }} + +{{ range hugo.Data.profile }} + {{ range . }} + {{ range .tags }} + {{ if eq (index . 0) "display_name" }} + {{ $displayName = index . 1 }} + {{ else if eq (index . 0) "name" }} + {{ $name = index . 1 }} + {{ else if eq (index . 0) "picture" }} + {{ $picture = index . 1 }} + {{ else if eq (index . 0) "about" }} + {{ $about = index . 1 }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} + +{{/* Fallback if display_name is empty */}} +{{ if not $displayName }} + {{ $displayName = $name }} +{{ end }} + +{{/* If still empty, use site title */}} +{{ if not $displayName }} + {{ $displayName = .Site.Title }} +{{ end }} + +{{/* Clean about text - remove markdown and HTML */}} +{{ $cleanAbout := $about | plainify | htmlUnescape }} +{{ $cleanAbout = trim $cleanAbout " \n\r\t" }} + +{{/* Truncate to 160 chars for SEO */}} +{{ $truncatedAbout := $cleanAbout }} +{{ if gt (len $truncatedAbout) 160 }} + {{ $truncatedAbout = substr $truncatedAbout 0 160 | printf "%s…" }} +{{ end }} + +{{/* Hugo escaping functions */}} +{{ $escapedTitle := $displayName | safeHTMLAttr }} +{{ $escapedDescription := $truncatedAbout | safeHTMLAttr }} +{{ $escapedPicture := $picture | safeURL }} +{{ $escapedSiteTitle := .Site.Title | safeHTMLAttr }} + +{{/* Build time in ISO 8601 format */}} +{{ $buildTime := now.Format "2006-01-02T15:04:05-07:00" }} +{{ $buildTimeRFC3339 := now.Format "2006-01-02T15:04:05Z07:00" }} + +{{/* Hugo version */}} +{{ $hugoVersion := hugo.Version }} + +{{/* Base URL */}} +{{ $baseURL := .Site.BaseURL | safeURL }} +{{ $permalink := .Permalink | safeURL }} + + +{{ $escapedTitle }}{{ if ne $escapedTitle $escapedSiteTitle }} | {{ $escapedSiteTitle }}{{ end }} + + + + + + + + + + + + + + +{{ if $picture }} + +{{ end }} + + + + + + + + + +{{ if $picture }} + + +{{ end }} + + + + + + + + + + + + + + + + + + + + diff --git a/themes/one-pager/static/images/videoposter.png b/themes/one-pager/static/images/videoposter.png new file mode 100644 index 0000000000000000000000000000000000000000..7c7f8f944c495b11f7cb6ed628ee1857d7867bc1 GIT binary patch literal 31431 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 Wj+#Bcnh6e}Ca93qmGe$q2>2fjQw%u( literal 0 HcmV?d00001 diff --git a/video-poster.svg b/video-poster.svg new file mode 100644 index 0000000..b82639c --- /dev/null +++ b/video-poster.svg @@ -0,0 +1,56 @@ + + + +