fresh-main #5
			
				
			
		
		
		
	|  | @ -7,7 +7,7 @@ import tailwind from '@astrojs/tailwind'; | |||
| 
 | ||||
| // https://astro.build/config
 | ||||
| export default defineConfig({ | ||||
|   site: 'https://laforceit.blog', | ||||
|   site: 'https://laforceit-blog.pages.dev', // Your current Cloudflare site
 | ||||
|   output: 'static', | ||||
|   // adapter: cloudflare(),  // Commented out for local development
 | ||||
|   integrations: [ | ||||
|  | @ -17,10 +17,14 @@ export default defineConfig({ | |||
|   ], | ||||
|   markdown: { | ||||
|     shikiConfig: { | ||||
|       theme: 'dracula', | ||||
|       theme: 'one-dark-pro', | ||||
|       wrap: true | ||||
|     }, | ||||
|     remarkPlugins: [], | ||||
|     rehypePlugins: [] | ||||
|   }, | ||||
|   compressHTML: false, // Disable HTML compression to avoid parsing errors
 | ||||
|   build: { | ||||
|     format: 'file',  // Use 'file' instead of 'directory' format
 | ||||
|   } | ||||
| }); | ||||
|  | @ -379,6 +379,70 @@ const navItems = [ | |||
| </style> | ||||
| 
 | ||||
| <script> | ||||
| 
 | ||||
|   // Handle mobile menu toggle | ||||
|   document.addEventListener('DOMContentLoaded', () => { | ||||
|     const menuBtn = document.getElementById('mobile-menu-btn'); | ||||
|     const mainNav = document.querySelector('.main-nav'); | ||||
|     const header = document.querySelector('.site-header'); | ||||
|      | ||||
|     if (menuBtn && mainNav) { | ||||
|       menuBtn.addEventListener('click', () => { | ||||
|         mainNav.classList.toggle('active'); | ||||
|         menuBtn.classList.toggle('mobile-menu-active'); | ||||
|       }); | ||||
|     } | ||||
|      | ||||
|     // Header scroll effect | ||||
|     window.addEventListener('scroll', () => { | ||||
|       if (window.scrollY > 50) { | ||||
|         header?.classList.add('scrolled'); | ||||
|       } else { | ||||
|         header?.classList.remove('scrolled'); | ||||
|       } | ||||
|     }); | ||||
|      | ||||
|     // Theme toggle functionality | ||||
|     const themeToggle = document.getElementById('theme-toggle'); | ||||
|      | ||||
|     if (themeToggle) { | ||||
|       themeToggle.addEventListener('click', () => { | ||||
|         document.documentElement.classList.toggle('light-mode'); | ||||
|          | ||||
|         // Store preference in localStorage | ||||
|         const isLightMode = document.documentElement.classList.contains('light-mode'); | ||||
|         localStorage.setItem('theme', isLightMode ? 'light' : 'dark'); | ||||
|       }); | ||||
|     } | ||||
|      | ||||
|     // Add interactive network nodes animation | ||||
|     const header_el = document.querySelector('.site-header'); | ||||
|      | ||||
|     if (header_el) { | ||||
|       // Create animated nodes | ||||
|       for (let i = 0; i < 5; i++) { | ||||
|         const node = document.createElement('div'); | ||||
|         node.className = 'nav-node'; | ||||
|         node.style.left = `${Math.random() * 100}%`; | ||||
|         node.style.animationDelay = `${Math.random() * 5}s`; | ||||
|         node.style.animationDuration = `${5 + Math.random() * 5}s`; | ||||
|         header_el.appendChild(node); | ||||
|       } | ||||
|     } | ||||
|      | ||||
| // Theme toggle functionality | ||||
| const themeToggle = document.getElementById('theme-toggle'); | ||||
| 	 | ||||
| if (themeToggle) { | ||||
|   themeToggle.addEventListener('click', () => { | ||||
| 	document.documentElement.classList.toggle('light-mode'); | ||||
| 	 | ||||
| 	// Store preference in localStorage | ||||
| 	const isLightMode = document.documentElement.classList.contains('light-mode'); | ||||
| 	localStorage.setItem('theme', isLightMode ? 'light' : 'dark'); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
|   // Handle mobile menu toggle | ||||
|   document.addEventListener('DOMContentLoaded', () => { | ||||
|     const menuBtn = document.getElementById('mobile-menu-btn'); | ||||
|  |  | |||
|  | @ -0,0 +1,93 @@ | |||
| --- | ||||
| // ThemeToggler.astro | ||||
| // A component to toggle between light and dark themes | ||||
| --- | ||||
| 
 | ||||
| <button id="theme-toggle" aria-label="Toggle dark mode" class="theme-toggle"> | ||||
|   <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="sun-icon"> | ||||
|     <circle cx="12" cy="12" r="5"></circle> | ||||
|     <line x1="12" y1="1" x2="12" y2="3"></line> | ||||
|     <line x1="12" y1="21" x2="12" y2="23"></line> | ||||
|     <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> | ||||
|     <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> | ||||
|     <line x1="1" y1="12" x2="3" y2="12"></line> | ||||
|     <line x1="21" y1="12" x2="23" y2="12"></line> | ||||
|     <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> | ||||
|     <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> | ||||
|   </svg> | ||||
|   <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="moon-icon"> | ||||
|     <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> | ||||
|   </svg> | ||||
| </button> | ||||
| 
 | ||||
| <style> | ||||
|   .theme-toggle { | ||||
|     background: none; | ||||
|     border: none; | ||||
|     padding: 0.25rem; | ||||
|     border-radius: 50%; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     color: var(--text-secondary); | ||||
|     cursor: pointer; | ||||
|     transition: color 0.3s ease, background-color 0.3s ease; | ||||
|     position: relative; | ||||
|     width: 34px; | ||||
|     height: 34px; | ||||
|   } | ||||
|    | ||||
|   .theme-toggle:hover { | ||||
|     color: var(--text-primary); | ||||
|     background: rgba(255, 255, 255, 0.1); | ||||
|   } | ||||
|    | ||||
|   .sun-icon, .moon-icon { | ||||
|     position: absolute; | ||||
|     transition: transform 0.5s ease, opacity 0.5s ease; | ||||
|   } | ||||
|    | ||||
|   html:not(.dark) .sun-icon { | ||||
|     opacity: 1; | ||||
|     transform: rotate(0); | ||||
|   } | ||||
|    | ||||
|   html:not(.dark) .moon-icon { | ||||
|     opacity: 0; | ||||
|     transform: rotate(90deg); | ||||
|   } | ||||
|    | ||||
|   html.dark .sun-icon { | ||||
|     opacity: 0; | ||||
|     transform: rotate(-90deg); | ||||
|   } | ||||
|    | ||||
|   html.dark .moon-icon { | ||||
|     opacity: 1; | ||||
|     transform: rotate(0); | ||||
|   } | ||||
| </style> | ||||
| 
 | ||||
| <script> | ||||
|   // Theme toggling logic | ||||
|   document.addEventListener('DOMContentLoaded', () => { | ||||
|     const themeToggle = document.getElementById('theme-toggle'); | ||||
|      | ||||
|     // Function to set theme | ||||
|     const setTheme = (isDark) => { | ||||
|       if (isDark) { | ||||
|         document.documentElement.classList.add('dark'); | ||||
|         localStorage.setItem('theme', 'dark'); | ||||
|       } else { | ||||
|         document.documentElement.classList.remove('dark'); | ||||
|         localStorage.setItem('theme', 'light'); | ||||
|       } | ||||
|     }; | ||||
|      | ||||
|     // Theme toggle click handler | ||||
|     themeToggle?.addEventListener('click', () => { | ||||
|       const isDark = document.documentElement.classList.contains('dark'); | ||||
|       setTheme(!isDark); | ||||
|     }); | ||||
|   }); | ||||
| </script> | ||||
|  | @ -23,6 +23,18 @@ const { | |||
|     <title>{title}</title> | ||||
|     <meta name="description" content={description} /> | ||||
|      | ||||
|     <!-- Theme initialization - Must be inline --> | ||||
|     <script is:inline> | ||||
|       // Initialize theme before page loads to prevent flash | ||||
|       const savedTheme = localStorage.getItem('theme'); | ||||
|       const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | ||||
|       if (savedTheme === 'light' || (!savedTheme && !prefersDark)) { | ||||
|         document.documentElement.classList.add('light-mode'); | ||||
|       } else { | ||||
|         document.documentElement.classList.remove('light-mode'); | ||||
|       } | ||||
|     </script> | ||||
|      | ||||
|     <!-- OpenGraph/Social Media Meta Tags --> | ||||
|     <meta property="og:title" content={title} /> | ||||
|     <meta property="og:description" content={description} /> | ||||
|  | @ -44,6 +56,9 @@ const { | |||
|     <!-- Favicon --> | ||||
|     <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> | ||||
|      | ||||
|     <!-- Theme CSS --> | ||||
|     <link rel="stylesheet" href="/styles/theme.css" /> | ||||
|      | ||||
|     <!-- Cytoscape Library for Knowledge Graph --> | ||||
|     <script src="https://unpkg.com/cytoscape@3.25.0/dist/cytoscape.min.js" is:inline></script> | ||||
|      | ||||
|  |  | |||
|  | @ -1,255 +1,246 @@ | |||
| import { getCollection } from 'astro:content'; | ||||
| --- | ||||
| // src/pages/tag/[tag].astro | ||||
| // Dynamic route for tag pages | ||||
| 
 | ||||
| import BaseLayout from '../../layouts/BaseLayout.astro'; | ||||
| import { getCollection } from 'astro:content'; | ||||
| 
 | ||||
| export async function getStaticPaths() { | ||||
|   const allPosts = await getCollection('posts'); | ||||
|    | ||||
|   // Get all unique tags from all posts | ||||
|   const uniqueTags = [...new Set(allPosts.flatMap(post => post.data.tags || []))]; | ||||
|    | ||||
|   // Create a page for each tag | ||||
|   return uniqueTags.map(tag => { | ||||
|     // Filter posts that have this tag | ||||
|     const filteredPosts = allPosts.filter(post =>  | ||||
|       post.data.tags && post.data.tags.includes(tag) | ||||
|     ); | ||||
|   const allPosts = await getCollection('blog'); | ||||
|   const uniqueTags = [...new Set(allPosts.map((post) => post.data.tags).flat())]; | ||||
| 
 | ||||
|   return uniqueTags.map((tag) => { | ||||
|     const filteredPosts = allPosts.filter((post) => post.data.tags.includes(tag)); | ||||
|     return { | ||||
|       params: { tag }, | ||||
|       props: { posts: filteredPosts, tag }, | ||||
|       props: { posts: filteredPosts }, | ||||
|     }; | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| const { posts, tag } = Astro.props; | ||||
| const { tag } = Astro.params; | ||||
| const { posts } = Astro.props; | ||||
| 
 | ||||
| // Sort posts by date | ||||
| // Format date | ||||
| const formatDate = (dateStr) => { | ||||
|   const date = new Date(dateStr); | ||||
|   return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }); | ||||
| }; | ||||
| 
 | ||||
| // Sort posts by date (newest first) | ||||
| const sortedPosts = posts.sort((a, b) => { | ||||
|   const dateA = a.data.pubDate ? new Date(a.data.pubDate) : new Date(0); | ||||
|   const dateB = b.data.pubDate ? new Date(b.data.pubDate) : new Date(0); | ||||
|   const dateA = new Date(a.data.pubDate); | ||||
|   const dateB = new Date(b.data.pubDate); | ||||
|   return dateB.getTime() - dateA.getTime(); | ||||
| }); | ||||
| --- | ||||
| 
 | ||||
| <BaseLayout title={`Posts tagged with "${tag}" | LaForce IT Blog`} description={`Articles and guides related to ${tag}`}> | ||||
|   <main class="container"> | ||||
|     <section class="tag-header"> | ||||
|       <h1 class="tag-title">Posts tagged with <span>#{tag}</span></h1> | ||||
|       <p class="tag-description"> | ||||
|         Browse all {sortedPosts.length} articles related to this topic | ||||
|       </p> | ||||
|       <a href="/tags" class="tag-link">View all tags</a> | ||||
|     </section> | ||||
|   <div class="container tag-page"> | ||||
|     <header class="tag-hero"> | ||||
|       <h1>Posts tagged with <span class="tag-highlight">{tag}</span></h1> | ||||
|       <p>Explore {sortedPosts.length} {sortedPosts.length === 1 ? 'article' : 'articles'} related to {tag}</p> | ||||
|     </header> | ||||
| 
 | ||||
|     <div class="blog-grid"> | ||||
|     <div class="posts-grid"> | ||||
|       {sortedPosts.map((post) => ( | ||||
|         <article class="post-card"> | ||||
|           {/* Temporarily removed conditional image rendering for debugging */} | ||||
|           <!-- Simplified image rendering that works reliably --> | ||||
|           <img | ||||
|             width={720} | ||||
|             height={360} | ||||
|             src="/images/placeholders/default.jpg" | ||||
|             src={post.data.heroImage || "/images/placeholders/default.jpg"} | ||||
|             alt="" | ||||
|             class="post-image" | ||||
|           /> | ||||
|           <div class="post-content"> | ||||
|             <div class="post-meta"> | ||||
|               <time datetime={post.data.pubDate ? new Date(post.data.pubDate).toISOString() : ''}> | ||||
|                 {post.data.pubDate ? new Date(post.data.pubDate).toLocaleDateString('en-us', { | ||||
|                   year: 'numeric', | ||||
|                   month: 'short', | ||||
|                   day: 'numeric', | ||||
|                 }) : 'No date'} | ||||
|               </time> | ||||
|               {post.data.category && ( | ||||
|                 <span class="post-category"> | ||||
|                   {post.data.category} | ||||
|                 </span> | ||||
|               )} | ||||
|             </div> | ||||
|             <h3 class="post-title"> | ||||
|             <time datetime={post.data.pubDate}>{formatDate(post.data.pubDate)}</time> | ||||
|             <h2 class="post-title"> | ||||
|               <a href={`/posts/${post.slug}/`}>{post.data.title}</a> | ||||
|               {post.data.draft && <span class="draft-badge">Draft</span>} | ||||
|             </h3> | ||||
|             </h2> | ||||
|             <p class="post-excerpt">{post.data.description}</p> | ||||
|             <div class="post-footer"> | ||||
|               <span class="post-read-time">{post.data.readTime || '5 min read'}</span> | ||||
|               <a href={`/posts/${post.slug}/`} class="read-more">Read More</a> | ||||
|             <div class="post-meta"> | ||||
|               <span class="reading-time">{post.data.minutesRead || '5 min'} read</span> | ||||
|               <ul class="post-tags"> | ||||
|                 {post.data.tags.map((tagName) => ( | ||||
|                   <li> | ||||
|                     <a href={`/tag/${tagName}`} class={tagName === tag ? 'current-tag' : ''}> | ||||
|                       {tagName} | ||||
|                     </a> | ||||
|                   </li> | ||||
|                 ))} | ||||
|               </ul> | ||||
|             </div> | ||||
|           </div> | ||||
|         </article> | ||||
|       ))} | ||||
|     </div> | ||||
|   </main> | ||||
| 
 | ||||
|     <a href="/tags" class="all-tags-link"> | ||||
|       <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | ||||
|         <line x1="19" y1="12" x2="5" y2="12"></line> | ||||
|         <polyline points="12 19 5 12 12 5"></polyline> | ||||
|       </svg> | ||||
|       View all tags | ||||
|     </a> | ||||
|   </div> | ||||
| </BaseLayout> | ||||
| 
 | ||||
| <style> | ||||
| .tag-header { | ||||
|   margin: 3rem 0; | ||||
|   .tag-page { | ||||
|     padding-top: 2rem; | ||||
|     padding-bottom: 4rem; | ||||
|   } | ||||
|    | ||||
|   .tag-hero { | ||||
|     text-align: center; | ||||
| } | ||||
|     margin-bottom: 3rem; | ||||
|     animation: fadeIn 0.5s ease-out; | ||||
|   } | ||||
|    | ||||
| .tag-title { | ||||
|   font-size: clamp(1.8rem, 4vw, 2.5rem); | ||||
|   margin-bottom: 1rem; | ||||
| } | ||||
|   @keyframes fadeIn { | ||||
|     from { opacity: 0; transform: translateY(10px); } | ||||
|     to { opacity: 1; transform: translateY(0); } | ||||
|   } | ||||
|    | ||||
| .tag-title span { | ||||
|   background: linear-gradient(90deg, var(--accent-primary), var(--accent-tertiary)); | ||||
|   .tag-hero h1 { | ||||
|     font-size: var(--font-size-3xl); | ||||
|     margin-bottom: 0.5rem; | ||||
|     line-height: 1.2; | ||||
|   } | ||||
|    | ||||
|   .tag-highlight { | ||||
|     background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary)); | ||||
|     -webkit-background-clip: text; | ||||
|     -webkit-text-fill-color: transparent; | ||||
|     background-clip: text; | ||||
|     color: transparent; | ||||
|   font-family: 'JetBrains Mono', monospace; | ||||
| } | ||||
|     font-weight: 700; | ||||
|   } | ||||
|    | ||||
| .tag-description { | ||||
|   .tag-hero p { | ||||
|     color: var(--text-secondary); | ||||
|   font-size: 1.1rem; | ||||
|   margin-bottom: 1rem; | ||||
| } | ||||
|     font-size: var(--font-size-lg); | ||||
|   } | ||||
|    | ||||
| .tag-link { | ||||
|   display: inline-block; | ||||
|   margin-top: 1rem; | ||||
|   color: var(--accent-primary); | ||||
|   text-decoration: none; | ||||
|   font-family: 'JetBrains Mono', monospace; | ||||
|   font-size: 0.9rem; | ||||
|   border-bottom: 1px dashed var(--accent-primary); | ||||
|   transition: all 0.3s ease; | ||||
| } | ||||
| 
 | ||||
| .tag-link:hover { | ||||
|   border-bottom: 1px solid var(--accent-primary); | ||||
| } | ||||
| 
 | ||||
| .draft-badge { | ||||
|   display: inline-block; | ||||
|   margin-left: 0.5rem; | ||||
|   padding: 0.25rem 0.5rem; | ||||
|   background-color: rgba(226, 232, 240, 0.2); | ||||
|   color: #94a3b8; | ||||
|   font-size: 0.75rem; | ||||
|   border-radius: 0.25rem; | ||||
|   vertical-align: middle; | ||||
| } | ||||
| 
 | ||||
| /* Include styles from blog index if needed, like .blog-grid, .post-card etc. */ | ||||
| .blog-grid { | ||||
|   .posts-grid { | ||||
|     display: grid; | ||||
|   grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); | ||||
|     grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); | ||||
|     gap: 2rem; | ||||
|   margin: 2rem 0 4rem; | ||||
| } | ||||
|     margin-bottom: 3rem; | ||||
|   } | ||||
|    | ||||
| .post-card { | ||||
|   .post-card { | ||||
|     background: var(--card-bg); | ||||
|   border-radius: 10px; | ||||
|   border: 1px solid var(--card-border); | ||||
|     border-radius: 12px; | ||||
|     overflow: hidden; | ||||
|   transition: all 0.3s ease; | ||||
|   position: relative; | ||||
|   z-index: 1; | ||||
| } | ||||
| 
 | ||||
| .post-card:hover { | ||||
|   transform: translateY(-5px); | ||||
|   box-shadow: 0 10px 30px rgba(6, 182, 212, 0.1); | ||||
|   border-color: rgba(56, 189, 248, 0.4); | ||||
| } | ||||
| 
 | ||||
| .post-card::before { | ||||
|   content: ''; | ||||
|   position: absolute; | ||||
|   inset: 0; | ||||
|   background: linear-gradient(135deg, rgba(6, 182, 212, 0.05), rgba(139, 92, 246, 0.05)); | ||||
|   z-index: -1; | ||||
|     border: 1px solid var(--border-primary); | ||||
|     transition: transform 0.3s ease, box-shadow 0.3s ease; | ||||
|     animation: fadeIn 0.5s ease-out forwards; | ||||
|     animation-delay: calc(var(--animation-order, 0) * 0.1s); | ||||
|     opacity: 0; | ||||
|   transition: opacity 0.3s ease; | ||||
| } | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|   } | ||||
|    | ||||
| .post-card:hover::before { | ||||
|   opacity: 1; | ||||
| } | ||||
|   .post-card:hover { | ||||
|     transform: translateY(-5px); | ||||
|     box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); | ||||
|     border-color: var(--accent-primary); | ||||
|   } | ||||
|    | ||||
| .post-image { | ||||
|   .post-image { | ||||
|     width: 100%; | ||||
|     height: 200px; | ||||
|     object-fit: cover; | ||||
|   border-bottom: 1px solid var(--card-border); | ||||
| } | ||||
|     border-bottom: 1px solid var(--border-primary); | ||||
|   } | ||||
|    | ||||
| .post-content { | ||||
|   .post-content { | ||||
|     padding: 1.5rem; | ||||
| } | ||||
| 
 | ||||
| .post-meta { | ||||
|     flex-grow: 1; | ||||
|     display: flex; | ||||
|   justify-content: space-between; | ||||
|   align-items: center; | ||||
|   margin-bottom: 1rem; | ||||
|   font-size: 0.85rem; | ||||
|   color: var(--text-secondary); | ||||
| } | ||||
|     flex-direction: column; | ||||
|   } | ||||
|    | ||||
| .post-category { | ||||
|   background: rgba(6, 182, 212, 0.1); | ||||
|   color: var(--accent-primary); | ||||
|   padding: 0.25rem 0.5rem; | ||||
|   border-radius: 4px; | ||||
|   font-family: 'JetBrains Mono', monospace; | ||||
|   font-size: 0.75rem; | ||||
| } | ||||
|   .post-content time { | ||||
|     color: var(--text-tertiary); | ||||
|     font-size: var(--font-size-sm); | ||||
|     font-family: var(--font-mono); | ||||
|   } | ||||
|    | ||||
| .post-title { | ||||
|   font-size: 1.25rem; | ||||
|   margin-bottom: 0.75rem; | ||||
|   .post-title { | ||||
|     font-size: var(--font-size-xl); | ||||
|     margin: 0.5rem 0 1rem; | ||||
|     line-height: 1.3; | ||||
| } | ||||
|   } | ||||
|    | ||||
| .post-title a { | ||||
|   .post-title a { | ||||
|     color: var(--text-primary); | ||||
|     text-decoration: none; | ||||
|   transition: color 0.3s ease; | ||||
| } | ||||
|     transition: color 0.2s ease; | ||||
|   } | ||||
|    | ||||
| .post-title a:hover { | ||||
|   .post-title a:hover { | ||||
|     color: var(--accent-primary); | ||||
| } | ||||
|   } | ||||
|    | ||||
| .post-excerpt { | ||||
|   .post-excerpt { | ||||
|     color: var(--text-secondary); | ||||
|   font-size: 0.9rem; | ||||
|     font-size: var(--font-size-md); | ||||
|     margin-bottom: 1.5rem; | ||||
|   display: -webkit-box; | ||||
|   -webkit-line-clamp: 3; | ||||
|   -webkit-box-orient: vertical; | ||||
|   overflow: hidden; | ||||
| } | ||||
|     line-height: 1.6; | ||||
|     flex-grow: 1; | ||||
|   } | ||||
|    | ||||
| .post-footer { | ||||
|   .post-meta { | ||||
|     display: flex; | ||||
|   justify-content: space-between; | ||||
|   align-items: center; | ||||
|   color: var(--text-secondary); | ||||
|   font-size: 0.85rem; | ||||
| } | ||||
|     flex-direction: column; | ||||
|     gap: 0.75rem; | ||||
|     margin-top: auto; | ||||
|   } | ||||
|    | ||||
| .read-more { | ||||
|   .reading-time { | ||||
|     color: var(--text-tertiary); | ||||
|     font-size: var(--font-size-sm); | ||||
|     font-family: var(--font-mono); | ||||
|   } | ||||
|    | ||||
|   .post-tags { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|     gap: 0.5rem; | ||||
|     list-style: none; | ||||
|     padding: 0; | ||||
|   } | ||||
|    | ||||
|   .post-tags li a { | ||||
|     display: block; | ||||
|     padding: 0.25rem 0.75rem; | ||||
|     background: rgba(56, 189, 248, 0.1); | ||||
|     border-radius: 20px; | ||||
|     color: var(--accent-primary); | ||||
|     font-size: var(--font-size-xs); | ||||
|     text-decoration: none; | ||||
|   font-weight: 500; | ||||
|     transition: all 0.2s ease; | ||||
|   } | ||||
|    | ||||
|   .post-tags li a:hover { | ||||
|     background: rgba(56, 189, 248, 0.2); | ||||
|     transform: translateY(-2px); | ||||
|   } | ||||
|    | ||||
|   .post-tags li a.current-tag { | ||||
|     background: var(--accent-primary); | ||||
|     color: var(--bg-primary); | ||||
|   } | ||||
|    | ||||
|   .all-tags-link { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   gap: 0.25rem; | ||||
|   transition: color 0.3s ease; | ||||
| } | ||||
| 
 | ||||
| .read-more:hover { | ||||
|   color: var(--accent-secondary); | ||||
| } | ||||
| 
 | ||||
| .read-more::after { | ||||
|   content: '→'; | ||||
| } | ||||
| </style> | ||||
|     gap: 0.5rem; | ||||
|     margin: 0 auto; | ||||
|     padding: 0.75rem 1.5rem; | ||||
|     background: var(--bg-secondary); | ||||
|     border: 1px solid var(--border-primary); | ||||
|     border-radius: 30px; | ||||
|  | @ -0,0 +1,82 @@ | |||
| /* Theme Variables - Dark/Light Mode Support */ | ||||
| 
 | ||||
| /* Dark theme (default) */ | ||||
| html { | ||||
|   /* Keep the default dark theme as defined in BaseLayout */ | ||||
| } | ||||
| 
 | ||||
| /* Light theme */ | ||||
| html.light-mode { | ||||
|   /* Primary Colors */ | ||||
|   --bg-primary: #f8fafc; | ||||
|   --bg-secondary: #f1f5f9; | ||||
|   --bg-tertiary: #e2e8f0; | ||||
|   --bg-code: #f1f5f9; | ||||
|   --text-primary: #0f172a; | ||||
|   --text-secondary: #334155; | ||||
|   --text-tertiary: #64748b; | ||||
|    | ||||
|   /* Accent Colors remain the same for brand consistency */ | ||||
|    | ||||
|   /* Glow Effects - lighter for light mode */ | ||||
|   --glow-primary: rgba(6, 182, 212, 0.1); | ||||
|   --glow-secondary: rgba(59, 130, 246, 0.1); | ||||
|   --glow-tertiary: rgba(139, 92, 246, 0.1); | ||||
|    | ||||
|   /* Border Colors */ | ||||
|   --border-primary: rgba(0, 0, 0, 0.1); | ||||
|   --border-secondary: rgba(0, 0, 0, 0.05); | ||||
|    | ||||
|   /* Card Background */ | ||||
|   --card-bg: rgba(255, 255, 255, 0.8); | ||||
|   --card-border: rgba(56, 189, 248, 0.3); /* Slightly stronger border */ | ||||
|    | ||||
|   /* UI Element Colors */ | ||||
|   --ui-element: #e2e8f0; | ||||
|   --ui-element-hover: #cbd5e1; | ||||
| } | ||||
| 
 | ||||
| /* Background adjustments for light mode */ | ||||
| html.light-mode body { | ||||
|   background-image:  | ||||
|     radial-gradient(circle at 20% 35%, rgba(6, 182, 212, 0.05) 0%, transparent 50%), | ||||
|     radial-gradient(circle at 75% 15%, rgba(59, 130, 246, 0.05) 0%, transparent 45%), | ||||
|     radial-gradient(circle at 85% 70%, rgba(139, 92, 246, 0.05) 0%, transparent 40%); | ||||
| } | ||||
| 
 | ||||
| /* Adding light mode grid overlay */ | ||||
| html.light-mode body::before { | ||||
|   background-image:  | ||||
|     linear-gradient(rgba(15, 23, 42, 0.03) 1px, transparent 1px), | ||||
|     linear-gradient(90deg, rgba(15, 23, 42, 0.03) 1px, transparent 1px); | ||||
| } | ||||
| 
 | ||||
| /* Theme transition for smooth switching */ | ||||
| html, body, * { | ||||
|   transition:  | ||||
|     background-color 0.3s ease, | ||||
|     color 0.3s ease, | ||||
|     border-color 0.3s ease, | ||||
|     box-shadow 0.3s ease; | ||||
| } | ||||
| 
 | ||||
| /* Knowledge Graph light mode adjustments */ | ||||
| html.light-mode .graph-container { | ||||
|   background: rgba(248, 250, 252, 0.6); | ||||
| } | ||||
| 
 | ||||
| html.light-mode .graph-loading { | ||||
|   background: rgba(241, 245, 249, 0.7); | ||||
| } | ||||
| 
 | ||||
| html.light-mode .graph-filters { | ||||
|   background: rgba(241, 245, 249, 0.7); | ||||
| } | ||||
| 
 | ||||
| html.light-mode .graph-legend { | ||||
|   background: rgba(241, 245, 249, 0.7); | ||||
| } | ||||
| 
 | ||||
| html.light-mode .node-details { | ||||
|   background: rgba(248, 250, 252, 0.9); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue