summaryrefslogtreecommitdiff
path: root/extras/html/themes/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'extras/html/themes/index.html')
-rw-r--r--extras/html/themes/index.html469
1 files changed, 469 insertions, 0 deletions
diff --git a/extras/html/themes/index.html b/extras/html/themes/index.html
new file mode 100644
index 0000000..ecef268
--- /dev/null
+++ b/extras/html/themes/index.html
@@ -0,0 +1,469 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Gemtexter Theme Gallery - 50 Unique Themes</title>
+ <style>
+ * {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ }
+
+ body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
+ background-color: #f5f5f5;
+ color: #333;
+ line-height: 1.6;
+ }
+
+ .header {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ text-align: center;
+ padding: 4em 2em;
+ box-shadow: 0 4px 20px rgba(0,0,0,0.1);
+ }
+
+ .header h1 {
+ font-size: 3em;
+ margin-bottom: 0.5em;
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
+ }
+
+ .header p {
+ font-size: 1.2em;
+ opacity: 0.9;
+ max-width: 600px;
+ margin: 0 auto;
+ }
+
+ .container {
+ max-width: 1400px;
+ margin: 0 auto;
+ padding: 2em;
+ }
+
+ .filters {
+ background: white;
+ padding: 2em;
+ border-radius: 12px;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
+ margin-bottom: 3em;
+ text-align: center;
+ }
+
+ .filters h2 {
+ margin-bottom: 1em;
+ color: #667eea;
+ }
+
+ .filter-buttons {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1em;
+ justify-content: center;
+ }
+
+ .filter-btn {
+ padding: 0.5em 1.5em;
+ border: 2px solid #667eea;
+ background: white;
+ color: #667eea;
+ border-radius: 25px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ font-size: 1em;
+ }
+
+ .filter-btn:hover, .filter-btn.active {
+ background: #667eea;
+ color: white;
+ }
+
+ .theme-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
+ gap: 2em;
+ }
+
+ .theme-card {
+ background: white;
+ border-radius: 12px;
+ overflow: hidden;
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+ position: relative;
+ }
+
+ .theme-card:hover {
+ transform: translateY(-4px);
+ box-shadow: 0 8px 30px rgba(0,0,0,0.12);
+ }
+
+ .theme-preview {
+ height: 200px;
+ background: #f0f0f0;
+ position: relative;
+ overflow: hidden;
+ }
+
+ .theme-preview img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ }
+
+ .theme-preview-placeholder {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 3em;
+ font-weight: bold;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ }
+
+ .theme-info {
+ padding: 1.5em;
+ }
+
+ .theme-name {
+ font-size: 1.3em;
+ font-weight: bold;
+ margin-bottom: 0.5em;
+ color: #333;
+ }
+
+ .theme-details {
+ color: #666;
+ font-size: 0.9em;
+ margin-bottom: 1em;
+ }
+
+ .theme-tags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5em;
+ margin-bottom: 1em;
+ }
+
+ .tag {
+ padding: 0.2em 0.8em;
+ background: #f0f0f0;
+ border-radius: 15px;
+ font-size: 0.85em;
+ color: #666;
+ }
+
+ .tag.layout {
+ background: #e3f2fd;
+ color: #1976d2;
+ }
+
+ .tag.color {
+ background: #fce4ec;
+ color: #c2185b;
+ }
+
+ .theme-actions {
+ display: flex;
+ gap: 1em;
+ }
+
+ .btn {
+ flex: 1;
+ padding: 0.8em;
+ text-align: center;
+ text-decoration: none;
+ border-radius: 8px;
+ transition: all 0.3s ease;
+ font-weight: 500;
+ }
+
+ .btn-preview {
+ background: #667eea;
+ color: white;
+ }
+
+ .btn-preview:hover {
+ background: #5a67d8;
+ }
+
+ .btn-download {
+ background: white;
+ color: #667eea;
+ border: 2px solid #667eea;
+ }
+
+ .btn-download:hover {
+ background: #667eea;
+ color: white;
+ }
+
+ .footer {
+ text-align: center;
+ padding: 3em 2em;
+ color: #666;
+ background: white;
+ margin-top: 4em;
+ }
+
+ .stats {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 2em;
+ margin: 3em 0;
+ text-align: center;
+ }
+
+ .stat {
+ background: white;
+ padding: 2em;
+ border-radius: 12px;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
+ }
+
+ .stat-number {
+ font-size: 3em;
+ font-weight: bold;
+ color: #667eea;
+ }
+
+ .stat-label {
+ color: #666;
+ margin-top: 0.5em;
+ }
+
+ @media (max-width: 768px) {
+ .header h1 {
+ font-size: 2em;
+ }
+
+ .theme-grid {
+ grid-template-columns: 1fr;
+ }
+ }
+ </style>
+</head>
+<body>
+ <div class="header">
+ <h1>Gemtexter Theme Gallery</h1>
+ <p>50 unique, hand-crafted themes for your Gemtext content. Each theme features carefully selected fonts, harmonious color palettes, and distinctive layouts.</p>
+ </div>
+
+ <div class="container">
+ <div class="stats">
+ <div class="stat">
+ <div class="stat-number">50</div>
+ <div class="stat-label">Unique Themes</div>
+ </div>
+ <div class="stat">
+ <div class="stat-number">24</div>
+ <div class="stat-label">Layout Types</div>
+ </div>
+ <div class="stat">
+ <div class="stat-number">15</div>
+ <div class="stat-label">Font Families</div>
+ </div>
+ <div class="stat">
+ <div class="stat-number">∞</div>
+ <div class="stat-label">Possibilities</div>
+ </div>
+ </div>
+
+ <div class="filters">
+ <h2>Filter by Layout</h2>
+ <div class="filter-buttons">
+ <button class="filter-btn active" onclick="filterThemes('all')">All Themes</button>
+ <button class="filter-btn" onclick="filterThemes('centered')">Centered</button>
+ <button class="filter-btn" onclick="filterThemes('wide')">Wide</button>
+ <button class="filter-btn" onclick="filterThemes('magazine')">Magazine</button>
+ <button class="filter-btn" onclick="filterThemes('card')">Card</button>
+ <button class="filter-btn" onclick="filterThemes('minimal')">Minimal</button>
+ <button class="filter-btn" onclick="filterThemes('brutalist')">Brutalist</button>
+ <button class="filter-btn" onclick="filterThemes('terminal')">Terminal</button>
+ <button class="filter-btn" onclick="filterThemes('book')">Book</button>
+ <button class="filter-btn" onclick="filterThemes('hero')">Hero</button>
+ <button class="filter-btn" onclick="filterThemes('dark')">Dark Themes</button>
+ <button class="filter-btn" onclick="filterThemes('light')">Light Themes</button>
+ </div>
+ </div>
+
+ <div class="theme-grid" id="themeGrid">
+ <!-- Themes will be inserted here by JavaScript -->
+ </div>
+ </div>
+
+ <div class="footer">
+ <p>All themes are free to use and include properly licensed fonts.</p>
+ <p>Generated with love for the Gemtexter community.</p>
+ </div>
+
+ <script>
+ // Theme data
+ const themes = [
+ {name: "vibrant_garden", layout: "hero", colorType: "light", fonts: ["Abril Fatface", "Lato"]},
+ {name: "pure_voyage", layout: "brutalist", colorType: "dark", fonts: ["Oxygen", "Lato"]},
+ {name: "twilight_nebula", layout: "floating", colorType: "dark", fonts: ["Roboto Slab", "Oxygen"]},
+ {name: "mystic_canyon", layout: "future", colorType: "dark", fonts: ["Merriweather", "Oxygen"]},
+ {name: "dynamic_forest", layout: "future", colorType: "light", fonts: ["Higher Jump", "Lato"]},
+ {name: "soft_horizon", layout: "geometric", colorType: "light", fonts: ["Pixelon", "Oxygen"]},
+ {name: "pastel_crystal", layout: "newspaper", colorType: "light", fonts: ["Repetition Scrolling", "Merriweather"]},
+ {name: "bright_light", layout: "magazine", colorType: "light", fonts: ["Typewriter", "Roboto Slab"]},
+ {name: "crisp_oasis", layout: "asymmetric", colorType: "light", fonts: ["Khand", "Lato"]},
+ {name: "sharp_canyon", layout: "card", colorType: "dark", fonts: ["Roboto Slab", "Oxygen"]},
+ {name: "strong_breeze", layout: "terminal", colorType: "dark", fonts: ["Oxygen", "Merriweather"]},
+ {name: "aurora_dawn", layout: "swiss", colorType: "dark", fonts: ["Merriweather", "Roboto Slab"]},
+ {name: "mystic_meadow", layout: "artistic", colorType: "light", fonts: ["Roboto Slab", "Oxygen"]},
+ {name: "vibrant_nebula", layout: "overlap", colorType: "dark", fonts: ["Higher Jump", "Oxygen"]},
+ {name: "sleek_river", layout: "sidebar", colorType: "light", fonts: ["Pixelon", "Roboto Slab"]},
+ {name: "clear_forest", layout: "gradient", colorType: "light", fonts: ["Repetition Scrolling", "Merriweather"]},
+ {name: "bold_pulse", layout: "book", colorType: "dark", fonts: ["Typewriter", "Roboto Slab"]},
+ {name: "fresh_field", layout: "organic", colorType: "light", fonts: ["Oxygen", "Lato"]},
+ {name: "clear_frost", layout: "newspaper", colorType: "dark", fonts: ["Roboto Slab", "Oxygen"]},
+ {name: "ember_mountain", layout: "brutalist", colorType: "light", fonts: ["Oxygen", "Lato"]},
+ {name: "refined_oasis", layout: "centered", colorType: "dark", fonts: ["Abril Fatface", "Lato"]},
+ {name: "sharp_mountain", layout: "wide", colorType: "light", fonts: ["Roboto Slab", "Lato"]},
+ {name: "deep_crystal", layout: "geometric", colorType: "dark", fonts: ["Abril Fatface", "Merriweather"]},
+ {name: "cozy_wave", layout: "overlap", colorType: "light", fonts: ["Roboto Slab", "Lato"]},
+ {name: "ember_mist", layout: "hero", colorType: "dark", fonts: ["Oxygen", "Merriweather"]},
+ {name: "vibrant_storm", layout: "technical", colorType: "light", fonts: ["Merriweather", "Roboto Slab"]},
+ {name: "pure_storm", layout: "organic", colorType: "dark", fonts: ["Higher Jump", "Oxygen"]},
+ {name: "cool_breeze", layout: "artistic", colorType: "light", fonts: ["Pixelon", "Roboto Slab"]},
+ {name: "ethereal_mist", layout: "minimal_grid", colorType: "dark", fonts: ["Repetition Scrolling", "Merriweather"]},
+ {name: "modern_rhythm", layout: "split", colorType: "light", fonts: ["Typewriter", "Roboto Slab"]},
+ {name: "aurora_breeze", layout: "terminal", colorType: "dark", fonts: ["Khand", "Lato"]},
+ {name: "muted_oasis", layout: "centered", colorType: "light", fonts: ["Oxygen", "Lato"]},
+ {name: "ember_night", layout: "masonry", colorType: "dark", fonts: ["Roboto Slab", "Lato"]},
+ {name: "modern_storm", layout: "book", colorType: "light", fonts: ["Oxygen", "Oxygen"]},
+ {name: "amber_glacier", layout: "magazine", colorType: "dark", fonts: ["Roboto Slab", "Merriweather"]},
+ {name: "twilight_horizon", layout: "card", colorType: "light", fonts: ["Merriweather", "Roboto Slab"]},
+ {name: "gentle_glacier", layout: "swiss", colorType: "dark", fonts: ["Roboto Slab", "Oxygen"]},
+ {name: "deep_sky", layout: "future", colorType: "light", fonts: ["Higher Jump", "Oxygen"]},
+ {name: "smooth_echo", layout: "sidebar", colorType: "dark", fonts: ["Pixelon", "Roboto Slab"]},
+ {name: "refined_aurora", layout: "wide", colorType: "light", fonts: ["Repetition Scrolling", "Merriweather"]},
+ {name: "radiant_voyage", layout: "gradient", colorType: "dark", fonts: ["Typewriter", "Roboto Slab"]},
+ {name: "cosmic_odyssey", layout: "hero", colorType: "light", fonts: ["Oxygen", "Lato"]},
+ {name: "neon_storm", layout: "brutalist", colorType: "dark", fonts: ["Abril Fatface", "Lato"]},
+ {name: "cosmic_dusk", layout: "retro", colorType: "light", fonts: ["Roboto Slab", "Oxygen"]},
+ {name: "cozy_crystal", layout: "asymmetric", colorType: "dark", fonts: ["Oxygen", "Lato"]},
+ {name: "clean_rhythm", layout: "floating", colorType: "light", fonts: ["Merriweather", "Oxygen"]},
+ {name: "pastel_canyon", layout: "minimal_grid", colorType: "dark", fonts: ["Higher Jump", "Lato"]},
+ {name: "clean_garden", layout: "newspaper", colorType: "light", fonts: ["Pixelon", "Oxygen"]},
+ {name: "twilight_meadow", layout: "masonry", colorType: "dark", fonts: ["Roboto Slab", "Oxygen"]},
+ {name: "bright_spark", layout: "split", colorType: "light", fonts: ["Roboto Slab", "Oxygen"]}
+ ];
+
+ // Generate theme cards
+ function generateThemeCards() {
+ const grid = document.getElementById('themeGrid');
+
+ themes.forEach(theme => {
+ const card = document.createElement('div');
+ card.className = 'theme-card';
+ card.setAttribute('data-layout', theme.layout);
+ card.setAttribute('data-color', theme.colorType);
+
+ const initial = theme.name.split('_').map(w => w[0].toUpperCase()).join('');
+
+ card.innerHTML = `
+ <div class="theme-preview">
+ ${getThemePreview(theme)}
+ </div>
+ <div class="theme-info">
+ <div class="theme-name">${theme.name.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}</div>
+ <div class="theme-details">${theme.fonts.join(' + ')}</div>
+ <div class="theme-tags">
+ <span class="tag layout">${theme.layout.replace(/_/g, ' ')}</span>
+ <span class="tag color">${theme.colorType}</span>
+ </div>
+ <div class="theme-actions">
+ <a href="${theme.name}/example.html" class="btn btn-preview">Preview</a>
+ <a href="#" class="btn btn-download" onclick="downloadTheme('${theme.name}'); return false;">Download</a>
+ </div>
+ </div>
+ `;
+
+ grid.appendChild(card);
+ });
+ }
+
+ function getThemePreview(theme) {
+ // Check if screenshot exists and use it, otherwise show placeholder
+ const screenshotPath = `screenshots/${theme.name}.png`;
+
+ // Use the actual screenshot image
+ return `
+ <img src="${screenshotPath}" alt="${theme.name} preview"
+ onerror="this.onerror=null; this.outerHTML=getFallbackPreview('${theme.name}', '${theme.layout}', '${theme.colorType}');"
+ style="width: 100%; height: 100%; object-fit: cover;">
+ `;
+ }
+
+ function getFallbackPreview(name, layout, colorType) {
+ // Fallback placeholder if image fails to load
+ const colors = {
+ 'dark': ['#0a0a0a', '#1a1a1a', '#2a2a2a'],
+ 'light': ['#ffffff', '#f8f8f8', '#eeeeee']
+ };
+
+ const bgColor = colors[colorType][0];
+ const accentColor = colorType === 'dark' ? '#667eea' : '#764ba2';
+ const textColor = colorType === 'dark' ? '#ffffff' : '#1a1a1a';
+
+ return `
+ <div class="theme-preview-placeholder" style="background: ${bgColor}; color: ${textColor}; position: relative; overflow: hidden;">
+ <div style="position: absolute; top: 0; left: 0; right: 0; height: 60px; background: ${accentColor}; opacity: 0.8;"></div>
+ <div style="position: relative; z-index: 1; font-size: 2.5em; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">
+ ${name.split('_').map(w => w[0].toUpperCase()).join('')}
+ </div>
+ <div style="position: absolute; bottom: 10px; left: 10px; right: 10px; font-size: 0.8em; opacity: 0.7;">
+ ${layout.replace(/_/g, ' ')}
+ </div>
+ </div>
+ `;
+ }
+
+ // Filter themes
+ function filterThemes(filter) {
+ const cards = document.querySelectorAll('.theme-card');
+ const buttons = document.querySelectorAll('.filter-btn');
+
+ // Update active button
+ buttons.forEach(btn => {
+ btn.classList.remove('active');
+ if (btn.textContent.toLowerCase().includes(filter) || (filter === 'all' && btn.textContent === 'All Themes')) {
+ btn.classList.add('active');
+ }
+ });
+
+ // Filter cards
+ cards.forEach(card => {
+ if (filter === 'all') {
+ card.style.display = 'block';
+ } else if (filter === 'dark' || filter === 'light') {
+ card.style.display = card.getAttribute('data-color') === filter ? 'block' : 'none';
+ } else {
+ const layout = card.getAttribute('data-layout');
+ card.style.display = layout.includes(filter) ? 'block' : 'none';
+ }
+ });
+ }
+
+ // Download theme (placeholder function)
+ function downloadTheme(themeName) {
+ alert(`To use the "${themeName}" theme:\n\n1. Copy the ${themeName} directory to your themes folder\n2. Set HTML_THEME_DIR=./extras/html/themes/${themeName} in your gemtexter.conf\n3. Run ./gemtexter --generate to apply the theme`);
+ }
+
+ // Make getFallbackPreview available globally for onerror handler
+ window.getFallbackPreview = getFallbackPreview;
+
+ // Initialize
+ generateThemeCards();
+ </script>
+</body>
+</html> \ No newline at end of file