14 Commits

Author SHA1 Message Date
e038d31671 Seperate CSS for music 2026-02-28 17:32:17 -05:00
8b74501e14 Add thin yellow box outline around announcement
- Add border and padding to .announcement class
- Makes 'EXCLUSIVE: Leaked mixtape' text stand out
2026-02-28 17:09:05 -05:00
c1ab8e831b Minor Manual Fixes to Lobster's code 2026-02-28 16:52:01 -05:00
447265f7ed Fix: Center blog post content properly
- Use flexbox on blog-post container to center all children
- Set max-width on post container to constrain width
- Ensure content paragraph takes full width and centers text
2026-02-28 16:45:00 -05:00
e5b6d785ed Fix: Image path for homepage preview and center blog content
- Use absolute path for image (/blog/src/img/...) so homepage preview loads correctly
- Center blog post content with max-width for better readability
2026-02-28 16:42:56 -05:00
73f6c462f8 Make blog page dynamic using JSON data
- Blog posts now load from blog/posts.json
- Create blog/script.js to dynamically render posts
- Each post displays: title, date, content, image
- Support hash-based navigation to specific posts
- Updated blog/index.html to load posts dynamically
- Added styling for blog posts and containers
- First post is 'Status' matching the original content
2026-02-28 16:38:42 -05:00
a965274a31 Add dynamic blog preview to homepage
- Create blog/posts.json for managing blog post metadata
- Add blog preview box (max 1/3 screen width) to homepage
- Fetch latest post dynamically with image and excerpt
- Updates automatically when new posts added to JSON
- Styled to fit no-scroll homepage layout
- Link to full blog page for each post
2026-02-28 16:30:19 -05:00
7e8727d1b5 Fixing OpenClaw's CSS formatting 2026-02-28 15:22:06 +00:00
2293a3f566 Fixing OpenClaw's formatting 2026-02-28 15:21:43 +00:00
a38d756f4b Add music platform with DGDN album player
- Create /music landing page with artist grid
- Add /music/Darnea artist page with album listing
- Build /music/Darnea/DGDN album player with clickable tracklist
- Auto-play next track on completion
- Dangrubb-branded styling with cyan accent colors
- FLAC player pulls from /src/audio/DGDN
- Move landing page links to bottom with yellow announcement box
2026-02-28 15:20:27 +00:00
025fe8a80b Updated blog with image 2025-09-25 20:55:52 -04:00
7b70740e46 Updated blog 2025-09-21 09:01:55 -04:00
c5a6b90d7e Changed Blog Location 2025-09-21 08:32:48 -04:00
b93c70542e Updated CV for 9/2025 2025-09-21 08:07:58 -04:00
51 changed files with 1467 additions and 60 deletions

254
blog/index.html Normal file
View File

@ -0,0 +1,254 @@
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>dangrubb.net</title>
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- partial:index.partial.html -->
<div class="bard">
<div class="strip" style="
--glitch-x-1: -2em;
--glitch-hue-1: -16deg;
--glitch-x-2: 2em;
--glitch-hue-2: 13deg;
background-position: 0 -0em;
height: 5em;
animation-name: glitch-9;
animation-duration: 9000ms;
animation-delay: 2s;
"></div>
<div class="strip" style="
--glitch-x-1: -1em;
--glitch-hue-1: -42deg;
--glitch-x-2: -6em;
--glitch-hue-2: -23deg;
background-position: 0 -5em;
height: 3em;
animation-name: glitch-5;
animation-duration: 5000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: -10em;
--glitch-hue-1: -42deg;
--glitch-x-2: -9em;
--glitch-hue-2: 45deg;
background-position: 0 -8em;
height: 3em;
animation-name: glitch-7;
animation-duration: 7000ms;
animation-delay: 0s;
"></div>
<div class="strip" style="
--glitch-x-1: -6em;
--glitch-hue-1: -11deg;
--glitch-x-2: 2em;
--glitch-hue-2: 29deg;
background-position: 0 -11em;
height: 5em;
animation-name: glitch-8;
animation-duration: 8000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: 0em;
--glitch-hue-1: 42deg;
--glitch-x-2: 2em;
--glitch-hue-2: -28deg;
background-position: 0 -16em;
height: 5em;
animation-name: glitch-6;
animation-duration: 6000ms;
animation-delay: 0s;
"></div>
<div class="strip" style="
--glitch-x-1: -3em;
--glitch-hue-1: -45deg;
--glitch-x-2: -5em;
--glitch-hue-2: -15deg;
background-position: 0 -21em;
height: 2em;
animation-name: glitch-7;
animation-duration: 7000ms;
animation-delay: 0s;
"></div>
<div class="strip" style="
--glitch-x-1: -5em;
--glitch-hue-1: 35deg;
--glitch-x-2: 9em;
--glitch-hue-2: 35deg;
background-position: 0 -23em;
height: 2em;
animation-name: glitch-6;
animation-duration: 6000ms;
animation-delay: 0s;
"></div>
<div class="strip" style="
--glitch-x-1: 10em;
--glitch-hue-1: 39deg;
--glitch-x-2: -8em;
--glitch-hue-2: 24deg;
background-position: 0 -25em;
height: 6em;
animation-name: glitch-7;
animation-duration: 7000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: -6em;
--glitch-hue-1: -46deg;
--glitch-x-2: -3em;
--glitch-hue-2: 18deg;
background-position: 0 -31em;
height: 6em;
animation-name: glitch-10;
animation-duration: 10000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: -8em;
--glitch-hue-1: -37deg;
--glitch-x-2: -6em;
--glitch-hue-2: 15deg;
background-position: 0 -37em;
height: 1em;
animation-name: glitch-9;
animation-duration: 9000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: -1em;
--glitch-hue-1: 16deg;
--glitch-x-2: 2em;
--glitch-hue-2: 25deg;
background-position: 0 -38em;
height: 2em;
animation-name: glitch-5;
animation-duration: 5000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: 5em;
--glitch-hue-1: 32deg;
--glitch-x-2: 10em;
--glitch-hue-2: -3deg;
background-position: 0 -40em;
height: 2em;
animation-name: glitch-9;
animation-duration: 9000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: 10em;
--glitch-hue-1: -26deg;
--glitch-x-2: 6em;
--glitch-hue-2: -45deg;
background-position: 0 -42em;
height: 4em;
animation-name: glitch-6;
animation-duration: 6000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: -7em;
--glitch-hue-1: -45deg;
--glitch-x-2: -8em;
--glitch-hue-2: 45deg;
background-position: 0 -46em;
height: 3em;
animation-name: glitch-5;
animation-duration: 5000ms;
animation-delay: 2s;
"></div>
<div class="strip" style="
--glitch-x-1: 4em;
--glitch-hue-1: 40deg;
--glitch-x-2: -8em;
--glitch-hue-2: 29deg;
background-position: 0 -49em;
height: 3em;
animation-name: glitch-6;
animation-duration: 6000ms;
animation-delay: 1s;
"></div>
<div class="strip" style="
--glitch-x-1: -4em;
--glitch-hue-1: 26deg;
--glitch-x-2: -6em;
--glitch-hue-2: -3deg;
background-position: 0 -52em;
height: 6em;
animation-name: glitch-10;
animation-duration: 10000ms;
animation-delay: 0s;
"></div>
<div class="strip" style="
--glitch-x-1: 6em;
--glitch-hue-1: 43deg;
--glitch-x-2: -1em;
--glitch-hue-2: -1deg;
background-position: 0 -58em;
height: 4em;
animation-name: glitch-8;
animation-duration: 8000ms;
animation-delay: 0s;
"></div>
</div>
<p>
dangrubb.net/blog
</p>
<p>
<a href="../index.html"><-- back to home</a>
</p>
<div id="blogsContainer" class="blogs-container">
<p style="color: #9d9aa4;">Loading blog posts...</p>
</div>
<!-- partial -->
<script src="./script.js"></script>
</body>
</html>

11
blog/posts.json Normal file
View File

@ -0,0 +1,11 @@
[
{
"id": "01",
"title": "Status",
"date": "2026-02-28",
"excerpt": "dangrubb.net is fully functional and operating at 18% of potential. When Blog updates are posted, this score will increase to 19%.",
"content": "<p>dangrubb.net is fully functional and operating at 18% of potential. When Blog updates are posted, this score will increase to 19%.</p>",
"image": "/blog/src/img/CannotConnect.JPEG",
"slug": "status"
}
]

53
blog/script.js Normal file
View File

@ -0,0 +1,53 @@
"use strict";
// Load and display blog posts from JSON
async function loadBlogPosts() {
try {
const response = await fetch('./posts.json');
const posts = await response.json();
const blogsContainer = document.getElementById('blogsContainer');
if (posts.length === 0) {
blogsContainer.innerHTML = '<div class="no-posts"><p>No blog posts yet.</p></div>';
return;
}
// Create HTML for each post
const postsHTML = posts.map(post => `
<article class="blog-post" id="${post.slug}">
<h2 class="blog-post-title">${post.title}</h2>
<div class="blog-post-date">${new Date(post.date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}</div>
<div class="blog-post-content">
${post.content}
</div>
<div class="blog-post-image">
<img src="${post.image}" alt="${post.title}" />
</div>
</article>
`).join('');
blogsContainer.innerHTML = postsHTML;
} catch (error) {
console.error('Error loading blog posts:', error);
document.getElementById('blogsContainer').innerHTML = '<div class="error"><p>Error loading blog posts.</p></div>';
}
}
// Load blog posts when page is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', loadBlogPosts);
} else {
loadBlogPosts();
}
// Handle hash-based navigation to specific posts
window.addEventListener('hashchange', () => {
const postId = window.location.hash.slice(1);
if (postId) {
const element = document.getElementById(postId);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

290
blog/style.css Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -201,13 +201,35 @@
</div>
</section>
</div>
<div class="resume__right">
<!--========== EXPERIENCE ==========-->
<section class="experience section" id="experience">
<h2 class="section-title">Experience</h2>
<div class="experience__container bd-grid">
<div class="experience__content">
<div class="experience__time">
<span class="experience__rounder"></span>
<span class="experience__line"></span>
</div>
<div class="experience__data bd-grid">
<h3 class="experience__title">IT Consultant and Support Technician</h3>
<span class="experience__company"
>2025 to Present | Blue Tech Innovation</span>
<p class="experience__description">
<ul class="experience__description">
<li>• Provide administration and internal support for company systems, including PCs, Macs, phones, printers, servers, and other related equipment.</li>
<li>• Offer end-user support for both office-based and remote employees.</li>
<li>• Ensure the health, stability, and best practices configuration of client infrastructures.</li>
<li>• Troubleshoot and resolve issues with the following technologies:</li>
<li>• Windows Server, VPN Clients, Group Policy, Folder Permissions</li>
<li>• Firewalls, Printer Servers, Office 365</li>
<li>• Mac systems, workstation and network connectivity issues</li>
<li>• Exchange Server, Microsoft Office Applications, and the latest Microsoft Office suite versions</li>
</ul>
</p>
</div>
</div>
<div class="experience__content">
<div class="experience__time">
<span class="experience__rounder"></span>
@ -216,8 +238,7 @@
<div class="experience__data bd-grid">
<h3 class="experience__title">Technical Account Manager</h3>
<span class="experience__company"
>2023 to Present | ITG</span
>
>2023 to 2025 | ITG</span>
<p class="experience__description">
<ul class="experience__description">
<li>• Ensure customer success with technical consulting and implementation of adaptive software and hardware.</li>
@ -235,13 +256,11 @@
<div class="experience__content">
<div class="experience__time">
<span class="experience__rounder"></span>
<span class="experience__line"></span>
<span class="experience__line__last"></span>
</div>
<div class="experience__data bd-grid">
<h3 class="experience__title">Field Technician</h3>
<span class="experience__company"
>2023 | Dell</span
>
<span class="experience__company">2023 | Dell</span>
<p class="experience__description">
<ul class="experience__description">
<li>• Managed a workload of repairs in a ticketing system.</li>
@ -253,28 +272,7 @@
</p>
</div>
</div>
<div class="experience__content">
<div class="experience__time">
<span class="experience__rounder"></span>
<!-- <span class="experience__line"></span> -->
</div>
<div class="experience__data bd-grid">
<h3 class="experience__title">
Lead Repair Technician
</h3>
<span class="experience__company"
>2021 to 2022 | T-Mobile</span
>
<p class="experience__description">
<ul class="experience__description">
<li>• Diagnosed and repaired cellphones, tablets, laptops, and other mobile devices.</li>
<li>• Efficiently diagnosed issues with customers' devices and performed all necessary repairs.</li>
<li>• Handled inventory and parts returns while ensuring systems were up to date.</li>
<li>• Exceeded SLA expectations completing 90% of repairs in under 90 minutes.</li>
</ul>
</p>
</div>
</div>
<a href="moreInformation.html" class="more__information">
<i class="bx bx-info-circle information__icon"></i>
More Information
@ -284,7 +282,7 @@
<!--========== CERTIFICATES ==========-->
<section class="certificate section" id="certificates">
<h2 class="section-title">Certificates</h2>
<h2 class="section-title">Certifications</h2>
<div class="certificate__container bd-grid">
<div class="certificate__content">

View File

@ -214,11 +214,37 @@
<h2 class="section-title">Experience</h2>
<div class="experience__container bd-grid">
<div class="experience__content">
<div class="experience__time">
<span class="experience__rounder"></span>
<span class="experience__line"></span>
</div>
<div class="experience__data bd-grid">
<h3 class="experience__title">IT Consultant and Support Technician</h3>
<span class="experience__company"
>2025 to Present | Blue Tech Innovation</span>
<p class="experience__description">
<ul class="experience__description">
<li>• Provide administration and internal support for company systems, including PCs, Macs, phones, printers, servers, and other related equipment.</li>
<li>• Offer end-user support for both office-based and remote employees.</li>
<li>• Ensure the health, stability, and best practices configuration of client infrastructures.</li>
<li>• Troubleshoot and resolve issues with the following technologies:</li>
<li>• Windows Server, VPN Clients, Group Policy, Folder Permissions</li>
<li>• Firewalls, Printer Servers, Office 365</li>
<li>• Mac systems, workstation and network connectivity issues</li>
<li>• Exchange Server, Microsoft Office Applications, and the latest Microsoft Office suite versions</li>
</ul>
</p>
</div>
</div>
<div class="experience__content">
<div class="experience__time">
<span class="experience__rounder"></span>
<span class="experience__line"></span>
</div>
<div class="experience__data bd-grid">
<h3 class="experience__title">Technical Account Manager</h3>
<span class="experience__company"

View File

@ -139,6 +139,11 @@ body.scale-cv {
height: 110%;
transform: translate(5px, 0);
}
.scale-cv .experience__line__last {
width: 1px;
height: 100%;
transform: translate(5px, 0);
}
.scale-cv .education__data,
.scale-cv .experience__data {
gap: 0.25rem;
@ -410,7 +415,14 @@ img {
.experience__line {
display: block;
width: 2px;
height: 110%;
height: 109%;
background-color: var(--text-color-light);
transform: translate(7px, 0);
}
.experience__line__last {
display: block;
width: 2px;
height: 100%;
background-color: var(--text-color-light);
transform: translate(7px, 0);
}
@ -430,6 +442,7 @@ img {
.education__year {
font-size: var(--smaller-font-size);
}
/*========== SKILLS AND LANGUAGES ==========*/
.skills__content,
.languages__content {

View File

@ -238,16 +238,33 @@
<p>
dangrubb.net
</p>
<p>
<a target="_parent" href="https://ai.dangrubb.net">ai</a>
<a target="_parent" href="https://ghost.dangrubb.net">blog</a>
<a target="_parent" href="https://pi.dangrubb.net/jellyfin">media</a>
<a target="_parent" href="https://pi.dangrubb.net/nextcloud">storage</a>
<a target="_parent" href="https://dangrubb.net/cv">cv</a>
<a target="_parent" href="https://pi.dangrubb.net/dangit">git</a></p>
<p class="announcement">
<a href="https://dangrubb.net/music">EXCLUSIVE: Leaked mixtape from Darnea's vault</a>
</p>
<div class="blog-preview-container">
<div class="blog-preview" id="latestBlogPreview">
<p style="color: #9d9aa4;">Loading latest post...</p>
</div>
</div>
<div class="debug">
<div class="code"></div>
</div>
<!-- Navigation Links (now pinned to bottom via CSS) -->
<nav class="bottom-nav">
<p>
<a target="_parent" href="https://ai.dangrubb.net">ai</a>
<a target="_parent" href="https://dangrubb.net/blog">blog</a>
<a target="_parent" href="https://pi.dangrubb.net/jellyfin">media</a>
<a target="_parent" href="https://pi.dangrubb.net/nextcloud">storage</a>
<a target="_parent" href="https://dangrubb.net/cv">cv</a>
<a target="_parent" href="https://pi.dangrubb.net/dangit">git</a>
</p>
</nav>
<!-- partial -->
<script src="./script.js"></script>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DGDN - Darnea | dangrubb.net</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="../../music.css">
<link rel="stylesheet" href="./player.css">
</head>
<body>
<div class="music-container">
<div class="music-header">
<h1><a href="/music">Music</a> / <a href="/music/Darnea">Darnea</a> / DGDN</h1>
</div>
<div class="album-player">
<div class="album-header">
<div class="album-artwork">🔥</div>
<div class="album-info">
<h2>DGDN</h2>
<p class="artist-name">Darnea</p>
<p class="album-desc">Leaked from the vault</p>
</div>
</div>
<div class="player-section">
<div id="now-playing" class="now-playing">
<p>Select a track to play</p>
</div>
<audio id="audio-player" controls></audio>
</div>
<div class="tracklist">
<h3>Tracklist</h3>
<ol id="tracks-list"></ol>
</div>
</div>
<div class="music-footer">
<p><a href="/music/Darnea">← back to artist</a></p>
</div>
</div>
<script src="./player.js"></script>
</body>
</html>

View File

@ -0,0 +1,139 @@
/* Album Player */
.album-player {
margin: 40px 0;
}
.album-header {
display: flex;
gap: 30px;
margin-bottom: 40px;
padding: 30px;
background: rgba(107, 225, 233, 0.05);
border-radius: 8px;
align-items: center;
}
.album-artwork {
font-size: 5rem;
min-width: 150px;
text-align: center;
}
.album-info h2 {
margin: 0 0 5px 0;
font-size: 2rem;
color: #9d9aa4;
}
.album-info .artist-name {
margin: 0 0 5px 0;
color: #6be1e9;
font-size: 1.1rem;
}
.album-info .album-desc {
margin: 0;
color: #6be1e9;
font-size: 0.9rem;
font-style: italic;
}
/* Now Playing */
.now-playing {
text-align: center;
padding: 20px;
background: rgba(107, 225, 233, 0.1);
border: 1px solid rgba(107, 225, 233, 0.3);
border-radius: 6px;
margin-bottom: 20px;
min-height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.now-playing p {
margin: 0;
color: #9d9aa4;
}
.now-playing.playing p {
color: #6be1e9;
font-weight: bold;
}
/* Audio Player */
#audio-player {
width: 100%;
margin-bottom: 30px;
accent-color: #6be1e9;
}
/* Tracklist */
.tracklist {
margin-top: 40px;
}
.tracklist h3 {
margin: 0 0 20px 0;
font-size: 1.3rem;
color: #9d9aa4;
}
.tracklist ol {
list-style-position: inside;
padding: 0;
margin: 0;
}
.tracklist li {
padding: 12px;
margin-bottom: 8px;
background: rgba(157, 154, 164, 0.05);
border: 1px solid rgba(107, 225, 233, 0.2);
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
color: #9d9aa4;
}
.tracklist li:hover {
background: rgba(107, 225, 233, 0.1);
border-color: rgba(107, 225, 233, 0.5);
}
.tracklist li.active {
background: rgba(107, 225, 233, 0.2);
border-color: #6be1e9;
color: #6be1e9;
font-weight: bold;
}
.track-duration {
float: right;
color: #6be1e9;
font-size: 0.9rem;
}
/* Responsive */
@media (max-width: 768px) {
.album-header {
flex-direction: column;
gap: 15px;
text-align: center;
}
.album-artwork {
font-size: 3rem;
}
.album-info h2 {
font-size: 1.5rem;
}
.tracklist li {
padding: 10px;
font-size: 0.9rem;
}
}

View File

@ -0,0 +1,71 @@
// Album player for DGDN
const tracks = [
{ title: "Dan Beat (bonus)", filename: "Dan Beat (bonus).flac" },
{ title: "Neigh V3", filename: "Neigh V3.flac" },
{ title: "On Ice", filename: "On Ice.flac" },
{ title: "Otish", filename: "Otish.flac" },
{ title: "Scan V2", filename: "Scan V2.flac" },
{ title: "balance v2", filename: "balance v2.flac" },
{ title: "eh ee uhn V2", filename: "eh ee uhn V2.flac" },
{ title: "held v3", filename: "held v3.flac" }
];
const audioPlayer = document.getElementById('audio-player');
const tracksList = document.getElementById('tracks-list');
const nowPlaying = document.getElementById('now-playing');
let currentTrackIndex = 0;
// Build tracklist
function initTracklist() {
tracks.forEach((track, index) => {
const li = document.createElement('li');
li.textContent = track.title;
li.dataset.index = index;
li.addEventListener('click', () => playTrack(index));
tracksList.appendChild(li);
});
}
// Play track
function playTrack(index) {
currentTrackIndex = index;
const track = tracks[index];
// Update audio source
audioPlayer.src = `/src/audio/DGDN/${track.filename}`;
audioPlayer.play();
// Update UI
updateNowPlaying(track.title);
updateActiveTrack();
}
// Update now playing display
function updateNowPlaying(title) {
nowPlaying.classList.add('playing');
nowPlaying.innerHTML = `<p>▶ Now playing: ${title}</p>`;
}
// Update active track in list
function updateActiveTrack() {
document.querySelectorAll('.tracklist li').forEach((li, i) => {
li.classList.toggle('active', i === currentTrackIndex);
});
}
// Auto-play next track when current ends
audioPlayer.addEventListener('ended', () => {
if (currentTrackIndex < tracks.length - 1) {
playTrack(currentTrackIndex + 1);
}
});
// Update active track when manually seeking/playing
audioPlayer.addEventListener('play', () => {
updateActiveTrack();
});
// Initialize
initTracklist();

34
music/Darnea/index.html Normal file
View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Darnea - dangrubb.net</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="../music.css">
</head>
<body>
<div class="music-container">
<div class="music-header">
<h1><a href="/music">Music</a> / Darnea</h1>
</div>
<div class="artist-detail">
<div class="artist-banner">🎤</div>
<h2>Darnea</h2>
</div>
<div class="albums-grid">
<div class="album-card">
<div class="album-cover">🔥</div>
<h3><a href="/music/Darnea/DGDN">DGDN</a></h3>
<p class="album-meta">8 tracks</p>
</div>
</div>
<div class="music-footer">
<p><a href="/music">← back to music</a></p>
</div>
</div>
</body>
</html>

29
music/index.html Normal file
View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>dangrubb.net Music</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/src/img/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="./music.css">
</head>
<body>
<div class="music-container">
<div class="music-header">
<h1><a href="/">dangrubb</a>.net/music</h1>
</div>
<div class="artists-grid">
<div class="artist-card">
<div class="artist-cover">🎤</div>
<h2><a href="/music/Darnea">Darnea</a></h2>
<p class="artist-meta">1 album</p>
</div>
</div>
<div class="music-footer">
<p><a href="/">← back home</a></p>
</div>
</div>
</body>
</html>

212
music/music.css Normal file
View File

@ -0,0 +1,212 @@
/* --- BASE STYLES (Merged from style.css) --- */
body {
background: #0d0a14;
padding: 40px 20px;
font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;
color: #9d9aa4;
/* Fixed the no-scroll issue here: */
min-height: 100vh;
margin: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
overflow-y: auto;
}
a {
color: #6be1e9;
text-decoration: none;
}
a:focus,
a:hover,
a:visited {
opacity: 0.8;
}
/* --- MUSIC PLATFORM STYLING --- */
.music-container {
max-width: 900px;
margin: 0 auto;
padding: 40px 20px;
flex: 1; /* Allows container to grow and push footer down */
}
.music-header {
text-align: center;
margin-bottom: 50px;
border-bottom: 2px solid rgba(107, 225, 233, 0.3);
padding-bottom: 20px;
}
.music-header h1 {
margin: 0;
font-size: 2rem;
color: #9d9aa4;
font-weight: bold;
}
.music-header h1 a {
color: #6be1e9;
}
/* Artists/Albums Grid */
.artists-grid,
.albums-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 30px;
margin: 40px 0;
}
.artist-card,
.album-card {
text-align: center;
padding: 20px;
background: rgba(157, 154, 164, 0.05);
border: 1px solid rgba(107, 225, 233, 0.2);
border-radius: 8px;
transition: all 0.3s ease;
}
.artist-card:hover,
.album-card:hover {
background: rgba(107, 225, 233, 0.1);
border-color: rgba(107, 225, 233, 0.5);
transform: translateY(-4px);
}
.artist-cover,
.album-cover {
font-size: 4rem;
margin-bottom: 15px;
}
.artist-card h2,
.album-card h3 {
margin: 10px 0;
font-size: 1.3rem;
color: #9d9aa4;
}
.artist-meta,
.album-meta {
color: #6be1e9;
font-size: 0.9rem;
margin: 0;
}
/* Artist Detail */
.artist-detail {
text-align: center;
margin: 40px 0;
padding: 40px 20px;
background: rgba(107, 225, 233, 0.05);
border-radius: 8px;
}
.artist-banner {
font-size: 5rem;
margin-bottom: 20px;
}
.artist-detail h2 {
margin: 0;
font-size: 2.5rem;
color: #9d9aa4;
}
/* Footer / Bottom Nav */
.music-footer {
text-align: center;
margin-top: 60px;
padding: 20px 0;
border-top: 2px solid rgba(107, 225, 233, 0.3);
}
.bottom-nav {
margin-top: auto;
width: 100%;
text-align: center;
padding: 20px 0;
}
.bottom-nav a {
margin: 0 10px;
display: inline-block;
}
/* --- BARD / IMAGE STYLES --- */
.bard {
margin: 0 auto 30px;
width: 100%;
max-width: 65em;
height: auto;
aspect-ratio: 1 / 0.95;
font-size: 2px;
flex-shrink: 0;
position: relative;
}
.bard img {
width: 100%;
height: auto;
position: absolute;
left: 0;
top: 0;
}
/* --- ANNOUNCEMENT & BLOG PREVIEW --- */
.announcement {
margin: 20px auto;
display: block;
border: 1px solid #ffff00;
padding: 10px 15px;
border-radius: 3px;
text-align: center;
max-width: 400px;
}
.announcement a {
color: #ffff00;
font-weight: bold;
}
.blog-preview-container {
margin: 30px auto;
max-width: 600px;
width: 100%;
display: flex;
justify-content: center;
}
.blog-preview {
border: 1px solid rgba(155, 169, 180, 0.3);
border-radius: 4px;
padding: 15px;
background: linear-gradient(135deg, rgba(13, 10, 20, 0.6), rgba(50, 30, 80, 0.3));
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
/* --- RESPONSIVE MEDIA QUERIES --- */
@media (max-width: 768px) {
.music-container {
padding: 20px 10px;
}
.music-header h1 {
font-size: 1.5rem;
}
.artists-grid,
.albums-grid {
grid-template-columns: 1fr;
}
.artist-banner {
font-size: 3rem;
}
.artist-detail h2 {
font-size: 1.8rem;
}
.bard {
font-size: 3px;
}
}

View File

@ -127,3 +127,40 @@ uncomment the code below.
// <pre>${css.join("\n\n")}</pre>
// </div>
// `;
// Load latest blog post preview
async function loadLatestBlogPost() {
try {
const response = await fetch('./blog/posts.json');
const posts = await response.json();
if (posts.length === 0) {
document.getElementById('latestBlogPreview').innerHTML = '<p style="color: #9d9aa4;">No blog posts yet.</p>';
return;
}
// Get the latest post (first in the array)
const latestPost = posts[0];
// Create the preview HTML
const previewHTML = `
<a href="./blog/#${latestPost.slug}" class="blog-preview-title">${latestPost.title}</a>
<div class="blog-preview-date">${new Date(latestPost.date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}</div>
<img src="${latestPost.image}" alt="${latestPost.title}" />
<p class="blog-preview-excerpt">${latestPost.excerpt}</p>
<a href="./blog/#${latestPost.slug}" class="blog-preview-link">Read more →</a>
`;
document.getElementById('latestBlogPreview').innerHTML = previewHTML;
} catch (error) {
console.error('Error loading blog posts:', error);
document.getElementById('latestBlogPreview').innerHTML = '<p style="color: #9d9aa4;">Error loading blog posts.</p>';
}
}
// Load blog preview when page is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', loadLatestBlogPost);
} else {
loadLatestBlogPost();
}

BIN
src/audio/._DGDN Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
src/audio/DGDN/._Otish.flac Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
src/audio/DGDN/On Ice.flac Normal file

Binary file not shown.

Binary file not shown.

BIN
src/audio/DGDN/Otish.flac Normal file

Binary file not shown.

Binary file not shown.

BIN
src/audio/DGDN/Scan V2.flac Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
src/audio/DGDN/held v3.flac Normal file

Binary file not shown.

Binary file not shown.

181
style.css
View File

@ -1,18 +1,23 @@
body {
background: #0d0a14;
padding: 40px 20px;
padding: 20px 20px 100px 20px;
font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;
color: #9d9aa4;
position: relative;
height: 100vh;
overflow-y: auto;
box-sizing: border-box;
}
.bard {
margin: 0 auto 40px;
margin: 0 auto 30px;
/* Remove fixed width in pixels */
width: 100%;
max-width: 65em; /* Keep the same max size for desktop */
height: auto;
aspect-ratio: 1 / 0.95; /* Maintains the proportion of the artwork */
font-size: 2px;
flex-shrink: 0;
}
/* Adjust media queries for better scaling */
@ -148,7 +153,7 @@ body {
}
}
p {
margin: 20px auto 0;
margin: 10px auto 0;
position: relative;
max-width: 400px;
text-align: center;
@ -156,6 +161,56 @@ p {
font-size: 0.875rem;
}
.announcement {
margin: 10px auto 0;
position: relative;
max-width: 400px;
text-align: center;
line-height: 1.3;
font-size: 0.875rem;
}
.announcement a {
color: #ffeb3b;
font-weight: bold;
text-decoration: none;
}
.announcement a:hover,
.announcement a:focus {
text-decoration: underline;
opacity: 0.85;
}
.debug {
margin: 40px auto 0;
position: relative;
max-width: 800px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 100%;
}
.links-bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20px;
text-align: center;
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
background: linear-gradient(to top, rgba(13, 10, 20, 0.95), rgba(13, 10, 20, 0.8));
backdrop-filter: blur(4px);
}
.links-bottom a {
color: #6be1e9;
}
a {
color: #6be1e9;
}
@ -209,3 +264,123 @@ a:focus-visible {
.column + .column {
color: #aa95bd;
}
/* Make body use flexbox to push nav to bottom */
body {
background: #0d0a14;
padding: 40px 20px;
font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;
color: #9d9aa4;
min-height: 100vh;
margin: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
overflow: hidden; /* Prevents scrollbar */
}
/* Color the announcement link yellow */
.announcement {
margin: 20px auto 0;
display: inline-block;
border: 1px solid #ffff00;
padding: 10px 15px;
border-radius: 3px;
}
.announcement a {
color: #ffff00;
font-weight: bold;
text-decoration: none;
}
.announcement a:hover {
text-decoration: underline;
}
/* Blog Preview Box */
.blog-preview-container {
margin: 30px auto 0;
max-width: 33%;
width: 100%;
display: flex;
justify-content: center;
}
.blog-preview {
border: 1px solid rgba(155, 169, 180, 0.3);
border-radius: 4px;
padding: 15px;
background: linear-gradient(135deg, rgba(13, 10, 20, 0.6), rgba(50, 30, 80, 0.3));
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
.blog-preview img {
width: 100%;
height: auto;
max-height: 150px;
object-fit: cover;
border-radius: 3px;
margin-bottom: 10px;
}
.blog-preview-title {
color: #ffff00;
font-weight: bold;
font-size: 0.95rem;
margin: 10px 0 5px;
text-decoration: none;
display: block;
}
.blog-preview-title:hover {
text-decoration: underline;
}
.blog-preview-date {
color: #aa95bd;
font-size: 0.8rem;
margin-bottom: 8px;
}
.blog-preview-excerpt {
color: #9d9aa4;
font-size: 0.85rem;
line-height: 1.4;
margin: 8px 0 10px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.blog-preview-link {
display: inline-block;
color: #6be1e9;
font-size: 0.8rem;
text-decoration: none;
}
.blog-preview-link:hover {
text-decoration: underline;
}
/* Push the navigation to the bottom using flexbox spacer */
.bottom-nav {
margin-top: auto;
width: 100%;
text-align: center;
display: flex;
justify-content: center;
}
.bottom-nav p {
margin: 0;
text-align: center;
}
.bottom-nav a {
margin: 0 10px;
display: inline-block;
}