Search

Damashi Peer Review - Stick With Link Colour Conventions

0 views

First Impressions and Performance

When you land on a site, the first thing you notice is how fast it responds. A page that loads in a fraction of a second feels polished, even if you’re on a slower connection. In this case, the home page arrived quickly enough to satisfy a dial‑up user, which is impressive by today's standards. Fast load times not only improve the user experience but also help search engines rank the page higher, because crawl budgets are conserved and visitors are less likely to bounce.

Beyond speed, visitors immediately scan the layout to understand what the site offers. A clear, visually distinct call to action - such as a banner or a prominent button - lets users know where to click next. The homepage does provide a snapshot of available products, which helps people gauge whether the store aligns with their needs. That snapshot also keeps them on the page, ready to explore more deeply.

However, visual first impressions can also turn away potential customers. The colour palette chosen for this site leans heavily into yellow, red, and blue. Those hues are eye‑catching, but when combined at high intensity they can appear cluttered or even aggressive. A discount video page dominated by bright reds and yellows may strain the eyes, especially for users with visual sensitivities. A more balanced, muted background can reduce eye fatigue and create a calmer browsing environment.

Colour consistency matters. Using different colour schemes across pages can confuse users about where they are and whether they’ve reached the same domain. When you see a bright header on one page and a pale green header on another, the transition feels abrupt, like moving between unrelated sections. Consistency builds trust; it signals that the pages belong to a unified brand experience.

Another early cue is how the site displays contact information. A visitor might want to call or email for a special order or a question about shipping. If the phone number and an email link are tucked away in the footer, that effort might be too much. Placing contact details prominently on the header or even in a sticky bar keeps them visible as users scroll.

Because the store focuses on a specific niche - karate books and videos - the first page should also reassure visitors that the inventory is authentic and up‑to‑date. Providing a brief statement such as “All titles are new releases from certified martial arts experts” adds credibility and helps differentiate the store from generic e‑commerce sites.

In sum, a fast, clean, and consistent design establishes confidence. By refining colour choices, consolidating contact details, and showcasing key products up front, the first impression can be both welcoming and persuasive. These early touches set the tone for the rest of the shopping experience.

Design, Colours, and Navigation

Colour usage should always support usability. The current approach places blue on headings that are not interactive, while red is reserved for unvisited links. Traditional web conventions favor blue for hyperlinks, making them instantly recognizable. Using blue for headings may cause confusion if users expect those elements to navigate somewhere. When a user encounters a blue heading, they might click and end up on a blank or unrelated page, which creates frustration.

Red, on the other hand, is typically associated with urgency or caution. Applying it to unvisited links could give the impression that the link is hazardous or requires special attention. If the goal is to highlight links, a subtle, contrasting shade of blue or a muted purple might work better. Consistency between link colour and page design reduces cognitive load.

The shopping pages stand out with a pale green header. This calm, natural tone contrasts nicely with the brighter palette used elsewhere. Adopting this soothing green across the entire site would create a cohesive visual identity and provide a sense of continuity. Green is also commonly linked to “go” or “proceed,” reinforcing the idea that the user is moving forward through the buying process.

When you consider navigation, the simplest solution is to keep all important links visible on a single page. For a small catalog, listing each author and their titles as separate clickable items on one page reduces the number of clicks needed. A visitor who wants to see all books by a particular trainer can find them immediately, without navigating back and forth. This reduces friction and encourages users to explore more deeply.

Quotes next to each item add personality and social proof. Readers of martial arts literature often appreciate a brief testimonial or a line from an instructor. Adding a sentence about the intended audience - such as “ideal for beginners” or “advanced techniques for seasoned practitioners” - provides useful context. A short description can help users decide whether a particular title aligns with their skill level and goals.

Shipping information should be transparent. The current approach suggests free shipping worldwide until a small print appears, which can feel deceptive. Visitors expect pricing to be visible early in the checkout process. Implementing a shipping calculator that displays estimated costs based on the user’s country - or grouping countries into tiers - can save users from abandoning the cart at the last moment. Quick, accurate shipping estimates keep the buying journey smooth and predictable.

One more tweak is the placement of the phone number and email link. Adding them to the header gives users a single point of contact they can reference at any time. If the header shares the green background, the contact details blend naturally with the rest of the navigation, enhancing the overall aesthetic without breaking the flow.

By aligning colours with usability norms, streamlining navigation, and delivering clear shipping data, the site can transform from a functional shop into an inviting destination for karate enthusiasts.

Graphics, Coding, and SEO Optimization

Image size directly impacts page load times, especially for users on slower connections. Some book cover images exceed 40 kilobytes, which slows down the whole page. Compressing these images to a lower resolution while maintaining legibility - say 200x300 pixels - can reduce file size dramatically. Tools like TinyPNG or ImageOptim let you strike a balance between visual quality and bandwidth usage. When an image is already compressed, adding a link to a higher resolution version for interested customers adds value without compromising initial load speed.

Videos are another area where optimization matters. While embedding a thumbnail that links to a YouTube video is efficient, consider lazy‑loading the video player so that it only loads when a user clicks “play.” This technique prevents the player’s JavaScript from blocking page rendering, keeping the initial experience snappy.

From a coding perspective, the tag should be near the top of the <head> section. Search engines read the page metadata in order, and a misplaced <title> can dilute its visibility. Keeping the <title> near the beginning ensures that crawlers capture the page’s main topic - karate books and videos - without delay.</p> <p>Keyword optimization remains an important factor. The current meta keywords include the word “karate” many times. Although search engines now prioritize content over keyword density, including the term once or twice in a natural way helps reinforce relevance. A concise list of varied, related keywords - such as “martial arts literature,” “karate instruction videos,” and “self‑defense training books” - provides a richer semantic profile.</p> <p>SEO extends beyond meta tags. Using descriptive, keyword‑rich alt text for images - like “Shaken To Win karate book cover” - helps visually impaired users and improves image search rankings. Structured data, such as schema.org markup for products, can display rich snippets in search results, drawing more traffic.</p> <p>Page structure also influences crawling efficiency. A logical hierarchy using</p><h2> and <h3> tags guides crawlers through the content, ensuring they index the most important sections. Avoid cluttering pages with too many headers; focus on the main headings that capture key concepts like “Book Collection” and “Instructional Video Library.”</p> <p>Finally, a responsive design that adapts to mobile devices is essential. A growing number of shoppers browse on phones or tablets. Ensuring that the green header, contact information, and product listings scale properly across screen sizes keeps users engaged and reduces bounce rates.</p> <p>Implementing these graphic and coding refinements will speed up page loads, improve accessibility, and make the site more attractive to both visitors and search engines. The combination of visual polish, clear navigation, and solid technical foundations creates a strong foundation for lasting customer engagement.</p></p></p></p></p></p></p></p></p></p></p></p></p></p></p></p></p></p></p></p></p></p></p> </div> <script> (function() { function initCopyableSections() { document.querySelectorAll('.article-content .copyable-section').forEach(function(section) { if (section.querySelector('.copyable-section__btn')) return; var btn = document.createElement('button'); btn.type = 'button'; btn.className = 'copyable-section__btn'; btn.setAttribute('aria-label', 'Copy to clipboard'); var label = section.getAttribute('data-copy-label'); btn.textContent = label ? 'Copy ' + label : 'Copy'; section.appendChild(btn); btn.addEventListener('click', function() { var contentEl = section.querySelector('.copyable-section__content'); var text; if (contentEl) { text = contentEl.textContent.trim(); } else { var clone = section.cloneNode(true); var btnClone = clone.querySelector('.copyable-section__btn'); if (btnClone) btnClone.parentNode.removeChild(btnClone); text = clone.textContent.trim(); } if (!text) return; navigator.clipboard.writeText(text).then(function() { var t = btn.textContent; btn.textContent = 'Copied!'; btn.classList.add('copied'); setTimeout(function() { btn.textContent = t; btn.classList.remove('copied'); }, 2000); }); }); }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCopyableSections); } else { initCopyableSections(); } })(); </script> <!-- Tags --> <div class="article-section-tags sidebar-widget" style="background: var(--github-bg-primary); border: 1px solid var(--github-border); border-radius: 12px; padding: 1.25rem; margin-bottom: 1.5rem;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.25rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border);"> <h3 style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); margin: 0; display: flex; align-items: center; gap: 0.5rem; letter-spacing: 0.01em;"> <i class="fas fa-tags" style="color: var(--github-primary); font-size: 0.875rem;"></i> Tags </h3> </div> <div style="display: flex; gap: 0.75rem; flex-wrap: wrap;"> <a href="https://www.murdok.org/news/tag/user-experience" style="display: inline-block; padding: 0.5rem 1rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; text-decoration: none; font-family: 'Inter', sans-serif; font-size: 0.875rem; transition: all 0.2s ease;" onmouseover="this.style.borderColor='var(--github-primary)'; this.style.color='var(--github-primary)';" onmouseout="this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-primary)';"> #User Experience </a> <a href="https://www.murdok.org/news/tag/web-performance" style="display: inline-block; padding: 0.5rem 1rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; text-decoration: none; font-family: 'Inter', sans-serif; font-size: 0.875rem; transition: all 0.2s ease;" onmouseover="this.style.borderColor='var(--github-primary)'; this.style.color='var(--github-primary)';" onmouseout="this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-primary)';"> #Web Performance </a> <a href="https://www.murdok.org/news/tag/link-color-conventions" style="display: inline-block; padding: 0.5rem 1rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; text-decoration: none; font-family: 'Inter', sans-serif; font-size: 0.875rem; transition: all 0.2s ease;" onmouseover="this.style.borderColor='var(--github-primary)'; this.style.color='var(--github-primary)';" onmouseout="this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-primary)';"> #Link Color Conventions </a> <a href="https://www.murdok.org/news/tag/seo" style="display: inline-block; padding: 0.5rem 1rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; text-decoration: none; font-family: 'Inter', sans-serif; font-size: 0.875rem; transition: all 0.2s ease;" onmouseover="this.style.borderColor='var(--github-primary)'; this.style.color='var(--github-primary)';" onmouseout="this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-primary)';"> #SEO </a> <a href="https://www.murdok.org/news/tag/site-speed" style="display: inline-block; padding: 0.5rem 1rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; text-decoration: none; font-family: 'Inter', sans-serif; font-size: 0.875rem; transition: all 0.2s ease;" onmouseover="this.style.borderColor='var(--github-primary)'; this.style.color='var(--github-primary)';" onmouseout="this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-primary)';"> #Site Speed </a> <a href="https://www.murdok.org/news/tag/design-best-practices" style="display: inline-block; padding: 0.5rem 1rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; text-decoration: none; font-family: 'Inter', sans-serif; font-size: 0.875rem; transition: all 0.2s ease;" onmouseover="this.style.borderColor='var(--github-primary)'; this.style.color='var(--github-primary)';" onmouseout="this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-primary)';"> #Design Best Practices </a> <a href="https://www.murdok.org/news/tag/accessibility" style="display: inline-block; padding: 0.5rem 1rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; text-decoration: none; font-family: 'Inter', sans-serif; font-size: 0.875rem; transition: all 0.2s ease;" onmouseover="this.style.borderColor='var(--github-primary)'; this.style.color='var(--github-primary)';" onmouseout="this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-primary)';"> #Accessibility </a> </div> </div> <!-- Correction Form --> <div class="article-section-correction sidebar-widget" style="background: var(--github-bg-primary); border: 1px solid var(--github-border); border-radius: 12px; padding: 1.25rem; margin-bottom: 1.5rem;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.25rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border);"> <h3 style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); margin: 0; display: flex; align-items: center; gap: 0.5rem; letter-spacing: 0.01em;"> <i class="fas fa-edit" style="color: var(--github-primary); font-size: 0.875rem;"></i> Suggest a Correction </h3> </div> <p style="color: var(--github-text-secondary); font-size: 0.9375rem; margin-bottom: 1.5rem;"> Found an error or have a suggestion? Let us know and we'll review it. </p> <form method="POST" action="https://www.murdok.org/api/submit-correction" id="correctionForm" style="display: flex; flex-direction: column; gap: 1rem;"> <input type="hidden" name="article_type" value="news"> <input type="hidden" name="article_id" value="4787"> <input type="hidden" name="article_url" value="https://www.murdok.org/news/damashi-peer-review-stick-with-link-colour-conventions"> <div> <label for="correction_name" style="display: block; font-family: 'Inter', sans-serif; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.5rem; font-size: 0.9375rem;"> Your Name <span style="color: #f43f5e;">*</span> </label> <input type="text" name="name" id="correction_name" autocomplete="name" required style="width: 100%; padding: 0.875rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; font-family: 'Inter', sans-serif; font-size: 0.9375rem;" placeholder="Your name"> </div> <div> <label for="correction_email" style="display: block; font-family: 'Inter', sans-serif; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.5rem; font-size: 0.9375rem;"> Your Email <span style="color: #f43f5e;">*</span> </label> <input type="email" name="email" id="correction_email" autocomplete="email" required style="width: 100%; padding: 0.875rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; font-family: 'Inter', sans-serif; font-size: 0.9375rem;" placeholder="your@email.com"> </div> <div> <label for="correction_message" style="display: block; font-family: 'Inter', sans-serif; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.5rem; font-size: 0.9375rem;"> Correction Details <span style="color: #f43f5e;">*</span> </label> <textarea name="message" id="correction_message" autocomplete="off" required rows="5" style="width: 100%; padding: 0.875rem; background: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; font-family: 'Inter', sans-serif; font-size: 0.9375rem; resize: vertical;" placeholder="Describe the error or suggestion..."></textarea> </div> <button type="submit" style="padding: 0.875rem 1.5rem; background: var(--github-primary); color: var(--github-bg-primary); border: none; border-radius: 8px; font-family: 'Inter', sans-serif; font-weight: 600; cursor: pointer; transition: all 0.2s ease; align-self: flex-start;" onmouseover="this.style.opacity='0.9';" onmouseout="this.style.opacity='1';"> <i class="fas fa-paper-plane" style="margin-right: 0.5rem;"></i> Submit Correction </button> </form> <div id="correctionMessage" style="display: none; margin-top: 1rem; padding: 1rem; border-radius: 8px; font-family: 'Inter', sans-serif;"></div> </div> <script> document.getElementById('correctionForm').addEventListener('submit', function(e) { e.preventDefault(); const form = this; const formData = new FormData(form); const messageDiv = document.getElementById('correctionMessage'); fetch('https://www.murdok.org/api/submit-correction', { method: 'POST', body: formData }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { if (data.success) { messageDiv.style.display = 'block'; messageDiv.style.background = 'rgba(34, 197, 94, 0.1)'; messageDiv.style.border = '1px solid var(--github-primary)'; messageDiv.style.color = 'var(--github-primary)'; messageDiv.textContent = 'Thank you! Your correction has been submitted.'; form.reset(); } else { messageDiv.style.display = 'block'; messageDiv.style.background = 'rgba(244, 63, 94, 0.1)'; messageDiv.style.border = '1px solid #f43f5e'; messageDiv.style.color = '#f43f5e'; messageDiv.textContent = data.error || 'An error occurred. Please try again.'; } }) .catch(error => { console.error('Correction submission error:', error); messageDiv.style.display = 'block'; messageDiv.style.background = 'rgba(244, 63, 94, 0.1)'; messageDiv.style.border = '1px solid #f43f5e'; messageDiv.style.color = '#f43f5e'; messageDiv.textContent = 'Network error. Please check your connection and try again.'; }); }); </script> <!-- Social Media Sharing --> <div class="article-section-share sidebar-widget" style="background: var(--github-bg-primary); border: 1px solid var(--github-border); border-radius: 12px; padding: 1.25rem; margin-bottom: 1.5rem;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.25rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border);"> <h3 style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); margin: 0; display: flex; align-items: center; gap: 0.5rem; letter-spacing: 0.01em;"> <i class="fas fa-share-alt" style="color: var(--github-primary); font-size: 0.875rem;"></i> Share this article </h3> </div> <div style="display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center;"> <!-- Facebook --> <a href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.murdok.org%2Fnews%2Fdamashi-peer-review-stick-with-link-colour-conventions" target="_blank" rel="noopener noreferrer" onclick="trackSocialShare('facebook', 4787);" style="display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: #1877F2; color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.2s ease; font-size: 1.25rem;" onmouseover="this.style.transform='translateY(-2px)';" onmouseout="this.style.transform='translateY(0)';" title="Share on Facebook"> <i class="fab fa-facebook-f"></i> </a> <!-- Twitter/X --> <a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.murdok.org%2Fnews%2Fdamashi-peer-review-stick-with-link-colour-conventions&text=Damashi+Peer+Review+-+Stick+With+Link+Colour+Conventions" target="_blank" rel="noopener noreferrer" onclick="trackSocialShare('twitter', 4787);" style="display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: #000000; color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.2s ease; font-size: 1.25rem;" onmouseover="this.style.transform='translateY(-2px)';" onmouseout="this.style.transform='translateY(0)';" title="Share on X (Twitter)"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="display: block;"> <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" fill="currentColor"/> </svg> </a> <!-- LinkedIn --> <a href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.murdok.org%2Fnews%2Fdamashi-peer-review-stick-with-link-colour-conventions" target="_blank" rel="noopener noreferrer" onclick="trackSocialShare('linkedin', 4787);" style="display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: #0077B5; color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.2s ease; font-size: 1.25rem;" onmouseover="this.style.transform='translateY(-2px)';" onmouseout="this.style.transform='translateY(0)';" title="Share on LinkedIn"> <i class="fab fa-linkedin-in"></i> </a> <!-- Reddit --> <a href="https://reddit.com/submit?url=https%3A%2F%2Fwww.murdok.org%2Fnews%2Fdamashi-peer-review-stick-with-link-colour-conventions&title=Damashi+Peer+Review+-+Stick+With+Link+Colour+Conventions" target="_blank" rel="noopener noreferrer" onclick="trackSocialShare('reddit', 4787);" style="display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: #FF4500; color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.2s ease; font-size: 1.25rem;" onmouseover="this.style.transform='translateY(-2px)';" onmouseout="this.style.transform='translateY(0)';" title="Share on Reddit"> <i class="fab fa-reddit-alien"></i> </a> <!-- WhatsApp --> <a href="https://wa.me/?text=Damashi+Peer+Review+-+Stick+With+Link+Colour+Conventions%20https%3A%2F%2Fwww.murdok.org%2Fnews%2Fdamashi-peer-review-stick-with-link-colour-conventions" target="_blank" rel="noopener noreferrer" onclick="trackSocialShare('whatsapp', 4787);" style="display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: #25D366; color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.2s ease; font-size: 1.25rem;" onmouseover="this.style.transform='translateY(-2px)';" onmouseout="this.style.transform='translateY(0)';" title="Share on WhatsApp"> <i class="fab fa-whatsapp"></i> </a> <!-- Telegram --> <a href="https://t.me/share/url?url=https%3A%2F%2Fwww.murdok.org%2Fnews%2Fdamashi-peer-review-stick-with-link-colour-conventions&text=Damashi+Peer+Review+-+Stick+With+Link+Colour+Conventions" target="_blank" rel="noopener noreferrer" onclick="trackSocialShare('telegram', 4787);" style="display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: #0088cc; color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.2s ease; font-size: 1.25rem;" onmouseover="this.style.transform='translateY(-2px)';" onmouseout="this.style.transform='translateY(0)';" title="Share on Telegram"> <i class="fab fa-telegram-plane"></i> </a> <!-- Email --> <a href="mailto:?subject=Damashi+Peer+Review+-+Stick+With+Link+Colour+Conventions&body=First+Impressions+and+Performance+When+you+land+on+a+site%2C+the+first+thing+you+notice+is+how+fast+it+responds.%0A%0Ahttps%3A%2F%2Fwww.murdok.org%2Fnews%2Fdamashi-peer-review-stick-with-link-colour-conventions" onclick="trackSocialShare('email', 4787);" style="display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: var(--github-text-secondary); color: #fff; border-radius: 8px; text-decoration: none; transition: all 0.2s ease; font-size: 1.25rem;" onmouseover="this.style.transform='translateY(-2px)';" onmouseout="this.style.transform='translateY(0)';" title="Share via Email"> <i class="fas fa-envelope"></i> </a> <!-- Copy Link --> <button onclick="copyArticleLink(4787);" style="display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: var(--github-bg-primary); border: 1px solid var(--github-border); color: var(--github-text-primary); border-radius: 8px; text-decoration: none; transition: all 0.2s ease; font-size: 1.25rem; cursor: pointer; padding: 0;" onmouseover="this.style.borderColor='var(--github-primary)'; this.style.color='var(--github-primary)'; this.style.transform='translateY(-2px)';" onmouseout="this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-primary)'; this.style.transform='translateY(0)';" title="Copy link"> <i class="fas fa-link"></i> </button> </div> </div> <!-- Comments Section --> <div class="article-section-comments" style="margin-top: 3rem; margin-bottom: 1.5rem;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.25rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border);"> <h2 style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); margin: 0; display: flex; align-items: center; gap: 0.5rem; letter-spacing: 0.01em;"> <i class="fas fa-comments" style="color: var(--github-primary); font-size: 0.875rem;"></i> Comments (0) </h2> </div> <div style="background: var(--github-bg-secondary); border: 1px solid var(--github-border); border-radius: 8px; padding: 1.25rem; margin-bottom: 1.5rem; text-align: center;"> <p style="color: var(--github-text-secondary); font-family: 'Inter', sans-serif; font-size: 0.9375rem; margin-bottom: 1rem;"> Please <a href="https://www.murdok.org/login?redirect=https%3A%2F%2Fwww.murdok.org%2Fnews%2Fdamashi-peer-review-stick-with-link-colour-conventions" style="color: var(--github-primary); text-decoration: none; font-weight: 600;" onmouseover="this.style.textDecoration='underline';" onmouseout="this.style.textDecoration='none';">sign in</a> to leave a comment. </p> </div> <!-- Comments List --> <div id="commentsList"> <p style="color: var(--github-text-secondary); font-family: 'Inter', sans-serif; font-size: 0.9375rem; text-align: center; padding: 2rem;"> No comments yet. Be the first to comment! </p> </div> </div> <!-- Related Posts --> <div class="article-section-related sidebar-widget" style="background: var(--github-bg-primary); border: 1px solid var(--github-border); border-radius: 12px; padding: 1.25rem; margin-bottom: 1.5rem;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.25rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border);"> <h2 style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); margin: 0; display: flex; align-items: center; gap: 0.5rem; letter-spacing: 0.01em;"> <i class="fas fa-newspaper" style="color: var(--github-primary); font-size: 0.875rem;"></i> Related Articles </h2> </div> <ul style="list-style: none; padding: 0; margin: 0;"> <li style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); transition: all 0.2s ease;" onmouseover="this.style.borderBottomColor='var(--github-border-hover)';" onmouseout="this.style.borderBottomColor='var(--github-border)';"> <a href="https://www.murdok.org/news/getting-visitors-to-stay-through-web-based-marketing" style="display: block; text-decoration: none; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.8';" onmouseout="this.style.opacity='1';"> <div style="width: 100%; height: 120px; border-radius: 6px; overflow: hidden; background: var(--github-bg-secondary); margin-bottom: 0.75rem; position: relative; display: flex; align-items: center; justify-content: center;"> <img src="https://www.murdok.org/assets/images/posts/default_post_10558_1770312562_6984d37273112_medium.jpg" alt="Getting Visitors To Stay Through Web Based Marketing" width="240" height="120" style="width: 100%; height: 100%; object-fit: cover; display: block;" loading="lazy" decoding="async"> </div> <div> <h3 style="font-family: 'Inter', sans-serif; font-size: 0.875rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.375rem; line-height: 1.4; transition: color 0.2s ease;" onmouseover="this.style.color='var(--github-primary)';" onmouseout="this.style.color='var(--github-text-primary)';"> Getting Visitors To Stay Through Web Based Marketing </h3> <div style="display: flex; align-items: center; gap: 1rem; font-size: 0.75rem; color: var(--github-text-muted);"> <span style="display: inline-flex; align-items: center; gap: 0.375rem;"><i class="fas fa-calendar" style="font-size: 0.6875rem;"></i> Aug 23, 2004</span> </div> </div> </a> </li> <li style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); transition: all 0.2s ease;" onmouseover="this.style.borderBottomColor='var(--github-border-hover)';" onmouseout="this.style.borderBottomColor='var(--github-border)';"> <a href="https://www.murdok.org/news/planning-for-your-website-s-future-get-search-engine-traffic" style="display: block; text-decoration: none; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.8';" onmouseout="this.style.opacity='1';"> <div style="width: 100%; height: 120px; border-radius: 6px; overflow: hidden; background: var(--github-bg-secondary); margin-bottom: 0.75rem; position: relative; display: flex; align-items: center; justify-content: center;"> <img src="https://www.murdok.org/assets/images/posts/default_post_10544_1770312561_6984d371568a2_medium.jpg" alt="Planning For Your Website's Future- Get Search Engine Traffic" width="240" height="120" style="width: 100%; height: 100%; object-fit: cover; display: block;" loading="lazy" decoding="async"> </div> <div> <h3 style="font-family: 'Inter', sans-serif; font-size: 0.875rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.375rem; line-height: 1.4; transition: color 0.2s ease;" onmouseover="this.style.color='var(--github-primary)';" onmouseout="this.style.color='var(--github-text-primary)';"> Planning For Your Website's Future- Get Search Engine Traffic </h3> <div style="display: flex; align-items: center; gap: 1rem; font-size: 0.75rem; color: var(--github-text-muted);"> <span style="display: inline-flex; align-items: center; gap: 0.375rem;"><i class="fas fa-calendar" style="font-size: 0.6875rem;"></i> Aug 20, 2004</span> </div> </div> </a> </li> <li style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); transition: all 0.2s ease;" onmouseover="this.style.borderBottomColor='var(--github-border-hover)';" onmouseout="this.style.borderBottomColor='var(--github-border)';"> <a href="https://www.murdok.org/news/keyword-phrases-in-linking-text" style="display: block; text-decoration: none; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.8';" onmouseout="this.style.opacity='1';"> <div style="width: 100%; height: 120px; border-radius: 6px; overflow: hidden; background: var(--github-bg-secondary); margin-bottom: 0.75rem; position: relative; display: flex; align-items: center; justify-content: center;"> <img src="https://www.murdok.org/assets/images/posts/default_post_10543_1770312561_6984d3713fe7a_medium.jpg" alt="Keyword Phrases in Linking Text " width="240" height="120" style="width: 100%; height: 100%; object-fit: cover; display: block;" loading="lazy" decoding="async"> </div> <div> <h3 style="font-family: 'Inter', sans-serif; font-size: 0.875rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.375rem; line-height: 1.4; transition: color 0.2s ease;" onmouseover="this.style.color='var(--github-primary)';" onmouseout="this.style.color='var(--github-text-primary)';"> Keyword Phrases in Linking Text </h3> <div style="display: flex; align-items: center; gap: 1rem; font-size: 0.75rem; color: var(--github-text-muted);"> <span style="display: inline-flex; align-items: center; gap: 0.375rem;"><i class="fas fa-calendar" style="font-size: 0.6875rem;"></i> Aug 20, 2004</span> </div> </div> </a> </li> </ul> </div> </article> </div> <!-- Right Sidebar - Widgets --> <div class="col-lg-3 right-sidebar-column" style="max-width: 360px; flex: 0 0 360px; min-height: 100px; padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; margin-top: 0; margin-bottom: 0; flex-shrink: 0;"> <div class="right-sidebar-wrapper" style="position: sticky; top: 2rem; width: 360px; padding-top: 0; padding-bottom: 1rem; padding-left: 0.75rem; padding-right: 0.75rem; margin-top: 0; margin-bottom: 0; box-sizing: border-box;"> <div class="sidebar-widget sidebar-promo-widget sidebar-promo-has-fallback" style="background: var(--github-bg-primary); border: 1px solid var(--github-border); border-radius: 12px; padding: 1.5rem 1.25rem; margin-bottom: 1.5rem; display: flex; align-items: center; justify-content: center;"> <script type="text/template" id="sidebar-adsense-tpl-sidebar-promo-6a04feeb84c0d"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4745231616627689"rn crossorigin="anonymous"><\/script>rn<!-- Murdok - Sidebar -->rn<ins class="adsbygoogle"rn style="display:inline-block;width:300px;height:250px"rn data-ad-client="ca-pub-4745231616627689"rn data-ad-slot="2420735192"></ins>rn<script>rn (adsbygoogle = window.adsbygoogle || []).push({});rn<\/script></script> <div id="sidebar-promo-content-sidebar-promo-6a04feeb84c0d" class="sidebar-adsense-slot sidebar-ad-slot" style="text-align: center; width: 300px; min-width: 300px; min-height: 250px; margin: 0 auto;" data-adsense-tpl="sidebar-adsense-tpl-sidebar-promo-6a04feeb84c0d"></div> <div class="sidebar-fallback-slot sidebar-ad-slot" style="text-align: center; width: 300px; min-width: 300px; min-height: 250px; margin: 0 auto;"><div style="width: 300px; height: 250px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; flex-direction: column; align-items: center; justify-content: center; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);"> <a href="https://murdok.org/contact" style="color: white; text-decoration: none; text-align: center; padding: 20px;"> <div style="font-size: 24px; font-weight: bold; margin-bottom: 15px;">📢</div> <div style="font-size: 20px; font-weight: bold; margin-bottom: 10px;">Advertise Here</div> <div style="font-size: 14px; opacity: 0.9;">Reach thousands of engaged readers</div> <div style="margin-top: 15px; background: white; color: #667eea; padding: 10px 20px; border-radius: 4px; font-weight: 600;">Contact Us</div> </a></div></div> </div> <div class="sidebar-widget cms-latest-news-widget" style="background: var(--github-bg-primary); border: 1px solid var(--github-border); border-radius: 12px; padding: 1.25rem; margin-bottom: 1.5rem; "> <h3 class="widget-title" style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 1.25rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); display: flex; align-items: center; gap: 0.5rem; letter-spacing: 0.01em;"> <i class="fas fa-blog" style="color: var(--github-primary); font-size: 0.875rem;"></i> Latest News </h3> <ul style="list-style: none; padding: 0; margin: 0;"> <li style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); transition: all 0.2s ease;" onmouseover="this.style.borderBottomColor='var(--github-border-hover)';" onmouseout="this.style.borderBottomColor='var(--github-border)';"> <a href="https://www.murdok.org/news/revision-prompts-to-tighten-prose-without-losing-your-voice" style="display: block; text-decoration: none; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.8';" onmouseout="this.style.opacity='1';"> <div style="width: 100%; height: 120px; border-radius: 6px; overflow: hidden; background: var(--github-bg-secondary); margin-bottom: 0.75rem; position: relative; display: flex; align-items: center; justify-content: center;"> <picture><img src="https://www.murdok.org/assets/images/posts/revision-prompts-to-tighten-prose-without-losing-your-voice-featured-grok-imagine-image-quality.jpg" alt="Revision Prompts to Tighten Prose Without Losing Your Voice" width="120" height="120" style="width: 100%; height: 100%; object-fit: cover; display: block;" loading="lazy" decoding="async"></picture> </div> <div> <h4 style="font-family: 'Inter', sans-serif; font-size: 0.875rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.375rem; line-height: 1.4; transition: color 0.2s ease;" onmouseover="this.style.color='var(--github-primary)';" onmouseout="this.style.color='var(--github-text-primary)';"> Revision Prompts to Tighten Prose Without Losing Your Voice </h4> <div style="font-size: 0.75rem; color: var(--github-text-muted);"> <i class="fas fa-calendar-alt" style="font-size: 0.6875rem; margin-right: 0.375rem;"></i>May 13, 2026 </div> </div> </a> </li> <li style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); transition: all 0.2s ease;" onmouseover="this.style.borderBottomColor='var(--github-border-hover)';" onmouseout="this.style.borderBottomColor='var(--github-border)';"> <a href="https://www.murdok.org/news/memoir-writers-using-ai-ethically-for-memory-prompts" style="display: block; text-decoration: none; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.8';" onmouseout="this.style.opacity='1';"> <div style="width: 100%; height: 120px; border-radius: 6px; overflow: hidden; background: var(--github-bg-secondary); margin-bottom: 0.75rem; position: relative; display: flex; align-items: center; justify-content: center;"> <picture><img src="https://www.murdok.org/assets/images/posts/memoir-writers-using-ai-ethically-for-memory-prompts-featured-grok-imagine-image-quality.jpg" alt="Memoir Writers Using AI Ethically for Memory Prompts" width="120" height="120" style="width: 100%; height: 100%; object-fit: cover; display: block;" loading="lazy" decoding="async"></picture> </div> <div> <h4 style="font-family: 'Inter', sans-serif; font-size: 0.875rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.375rem; line-height: 1.4; transition: color 0.2s ease;" onmouseover="this.style.color='var(--github-primary)';" onmouseout="this.style.color='var(--github-text-primary)';"> Memoir Writers Using AI Ethically for Memory Prompts </h4> <div style="font-size: 0.75rem; color: var(--github-text-muted);"> <i class="fas fa-calendar-alt" style="font-size: 0.6875rem; margin-right: 0.375rem;"></i>May 13, 2026 </div> </div> </a> </li> <li style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); transition: all 0.2s ease;" onmouseover="this.style.borderBottomColor='var(--github-border-hover)';" onmouseout="this.style.borderBottomColor='var(--github-border)';"> <a href="https://www.murdok.org/news/creative-poetry-prompts-specifying-meter-image-and-volta" style="display: block; text-decoration: none; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.8';" onmouseout="this.style.opacity='1';"> <div style="width: 100%; height: 120px; border-radius: 6px; overflow: hidden; background: var(--github-bg-secondary); margin-bottom: 0.75rem; position: relative; display: flex; align-items: center; justify-content: center;"> <picture><img src="https://www.murdok.org/assets/images/posts/creative-poetry-prompts-specifying-meter-image-and-volta-featured-grok-imagine-image-quality.jpg" alt="Creative Poetry Prompts Specifying Meter, Image, and Volta" width="120" height="120" style="width: 100%; height: 100%; object-fit: cover; display: block;" loading="lazy" decoding="async"></picture> </div> <div> <h4 style="font-family: 'Inter', sans-serif; font-size: 0.875rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.375rem; line-height: 1.4; transition: color 0.2s ease;" onmouseover="this.style.color='var(--github-primary)';" onmouseout="this.style.color='var(--github-text-primary)';"> Creative Poetry Prompts Specifying Meter, Image, and Volta </h4> <div style="font-size: 0.75rem; color: var(--github-text-muted);"> <i class="fas fa-calendar-alt" style="font-size: 0.6875rem; margin-right: 0.375rem;"></i>May 13, 2026 </div> </div> </a> </li> <li style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); transition: all 0.2s ease;" onmouseover="this.style.borderBottomColor='var(--github-border-hover)';" onmouseout="this.style.borderBottomColor='var(--github-border)';"> <a href="https://www.murdok.org/news/iterative-prompts-for-turning-messy-outlines-into-dynamic-scenes" style="display: block; text-decoration: none; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.8';" onmouseout="this.style.opacity='1';"> <div style="width: 100%; height: 120px; border-radius: 6px; overflow: hidden; background: var(--github-bg-secondary); margin-bottom: 0.75rem; position: relative; display: flex; align-items: center; justify-content: center;"> <picture><img src="https://www.murdok.org/assets/images/posts/iterative-prompts-for-turning-messy-outlines-into-dynamic-scenes-featured-grok-imagine-image-quality.jpg" alt="Iterative Prompts for Turning Messy Outlines into Dynamic Scenes" width="120" height="120" style="width: 100%; height: 100%; object-fit: cover; display: block;" loading="lazy" decoding="async"></picture> </div> <div> <h4 style="font-family: 'Inter', sans-serif; font-size: 0.875rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.375rem; line-height: 1.4; transition: color 0.2s ease;" onmouseover="this.style.color='var(--github-primary)';" onmouseout="this.style.color='var(--github-text-primary)';"> Iterative Prompts for Turning Messy Outlines into Dynamic Scenes </h4> <div style="font-size: 0.75rem; color: var(--github-text-muted);"> <i class="fas fa-calendar-alt" style="font-size: 0.6875rem; margin-right: 0.375rem;"></i>May 12, 2026 </div> </div> </a> </li> <li style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--github-border); transition: all 0.2s ease;" onmouseover="this.style.borderBottomColor='var(--github-border-hover)';" onmouseout="this.style.borderBottomColor='var(--github-border)';"> <a href="https://www.murdok.org/news/ai-powered-character-questionnaires-that-feel-truly-specific" style="display: block; text-decoration: none; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.8';" onmouseout="this.style.opacity='1';"> <div style="width: 100%; height: 120px; border-radius: 6px; overflow: hidden; background: var(--github-bg-secondary); margin-bottom: 0.75rem; position: relative; display: flex; align-items: center; justify-content: center;"> <picture><img src="https://www.murdok.org/assets/images/posts/ai-powered-character-questionnaires-that-feel-truly-specific-featured-grok-imagine-image-quality.jpg" alt="AI-Powered Character Questionnaires That Feel Truly Specific" width="120" height="120" style="width: 100%; height: 100%; object-fit: cover; display: block;" loading="lazy" decoding="async"></picture> </div> <div> <h4 style="font-family: 'Inter', sans-serif; font-size: 0.875rem; font-weight: 600; color: var(--github-text-primary); margin-bottom: 0.375rem; line-height: 1.4; transition: color 0.2s ease;" onmouseover="this.style.color='var(--github-primary)';" onmouseout="this.style.color='var(--github-text-primary)';"> AI-Powered Character Questionnaires That Feel Truly Specific </h4> <div style="font-size: 0.75rem; color: var(--github-text-muted);"> <i class="fas fa-calendar-alt" style="font-size: 0.6875rem; margin-right: 0.375rem;"></i>May 12, 2026 </div> </div> </a> </li> </ul> </div> </div> </div> </div> </div> <style> /* Article sections - match sidebar widget styling exactly */ .article-section-tags.sidebar-widget, .article-section-correction.sidebar-widget, .article-section-share.sidebar-widget, .article-section-comments.sidebar-widget, .article-section-related.sidebar-widget { background: var(--github-bg-primary) !important; border: 1px solid var(--github-border) !important; border-radius: 12px !important; padding: 1.25rem !important; margin-bottom: 1.5rem !important; } [data-bs-theme="dark"] .article-section-tags.sidebar-widget, [data-theme="dark"] .article-section-tags.sidebar-widget, [data-bs-theme="dark"] .article-section-correction.sidebar-widget, [data-theme="dark"] .article-section-correction.sidebar-widget, [data-bs-theme="dark"] .article-section-share.sidebar-widget, [data-theme="dark"] .article-section-share.sidebar-widget, [data-bs-theme="dark"] .article-section-comments.sidebar-widget, [data-theme="dark"] .article-section-comments.sidebar-widget, [data-bs-theme="dark"] .article-section-related.sidebar-widget, [data-theme="dark"] .article-section-related.sidebar-widget { background: #000 !important; } /* Content inside sections should match sidebar container background in dark mode */ [data-bs-theme="dark"] .article-section-tags.sidebar-widget > *, [data-theme="dark"] .article-section-tags.sidebar-widget > *, [data-bs-theme="dark"] .article-section-correction.sidebar-widget > *, [data-theme="dark"] .article-section-correction.sidebar-widget > *, [data-bs-theme="dark"] .article-section-share.sidebar-widget > *, [data-theme="dark"] .article-section-share.sidebar-widget > *, [data-bs-theme="dark"] .article-section-comments.sidebar-widget > *, [data-theme="dark"] .article-section-comments.sidebar-widget > *, [data-bs-theme="dark"] .article-section-related.sidebar-widget > *, [data-theme="dark"] .article-section-related.sidebar-widget > * { background: transparent !important; } /* Form inputs and internal containers should match sidebar background */ [data-bs-theme="dark"] .article-section-correction.sidebar-widget input, [data-theme="dark"] .article-section-correction.sidebar-widget input, [data-bs-theme="dark"] .article-section-correction.sidebar-widget textarea, [data-theme="dark"] .article-section-correction.sidebar-widget textarea, [data-bs-theme="dark"] .article-section-comments.sidebar-widget input, [data-theme="dark"] .article-section-comments.sidebar-widget input, [data-bs-theme="dark"] .article-section-comments.sidebar-widget textarea, [data-theme="dark"] .article-section-comments.sidebar-widget textarea, [data-bs-theme="dark"] .article-section-correction.sidebar-widget .comment-form-container, [data-theme="dark"] .article-section-correction.sidebar-widget .comment-form-container { background: #000 !important; } /* Internal divs with backgrounds should match sidebar */ [data-bs-theme="dark"] .article-section-comments.sidebar-widget .comment-form-container, [data-theme="dark"] .article-section-comments.sidebar-widget .comment-form-container, [data-bs-theme="dark"] .article-section-comments.sidebar-widget > div[style*="background"], [data-theme="dark"] .article-section-comments.sidebar-widget > div[style*="background"], [data-bs-theme="dark"] .article-section-related.sidebar-widget ul li div[style*="background"], [data-theme="dark"] .article-section-related.sidebar-widget ul li div[style*="background"], [data-bs-theme="dark"] .article-section-tags.sidebar-widget a[style*="background"], [data-theme="dark"] .article-section-tags.sidebar-widget a[style*="background"] { background: #000 !important; } /* Ensure all content containers match sidebar background */ [data-bs-theme="dark"] .article-section-tags.sidebar-widget > div, [data-theme="dark"] .article-section-tags.sidebar-widget > div, [data-bs-theme="dark"] .article-section-correction.sidebar-widget > div, [data-theme="dark"] .article-section-correction.sidebar-widget > div, [data-bs-theme="dark"] .article-section-share.sidebar-widget > div, [data-theme="dark"] .article-section-share.sidebar-widget > div, [data-bs-theme="dark"] .article-section-comments.sidebar-widget > div, [data-theme="dark"] .article-section-comments.sidebar-widget > div, [data-bs-theme="dark"] .article-section-related.sidebar-widget > div, [data-theme="dark"] .article-section-related.sidebar-widget > div { background: transparent !important; } /* Ensure proper flex layout for news single page - match news listing page */ .news-main-content { flex: 1 1 0 !important; min-width: 0 !important; max-width: none !important; width: auto !important; padding-left: 1.5rem !important; padding-right: 1.5rem !important; } /* Desktop layout - ensure proper flex behavior */ @media (min-width: 992px) { .row.g-4 { display: flex !important; flex-wrap: nowrap !important; align-items: flex-start !important; } .left-sidebar-column, .right-sidebar-column { flex: 0 0 auto !important; max-width: 360px !important; min-width: 0 !important; } .news-main-content { flex: 1 1 0 !important; min-width: 900px !important; /* Comfortable reading width for articles - matches typical news page width */ max-width: none !important; width: auto !important; padding-left: 1.5rem !important; padding-right: 1.5rem !important; } } /* On mobile, allow wrapping */ @media (max-width: 991px) { .row.g-4 { flex-wrap: wrap !important; } .left-sidebar-column, .right-sidebar-column { width: 100% !important; max-width: 100% !important; flex: 0 0 100% !important; } .news-main-content { width: 100% !important; max-width: 100% !important; flex: 0 0 100% !important; min-width: 0 !important; padding-left: 0 !important; padding-right: 0 !important; } } </style> <script> // Dynamically adjust main content column width based on sidebars document.addEventListener('DOMContentLoaded', function() { const mainContent = document.getElementById('news-main-content'); if (!mainContent) return; const hasLeftSidebar = document.querySelector('.left-sidebar-column') !== null; const hasRightSidebar = document.querySelector('.right-sidebar-column') !== null; const row = mainContent.closest('.row'); // Main content should always flex to fill remaining space mainContent.style.flex = '1 1 0'; mainContent.style.minWidth = '0'; // On desktop (>= 992px), prevent wrapping when sidebars are present function updateLayout() { if (window.innerWidth >= 992) { if (hasLeftSidebar || hasRightSidebar) { if (row) { row.style.flexWrap = 'nowrap'; } } } else { // On mobile, allow wrapping if (row) { row.style.flexWrap = 'wrap'; } } } // Update on load and resize updateLayout(); window.addEventListener('resize', updateLayout); }); </script> <script> // Handle hash links on page load (for any internal links) document.addEventListener('DOMContentLoaded', function() { // Add scroll offset for fixed headers const headings = document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]'); headings.forEach(heading => { heading.style.scrollMarginTop = '100px'; heading.style.scrollPaddingTop = '100px'; }); // Handle hash links on page load if (window.location.hash) { setTimeout(function() { const targetId = window.location.hash.substring(1); const targetElement = document.getElementById(targetId); if (targetElement) { const headerOffset = 100; const elementPosition = targetElement.getBoundingClientRect().top; const offsetPosition = elementPosition + window.pageYOffset - headerOffset; window.scrollTo({ top: offsetPosition, behavior: 'smooth' }); } }, 100); } }); // Track social media shares function trackSocialShare(platform, postId) { fetch('https://www.murdok.org/api/news-share', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ post_id: postId, platform: platform }) }).catch(err => console.log('Share tracking error', err)); } // Copy article link to clipboard function copyArticleLink(postId) { const url = window.location.href; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(url).then(() => { showCopyNotification('Link copied to clipboard!'); trackSocialShare('copy', postId); }).catch(err => { fallbackCopyText(url, postId); }); } else { fallbackCopyText(url, postId); } } function fallbackCopyText(text, postId) { const input = document.createElement('input'); input.value = text; input.style.position = 'fixed'; input.style.opacity = '0'; document.body.appendChild(input); input.select(); input.setSelectionRange(0, 99999); // For mobile devices try { document.execCommand('copy'); showCopyNotification('Link copied to clipboard!'); if (postId) { trackSocialShare('copy', postId); } } catch (err) { showCopyNotification('Failed to copy link. Please copy manually: ' + text); } document.body.removeChild(input); } function showCopyNotification(message) { // Create notification element const notification = document.createElement('div'); notification.textContent = message; notification.style.cssText = 'position: fixed; bottom: 2rem; right: 2rem; background: var(--github-primary); color: var(--github-bg-primary); padding: 1rem 1.5rem; border-radius: 8px; z-index: 10000; font-family: "Inter", sans-serif; font-weight: 600; font-size: 0.9375rem; animation: slideIn 0.3s ease;'; // Add animation const style = document.createElement('style'); style.textContent = '@keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }'; document.head.appendChild(style); document.body.appendChild(notification); // Remove after 3 seconds setTimeout(() => { notification.style.animation = 'slideIn 0.3s ease reverse'; setTimeout(() => { if (document.body.contains(notification)) { document.body.removeChild(notification); } if (document.head.contains(style)) { document.head.removeChild(style); } }, 300); }, 3000); } // Comments functionality document.getElementById('commentForm')?.addEventListener('submit', function(e) { e.preventDefault(); const form = this; const formData = new FormData(form); const messageDiv = document.getElementById('commentMessage'); fetch('https://www.murdok.org/api/article-comment', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if (data.success) { messageDiv.style.display = 'block'; messageDiv.style.background = 'rgba(34, 197, 94, 0.1)'; messageDiv.style.border = '1px solid var(--github-primary)'; messageDiv.style.color = 'var(--github-primary)'; messageDiv.textContent = 'Comment posted successfully!'; form.reset(); document.getElementById('parent_comment_id').value = ''; document.getElementById('cancelReplyBtn').style.display = 'none'; // Reload page to show new comment setTimeout(() => window.location.reload(), 1000); } else { messageDiv.style.display = 'block'; messageDiv.style.background = 'rgba(244, 63, 94, 0.1)'; messageDiv.style.border = '1px solid #f43f5e'; messageDiv.style.color = '#f43f5e'; messageDiv.textContent = data.error || 'An error occurred. Please try again.'; } }) .catch(error => { console.error('Comment submission error:', error); messageDiv.style.display = 'block'; messageDiv.style.background = 'rgba(244, 63, 94, 0.1)'; messageDiv.style.border = '1px solid #f43f5e'; messageDiv.style.color = '#f43f5e'; messageDiv.textContent = 'Network error. Please check your connection and try again.'; }); }); function replyToComment(commentId, commenterName) { document.getElementById('parent_comment_id').value = commentId; document.getElementById('comment_text').placeholder = 'Reply to ' + commenterName + '...'; document.getElementById('comment_text').focus(); document.getElementById('cancelReplyBtn').style.display = 'inline-block'; document.getElementById('comment_text').scrollIntoView({ behavior: 'smooth', block: 'center' }); } function cancelReply() { document.getElementById('parent_comment_id').value = ''; document.getElementById('comment_text').placeholder = 'Write your comment here...'; document.getElementById('cancelReplyBtn').style.display = 'none'; } function deleteComment(commentId) { if (!confirm('Are you sure you want to delete this comment?')) { return; } const formData = new FormData(); formData.append('action', 'delete'); formData.append('comment_id', commentId); fetch('https://www.murdok.org/api/article-comment', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if (data.success) { window.location.reload(); } else { alert(data.error || 'Failed to delete comment'); } }) .catch(error => { console.error('Delete comment error:', error); alert('Network error. Please try again.'); }); } // Favorite button functionality const favoriteBtn = document.getElementById('favoriteBtn'); if (favoriteBtn) { favoriteBtn.addEventListener('click', function() { const postId = this.dataset.postId; const isFavorited = this.dataset.isFavorited === '1'; // Check if user is logged in // Show signup modal showSignupModal(); return; // Toggle favorite const formData = new FormData(); formData.append('action', 'toggle'); formData.append('post_id', postId); // Disable button during request this.disabled = true; const originalText = this.querySelector('.favorite-text').textContent; this.querySelector('.favorite-text').textContent = '...'; fetch('https://www.murdok.org/api/favorite', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { this.disabled = false; if (data.success) { // Toggle state const newIsFavorited = !isFavorited; this.dataset.isFavorited = newIsFavorited ? '1' : '0'; // Update button appearance const heartIcon = this.querySelector('i.fa-heart'); if (newIsFavorited) { this.style.background = '#dc3545'; this.style.borderColor = '#dc3545'; this.style.color = 'white'; if (heartIcon) heartIcon.style.color = 'white'; this.querySelector('.favorite-text').textContent = 'Favorited'; } else { this.style.background = 'transparent'; this.style.borderColor = '#dc3545'; this.style.color = '#f87171'; if (heartIcon) heartIcon.style.color = '#f87171'; const favoriteText = this.querySelector('.favorite-text'); if (favoriteText) { favoriteText.textContent = 'Favorite'; favoriteText.style.color = '#f87171'; } } // Show toast notification if (typeof GitHubToast !== 'undefined') { GitHubToast.success(newIsFavorited ? 'Article added to favorites' : 'Article removed from favorites'); } // Refresh favorites count in sidebar if widget exists if (typeof refreshFavoritesWidget === 'function') { refreshFavoritesWidget(); } } else { this.querySelector('.favorite-text').textContent = originalText; if (typeof GitHubToast !== 'undefined') { GitHubToast.error(data.error || 'Failed to update favorite'); } else { alert(data.error || 'Failed to update favorite'); } } }) .catch(error => { this.disabled = false; this.querySelector('.favorite-text').textContent = originalText; console.error('Favorite error:', error); if (typeof GitHubToast !== 'undefined') { GitHubToast.error('Network error. Please try again.'); } else { alert('Network error. Please try again.'); } }); }); } // Signup modal function function showSignupModal() { // Create modal if it doesn't exist let modal = document.getElementById('signupModal'); if (!modal) { modal = document.createElement('div'); modal.id = 'signupModal'; modal.className = 'modal fade'; modal.setAttribute('tabindex', '-1'); modal.innerHTML = ` <div class="modal-dialog modal-dialog-centered"> <div class="modal-content" style="background: var(--github-bg-primary); border: 1px solid var(--github-border); border-radius: 12px;"> <div class="modal-header" style="border-bottom: 1px solid var(--github-border); padding: 1.5rem;"> <h5 class="modal-title" style="font-family: 'Inter', sans-serif; font-size: 1.5rem; font-weight: 700; color: var(--github-text-primary);"> <i class="fas fa-user-plus" style="color: var(--github-primary); margin-right: 0.5rem;"></i> Sign Up to Favorite Articles </h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" style="opacity: 1; background-color: var(--github-text-secondary); border-radius: 4px; padding: 0.5rem; cursor: pointer; filter: invert(1);" title="Close"></button> </div> <div class="modal-body" style="padding: 2rem;"> <p style="color: var(--github-text-secondary); font-family: 'Inter', sans-serif; margin-bottom: 1.5rem;"> Create an account to save your favorite articles and access them anytime. </p> <form method="POST" action="https://www.murdok.org/signup" id="modalSignupForm"> <input type="hidden" name="recaptcha_token" id="modal_recaptcha_token"> <div style="margin-bottom: 1rem;"> <label style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); display: block; margin-bottom: 0.5rem;"> Username <span style="color: #ef4444;">*</span> </label> <input type="text" name="username" required pattern="[a-zA-Z0-9_\-]{3,20}" style="width: 100%; background: var(--github-bg-secondary); border: 1px solid var(--github-border); border-radius: 8px; color: var(--github-text-primary); font-family: 'Inter', sans-serif; font-size: 0.9375rem; padding: 0.75rem 1rem;" onfocus="this.style.borderColor='var(--github-primary)';" onblur="this.style.borderColor='var(--github-border)';"> </div> <div style="margin-bottom: 1rem;"> <label style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); display: block; margin-bottom: 0.5rem;"> Email <span style="color: #ef4444;">*</span> </label> <input type="email" name="email" required style="width: 100%; background: var(--github-bg-secondary); border: 1px solid var(--github-border); border-radius: 8px; color: var(--github-text-primary); font-family: 'Inter', sans-serif; font-size: 0.9375rem; padding: 0.75rem 1rem;" onfocus="this.style.borderColor='var(--github-primary)';" onblur="this.style.borderColor='var(--github-border)';"> </div> <div style="margin-bottom: 1.5rem;"> <label style="font-family: 'Inter', sans-serif; font-size: 0.9375rem; font-weight: 600; color: var(--github-text-primary); display: block; margin-bottom: 0.5rem;"> Password <span style="color: #ef4444;">*</span> </label> <input type="password" name="password" required minlength="6" style="width: 100%; background: var(--github-bg-secondary); border: 1px solid var(--github-border); border-radius: 8px; color: var(--github-text-primary); font-family: 'Inter', sans-serif; font-size: 0.9375rem; padding: 0.75rem 1rem;" onfocus="this.style.borderColor='var(--github-primary)';" onblur="this.style.borderColor='var(--github-border)';"> </div> <button type="submit" style="width: 100%; background: var(--github-primary); color: #000000; border: 1px solid var(--github-primary); border-radius: 8px; padding: 0.875rem 1.5rem; font-family: 'Inter', sans-serif; font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease;" onmouseover="this.style.opacity='0.9';" onmouseout="this.style.opacity='1';"> <i class="fas fa-user-plus" style="margin-right: 0.5rem;"></i> Create Account </button> </form> <div style="text-align: center; margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid var(--github-border);"> <p style="margin: 0; color: var(--github-text-secondary); font-size: 0.9375rem; font-family: 'Inter', sans-serif;"> Already have an account? <a href="https://www.murdok.org/login" style="color: var(--github-primary); text-decoration: none; font-weight: 600;" onmouseover="this.style.textDecoration='underline';" onmouseout="this.style.textDecoration='none';"> Sign In </a> </p> </div> </div> </div> </div> `; document.body.appendChild(modal); // Handle reCAPTCHA for modal form (function() { var recaptchaSiteKey = String("6LdJ01IsAAAAAHyuodz2yefPjZa8q9CoeQB0l_xE" || ''); if (recaptchaSiteKey === '') return; var modalForm = document.getElementById('modalSignupForm'); if (modalForm) { modalForm.addEventListener('submit', function(e) { e.preventDefault(); if (typeof grecaptcha !== 'undefined' && grecaptcha.ready) { grecaptcha.ready(function() { grecaptcha.execute(recaptchaSiteKey, { action: String('signup') }) .then(function(token) { document.getElementById('modal_recaptcha_token').value = token; modalForm.submit(); }) .catch(function(err) { document.getElementById('modal_recaptcha_token').value = ''; modalForm.submit(); }); }); } else { modalForm.submit(); } }); } })(); } // Show modal - check if Bootstrap is loaded if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { try { const bsModal = new bootstrap.Modal(modal); bsModal.show(); } catch (e) { console.error('Bootstrap Modal error:', e); // Fallback: show modal manually modal.style.display = 'block'; modal.classList.add('show'); document.body.classList.add('modal-open'); const backdrop = document.createElement('div'); backdrop.className = 'modal-backdrop fade show'; document.body.appendChild(backdrop); // Close button functionality for fallback const closeBtn = modal.querySelector('.btn-close'); if (closeBtn) { closeBtn.onclick = () => { modal.style.display = 'none'; modal.classList.remove('show'); document.body.classList.remove('modal-open'); backdrop.remove(); }; } // Backdrop click to close backdrop.onclick = () => { modal.style.display = 'none'; modal.classList.remove('show'); document.body.classList.remove('modal-open'); backdrop.remove(); }; // ESC key to close const escHandler = (e) => { if (e.key === 'Escape' && modal.classList.contains('show')) { modal.style.display = 'none'; modal.classList.remove('show'); document.body.classList.remove('modal-open'); backdrop.remove(); document.removeEventListener('keydown', escHandler); } }; document.addEventListener('keydown', escHandler); document.body.appendChild(backdrop); } } else { // Fallback: show modal manually modal.style.display = 'block'; modal.classList.add('show'); document.body.classList.add('modal-open'); const backdrop = document.createElement('div'); backdrop.className = 'modal-backdrop fade show'; document.body.appendChild(backdrop); // Close button functionality for fallback const closeBtn = modal.querySelector('.btn-close'); if (closeBtn) { closeBtn.onclick = () => { modal.style.display = 'none'; modal.classList.remove('show'); document.body.classList.remove('modal-open'); backdrop.remove(); }; } // Backdrop click to close backdrop.onclick = () => { modal.style.display = 'none'; modal.classList.remove('show'); document.body.classList.remove('modal-open'); backdrop.remove(); }; // ESC key to close const escHandler = (e) => { if (e.key === 'Escape' && modal.classList.contains('show')) { modal.style.display = 'none'; modal.classList.remove('show'); document.body.classList.remove('modal-open'); backdrop.remove(); document.removeEventListener('keydown', escHandler); } }; document.addEventListener('keydown', escHandler); } } </script> </main> <!-- Footer --> <footer class="border-top mt-5" style="background-color: var(--github-bg-secondary); border-color: var(--github-border) !important;"> <div class="container py-4"> <div class="row g-4"> <!-- Logo --> <div class="col-lg-3 col-md-4"> <div class="mb-3"> <div class="d-flex align-items-center mb-2"> <img src="/assets/images/uploads/logo_dark_1768218367.png" alt="Murdok" width="120" height="32" class="footer-logo-dark" style="max-width: 120px; object-fit: contain;"> </div> <p style="font-family: 'Inter', sans-serif; font-size: 0.875rem; color: var(--github-text-secondary); margin: 0; line-height: 1.5;"> Creative Writing With Artificial Intelligence </p> </div> </div> <!-- Navigation Links --> <div class="col-lg-6 col-md-4"> <div class="row g-4"> <div class="col-6"> <h3 class="fw-bold mb-3" style="color: var(--github-text-primary); text-transform: uppercase; font-size: 0.75rem; letter-spacing: 0.5px; margin: 0 0 1rem 0;"> Navigation </h3> <ul class="list-unstyled mb-0"> <li class="mb-2"><a href="/" class="text-decoration-none fw-medium d-flex align-items-center gap-2" style="color: var(--github-text-secondary); font-size: 14px; transition: color 0.2s ease;"><i class="fas fa-home" style="width: 16px; text-align: center;"></i> Home</a></li> <li class="mb-2"><a href="/news" class="text-decoration-none fw-medium d-flex align-items-center gap-2" style="color: var(--github-text-secondary); font-size: 14px; transition: color 0.2s ease;"><i class="fas fa-newspaper" style="width: 16px; text-align: center;"></i> News</a></li> <li class="mb-2"><a href="/wiki" class="text-decoration-none fw-medium d-flex align-items-center gap-2" style="color: var(--github-text-secondary); font-size: 14px; transition: color 0.2s ease;"><i class="fas fa-book" style="width: 16px; text-align: center;"></i> Wiki</a></li> <li class="mb-2"><a href="/search" class="text-decoration-none fw-medium d-flex align-items-center gap-2" style="color: var(--github-text-secondary); font-size: 14px; transition: color 0.2s ease;"><i class="fas fa-search" style="width: 16px; text-align: center;"></i> Search</a></li> </ul> </div> <div class="col-6"> <h3 class="fw-bold mb-3" style="color: var(--github-text-primary); text-transform: uppercase; font-size: 12px; letter-spacing: 0.5px; font-size: 0.75rem; margin: 0 0 1rem 0;"> Support </h3> <ul class="list-unstyled mb-0"> <li class="mb-2"><a href="/contact" class="text-decoration-none fw-medium d-flex align-items-center gap-2" style="color: var(--github-text-secondary); font-size: 14px; transition: color 0.2s ease;"><i class="fas fa-envelope" style="width: 16px; text-align: center;"></i> Contact</a></li> <li class="mb-2"><a href="/privacy" class="text-decoration-none fw-medium d-flex align-items-center gap-2" style="color: var(--github-text-secondary); font-size: 14px; transition: color 0.2s ease;"><i class="fas fa-shield-alt" style="width: 16px; text-align: center;"></i> Privacy</a></li> <li class="mb-2"><a href="/terms" class="text-decoration-none fw-medium d-flex align-items-center gap-2" style="color: var(--github-text-secondary); font-size: 14px; transition: color 0.2s ease;"><i class="fas fa-file-contract" style="width: 16px; text-align: center;"></i> Terms</a></li> <li class="mb-2"><a href="/sitemap" class="text-decoration-none fw-medium d-flex align-items-center gap-2" style="color: var(--github-text-secondary); font-size: 14px; transition: color 0.2s ease;"><i class="fas fa-sitemap" style="width: 16px; text-align: center;"></i> Sitemap</a></li> </ul> </div> </div> </div> <!-- Copyright, Social Media, and Theme Toggle --> <div class="col-lg-3 col-md-4"> <div class="d-flex flex-column align-items-md-end"> <div class="d-flex align-items-center gap-2 mb-3 flex-wrap justify-content-md-end"> <a href="https://x.com/MurdokActual" target="_blank" rel="noopener noreferrer" class="text-decoration-none d-flex align-items-center justify-content-center" style="width: 36px; height: 36px; border-radius: 50%; background-color: var(--github-bg-secondary); border: 1px solid var(--github-border); color: var(--github-text-secondary); transition: all 0.2s ease;" onmouseover="this.style.backgroundColor='#000000'; this.style.borderColor='#000000'; this.style.color='white'; this.style.transform='translateY(-2px)';" onmouseout="this.style.backgroundColor='var(--github-bg-secondary)'; this.style.borderColor='var(--github-border)'; this.style.color='var(--github-text-secondary)'; this.style.transform='translateY(0)';" title="Twitter"> <i class="fab fa-x-twitter" style="font-size: 16px;"></i> </a> </div> <p class="mb-3 fw-medium text-md-end" style="color: var(--github-text-secondary); font-size: 13px;"> © 2026 Murdok. All rights reserved. </p> </div> </div> </div> </div> </footer> <!-- Bootstrap 5.3.3 JS Bundle (admin loads in header to avoid bootstrap undefined on sidebar-widgets) --> <script src="/assets/js/bootstrap.bundle.min.js" defer></script> <!-- jQuery 3.7.1 --> <script src="/assets/js/jquery.min.js" defer></script> <!-- Alpine.js --> <script src="/assets/js/alpine.min.js" defer></script> <!-- Cropper.js (only load on profile page or admin pages) - defer for Core Web Vitals --> <!-- Footer Styles --> <style> /* Footer link hover effects */ footer a { transition: color 0.2s ease, transform 0.2s ease; } footer a:hover { color: var(--github-primary) !important; transform: translateX(2px); } /* Logo hover effect */ footer img:hover { transform: scale(1.05); transition: transform 0.2s ease; } footer button:hover { background-color: var(--github-bg-secondary) !important; transform: scale(1.05); } </style> <!-- GitHub-inspired Utility Functions --> <script> // Global image error handler - provides fallback for missing images function handleImageError(img) { // Create a placeholder SVG const placeholder = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgZmlsbD0iI2Y2ZjhmYSIvPjx0ZXh0IHg9IjUwJSIgeT0iNTAlIiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMTQiIGZpbGw9IiM2NTZkNzYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGR5PSIuM2VtIj5JbWFnZSBub3QgYXZhaWxhYmxlPC90ZXh0Pjwvc3ZnPg=='; // Replace with placeholder if not already using it if (img.src !== placeholder) { img.onerror = null; // Prevent infinite loop img.src = placeholder; img.style.backgroundColor = 'var(--github-bg-secondary, #f6f8fa)'; img.style.display = 'block'; } else { // If placeholder also fails, hide the image img.style.display = 'none'; } } // Ensure dark theme is set (site is dark-only) document.addEventListener('DOMContentLoaded', function() { document.documentElement.setAttribute('data-bs-theme', 'dark'); }); // GitHub-inspired Toast System class GitHubToast { static show(message, type = 'info', duration = 5000) { // Ensure toast container exists let toastContainer = document.getElementById('toastContainer'); if (!toastContainer) { toastContainer = document.createElement('div'); toastContainer.id = 'toastContainer'; toastContainer.className = 'toast-container'; toastContainer.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 9999; max-width: 400px;'; document.body.appendChild(toastContainer); } const toastId = 'toast-' + Date.now(); const bgClass = type === 'success' ? 'bg-success' : type === 'error' ? 'bg-danger' : type === 'warning' ? 'bg-warning' : 'bg-primary'; const iconClass = type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-triangle' : type === 'warning' ? 'fa-exclamation-circle' : 'fa-info-circle'; const toastHTML = ` <div id="${toastId}" class="toast align-items-center text-white ${bgClass} border-0" role="alert" aria-live="assertive" aria-atomic="true" style="display: block; opacity: 0; transition: opacity 0.3s ease;"> <div class="d-flex"> <div class="toast-body"> <i class="fas ${iconClass} me-2"></i> ${this.escapeHtml(message)} </div> <button type="button" class="btn-close btn-close-white me-2 m-auto" onclick="document.getElementById('${toastId}').remove()" aria-label="Close"></button> </div> </div> `; toastContainer.insertAdjacentHTML('beforeend', toastHTML); const toastElement = document.getElementById(toastId); // Show toast with animation setTimeout(() => { toastElement.style.opacity = '1'; }, 10); // Use Bootstrap Toast if available, otherwise use fallback if (typeof bootstrap !== 'undefined' && bootstrap.Toast) { const toast = new bootstrap.Toast(toastElement, { delay: duration }); toast.show(); toastElement.addEventListener('hidden.bs.toast', () => { toastElement.remove(); }); } else { // Fallback: simple show/hide toastElement.style.opacity = '1'; // Auto-dismiss if (duration > 0) { setTimeout(() => { toastElement.style.opacity = '0'; setTimeout(() => { if (toastElement.parentNode) { toastElement.remove(); } }, 300); }, duration); } } } static escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } static success(message, duration = 5000) { this.show(message, 'success', duration); } static error(message, duration = 5000) { this.show(message, 'error', duration); } static warning(message, duration = 5000) { this.show(message, 'warning', duration); } static info(message, duration = 5000) { this.show(message, 'info', duration); } } // GitHub-inspired Modal System class GitHubModal { static show(options = {}) { const { title = '', body = '', footer = '', size = 'md', backdrop = true, keyboard = true } = options; const modalId = 'github-modal-' + Date.now(); const sizeClass = size === 'lg' ? 'modal-lg' : size === 'sm' ? 'modal-sm' : ''; const modalHTML = ` <div class="modal fade" id="${modalId}" tabindex="-1" ${backdrop ? '' : 'data-bs-backdrop="static"'} ${keyboard ? '' : 'data-bs-keyboard="false"'}> <div class="modal-dialog ${sizeClass}"> <div class="modal-content"> ${title ? `<div class="modal-header"> <h5 class="modal-title">${title}</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div>` : ''} ${body ? `<div class="modal-body">${body}</div>` : ''} ${footer ? `<div class="modal-footer">${footer}</div>` : ''} </div> </div> </div> `; document.body.insertAdjacentHTML('beforeend', modalHTML); const modalElement = document.getElementById(modalId); // Use Bootstrap Modal if available, otherwise use vanilla JS let modal; if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { modal = new bootstrap.Modal(modalElement); modalElement.addEventListener('hidden.bs.modal', () => { modalElement.remove(); }); modal.show(); } else { // Fallback: show modal manually modalElement.style.display = 'block'; modalElement.classList.add('show'); document.body.classList.add('modal-open'); const backdrop = document.createElement('div'); backdrop.className = 'modal-backdrop fade show'; backdrop.onclick = () => { modalElement.style.display = 'none'; modalElement.classList.remove('show'); document.body.classList.remove('modal-open'); backdrop.remove(); modalElement.remove(); }; document.body.appendChild(backdrop); // Store backdrop reference for cleanup modalElement._backdrop = backdrop; // Close on ESC key const escHandler = (e) => { if (e.key === 'Escape' && modalElement.classList.contains('show')) { backdrop.click(); document.removeEventListener('keydown', escHandler); } }; document.addEventListener('keydown', escHandler); // Add hide method for compatibility modal = { hide: () => { backdrop.click(); }, _element: modalElement }; } return { modal, element: modalElement }; } static confirm(message, title = 'Confirm', confirmText = 'OK', cancelText = 'Cancel') { return new Promise((resolve) => { let settled = false; const finish = (value) => { if (settled) { return; } settled = true; resolve(value); }; const footer = ` <button type="button" class="btn btn-secondary github-modal-btn-cancel" data-bs-dismiss="modal">${cancelText}</button> <button type="button" class="btn btn-primary github-modal-btn-ok">${confirmText}</button> `; const { modal, element: modalElement } = this.show({ title, body: `<p class="mb-0">${message}</p>`, footer }); const confirmBtn = modalElement ? modalElement.querySelector('.github-modal-btn-ok') : null; const cancelBtn = modalElement ? modalElement.querySelector('.github-modal-btn-cancel') : null; const hideModal = () => { if (modal && typeof modal.hide === 'function') { modal.hide(); } else if (modalElement) { modalElement.style.display = 'none'; modalElement.classList.remove('show'); document.body.classList.remove('modal-open'); const back = modalElement._backdrop || document.querySelector('.modal-backdrop'); if (back) { back.remove(); } modalElement.remove(); } }; if (confirmBtn) { confirmBtn.addEventListener('click', () => { finish(true); hideModal(); }); } if (cancelBtn) { cancelBtn.addEventListener('click', () => { finish(false); hideModal(); }); } // Dismiss via X, Escape, or backdrop — only if not already confirmed/cancelled if (modalElement && typeof bootstrap !== 'undefined' && bootstrap.Modal) { modalElement.addEventListener('hidden.bs.modal', () => { finish(false); }); } else if (modalElement) { const backdrop = modalElement._backdrop || document.querySelector('.modal-backdrop'); if (backdrop) { backdrop.addEventListener('click', () => finish(false)); } } }); } } // GitHub-inspired Table Initializers class GitHubTables { static initTabulator(selector, columns, options = {}) { const defaultOptions = { layout: "fitColumns", responsiveLayout: "collapse", pagination: "local", paginationSize: 25, paginationSizeSelector: [10, 25, 50, 100], movableColumns: true, resizableRows: true, placeholder: "No data available", height: "auto" }; return new Tabulator(selector, { columns, ...defaultOptions, ...options }); } } // GitHub-inspired Form Enhancements class GitHubForms { static initSelect2(selector, options = {}) { const defaultOptions = { theme: 'bootstrap-5', width: '100%', placeholder: 'Select an option...', allowClear: true }; return $(selector).select2({ ...defaultOptions, ...options }); } static initSimpleBar(selector) { return new SimpleBar(document.querySelector(selector)); } static initCharts() { // Initialize any Chart.js instances on the page const chartCanvases = document.querySelectorAll('canvas[data-chart]'); chartCanvases.forEach(canvas => { const chartType = canvas.dataset.chart; const chartData = JSON.parse(canvas.dataset.chartData || '{}'); new Chart(canvas, { type: chartType, data: chartData, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: chartType === 'line' || chartType === 'bar' ? { y: { beginAtZero: true, grid: { color: 'rgba(0,0,0,0.1)' } }, x: { grid: { display: false } } } : {} } }); }); } } // Initialize everything when DOM is ready document.addEventListener('DOMContentLoaded', function() { // Add loading states to forms document.querySelectorAll('form').forEach(form => { form.addEventListener('submit', function(e) { const submitBtn = form.querySelector('button[type="submit"], .github-btn-primary'); if (submitBtn && !submitBtn.classList.contains('no-loading')) { submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Loading...'; submitBtn.disabled = true; } }); }); // Add keyboard shortcuts document.addEventListener('keydown', function(e) { // Ctrl/Cmd + K for search focus if ((e.ctrlKey || e.metaKey) && e.key === 'k') { e.preventDefault(); const searchInput = document.querySelector('input[type="search"], [data-search]'); if (searchInput) { searchInput.focus(); } } // Escape to close modals if (e.key === 'Escape') { if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { const modals = document.querySelectorAll('.modal.show'); modals.forEach(modal => { const bsModal = bootstrap.Modal.getInstance(modal); if (bsModal) { bsModal.hide(); } }); } } }); }); // Make classes globally available window.GitHubToast = GitHubToast; window.GitHubModal = GitHubModal; window.GitHubTables = GitHubTables; window.GitHubForms = GitHubForms; </script> <!-- Responsive Header Search Toggle --> <script> document.addEventListener('DOMContentLoaded', function() { const searchToggle = document.getElementById('headerSearchToggle'); const searchForm = document.getElementById('headerSearchForm'); const searchInput = document.getElementById('headerSearchInput'); if (searchToggle && searchForm) { // Toggle search form on icon click searchToggle.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); searchForm.classList.toggle('expanded'); if (searchForm.classList.contains('expanded')) { searchInput.focus(); } }); // Close search form when clicking outside document.addEventListener('click', function(e) { if (!searchForm.contains(e.target) && !searchToggle.contains(e.target)) { searchForm.classList.remove('expanded'); } }); // Close search form on escape key document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && searchForm.classList.contains('expanded')) { searchForm.classList.remove('expanded'); } }); // Close search form after form submission on mobile if (searchForm) { searchForm.addEventListener('submit', function() { if (window.innerWidth <= 991) { setTimeout(function() { searchForm.classList.remove('expanded'); }, 100); } }); } } }); // Fix hamburger menu on mobile - ensure Bootstrap collapse works // Wait for Bootstrap to be available (it loads in the footer) function initHamburgerMenu() { // Check if Bootstrap is loaded, if not wait a bit and retry if (typeof bootstrap === 'undefined' || !bootstrap.Collapse) { setTimeout(initHamburgerMenu, 100); return; } // Initialize public navbar collapse const publicNavbar = document.getElementById('publicNavbar'); const publicNavbarToggle = document.getElementById('publicNavbarToggle'); if (publicNavbar && publicNavbarToggle) { // Initialize collapse instance if it doesn't exist let publicCollapse = bootstrap.Collapse.getInstance(publicNavbar); if (!publicCollapse) { publicCollapse = new bootstrap.Collapse(publicNavbar, { toggle: false }); } // Ensure the toggle button works publicNavbarToggle.addEventListener('click', function(e) { if (publicCollapse) { publicCollapse.toggle(); } }); } // Initialize admin navbar collapse const adminNavbar = document.getElementById('adminNavbar'); const adminNavbarToggle = document.querySelector('[data-bs-target="#adminNavbar"]'); if (adminNavbar && adminNavbarToggle) { // Initialize collapse instance if it doesn't exist let adminCollapse = bootstrap.Collapse.getInstance(adminNavbar); if (!adminCollapse) { adminCollapse = new bootstrap.Collapse(adminNavbar, { toggle: false }); } // Ensure the toggle button works adminNavbarToggle.addEventListener('click', function(e) { if (adminCollapse) { adminCollapse.toggle(); } }); } } // Start initialization when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initHamburgerMenu); } else { initHamburgerMenu(); } </script> </body> </html>