mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Fix: Restore public directory from accidental regression
Commit3d9f4aeaccidentally reverted public/app.js and public/css/main.css (plus other files) to old versions. This broke the site because: - app.js imported from deleted files (commands.js, skills.js) - main.css lost 1200+ lines of Renaissance redesign (split comparison, etc.) Restored from commit343e342which had the working frontend. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
7c3e76663b
commit
5d65154dee
+90
-44
@@ -1,64 +1,101 @@
|
||||
// ============================================
|
||||
// MAIN APP - Entry point and orchestration
|
||||
// ============================================
|
||||
|
||||
import {
|
||||
filterCommands,
|
||||
renderCommandsGrid,
|
||||
renderWorkflowDiagram,
|
||||
selectCommand,
|
||||
setupCategoryTabs,
|
||||
} from "./js/commands.js";
|
||||
import { renderSkillsNav, selectSkill } from "./js/skills.js";
|
||||
initGlassTerminal,
|
||||
renderTerminalLayout,
|
||||
} from "./js/components/glass-terminal.js";
|
||||
import { initLensEffect } from "./js/components/lens.js";
|
||||
import { initFrameworkViz } from "./js/components/framework-viz.js";
|
||||
import { initHeroEffect } from "./js/effects/liquid-canvas.js";
|
||||
import { initScrollReveal } from "./js/utils/reveal.js";
|
||||
import { initScrollIndicator, initSmoothScroll, initHashTracking } from "./js/utils/scroll.js";
|
||||
|
||||
// ============================================
|
||||
// STATE
|
||||
// ============================================
|
||||
|
||||
let allSkills = [];
|
||||
let allCommands = [];
|
||||
|
||||
// ============================================
|
||||
// INITIALIZATION
|
||||
// CONTENT LOADING
|
||||
// ============================================
|
||||
|
||||
async function loadContent() {
|
||||
try {
|
||||
const [skillsRes, commandsRes] = await Promise.all([
|
||||
fetch("/api/skills"),
|
||||
const [commandsRes, patternsRes] = await Promise.all([
|
||||
fetch("/api/commands"),
|
||||
fetch("/api/patterns"),
|
||||
]);
|
||||
|
||||
allSkills = await skillsRes.json();
|
||||
allCommands = await commandsRes.json();
|
||||
const patternsData = await patternsRes.json();
|
||||
|
||||
// Render skills
|
||||
renderSkillsNav(allSkills, (skill) => selectSkill(skill, allSkills));
|
||||
// Render commands (Glass Terminal)
|
||||
renderTerminalLayout(allCommands);
|
||||
|
||||
// Render commands
|
||||
renderWorkflowDiagram(allCommands, (cmd) =>
|
||||
selectCommand(cmd, allCommands),
|
||||
);
|
||||
renderCommandsGrid(allCommands, (cmd) => selectCommand(cmd, allCommands));
|
||||
setupCategoryTabs(filterCommands);
|
||||
|
||||
// Select first items by default
|
||||
if (allSkills.length > 0) selectSkill(allSkills[0], allSkills);
|
||||
if (allCommands.length > 0) selectCommand(allCommands[0], allCommands);
|
||||
// Render patterns with tabbed navigation
|
||||
renderPatternsWithTabs(patternsData.patterns, patternsData.antipatterns);
|
||||
} catch (error) {
|
||||
console.error("Failed to load content:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// UTILITIES
|
||||
// ============================================
|
||||
function renderPatternsWithTabs(patterns, antipatterns) {
|
||||
const container = document.getElementById("patterns-categories");
|
||||
if (!container || !patterns || !antipatterns) return;
|
||||
|
||||
function animateIn() {
|
||||
const elements = document.querySelectorAll("[data-animate]:not(.animated)");
|
||||
elements.forEach((el, i) => {
|
||||
el.style.animationDelay = `${i * 0.05}s`;
|
||||
el.classList.add("animated");
|
||||
// Create a map of antipatterns by category name
|
||||
const antipatternMap = {};
|
||||
antipatterns.forEach(cat => {
|
||||
antipatternMap[cat.name] = cat.items;
|
||||
});
|
||||
|
||||
// Build tabs
|
||||
const tabsHTML = patterns
|
||||
.map((category, i) => `<button class="pattern-tab${i === 0 ? ' active' : ''}" data-tab="${category.name}">${category.name}</button>`)
|
||||
.join("");
|
||||
|
||||
// Build panels
|
||||
const panelsHTML = patterns
|
||||
.map((category, i) => {
|
||||
const antiItems = antipatternMap[category.name] || [];
|
||||
return `
|
||||
<div class="pattern-panel${i === 0 ? ' active' : ''}" data-panel="${category.name}">
|
||||
<div class="pattern-columns">
|
||||
<div class="pattern-column pattern-column--anti">
|
||||
<span class="pattern-column-label">Don't</span>
|
||||
<ul class="pattern-list">
|
||||
${antiItems.map((item) => `<li class="pattern-item pattern-item--anti">${item}</li>`).join("")}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pattern-column pattern-column--do">
|
||||
<span class="pattern-column-label">Do</span>
|
||||
<ul class="pattern-list">
|
||||
${category.items.map((item) => `<li class="pattern-item pattern-item--do">${item}</li>`).join("")}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
.join("");
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="pattern-tabs">${tabsHTML}</div>
|
||||
<div class="pattern-panels">${panelsHTML}</div>
|
||||
`;
|
||||
|
||||
// Tab click handling
|
||||
container.querySelectorAll('.pattern-tab').forEach(tab => {
|
||||
tab.addEventListener('click', () => {
|
||||
const tabName = tab.dataset.tab;
|
||||
|
||||
// Update active tab
|
||||
container.querySelectorAll('.pattern-tab').forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
|
||||
// Update active panel
|
||||
container.querySelectorAll('.pattern-panel').forEach(p => p.classList.remove('active'));
|
||||
container.querySelector(`[data-panel="${tabName}"]`).classList.add('active');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,13 +116,22 @@ document.addEventListener("click", (e) => {
|
||||
// STARTUP
|
||||
// ============================================
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", loadContent);
|
||||
} else {
|
||||
function init() {
|
||||
initSmoothScroll();
|
||||
initScrollIndicator();
|
||||
initHashTracking();
|
||||
initHeroEffect();
|
||||
initLensEffect();
|
||||
initScrollReveal();
|
||||
initGlassTerminal();
|
||||
initFrameworkViz();
|
||||
loadContent();
|
||||
}
|
||||
window.addEventListener("load", () => {
|
||||
document.body.classList.add("loaded");
|
||||
animateIn();
|
||||
});
|
||||
|
||||
document.body.classList.add("loaded");
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
|
||||
+1369
-179
File diff suppressed because it is too large
Load Diff
+261
-136
@@ -9,191 +9,316 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;0,700;1,300;1,400&family=Instrument+Sans:wght@400;500;600;700&family=Inter:wght@400;500;600&family=Space+Grotesk:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="tailwindcss" />
|
||||
<link rel="stylesheet" href="./css/main.css">
|
||||
|
||||
<!-- Import Maps for ES Module dependencies -->
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"lenis": "https://cdn.jsdelivr.net/npm/lenis@1.3.16/+esm",
|
||||
"motion": "https://cdn.jsdelivr.net/npm/motion@12.23.26/+esm",
|
||||
"three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 1. HERO - Hook with the problem statement -->
|
||||
<header class="hero">
|
||||
<div class="hero-grid">
|
||||
<body class="min-h-screen overflow-x-hidden leading-relaxed">
|
||||
<!-- Grain Overlay -->
|
||||
<div class="grain-overlay" aria-hidden="true"></div>
|
||||
|
||||
<!-- 1. HERO - Liquid Typography -->
|
||||
<header class="hero-section" id="hero">
|
||||
<canvas class="hero-canvas" id="hero-canvas"></canvas>
|
||||
<div class="hero-container">
|
||||
<div class="hero-content">
|
||||
<h1 class="title">
|
||||
<span class="title-main">Impeccable style</span>
|
||||
<span class="title-sub">made easy</span>
|
||||
<p class="hero-eyebrow" data-reveal data-split-text>The Anti-Slop Framework for AI Design</p>
|
||||
<h1 class="hero-title" data-reveal>
|
||||
<span class="hero-title-line" data-split-text>Impeccable</span>
|
||||
<span class="hero-title-line hero-title-accent" data-split-text>Style</span>
|
||||
</h1>
|
||||
<p class="tagline">Your LLM can design beautiful interfaces.<br>It just needs to know what to ask for.</p>
|
||||
<p class="providers">Works with Cursor · Claude Code · Gemini CLI · Codex CLI</p>
|
||||
</div>
|
||||
<div class="hero-decoration" aria-hidden="true">
|
||||
<div class="deco-line"></div>
|
||||
<div class="deco-circle"></div>
|
||||
<p class="hero-subtitle" data-reveal>One design skill and 15 commands that work across Cursor, Claude Code, Gemini CLI, and Codex CLI. Stop getting generic AI output. Start getting intentional design.</p>
|
||||
<div class="hero-cta" data-reveal>
|
||||
<a href="#downloads" class="btn btn-primary">Get the Framework</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-scroll-indicator" aria-hidden="true">
|
||||
<span>Scroll</span>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M12 5v14M19 12l-7 7-7-7"/>
|
||||
</svg>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<!-- 2. THE PROBLEM - Show the "AI slop" aesthetic -->
|
||||
<section class="problem-section">
|
||||
<div class="problem-grid">
|
||||
<div class="problem-content">
|
||||
<h2 class="section-title">The Problem</h2>
|
||||
<p class="problem-lead">LLMs are biased toward safe, generic design choices. Without guidance, you get the same predictable aesthetic every time.</p>
|
||||
<main class="site-content">
|
||||
<!-- 2. THE PROBLEM - AI Design Bias -->
|
||||
<section class="problem-section" id="problem">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">01</span>
|
||||
<h2 class="section-title">AI Has Design Bias</h2>
|
||||
</div>
|
||||
<div class="problem-content">
|
||||
<p class="section-lead" data-reveal>Every LLM learned from the same generic templates. Without guidance, you get the same predictable mistakes—every single time.</p>
|
||||
|
||||
<!-- Bias Examples Grid -->
|
||||
<div class="bias-grid" data-reveal>
|
||||
<div class="bias-item">
|
||||
<span class="bias-icon">Aa</span>
|
||||
<div class="bias-content">
|
||||
<strong>Safe fonts</strong>
|
||||
<span>Defaults to Inter, Roboto, system fonts</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bias-item">
|
||||
<span class="bias-icon">◐</span>
|
||||
<div class="bias-content">
|
||||
<strong>Purple gradients</strong>
|
||||
<span>Purple-to-blue on white backgrounds</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bias-item">
|
||||
<span class="bias-icon">▢</span>
|
||||
<div class="bias-content">
|
||||
<strong>Cards everywhere</strong>
|
||||
<span>Wraps everything in rounded boxes</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bias-item">
|
||||
<span class="bias-icon">◫</span>
|
||||
<div class="bias-content">
|
||||
<strong>Gray on color</strong>
|
||||
<span>Gray text on colored backgrounds</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bias-item">
|
||||
<span class="bias-icon">≡</span>
|
||||
<div class="bias-content">
|
||||
<strong>Centered everything</strong>
|
||||
<span>Centers all text and layouts</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bias-item">
|
||||
<span class="bias-icon">◌</span>
|
||||
<div class="bias-content">
|
||||
<strong>Decorative shadows</strong>
|
||||
<span>Adds shadows without purpose</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="problem-showcase">
|
||||
<div class="ai-slop-demo">
|
||||
<div class="slop-card">
|
||||
<div class="slop-header">
|
||||
<div class="slop-avatar"></div>
|
||||
<div class="slop-text">
|
||||
<div class="slop-title">Welcome to Our Platform</div>
|
||||
<div class="slop-subtitle">The best solution for your needs</div>
|
||||
|
||||
<div class="split-comparison" id="lens-comparison">
|
||||
<div class="split-container">
|
||||
<!-- Before: AI Slop -->
|
||||
<div class="split-before">
|
||||
<div class="slop-card">
|
||||
<div class="slop-header">
|
||||
<div class="slop-avatar"></div>
|
||||
<div class="slop-text">
|
||||
<div class="slop-title">Welcome to Our Platform</div>
|
||||
<div class="slop-subtitle">The best solution for your needs</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="slop-body">Lorem ipsum dolor sit amet, consectetur adipiscing elit. This is generic placeholder text.</p>
|
||||
<button class="slop-button">Get Started</button>
|
||||
</div>
|
||||
<!-- Callout labels pointing to issues -->
|
||||
<div class="slop-callouts">
|
||||
<span class="slop-callout" data-point="font">Inter font (again)</span>
|
||||
<span class="slop-callout" data-point="gradient">Purple gradient</span>
|
||||
<span class="slop-callout" data-point="copy">Generic copy</span>
|
||||
<span class="slop-callout" data-point="rounded">Cards on cards</span>
|
||||
</div>
|
||||
<p class="slop-body">Lorem ipsum dolor sit amet, consectetur adipiscing elit. This is generic placeholder text in a card layout.</p>
|
||||
<button class="slop-button">Get Started</button>
|
||||
</div>
|
||||
<div class="slop-labels">
|
||||
<span class="slop-label" data-point="font">Inter font</span>
|
||||
<span class="slop-label" data-point="gradient">Purple gradient</span>
|
||||
<span class="slop-label" data-point="layout">Card layout</span>
|
||||
<span class="slop-label" data-point="copy">Generic copy</span>
|
||||
<!-- After: Impeccable (shown through split) -->
|
||||
<div class="split-after">
|
||||
<div class="impeccable-card">
|
||||
<p class="impeccable-eyebrow">Introducing</p>
|
||||
<h3 class="impeccable-title">Thoughtful Design</h3>
|
||||
<p class="impeccable-body">Every element serves a purpose. Hierarchy guides the eye. Whitespace breathes.</p>
|
||||
<button class="impeccable-button">Explore</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- The Divider -->
|
||||
<div class="split-divider">
|
||||
<span class="split-label">With Skills</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="split-labels">
|
||||
<div class="split-label-item" data-point="before">
|
||||
<span class="split-label-dot"></span>
|
||||
<span>Generic AI Output</span>
|
||||
</div>
|
||||
<div class="split-label-item" data-point="after">
|
||||
<span class="split-label-dot split-label-dot--accent"></span>
|
||||
<span>With Design Skills</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. THE SOLUTION - Brief explanation -->
|
||||
<section class="solution-section">
|
||||
<div class="solution-grid">
|
||||
<div class="solution-content">
|
||||
<h2 class="section-title">The Solution</h2>
|
||||
<p class="solution-lead">Teach your AI assistant the language of design. <strong>Skills</strong> provide deep design knowledge. <strong>Commands</strong> give you precise control over the creative process.</p>
|
||||
</div>
|
||||
<div class="solution-cards">
|
||||
<div class="solution-card">
|
||||
<div class="solution-icon">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>8 Skills</h3>
|
||||
<p>Deep knowledge in typography, color, motion, spatial design, and more. The AI learns <em>how</em> to think about design.</p>
|
||||
</div>
|
||||
<div class="solution-card">
|
||||
<div class="solution-icon">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M6.75 7.5l3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0021 18V6a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 6v12a2.25 2.25 0 002.25 2.25z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>15 Commands</h3>
|
||||
<p>Precise actions like <code>/bolder</code>, <code>/animate</code>, <code>/audit</code>. Steer the AI through iterative design refinement.</p>
|
||||
</div>
|
||||
<!-- 3. THE ANTIDOTE - Patterns & Anti-Patterns -->
|
||||
<section class="antidote-section" id="antidote">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">02</span>
|
||||
<h2 class="section-title">The Antidote</h2>
|
||||
</div>
|
||||
<div class="antidote-content">
|
||||
<p class="section-lead" data-reveal>The original Claude frontend-design skill says to avoid Arial and Inter. We've expanded it with 60+ specific patterns that fight model bias across every design domain.</p>
|
||||
|
||||
<!-- Patterns by category with tabs -->
|
||||
<div class="patterns-categories" id="patterns-categories">
|
||||
<!-- Rendered by JS -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. SKILLS SHOWCASE - Interactive demos -->
|
||||
<section class="skills-section" id="skills-section">
|
||||
<div class="section-header-sticky">
|
||||
<h2 class="section-title">Skills</h2>
|
||||
<p class="section-subtitle">Design knowledge that transforms AI output</p>
|
||||
<!-- 4. THE SOLUTION - Two-part system -->
|
||||
<section class="solution-section" id="solution">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">03</span>
|
||||
<h2 class="section-title">The Framework</h2>
|
||||
</div>
|
||||
<div class="skills-layout">
|
||||
<nav class="skills-nav" id="skills-nav">
|
||||
<div class="loading">Loading...</div>
|
||||
</nav>
|
||||
<div class="skills-showcase" id="skills-detail">
|
||||
<div class="loading">Select a skill to see it in action</div>
|
||||
<div class="solution-content">
|
||||
<p class="section-lead" data-reveal>One comprehensive skill with deep expertise, plus 15 commands that form the language of design.</p>
|
||||
|
||||
<div class="solution-visual-interactive" id="framework-viz-container" data-reveal>
|
||||
<!-- Subway map generated by JS -->
|
||||
</div>
|
||||
|
||||
<div class="solution-result" data-reveal>
|
||||
<span class="result-arrow">↓</span>
|
||||
<p class="result-text">Together, they transform generic output into <em>impeccable</em> design.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. COMMANDS - Sidebar nav + details (mirrors skills layout) -->
|
||||
<!-- 4. COMMANDS - Glass Terminal -->
|
||||
<section class="commands-section" id="commands-section">
|
||||
<div class="section-header-sticky">
|
||||
<h2 class="section-title">Commands</h2>
|
||||
<p class="section-subtitle">Precise control over the design process</p>
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">04</span>
|
||||
<h2 class="section-title">Commands in Action</h2>
|
||||
<p class="section-subtitle">See how commands transform your designs</p>
|
||||
</div>
|
||||
|
||||
<div class="commands-gallery">
|
||||
<!-- Rendered by JS -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. PLATFORMS -->
|
||||
<section class="platforms-section" id="downloads">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">05</span>
|
||||
<h2 class="section-title">One Framework, Every Agent Harness</h2>
|
||||
<p class="section-subtitle">We wrote it once, then compiled it for each platform. Same design intelligence, native to your workflow.</p>
|
||||
</div>
|
||||
|
||||
<div class="commands-layout">
|
||||
<!-- Commands nav (left sidebar) -->
|
||||
<nav class="commands-nav" id="workflow-diagram">
|
||||
<!-- Will be rendered by JS -->
|
||||
</nav>
|
||||
|
||||
<!-- Command detail (right side) -->
|
||||
<div class="commands-showcase" id="commands-detail">
|
||||
<div class="loading">Select a command to view details</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. DOWNLOAD BUNDLES - After demonstrating value -->
|
||||
<section class="downloads-section" id="downloads">
|
||||
<div class="downloads-header">
|
||||
<h2 class="section-title">Get Started</h2>
|
||||
<p class="downloads-lead">Download the complete bundle for your preferred AI tool. Extract into your project root and start creating.</p>
|
||||
</div>
|
||||
<div class="download-grid">
|
||||
<article class="download-card" data-animate>
|
||||
<div class="card-inner">
|
||||
<div class="card-header">
|
||||
<h3>Cursor</h3>
|
||||
<span class="badge">Rules + Commands</span>
|
||||
</div>
|
||||
<p>Commands and rules for Cursor IDE. Works via appending, no frontmatter required.</p>
|
||||
<button class="btn btn-primary" data-bundle="cursor">Download</button>
|
||||
<div class="downloads-grid">
|
||||
<article class="download-card" data-reveal>
|
||||
<div class="download-card-icon">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M9 3H5a2 2 0 00-2 2v4m6-6h10a2 2 0 012 2v4M9 3v18m0 0h10a2 2 0 002-2v-4M9 21H5a2 2 0 01-2-2v-4m0-6v6m18-6v6"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="download-card-content">
|
||||
<h3 class="download-card-title">Cursor</h3>
|
||||
<span class="download-card-badge">Rules + Commands</span>
|
||||
<p class="download-card-desc">Commands and rules for Cursor IDE. Works via appending, no frontmatter required.</p>
|
||||
</div>
|
||||
<button class="btn btn-primary" data-bundle="cursor">
|
||||
<span>Download</span>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/>
|
||||
</svg>
|
||||
</button>
|
||||
</article>
|
||||
|
||||
<article class="download-card" data-animate>
|
||||
<div class="card-inner">
|
||||
<div class="card-header">
|
||||
<h3>Claude Code</h3>
|
||||
<span class="badge">Full Featured</span>
|
||||
</div>
|
||||
<p>Complete YAML frontmatter with argument support. Follows Anthropic Skills specification.</p>
|
||||
<button class="btn btn-primary" data-bundle="claude-code">Download</button>
|
||||
<article class="download-card" data-reveal>
|
||||
<div class="download-card-icon">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="download-card-content">
|
||||
<h3 class="download-card-title">Claude Code</h3>
|
||||
<span class="download-card-badge">Full Featured</span>
|
||||
<p class="download-card-desc">Complete YAML frontmatter with argument support. Follows Anthropic Skills specification.</p>
|
||||
</div>
|
||||
<button class="btn btn-primary" data-bundle="claude-code">
|
||||
<span>Download</span>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/>
|
||||
</svg>
|
||||
</button>
|
||||
</article>
|
||||
|
||||
<article class="download-card" data-animate>
|
||||
<div class="card-inner">
|
||||
<div class="card-header">
|
||||
<h3>Gemini CLI</h3>
|
||||
<span class="badge">TOML + Modular</span>
|
||||
</div>
|
||||
<p>TOML-formatted commands with modular skill imports via GEMINI.md.</p>
|
||||
<button class="btn btn-primary" data-bundle="gemini">Download</button>
|
||||
<article class="download-card" data-reveal>
|
||||
<div class="download-card-icon">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="download-card-content">
|
||||
<h3 class="download-card-title">Gemini CLI</h3>
|
||||
<span class="download-card-badge">TOML + Modular</span>
|
||||
<p class="download-card-desc">TOML-formatted commands with modular skill imports via GEMINI.md.</p>
|
||||
</div>
|
||||
<button class="btn btn-primary" data-bundle="gemini">
|
||||
<span>Download</span>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/>
|
||||
</svg>
|
||||
</button>
|
||||
</article>
|
||||
|
||||
<article class="download-card" data-animate>
|
||||
<div class="card-inner">
|
||||
<div class="card-header">
|
||||
<h3>Codex CLI</h3>
|
||||
<span class="badge">Prompts + Routing</span>
|
||||
</div>
|
||||
<p>Custom prompt format with skill routing through AGENTS.md architecture.</p>
|
||||
<button class="btn btn-primary" data-bundle="codex">Download</button>
|
||||
<article class="download-card" data-reveal>
|
||||
<div class="download-card-icon">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="download-card-content">
|
||||
<h3 class="download-card-title">Codex CLI</h3>
|
||||
<span class="download-card-badge">Prompts + Routing</span>
|
||||
<p class="download-card-desc">Custom prompt format with skill routing through AGENTS.md architecture.</p>
|
||||
</div>
|
||||
<button class="btn btn-primary" data-bundle="codex">
|
||||
<span>Download</span>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/>
|
||||
</svg>
|
||||
</button>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 7. OPEN SOURCE -->
|
||||
<section class="contribute">
|
||||
<div class="contribute-content">
|
||||
<h2>Open Source</h2>
|
||||
<p>View the source, contribute skills and commands, or report issues on GitHub.</p>
|
||||
<a href="https://github.com/pbakaus/vibe-design-plugins" class="btn btn-secondary">View Repository</a>
|
||||
<section class="opensource-section" id="opensource">
|
||||
<div class="opensource-content" data-reveal>
|
||||
<h2 class="opensource-title">Open Source</h2>
|
||||
<p class="opensource-desc">View the source, contribute skills and commands, or report issues on GitHub.</p>
|
||||
<a href="https://github.com/pbakaus/vibe-design-plugins" class="btn btn-secondary">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||
</svg>
|
||||
<span>View Repository</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<footer class="site-footer">
|
||||
<div class="footer-content">
|
||||
<p>impeccable.style</p>
|
||||
<p><a href="https://github.com/pbakaus/vibe-design-plugins">GitHub</a></p>
|
||||
<div class="footer-brand">
|
||||
<span class="footer-logo">impeccable.style</span>
|
||||
<p class="footer-tagline">The anti-slop framework for AI design</p>
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<a href="#antidote">Anti-Patterns</a>
|
||||
<a href="#commands-section">Commands</a>
|
||||
<a href="#downloads">Downloads</a>
|
||||
<a href="https://github.com/pbakaus/vibe-design-plugins">GitHub</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
@@ -133,4 +133,3 @@ function setupInteractions() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
* Periodic Table of Commands
|
||||
* Clean grid visualization showing all commands organized by category
|
||||
*/
|
||||
|
||||
import { commandCategories, commandRelationships } from '../data.js';
|
||||
|
||||
const categoryColors = {
|
||||
diagnostic: { bg: '#fdf4ff', border: '#d946ef', text: '#a21caf' },
|
||||
quality: { bg: '#f0fdf4', border: '#22c55e', text: '#15803d' },
|
||||
intensity: { bg: '#fffbeb', border: '#f59e0b', text: '#b45309' },
|
||||
adaptation: { bg: '#eff6ff', border: '#3b82f6', text: '#1d4ed8' },
|
||||
enhancement: { bg: '#fdf2f8', border: '#ec4899', text: '#be185d' },
|
||||
system: { bg: '#f9fafb', border: '#6b7280', text: '#374151' }
|
||||
};
|
||||
|
||||
const categoryLabels = {
|
||||
diagnostic: 'Diagnostic',
|
||||
quality: 'Quality',
|
||||
intensity: 'Intensity',
|
||||
adaptation: 'Adaptation',
|
||||
enhancement: 'Enhancement',
|
||||
system: 'System'
|
||||
};
|
||||
|
||||
// Short symbols for each command (like element symbols)
|
||||
const commandSymbols = {
|
||||
audit: 'Au',
|
||||
normalize: 'No',
|
||||
polish: 'Po',
|
||||
optimize: 'Op',
|
||||
harden: 'Ha',
|
||||
clarify: 'Cl',
|
||||
simplify: 'Si',
|
||||
adapt: 'Ad',
|
||||
extract: 'Ex',
|
||||
animate: 'An',
|
||||
colorize: 'Co',
|
||||
delight: 'De',
|
||||
bolder: 'Bo',
|
||||
quieter: 'Qu',
|
||||
onboard: 'On'
|
||||
};
|
||||
|
||||
// Atomic numbers (just for visual interest)
|
||||
const commandNumbers = {
|
||||
audit: 1,
|
||||
normalize: 2,
|
||||
polish: 3,
|
||||
optimize: 4,
|
||||
harden: 5,
|
||||
clarify: 6,
|
||||
simplify: 7,
|
||||
adapt: 8,
|
||||
extract: 9,
|
||||
animate: 10,
|
||||
colorize: 11,
|
||||
delight: 12,
|
||||
bolder: 13,
|
||||
quieter: 14,
|
||||
onboard: 15
|
||||
};
|
||||
|
||||
export class PeriodicTable {
|
||||
constructor(container) {
|
||||
this.container = container;
|
||||
this.infoPanel = null;
|
||||
this.activeElement = null;
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.container.innerHTML = '';
|
||||
this.container.style.cssText = `
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
padding: 20px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
`;
|
||||
|
||||
this.renderTable();
|
||||
this.renderInfoPanel();
|
||||
}
|
||||
|
||||
renderTable() {
|
||||
// Group commands by category
|
||||
const groups = {};
|
||||
Object.entries(commandCategories).forEach(([cmd, cat]) => {
|
||||
if (!groups[cat]) groups[cat] = [];
|
||||
groups[cat].push(cmd);
|
||||
});
|
||||
|
||||
// Category order
|
||||
const categoryOrder = ['diagnostic', 'quality', 'adaptation', 'enhancement', 'intensity', 'system'];
|
||||
|
||||
// Create grid container
|
||||
const grid = document.createElement('div');
|
||||
grid.style.cssText = `
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 16px;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
categoryOrder.forEach(cat => {
|
||||
const commands = groups[cat];
|
||||
if (!commands) return;
|
||||
|
||||
const group = this.createCategoryGroup(cat, commands);
|
||||
grid.appendChild(group);
|
||||
});
|
||||
|
||||
this.container.appendChild(grid);
|
||||
}
|
||||
|
||||
renderInfoPanel() {
|
||||
this.infoPanel = document.createElement('div');
|
||||
this.infoPanel.style.cssText = `
|
||||
background: var(--color-cream);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
padding: 16px 20px;
|
||||
height: 96px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
// Default state
|
||||
this.showDefaultInfo();
|
||||
|
||||
this.container.appendChild(this.infoPanel);
|
||||
}
|
||||
|
||||
showDefaultInfo() {
|
||||
this.infoPanel.innerHTML = `
|
||||
<div style="
|
||||
font-family: var(--font-body);
|
||||
font-size: 14px;
|
||||
color: var(--color-ash);
|
||||
font-style: italic;
|
||||
">
|
||||
Hover over a command to see details
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
showCommandInfo(cmd) {
|
||||
const category = commandCategories[cmd];
|
||||
const colors = categoryColors[category];
|
||||
const rel = commandRelationships[cmd] || {};
|
||||
|
||||
// Normalize to arrays (pairs can be string or array)
|
||||
const toArray = (val) => {
|
||||
if (!val) return [];
|
||||
if (Array.isArray(val)) return val;
|
||||
return [val];
|
||||
};
|
||||
|
||||
const pairs = toArray(rel.pairs);
|
||||
const leadsTo = toArray(rel.leadsTo);
|
||||
const combinesWith = toArray(rel.combinesWith);
|
||||
|
||||
// Build related info
|
||||
let relatedHtml = '';
|
||||
|
||||
if (pairs.length > 0) {
|
||||
const list = pairs.map(p => `<span style="font-family: var(--font-mono); color: var(--color-ink)">/${p}</span>`).join(', ');
|
||||
relatedHtml += `<span style="color: var(--color-ash)">Pairs with:</span> ${list}`;
|
||||
}
|
||||
if (combinesWith.length > 0) {
|
||||
const list = combinesWith.map(p => `<span style="font-family: var(--font-mono); color: var(--color-ink)">/${p}</span>`).join(', ');
|
||||
if (relatedHtml) relatedHtml += '<span style="color: var(--color-mist); margin: 0 8px;">•</span>';
|
||||
relatedHtml += `<span style="color: var(--color-ash)">Combines with:</span> ${list}`;
|
||||
}
|
||||
if (leadsTo.length > 0) {
|
||||
const list = leadsTo.map(p => `<span style="font-family: var(--font-mono); color: var(--color-ink)">/${p}</span>`).join(', ');
|
||||
if (relatedHtml) relatedHtml += '<span style="color: var(--color-mist); margin: 0 8px;">•</span>';
|
||||
relatedHtml += `<span style="color: var(--color-ash)">Then:</span> ${list}`;
|
||||
}
|
||||
|
||||
this.infoPanel.innerHTML = `
|
||||
<div style="flex: 1; min-width: 0;">
|
||||
<div style="
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 10px;
|
||||
margin-bottom: 4px;
|
||||
">
|
||||
<span style="
|
||||
font-family: var(--font-mono);
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: var(--color-ink);
|
||||
">/${cmd}</span>
|
||||
<span style="
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: ${colors.text};
|
||||
font-weight: 500;
|
||||
">${categoryLabels[category]}</span>
|
||||
</div>
|
||||
<div style="
|
||||
font-family: var(--font-body);
|
||||
font-size: 13px;
|
||||
color: var(--color-charcoal);
|
||||
line-height: 1.4;
|
||||
margin-bottom: ${relatedHtml ? '6px' : '0'};
|
||||
">${rel.flow || 'Design command'}</div>
|
||||
${relatedHtml ? `<div style="font-size: 12px; line-height: 1.4;">${relatedHtml}</div>` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
createCategoryGroup(category, commands) {
|
||||
const colors = categoryColors[category];
|
||||
|
||||
const group = document.createElement('div');
|
||||
group.style.cssText = `
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
`;
|
||||
|
||||
// Category label
|
||||
const label = document.createElement('div');
|
||||
label.style.cssText = `
|
||||
font-family: var(--font-body);
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: ${colors.text};
|
||||
padding-left: 2px;
|
||||
`;
|
||||
label.textContent = categoryLabels[category];
|
||||
group.appendChild(label);
|
||||
|
||||
// Elements row
|
||||
const row = document.createElement('div');
|
||||
row.style.cssText = `
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
`;
|
||||
|
||||
commands.forEach(cmd => {
|
||||
const element = this.createElement(cmd, category);
|
||||
row.appendChild(element);
|
||||
});
|
||||
|
||||
group.appendChild(row);
|
||||
return group;
|
||||
}
|
||||
|
||||
createElement(cmd, category) {
|
||||
const colors = categoryColors[category];
|
||||
|
||||
const el = document.createElement('div');
|
||||
el.style.cssText = `
|
||||
width: 56px;
|
||||
height: 64px;
|
||||
background: ${colors.bg};
|
||||
border: 1.5px solid ${colors.border};
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
// Atomic number
|
||||
const number = document.createElement('div');
|
||||
number.style.cssText = `
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 5px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 7px;
|
||||
color: ${colors.text};
|
||||
opacity: 0.5;
|
||||
`;
|
||||
number.textContent = commandNumbers[cmd];
|
||||
el.appendChild(number);
|
||||
|
||||
// Symbol
|
||||
const symbol = document.createElement('div');
|
||||
symbol.style.cssText = `
|
||||
font-family: var(--font-display);
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: ${colors.text};
|
||||
line-height: 1;
|
||||
`;
|
||||
symbol.textContent = commandSymbols[cmd];
|
||||
el.appendChild(symbol);
|
||||
|
||||
// Command name
|
||||
const name = document.createElement('div');
|
||||
name.style.cssText = `
|
||||
font-family: var(--font-mono);
|
||||
font-size: 8px;
|
||||
color: ${colors.text};
|
||||
opacity: 0.7;
|
||||
margin-top: 3px;
|
||||
`;
|
||||
name.textContent = `/${cmd}`;
|
||||
el.appendChild(name);
|
||||
|
||||
// Hover effects
|
||||
el.addEventListener('mouseenter', () => {
|
||||
// Visual feedback
|
||||
el.style.transform = 'translateY(-2px)';
|
||||
el.style.boxShadow = `0 4px 12px ${colors.border}40`;
|
||||
|
||||
// Update info panel
|
||||
this.showCommandInfo(cmd);
|
||||
|
||||
// Track active element
|
||||
if (this.activeElement) {
|
||||
this.activeElement.style.transform = 'translateY(0)';
|
||||
this.activeElement.style.boxShadow = 'none';
|
||||
}
|
||||
this.activeElement = el;
|
||||
});
|
||||
|
||||
el.addEventListener('mouseleave', () => {
|
||||
el.style.transform = 'translateY(0)';
|
||||
el.style.boxShadow = 'none';
|
||||
});
|
||||
|
||||
// Click to scroll to command
|
||||
el.addEventListener('click', () => {
|
||||
const target = document.getElementById(`cmd-${cmd}`);
|
||||
if (target) {
|
||||
target.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
});
|
||||
|
||||
return el;
|
||||
}
|
||||
}
|
||||
|
||||
export function initFrameworkViz() {
|
||||
const container = document.getElementById('framework-viz-container');
|
||||
if (container) {
|
||||
new PeriodicTable(container);
|
||||
}
|
||||
}
|
||||
@@ -183,4 +183,3 @@ function updateTerminal(cmd, container, allCommands) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,4 +13,3 @@ export function initLensEffect() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -127,4 +127,3 @@ export function setupDemoTabs() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -41,4 +41,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,4 +21,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -39,4 +39,3 @@ export function getCommandDemo(commandId) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -39,4 +39,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,4 +3,3 @@ export { commandDemos, getCommandDemo } from "./commands/index.js";
|
||||
export { getSkillDemo, skillDemos } from "./skills/index.js";
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -65,4 +65,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,4 +23,3 @@ export function getSkillDemo(skillId) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -76,4 +76,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -66,4 +66,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -88,4 +88,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -59,4 +59,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -35,4 +35,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -68,4 +68,3 @@ export default {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -156,4 +156,3 @@ export function initHeroEffect() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,4 +15,3 @@ export function initScrollReveal() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -100,4 +100,3 @@ export function initHashTracking() {
|
||||
// Initial check
|
||||
updateHash();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user