<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>About u :D</title>
    <link rel="stylesheet" href="lib/style.css" />
    <script>
      // remove me
      document.addEventListener('DOMContentLoaded', () => {
  // alert('https://github.com/deeegen/public-profile-template');
});

    </script>
  </head>
  <body>
    <header class="header" style="position: relative;">
  <h1>Welcome!</h1>
  <canvas id="oscilloscope" style="
    position: absolute;
    top: 60px;
    left: 0;
    width: 100%;
    height: 100px;
    z-index: 0;
    background-color: transparent;
  "></canvas>
  <audio id="audio" controls crossorigin="anonymous" style="position: relative; z-index: 1;"></audio>
  <ul id="playlist"></ul>
</header>


    <section class="grid">
      <div class="iframe-overlay" id="iframeOverlay">
        <div class="close-btn" id="closeOverlay">×</div>
        <iframe id="iframeContent" src=""></iframe>
      </div>

      <div class="side-container">
        <div class="profile">
          <div class="profile-picture-container">
            <img
              src="https://tr.rbxcdn.com/180DAY-3f9aceb0bb3efd1c0283638edb3f84bf/420/420/Hat/Webp/noFilter"
              alt="Profile picture"
              class="profile-img"
            />
          </div>
          <h2>@username</h2>
          <div class="status">Status</div>
          <p>Share a short bio or tagline here.</p>

          <div class="social-links">
            <a href="#" target="_blank" class="social-btn" title="Twitter">
              <img src="https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png" alt="Twitter" />
            </a>
            <a href="#" target="_blank" class="social-btn" title="GitHub">
              <img src="https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png" alt="GitHub" />
            </a>
            <a href="#" target="_blank" class="social-btn" title="LinkedIn">
              <img src="https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png" alt="LinkedIn" />
            </a>
          </div>
        </div>

        <div class="media">
          <img src="https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png" alt="Media Image" />
          <p><strong>Interests:</strong></p>
          <p>- Interest one</p>
          <p>- Interest two</p>
          <p>- Interest three</p>
        </div>

        <button id="openBlog" class="blog-btn">Open Blog</button>
      </div>

      <div class="main">
        <div class="main-text">
          <div class="title">Main Title</div>
          <div class="subtitle">Subtitle goes here</div>
        </div>

        <div class="main-content-section">
          <h3>Section Title</h3>
          <p>Write your content here.</p>
        </div>

        <div class="main-content-section">
          <h3>Another Section</h3>
          <ul>
            <li>First item</li>
            <li>Second item</li>
            <li>Third item</li>
          </ul>
        </div>
      </div>
    </section>
    <script type="application/json" id="playlist-data">
      [
        {"title": "Song One", "url": "https://files.catbox.moe/a61oxd.mp3"},
        {"title": "Song Two", "url": "https://files.catbox.moe/7yydn8.mp3"},
        {"title": "Song Three", "url": "songs/song3.mp3"}
      ]
    </script>
    <script src="lib/player.js"></script>
    <script src="lib/overlays.js"></script>
  </body>
</html>
/* ============================
   1. BASIC SETUP FOR ALL ELEMENTS
   ============================ */

/* This part makes sure everything starts with no extra space around or inside elements,
   and that sizes are easier to manage. You usually don't need to change this. */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Prevent scroll on blog */
.no-scroll {
  overflow: hidden;
  height: 100vh;
}

/* This sets the basic look of your page: the font style, background color, and text color.
   Change colors here by updating the variables in section 2 below. */
body {
  font-family: Arial, sans-serif;
  line-height: 1.6;
  background-color: var(--color-background);
  color: var(--color-text);
}

/* Links (clickable text) will have no underline and inherit text color.
   You can change how links look by changing these styles. */
a {
  text-decoration: none;
  color: inherit;
}

/* ============================
   2. COLORS, SIZES & SPACES YOU CAN CHANGE EASILY
   ============================ */

/* Here are all the main colors, sizes, and spacing used on the page.
   To change colors or sizes, just replace the values here.
   For example, to change background color, update --color-background below. */
:root {
  --color-background: #fafafa;        /* Page background color */
  --color-surface: #ffffff;           /* Background for boxes/cards */
  --color-border: #e0e0e0;            /* Border color around boxes */
  --color-text: #333333;              /* Main text color */
  --color-muted: #666666;             /* Secondary text color */
  --color-muted-bg: #f5f5f5;          /* Background for muted areas */
  --color-hover-bg: #eaeaea;          /* Background when you hover on items */
  --color-focus: #005fcc;             /* Outline color when an item is focused */
  --border-radius: 8px;               /* How rounded corners are */
  --box-shadow-light: 0 2px 4px rgba(0, 0, 0, 0.05); /* Light shadow for depth */
  --box-shadow-hover: 0 4px 8px rgba(0, 0, 0, 0.1);  /* Shadow on hover */
  --spacing-xs: 4px;                  /* Extra small space */
  --spacing-s: 6px;                   /* Small space */
  --spacing-m: 10px;                  /* Medium space */
  --spacing-l: 20px;                  /* Large space */
  --font-size-base: 1rem;             /* Base font size */
  --font-size-small: 0.95rem;         /* Small font size */
  --font-size-large: 1.1rem;          /* Large font size */
  --font-size-xl: 1.5rem;             /* Extra large font size */
  --font-size-xxl: 2rem;              /* Double extra large font size */
}

/* ============================
   3. BOX STYLES (CARDS & SECTIONS)
   ============================ */

/* Boxes with white background, border, rounded corners, and subtle shadow.
   You can change how these boxes look by editing colors or border-radius in section 2. */
.surface {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius);
  box-shadow: var(--box-shadow-light);
}

/* These sections use the same box style.
   To change their look, change the variables in section 2 above. */
header,
.side-container,
.main,
.media,
.main-content-section {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius);
  box-shadow: var(--box-shadow-light);
}

/* ============================
   4. PAGE LAYOUT
   ============================ */

/* This sets up the main layout with two columns: a side area and a main area.
   Change the spacing or max width here if you want the page wider or narrower. */
.grid {
  display: grid;
  grid-template-areas: "side main";
  grid-template-columns: 1fr 2fr;
  gap: var(--spacing-l);
  padding: var(--spacing-l);
  max-width: 1200px;
  margin: 0 auto;  /* Centers the page */
}

/* Side container styles: stacked vertically with spacing */
.side-container {
  grid-area: side;
  padding: var(--spacing-l);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-l);
}

/* Main container styles: stacked vertically with spacing */
.main {
  grid-area: main;
  padding: var(--spacing-l);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-l);
}

/* ============================
   5. HEADER (TOP OF THE PAGE)
   ============================ */

/* Header is centered with padding and space below */
.header {
  text-align: center;
  padding: 1.5rem var(--spacing-l);
  margin-bottom: var(--spacing-l);
}

/* Main title font size and spacing */
.header h1 {
  font-size: var(--font-size-xxl);
  margin-bottom: var(--spacing-s);
}

/* Audio player style: size and rounded corners */
.header audio {
  width: 100%;
  max-width: 360px;
  height: 50px;
  margin: 0 auto;
  display: block;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.5);
  opacity: 0.9;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  background-clip: padding-box;
  outline: none;
}

.header audio:focus {
  border-color: rgba(255, 255, 255, 0.6);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.3);
}

/* Playlist container: items arranged in rows and wrap to next line */
#playlist {
  list-style: none;  /* Remove bullet points */
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-m);
  justify-content: center;
  margin-top: var(--spacing-s);
}

/* Individual playlist item style */
#playlist li {
  background-color: var(--color-muted-bg);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  padding: var(--spacing-s) var(--spacing-l);
  cursor: pointer;  /* Shows it can be clicked */
  font-size: var(--font-size-small);
  color: var(--color-text);
  user-select: none;  /* Prevents text highlight on click */
  transition: background-color 0.2s, box-shadow 0.2s; /* Smooth hover effect */
  white-space: nowrap; /* Keep text on one line */
  /* To make these items keyboard-focusable, your HTML should include tabindex="0" */
}

/* Changes appearance when hovering or focusing (keyboard) on playlist items */
#playlist li:hover,
#playlist li:focus {
  background-color: var(--color-hover-bg);
  box-shadow: var(--box-shadow-hover);
  outline: none;
}

/* Fix buttons kind of */
#playlist li.selected {
  background-color: transparent;
  border-color: #bbb;
  font-weight: 600;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.playlist-button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 12px 16px;
  font-size: 1rem;
  background: none;
  border: none;
  cursor: pointer;
  border-radius: 6px;
  transition: background 0.2s;
}

.playlist-button:hover,
.playlist-button:focus {
  background-color: #e0e0e0;
  outline: none;
}

li.selected .playlist-button {
  background-color: transparent;
  font-weight: bold;
}

/* ============================
   6. PROFILE (SIDE BAR)
   ============================ */

/* Center text inside profile area with padding */
.profile {
  text-align: center;
  padding: var(--spacing-l);
}

/* Container for profile picture with margin below */
.profile-picture-container {
  display: inline-block;
  position: relative;
  margin-bottom: var(--spacing-s);
}

/* Profile picture shape and size */
.profile-picture-container .profile-img {
  width: 7.5rem;  /* About 120px */
  height: 7.5rem;
  border-radius: 50%;  /* Make it round */
  border: 2px solid var(--color-border);
}

/* Profile name font size and spacing */
.profile h2 {
  font-size: var(--font-size-xl);
  margin-bottom: var(--spacing-s);
}

/* Status label style */
.status {
  display: inline-block;
  padding: var(--spacing-xs) var(--spacing-m);
  border-radius: 12px;
  font-size: var(--font-size-small);
  border: 1px solid var(--color-border);
  background-color: var(--color-muted-bg);
}

/* Profile description paragraph */
.profile p {
  margin-top: var(--spacing-s);
  font-size: var(--font-size-small);
}

/* ============================
   7. SOCIAL LINKS (SIDE BAR)
   ============================ */

/* Social icons arranged in a row with spacing */
.social-links {
  display: flex;
  justify-content: center;
  gap: var(--spacing-m);
  margin-top: var(--spacing-s);
}

/* Button style for social icons: round, centered content */
.social-btn {
  width: 40px;
  height: 40px;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.2s, box-shadow 0.2s;
  /* In your HTML, use <a> or <button> for best accessibility */
}

/* Hover and keyboard focus effects for social buttons */
.social-btn:hover,
.social-btn:focus {
  transform: translateY(-2px);
  box-shadow: var(--box-shadow-hover);
  outline: none;
}

/* Image inside social button fills entire button */
.social-btn img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Special button style for blog link */
.blog-btn {
  display: block;
  margin: 10px auto;
  width: 80%;
  padding: 12px 20px;
  font-size: 16px;
  color: #333;
  background-color: #f0f0f0;
  border: 2px solid #ccc;
  border-radius: 6px;
  filter: grayscale(100%);
  transition: all 0.3s ease;
  cursor: pointer;
}

/* Hover effect for blog button */
.blog-btn:hover {
  background-color: #e0e0e0;
  filter: grayscale(60%);
}

/* ============================
   8. MEDIA SECTION (SIDE BAR)
   ============================ */

/* Media section padding and vertical layout */
.media {
  padding: var(--spacing-l);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-s);
  overflow-y: auto;  /* Scroll if too tall */
}

/* Images inside media section have max width and border */
.media img {
  width: 100%;
  max-width: 200px;
  border: 1px solid var(--color-border);
  border-radius: 4px;
}

/* Text inside media section */
.media p {
  font-size: var(--font-size-small);
}

/* ============================
   9. MAIN CONTENT SECTIONS
   ============================ */

/* Main text container: centered with space below */
.main-text {
  text-align: center;
  margin-bottom: var(--spacing-l);
}

/* Title style */
.main-text .title {
  font-size: 1.8rem;
  margin-bottom: var(--spacing-s);
}

/* Subtitle style */
.main-text .subtitle {
  font-size: var(--font-size-large);
  color: var(--color-muted);
}

/* Main content section padding */
.main-content-section {
  padding: var(--spacing-l);
}

/* Headings inside main content */
.main-content-section h3 {
  font-size: 1.3rem;
  margin-bottom: var(--spacing-s);
  border-bottom: 1px solid var(--color-border);
  padding-bottom: var(--spacing-xs);
}

/* Paragraphs and list items spacing and size */
.main-content-section p,
.main-content-section li {
  margin-bottom: var(--spacing-s);
  font-size: var(--font-size-small);
}

/* Lists with bullet points and indent */
.main-content-section ul {
  list-style: disc;
  margin-left: var(--spacing-l);
}

/* ============================
   10. POP-UP OVERLAY (IFRAME MODAL)
   ============================ */

/* Hidden by default. This is the dark transparent background behind the pop-up box */
.iframe-overlay {
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 999;
}

/* When active, show the overlay and center its content */
.iframe-overlay.active {
  display: flex;
}

/* The pop-up box with no border and rounded corners */
.iframe-overlay iframe {
  width: 90%;
  height: 90%;
  border: none;
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* Close button for the pop-up, positioned top right */
.iframe-overlay .close-btn {
  position: absolute;
  top: var(--spacing-l);
  right: var(--spacing-l);
  font-size: 1.5rem;
  cursor: pointer;
  background: transparent;
  border: none;
}

/* ============================
   11. HOW TO SEE FOCUSED ELEMENTS (KEYBOARD NAVIGATION)
   ============================ */

/* When you tab through links, buttons, or playlist items, a blue outline appears to show focus */
a:focus,
button:focus,
#playlist li:focus,
.social-btn:focus {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
[
  {
    "title": "Blog 1",
    "date": "June 5, 2025",
    "content": "Text text text [img]https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png[/img]."
  },
  {
    "title": "Blog 2",
    "date": "June 2, 2025",
    "content": "Text text text."
  },
  {
    "title": "Blog 3",
    "date": "May 25, 2025",
    "content": "Text text text."
  }
]
/* ============================
   RESOURCES FOR LEARNING CSS
   ============================ */

/*
  Here are some high-quality, newb-friendly resources to learn more about CSS:
  
  1. **MDN Web Docs - CSS**
     - Comprehensive documentation and tutorials on CSS.
     - https://developer.mozilla.org/en-US/docs/Web/CSS

  2. **CSS-Tricks**
     - A website dedicated to providing in-depth articles and guides on CSS.
     - https://css-tricks.com/

  3. **W3Schools**
     - Offers easy-to-follow tutorials and examples for beginners.
     - https://www.w3schools.com/css/

  4. **FreeCodeCamp**
     - Provides interactive tutorials and projects to learn CSS.
     - https://www.freecodecamp.org/learn/css/

  5. **Flexbox Froggy**
     - A fun game to learn CSS Flexbox layout.
     - https://flexboxfroggy.com/

  6. **Grid Garden**
     - A game for learning CSS Grid layout.
     - https://cssgridgarden.com/

  7. **Codecademy**
     - Offers interactive courses on CSS and responsive design.
     - https://www.codecademy.com/learn/learn-css

  8. **CSS Zen Garden**
     - A showcase of what can be accomplished visually through CSS-based design.
     - http://www.csszengarden.com/

  9. **Smashing Magazine**
     - Features articles, tutorials, and resources on modern CSS techniques.
     - https://www.smashingmagazine.com/category/css

  10. **A Complete Guide to Flexbox**
     - A detailed guide on CSS Flexbox by CSS-Tricks.
     - https://css-tricks.com/snippets/css/a-guide-to-flexbox/

  11. **A Complete Guide to Grid**
     - A comprehensive guide on CSS Grid by CSS-Tricks.
     - https://css-tricks.com/snippets/css/complete-guide-grid/

  12. **Learn CSS Layout**
     - A step-by-step guide to CSS layout techniques.
     - http://learnlayout.com/

  13. **CSS Reference**
     - A visual guide to CSS by Codrops.
     - https://tympanus.net/codrops/css_reference/

  14. **The Odin Project**
     - Offers a full-stack curriculum that includes CSS.
     - https://www.theodinproject.com/paths/foundations/courses/foundations#css-foundations

  15. **Khan Academy**
     - Provides free courses on web development, including CSS.
     - https://www.khanacademy.org/computing/computer-programming/html-css

  These resources will help you deepen your understanding of CSS and improve your web development skills. Happy coding!
*/

/* ============================
   END OF FILE
   ============================ */
document.addEventListener("DOMContentLoaded", () => {
  const audio = document.getElementById("audio");
  const canvas = document.getElementById("oscilloscope");
  const playlistDataEl = document.getElementById("playlist-data");
  const playlistEl = document.getElementById("playlist");

  if (!audio || !canvas || !playlistDataEl || !playlistEl) {
    console.error("Required DOM elements missing.");
    return;
  }

  // Parse playlist JSON from DOM
  let playlist;
  try {
    playlist = JSON.parse(playlistDataEl.textContent);
  } catch (e) {
    console.error("Failed to parse playlist JSON:", e);
    return;
  }

  // === Optimized Oscilloscope Class ===
  class Oscilloscope {
    constructor(audioElement, canvasElement, options = {}) {
      this.audio = audioElement;
      this.canvas = canvasElement;
      this.ctx = canvasElement.getContext("2d");

      this.audioContext = null;
      this.analyser = null;
      this.source = null;
      this.animationId = null;
      this.dataArray = null;
      this.bufferLength = 0;

      // Configuration: adjustable FFT size and FPS cap
      this.fftSize = options.fftSize || 1024;
      this.fps = options.fps || 30; // throttle to 30 FPS
      this.lastRenderTime = 0;

      this._resizeHandler = () => this._resizeCanvas();

      this._init();
    }

    _init() {
      const AudioCtx = window.AudioContext || window.webkitAudioContext;
      if (!AudioCtx) {
        console.warn("Web Audio API not supported.");
        return;
      }

      this.audioContext = new AudioCtx();
      this.analyser = this.audioContext.createAnalyser();
      this.analyser.fftSize = this.fftSize;
      this.bufferLength = this.analyser.fftSize;
      this.dataArray = new Uint8Array(this.bufferLength);

      this.source = this.audioContext.createMediaElementSource(this.audio);
      this.source.connect(this.analyser);
      this.analyser.connect(this.audioContext.destination);

      this._resizeCanvas();
      window.addEventListener("resize", this._resizeHandler);

      if (this.audioContext.state === "suspended") {
        const resume = () => {
          this.audioContext.resume();
          this.start();
          window.removeEventListener("click", resume);
          window.removeEventListener("keydown", resume);
        };
        window.addEventListener("click", resume);
        window.addEventListener("keydown", resume);
      } else {
        this.start();
      }
    }

    _resizeCanvas() {
      const dpr = window.devicePixelRatio || 1;
      this.canvas.width = this.canvas.clientWidth * dpr;
      this.canvas.height = this.canvas.clientHeight * dpr;
      this.ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform before scaling
      this.ctx.scale(dpr, dpr);
    }

    start() {
      if (this.animationId) return;
      const draw = (timestamp) => {
        this.animationId = requestAnimationFrame(draw);

        // Throttle FPS
        if (timestamp - this.lastRenderTime < 1000 / this.fps) return;
        this.lastRenderTime = timestamp;

        // Optionally skip rendering if audio is paused
        if (this.audio.paused) {
          this.ctx.clearRect(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
          return;
        }

        this.analyser.getByteTimeDomainData(this.dataArray);

        const width = this.canvas.clientWidth;
        const height = this.canvas.clientHeight;
        const ctx = this.ctx;

        ctx.clearRect(0, 0, width, height);

        ctx.lineWidth = 2;
        ctx.strokeStyle = "#595959";
        ctx.beginPath();

        const sliceWidth = width / this.bufferLength;
        let x = 0;

        for (let i = 0; i < this.bufferLength; i++) {
          const v = this.dataArray[i] / 128.0;
          const y = (v * height) / 2;

          if (i === 0) {
            ctx.moveTo(x, y);
          } else {
            ctx.lineTo(x, y);
          }
          x += sliceWidth;
        }

        ctx.lineTo(width, height / 2);
        ctx.stroke();
      };

      this.animationId = requestAnimationFrame(draw);
    }

    stop() {
      if (this.animationId) {
        cancelAnimationFrame(this.animationId);
        this.animationId = null;
      }
    }

    destroy() {
      this.stop();
      if (this.source) this.source.disconnect();
      if (this.analyser) this.analyser.disconnect();
      if (this.audioContext) this.audioContext.close();
      window.removeEventListener("resize", this._resizeHandler);
    }
  }

  // === Audio Playlist Logic ===
  (() => {
    let currentTrackIndex = null;

    function getRandomTrackIndex(excludeIndex) {
      if (!playlist || playlist.length === 0) return -1;
      let index;
      do {
        index = Math.floor(Math.random() * playlist.length);
      } while (index === excludeIndex && playlist.length > 1);
      return index;
    }

    function loadTrack(index) {
      if (!playlist[index]) return;
      currentTrackIndex = index;
      audio.src = playlist[index].url;
      audio.play().catch((err) => console.warn("Audio playback failed", err));
      updateSelection(index);
    }

    function updateSelection(selectedIndex) {
      Array.from(playlistEl.children).forEach((li, idx) => {
        li.classList.toggle("selected", idx === selectedIndex);
      });
    }

    playlist.forEach((song, idx) => {
  const li = document.createElement("li");
  const button = document.createElement("button");

  button.textContent = song.title;
  button.className = "playlist-button";
  button.addEventListener("click", () => loadTrack(idx));

  li.appendChild(button);
  playlistEl.appendChild(li);
});


    const firstIndex = getRandomTrackIndex(null);
    if (firstIndex !== -1) loadTrack(firstIndex);

    audio.addEventListener("ended", () => {
      const nextIndex = getRandomTrackIndex(currentTrackIndex);
      if (nextIndex !== -1) loadTrack(nextIndex);
    });
  })();

  new Oscilloscope(audio, canvas, { fftSize: 1024, fps: 30 });
});
(() => {
  const overlay = document.getElementById("iframeOverlay");
  const iframe = document.getElementById("iframeContent");
  const openBlogBtn = document.getElementById("openBlog");
  const closeOverlayBtn = document.getElementById("closeOverlay");

  const disableBodyScroll = () => {
    document.body.classList.add("no-scroll");

    // Prevent scroll via keyboard
    window.addEventListener("keydown", preventScrollKeys, true);
    // Prevent wheel-based scrolling
    window.addEventListener("wheel", preventDefault, { passive: false });
    window.addEventListener("touchmove", preventDefault, { passive: false });
  };

  const enableBodyScroll = () => {
    document.body.classList.remove("no-scroll");

    window.removeEventListener("keydown", preventScrollKeys, true);
    window.removeEventListener("wheel", preventDefault);
    window.removeEventListener("touchmove", preventDefault);
  };

  const preventDefault = (e) => e.preventDefault();

  const preventScrollKeys = (e) => {
    const keys = [
      "ArrowUp", "ArrowDown",
      "PageUp", "PageDown",
      "Space", " ",
      "Home", "End"
    ];
    if (keys.includes(e.key)) {
      e.preventDefault();
    }
  };

  const scrollToTop = () => {
    return new Promise((resolve) => {
      // Scroll smoothly to top
      window.scrollTo({ top: 0, behavior: "smooth" });

      // Wait until scroll completes
      let lastPosition = -1;
      const check = () => {
        const current = window.scrollY || document.documentElement.scrollTop;
        if (current === 0 || current === lastPosition) {
          resolve();
        } else {
          lastPosition = current;
          requestAnimationFrame(check);
        }
      };
      check();
    });
  };

  if (overlay && iframe && openBlogBtn && closeOverlayBtn) {
    openBlogBtn.addEventListener("click", async () => {
      await scrollToTop();
      iframe.src = "views/blog.html";
      overlay.classList.add("active");
      disableBodyScroll();
    });

    closeOverlayBtn.addEventListener("click", () => {
      overlay.classList.remove("active");
      iframe.src = "";
      enableBodyScroll();
    });
  }

  document.querySelectorAll(".social-btn").forEach((btn) => {
    btn.addEventListener("click", () => {
      if (btn !== openBlogBtn) {
        alert("Opening " + btn.title);
      }
    });
  });
})();
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <style>
    body {
      font-family: sans-serif;
      background: #f4f4f4;
      color: #333;
      padding: 20px;
    }

    .container {
      max-width: 700px;
      margin: auto;
      background: white;
      padding: 20px;
      border-radius: 6px;
    }

    h1 {
      font-size: 24px;
      border-bottom: 2px solid #333;
      padding-bottom: 10px;
    }

    .post {
      margin-bottom: 30px;
    }

    .post h2 {
      font-size: 20px;
      color: #0073e6;
    }

    .date {
      font-size: 14px;
      color: #777;
    }

    .post img {
  width: 40%;
  height: auto;
  display: block;
  margin: 10px 0;
  border-radius: 4px;
  object-fit: contain;
}


    @media (max-width: 600px) {
      body {
        padding: 10px;
      }

      .container {
        padding: 15px;
      }

      h1 {
        font-size: 20px;
      }

      .post h2 {
        font-size: 18px;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>Ur blog :3</h1>
    <div id="posts"></div>
  </div>

  <script>
  /**
   * Replaces [img]...[/img] blocks with <img> tags safely.
   * Supports multiple image tags in the content.
   * @param {string} content - Blog post content string
   * @returns {string} - Processed HTML string
   */
  function parseContent(content) {
    // Simple image tag parser - assumes well-formed input
    return content.replace(/\[img\](.*?)\[\/img\]/gi, (match, url) => {
      // Optionally, validate or sanitize the URL here
      const safeUrl = url.trim();
      return `<img src="${safeUrl}" alt="blog image" style="max-width: 100%; margin: 10px 0;" />`;
    });
  }

  fetch('../lib/blogs.json')
    .then(response => response.json())
    .then(data => {
      const postsContainer = document.getElementById('posts');
      data.forEach(post => {
        const postElement = document.createElement('div');
        postElement.className = 'post';

        const parsedContent = parseContent(post.content);

        postElement.innerHTML = `
          <h2>${post.title}</h2>
          <div class="date">${post.date}</div>
          <div>${parsedContent}</div>
        `;

        postsContainer.appendChild(postElement);
      });
    })
    .catch(error => {
      console.error('Error loading blog posts:', error);
    });
</script>
</body>
</html>
Lag reduction (Oscilloscope)

Blog [img] tags
Scroll lock on blog
Fixed audio player
added oscilloscope

Added additional styling to the blog button
Explanatory comments in javascript
Added more in-depth notes to the css, along with references for newbs
https://github.com/deeegen/public-profile-template/blob/main/TUT.md

(WIP) in depth tutorial on this website templates components--


also -
https://ezgif.com/optimize recommended if you're gonna use gifs and the oscilloscope