|
10 | 10 | <meta property="og:type" content="website" /> |
11 | 11 | {% if site.ogImage %}<meta property="og:image" content="{{ site.ogImage }}" />{% endif %} |
12 | 12 | {% if site.favicon %}<link rel="icon" href="{{ site.favicon }}" />{% endif %} |
| 13 | + <script> |
| 14 | + (function(){var t=localStorage.getItem('theme');if(t==='light')document.documentElement.setAttribute('data-theme','light');else if(t==='dark')document.documentElement.setAttribute('data-theme','dark');})(); |
| 15 | + </script> |
13 | 16 | <style> |
14 | 17 | @font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url('fonts/inter-regular.woff2') format('woff2'); } |
15 | 18 | @font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap; src: url('fonts/inter-medium.woff2') format('woff2'); } |
|
27 | 30 | --border: #30363d; |
28 | 31 | --text: #e6edf3; |
29 | 32 | --text-dim: #8b949e; |
| 33 | + --nav-bg: rgba(13,17,23,0.85); |
30 | 34 | --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; |
31 | 35 | --font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace; |
32 | 36 | --hero-from: {{ site.heroGradientFrom | default('#0d1117') }}; |
33 | 37 | --hero-to: {{ site.heroGradientTo | default('#161b22') }}; |
34 | 38 | } |
35 | 39 |
|
| 40 | + /* LIGHT THEME (OS preference, no explicit data-theme) */ |
| 41 | + @media (prefers-color-scheme: light) { |
| 42 | + html:not([data-theme="dark"]) { |
| 43 | + --bg: #f6f8fa; --bg2: #ffffff; --bg3: #f0f2f5; |
| 44 | + --border: #d0d7de; --text: #1f2328; --text-dim: #656d76; |
| 45 | + --nav-bg: rgba(255,255,255,0.88); |
| 46 | + --hero-from: #f0f2f5; --hero-to: #f6f8fa; |
| 47 | + } |
| 48 | + html:not([data-theme="dark"]) a { color: var(--accent); } |
| 49 | + html:not([data-theme="dark"]) a:hover { color: var(--accent-light); } |
| 50 | + html:not([data-theme="dark"]) .hero h1 { background: linear-gradient(135deg, var(--text), var(--accent)); -webkit-background-clip: text; background-clip: text; } |
| 51 | + html:not([data-theme="dark"]) .data-table tr:hover td { background: rgba(0,0,0,0.03); } |
| 52 | + html:not([data-theme="dark"]) .search-input { background: var(--bg3); } |
| 53 | + html:not([data-theme="dark"]) .install-steps code { background: var(--bg3); } |
| 54 | + } |
| 55 | + /* LIGHT THEME (explicit toggle) */ |
| 56 | + [data-theme="light"] { |
| 57 | + --bg: #f6f8fa; --bg2: #ffffff; --bg3: #f0f2f5; |
| 58 | + --border: #d0d7de; --text: #1f2328; --text-dim: #656d76; |
| 59 | + --nav-bg: rgba(255,255,255,0.88); |
| 60 | + --hero-from: #f0f2f5; --hero-to: #f6f8fa; |
| 61 | + } |
| 62 | + [data-theme="light"] a { color: var(--accent); } |
| 63 | + [data-theme="light"] a:hover { color: var(--accent-light); } |
| 64 | + [data-theme="light"] .hero h1 { background: linear-gradient(135deg, var(--text), var(--accent)); -webkit-background-clip: text; background-clip: text; } |
| 65 | + [data-theme="light"] .data-table tr:hover td { background: rgba(0,0,0,0.03); } |
| 66 | + [data-theme="light"] .search-input { background: var(--bg3); } |
| 67 | + [data-theme="light"] .install-steps code { background: var(--bg3); } |
| 68 | +
|
36 | 69 | html { scroll-behavior: smooth; } |
37 | 70 | body { font-family: var(--font-sans); background: var(--bg); color: var(--text); line-height: 1.6; min-height: 100vh; } |
38 | 71 | a { color: var(--accent-light); text-decoration: none; transition: color 0.2s; } |
39 | 72 | a:hover { color: #fff; } |
40 | 73 |
|
41 | 74 | /* NAV */ |
42 | | - .nav { position: sticky; top: 0; z-index: 100; background: rgba(13,17,23,0.85); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); padding: 0 1.5rem; } |
| 75 | + .nav { position: sticky; top: 0; z-index: 100; background: var(--nav-bg); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); padding: 0 1.5rem; } |
43 | 76 | .nav-inner { max-width: 1100px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; height: 56px; } |
44 | 77 | .nav-brand { font-weight: 700; font-size: 1rem; color: var(--text); white-space: nowrap; } |
45 | | - .nav-links { display: flex; gap: 1.5rem; list-style: none; } |
| 78 | + .nav-links { display: flex; gap: 1.5rem; list-style: none; align-items: center; } |
46 | 79 | .nav-links a { color: var(--text-dim); font-size: 0.875rem; font-weight: 500; transition: color 0.2s; } |
47 | 80 | .nav-links a:hover, .nav-links a.active { color: var(--accent-light); } |
48 | 81 | .nav-toggle { display: none; background: none; border: none; color: var(--text); cursor: pointer; padding: 0.5rem; } |
49 | 82 | .nav-toggle svg { width: 24px; height: 24px; } |
| 83 | + .theme-toggle { background: none; border: 1px solid var(--border); border-radius: 6px; color: var(--text-dim); cursor: pointer; padding: 0.25rem 0.5rem; font-size: 0.8125rem; transition: color 0.2s, border-color 0.2s; display: inline-flex; align-items: center; gap: 0.3rem; font-family: var(--font-sans); } |
| 84 | + .theme-toggle:hover { color: var(--accent-light); border-color: var(--accent); } |
| 85 | + .theme-toggle svg { width: 14px; height: 14px; } |
50 | 86 |
|
51 | 87 | /* HERO */ |
52 | | - .hero { text-align: center; padding: 5rem 1.5rem 4.5rem; background: linear-gradient(180deg, var(--hero-from) 0%, var(--hero-to) 70%, var(--bg) 100%); position: relative; } |
| 88 | + .hero { text-align: center; padding: 4rem 1.5rem 4.5rem; background: linear-gradient(180deg, var(--hero-from) 0%, var(--hero-to) 70%, var(--bg) 100%); position: relative; } |
53 | 89 | .hero-inner { max-width: 720px; margin: 0 auto; } |
| 90 | + .hero-logo { width: 80px; height: 80px; border-radius: 50%; object-fit: cover; margin-bottom: 1.25rem; box-shadow: 0 4px 24px rgba(0,0,0,0.3); border: 2px solid var(--border); } |
54 | 91 | .hero h1 { font-size: 2.75rem; font-weight: 700; margin-bottom: 1rem; background: linear-gradient(135deg, var(--text), var(--accent-light)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } |
55 | 92 | .hero p { font-size: 1.125rem; color: var(--text-dim); margin-bottom: 2rem; max-width: 600px; margin-left: auto; margin-right: auto; } |
56 | 93 | .stats { display: flex; justify-content: center; gap: 2.5rem; flex-wrap: wrap; margin-bottom: 2rem; } |
|
66 | 103 | .content-area { max-width: 1040px; margin: 0 auto; padding: 2rem 1.5rem 0; } |
67 | 104 |
|
68 | 105 | /* SECTIONS */ |
69 | | - .section { background: var(--bg2); border: 1px solid var(--border); border-radius: 12px; padding: 1.75rem 2rem; margin-bottom: 1.25rem; } |
| 106 | + .section { background: var(--bg2); border: 1px solid var(--border); border-top: 2px solid var(--accent); border-radius: 12px; padding: 1.75rem 2rem; margin-bottom: 1.25rem; box-shadow: 0 -2px 20px color-mix(in srgb, var(--accent) 8%, transparent); } |
70 | 107 | .section-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1rem; padding-bottom: 0.625rem; border-bottom: 1px solid var(--border); flex-wrap: wrap; } |
71 | 108 | .section-header h2 { font-size: 1.25rem; font-weight: 700; margin: 0; } |
72 | 109 | .count { font-size: 0.8125rem; font-weight: 500; color: var(--text-dim); background: var(--bg3); padding: 0.15rem 0.6rem; border-radius: 12px; } |
|
92 | 129 | details.cat-group[open] > summary::before { transform: rotate(90deg); } |
93 | 130 | details.cat-group > summary:hover { background: var(--bg3); } |
94 | 131 | details.cat-group > summary .cat-count { font-weight: 400; color: var(--text-dim); font-size: 0.75rem; margin-left: auto; } |
95 | | - details.cat-group > .cat-body { padding: 0.25rem 0 0.5rem; } |
| 132 | + details.cat-group > .cat-body { overflow: hidden; } |
| 133 | +
|
| 134 | + /* EXPAND ANIMATION */ |
| 135 | + .cat-body-anim { transition: max-height 0.25s ease, opacity 0.2s ease; overflow: hidden; } |
96 | 136 |
|
97 | 137 | /* TABLE */ |
98 | 138 | .data-table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; } |
|
122 | 162 | .back-to-top svg { width: 20px; height: 20px; } |
123 | 163 |
|
124 | 164 | /* FOOTER */ |
125 | | - footer { text-align: center; padding: 2.5rem 1.5rem; color: var(--text-dim); font-size: 0.8125rem; margin-top: 1rem; } |
| 165 | + footer { text-align: center; padding: 2rem 1.5rem 2.5rem; color: var(--text-dim); font-size: 0.8125rem; margin-top: 1rem; } |
126 | 166 | footer a { color: var(--accent-light); } |
| 167 | + .footer-inner { max-width: 1040px; margin: 0 auto; } |
| 168 | + .footer-links { display: flex; justify-content: center; gap: 1.25rem; margin-bottom: 1rem; flex-wrap: wrap; } |
| 169 | + .footer-links a { display: inline-flex; align-items: center; gap: 0.35rem; color: var(--text-dim); transition: color 0.2s; } |
| 170 | + .footer-links a:hover { color: var(--accent-light); } |
| 171 | + .footer-links svg { width: 16px; height: 16px; } |
| 172 | + .footer-divider { width: 60px; height: 2px; background: var(--accent); margin: 0 auto 1rem; border-radius: 1px; opacity: 0.4; } |
| 173 | + .footer-meta { display: flex; justify-content: center; gap: 0.5rem; flex-wrap: wrap; font-size: 0.75rem; } |
| 174 | + .footer-meta span { opacity: 0.7; } |
| 175 | + .footer-directory { margin-top: 0.75rem; font-size: 0.6875rem; opacity: 0.5; } |
127 | 176 |
|
128 | 177 | /* RESPONSIVE */ |
129 | 178 | @media (max-width: 768px) { |
130 | 179 | .hero h1 { font-size: 2rem; } |
| 180 | + .hero-logo { width: 64px; height: 64px; } |
131 | 181 | .stats { gap: 1.25rem; } |
132 | 182 | .stat-val { font-size: 1.5rem; } |
133 | 183 | .nav-links { gap: 0.75rem; } |
|
136 | 186 | } |
137 | 187 | @media (max-width: 640px) { |
138 | 188 | .nav-toggle { display: block; } |
139 | | - .nav-links { display: none; position: absolute; top: 56px; left: 0; right: 0; flex-direction: column; background: rgba(13,17,23,0.97); border-bottom: 1px solid var(--border); padding: 1rem 1.5rem; gap: 0.75rem; } |
| 189 | + .nav-links { display: none; position: absolute; top: 56px; left: 0; right: 0; flex-direction: column; background: var(--nav-bg); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); padding: 1rem 1.5rem; gap: 0.75rem; } |
140 | 190 | .nav-links.open { display: flex; } |
141 | 191 | .hero { padding: 3rem 1rem 2.5rem; } |
142 | 192 | .hero h1 { font-size: 1.5rem; } |
|
172 | 222 | {% if mcp_tools %}<li><a href="#mcp-tools">MCP Tools</a></li>{% endif %} |
173 | 223 | <li><a href="#install">Install</a></li> |
174 | 224 | <li><a href="{{ site.links.github | default(plugin.repository) }}">GitHub</a></li> |
| 225 | + <li> |
| 226 | + <button class="theme-toggle" id="themeToggle" aria-label="Toggle theme"> |
| 227 | + <svg id="themeIcon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg> |
| 228 | + </button> |
| 229 | + </li> |
175 | 230 | </ul> |
176 | 231 | </div> |
177 | 232 | </nav> |
178 | 233 |
|
179 | 234 | <!-- Hero --> |
180 | 235 | <section class="hero"> |
181 | 236 | <div class="hero-inner"> |
| 237 | + {% if plugin.logo %}<img class="hero-logo" src="{{ plugin.logo }}" alt="{{ plugin.displayName }} logo" />{% endif %} |
182 | 238 | <h1>{{ plugin.displayName }}</h1> |
183 | 239 | <p>{{ plugin.description }}</p> |
184 | 240 | <div class="stats"> |
|
342 | 398 |
|
343 | 399 | <!-- Footer --> |
344 | 400 | <footer> |
345 | | - <p> |
346 | | - Built by <a href="{{ plugin.author.url | default('https://github.com/TMHSDigital') }}">{{ plugin.author.name | default('TMHSDigital') }}</a> |
347 | | - · {{ plugin.license | default('CC-BY-NC-ND-4.0') }} |
348 | | - · v{{ plugin.version | default('0.0.0') }} |
349 | | - </p> |
| 401 | + <div class="footer-inner"> |
| 402 | + <div class="footer-links"> |
| 403 | + <a href="{{ site.links.github | default(plugin.repository) }}"> |
| 404 | + <svg viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg> |
| 405 | + GitHub |
| 406 | + </a> |
| 407 | + {% if site.links.npm %} |
| 408 | + <a href="{{ site.links.npm }}"> |
| 409 | + <svg viewBox="0 0 16 16" fill="currentColor"><path d="M0 0v16h16V0H0zm13 13H8V5H5v8H3V3h10v10z"/></svg> |
| 410 | + npm |
| 411 | + </a> |
| 412 | + {% endif %} |
| 413 | + <a href="https://tmhsdigital.github.io/Developer-Tools-Directory/"> |
| 414 | + <svg viewBox="0 0 16 16" fill="currentColor"><path d="M1.5 1.75V13.5h13.05l.001-11.75H1.5zM0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v11.5A1.75 1.75 0 0114.25 15H1.75A1.75 1.75 0 010 13.25V1.75zM9.22 3.72a.75.75 0 000 1.06L10.69 6.25H6.75a.75.75 0 000 1.5h3.94l-1.47 1.47a.75.75 0 101.06 1.06l2.75-2.75a.75.75 0 000-1.06L10.28 3.72a.75.75 0 00-1.06 0z"/></svg> |
| 415 | + All Tools |
| 416 | + </a> |
| 417 | + </div> |
| 418 | + <div class="footer-divider"></div> |
| 419 | + <div class="footer-meta"> |
| 420 | + <span>v{{ plugin.version | default('0.0.0') }}</span> |
| 421 | + <span>·</span> |
| 422 | + <span>{{ plugin.license | default('CC-BY-NC-ND-4.0') }}</span> |
| 423 | + <span>·</span> |
| 424 | + <span>Built {{ build_date }}</span> |
| 425 | + </div> |
| 426 | + <div class="footer-directory"> |
| 427 | + Part of <a href="https://tmhsdigital.github.io/Developer-Tools-Directory/">TMHSDigital Developer Tools</a> |
| 428 | + </div> |
| 429 | + </div> |
350 | 430 | </footer> |
351 | 431 |
|
352 | 432 | <!-- Toast --> |
|
370 | 450 | }; |
371 | 451 | })(); |
372 | 452 |
|
| 453 | + /* Theme toggle (dark / light / auto) */ |
| 454 | + (function () { |
| 455 | + var btn = document.getElementById('themeToggle'); |
| 456 | + var icon = document.getElementById('themeIcon'); |
| 457 | + var sunSvg = '<circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>'; |
| 458 | + var moonSvg = '<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>'; |
| 459 | + var autoSvg = '<circle cx="12" cy="12" r="10"/><path d="M12 2a10 10 0 0 1 0 20V2z"/>'; |
| 460 | + var states = ['dark', 'light', 'auto']; |
| 461 | + function getState() { return localStorage.getItem('theme') || 'auto'; } |
| 462 | + function apply(state) { |
| 463 | + if (state === 'light') { document.documentElement.setAttribute('data-theme', 'light'); } |
| 464 | + else if (state === 'dark') { document.documentElement.setAttribute('data-theme', 'dark'); } |
| 465 | + else { document.documentElement.removeAttribute('data-theme'); } |
| 466 | + if (state === 'auto') localStorage.removeItem('theme'); |
| 467 | + else localStorage.setItem('theme', state); |
| 468 | + updateIcon(state); |
| 469 | + } |
| 470 | + function updateIcon(state) { |
| 471 | + if (state === 'light') icon.innerHTML = sunSvg; |
| 472 | + else if (state === 'dark') icon.innerHTML = moonSvg; |
| 473 | + else icon.innerHTML = autoSvg; |
| 474 | + btn.title = 'Theme: ' + state; |
| 475 | + } |
| 476 | + btn.addEventListener('click', function () { |
| 477 | + var cur = getState(); |
| 478 | + var next = states[(states.indexOf(cur) + 1) % states.length]; |
| 479 | + apply(next); |
| 480 | + }); |
| 481 | + updateIcon(getState()); |
| 482 | + })(); |
| 483 | +
|
373 | 484 | /* Animated stat counters */ |
374 | 485 | (function () { |
375 | 486 | var prefersReduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; |
|
459 | 570 | }); |
460 | 571 | })(); |
461 | 572 |
|
462 | | - /* Section collapse/expand toggles (Skills, Rules) */ |
| 573 | + /* Section collapse/expand toggles */ |
463 | 574 | (function () { |
464 | 575 | document.querySelectorAll('.toggle-section').forEach(function (btn) { |
465 | 576 | var targetId = btn.getAttribute('data-target'); |
|
471 | 582 | }); |
472 | 583 | })(); |
473 | 584 |
|
| 585 | + /* Smooth expand/collapse animation */ |
| 586 | + (function () { |
| 587 | + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; |
| 588 | + document.querySelectorAll('details.cat-group').forEach(function (det) { |
| 589 | + var body = det.querySelector('.cat-body'); |
| 590 | + if (!body) return; |
| 591 | + det.addEventListener('toggle', function () { |
| 592 | + if (det.open) { |
| 593 | + body.style.maxHeight = '0'; |
| 594 | + body.style.opacity = '0'; |
| 595 | + body.classList.add('cat-body-anim'); |
| 596 | + requestAnimationFrame(function () { |
| 597 | + body.style.maxHeight = body.scrollHeight + 'px'; |
| 598 | + body.style.opacity = '1'; |
| 599 | + }); |
| 600 | + setTimeout(function () { body.style.maxHeight = 'none'; body.classList.remove('cat-body-anim'); }, 260); |
| 601 | + } |
| 602 | + }); |
| 603 | + }); |
| 604 | + })(); |
| 605 | +
|
474 | 606 | /* Scroll spy */ |
475 | 607 | (function () { |
476 | 608 | var links = document.querySelectorAll('.nav-links a[href^="#"]'); |
|
0 commit comments