mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-14 23:26:39 +03:00
Redesign hero, add theme toggle, fix dark mode
- Remove GPU-intensive shader from hero section - Combine hero with problem section for immediate impact - Add before/after demo directly in first viewport - Move "works with" logos inline with CTA - Remove redundant "Common AI defaults" tags - Add three-way theme toggle (light/system/dark) - Persist theme preference to localStorage - Position toggle in bottom-right corner - Fix dark mode throughout: - Update glass terminal and source window backgrounds - Add CSS custom properties for framework category colors - Muted dark backgrounds with brighter text for cards - Replace smooth scroll with instant jump for anchor links - Remove Lenis smooth scroll library dependency Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
a11df4f476
commit
6b77213f91
+4
-5
@@ -4,9 +4,9 @@ import {
|
||||
} from "./js/components/glass-terminal.js";
|
||||
import { initLensEffect } from "./js/components/lens.js";
|
||||
import { initFrameworkViz } from "./js/components/framework-viz.js";
|
||||
import { initHeroShader } from "./js/effects/hero-shader.js";
|
||||
import { initScrollReveal } from "./js/utils/reveal.js";
|
||||
import { initScrollIndicator, initSmoothScroll, initHashTracking } from "./js/utils/scroll.js";
|
||||
import { initAnchorScroll, initHashTracking } from "./js/utils/scroll.js";
|
||||
import { initThemeToggle } from "./js/utils/theme.js";
|
||||
|
||||
// ============================================
|
||||
// STATE
|
||||
@@ -315,10 +315,9 @@ function initLightbox() {
|
||||
// ============================================
|
||||
|
||||
function init() {
|
||||
initSmoothScroll();
|
||||
initScrollIndicator();
|
||||
initThemeToggle();
|
||||
initAnchorScroll();
|
||||
initHashTracking();
|
||||
initHeroShader();
|
||||
initLensEffect();
|
||||
initScrollReveal();
|
||||
initGlassTerminal();
|
||||
|
||||
+242
-260
@@ -61,11 +61,78 @@
|
||||
--color-accent-hover: oklch(52% 0.25 350);
|
||||
--color-accent-dim: oklch(60% 0.25 350 / 0.15);
|
||||
--color-accent-soft: oklch(60% 0.25 350 / 0.25);
|
||||
|
||||
/* Framework category colors - Light mode */
|
||||
--cat-diagnostic-bg: #fdf4ff;
|
||||
--cat-diagnostic-border: #d946ef;
|
||||
--cat-diagnostic-text: #a21caf;
|
||||
|
||||
--cat-quality-bg: #f0fdf4;
|
||||
--cat-quality-border: #22c55e;
|
||||
--cat-quality-text: #15803d;
|
||||
|
||||
--cat-intensity-bg: #fffbeb;
|
||||
--cat-intensity-border: #f59e0b;
|
||||
--cat-intensity-text: #b45309;
|
||||
|
||||
--cat-adaptation-bg: #eff6ff;
|
||||
--cat-adaptation-border: #3b82f6;
|
||||
--cat-adaptation-text: #1d4ed8;
|
||||
|
||||
--cat-enhancement-bg: #fdf2f8;
|
||||
--cat-enhancement-border: #ec4899;
|
||||
--cat-enhancement-text: #be185d;
|
||||
|
||||
--cat-system-bg: #f5f5f4;
|
||||
--cat-system-border: #78716c;
|
||||
--cat-system-text: #44403c;
|
||||
}
|
||||
|
||||
/* Dark Mode */
|
||||
/* Dark Mode - Class-based for toggle support */
|
||||
html.dark {
|
||||
--color-ink: oklch(98% 0 0);
|
||||
--color-text: oklch(98% 0 0);
|
||||
--color-paper: oklch(10% 0 0);
|
||||
--color-cream: oklch(12% 0.005 350);
|
||||
--color-charcoal: oklch(92% 0 0);
|
||||
--color-ash: oklch(65% 0 0);
|
||||
--color-mist: oklch(20% 0 0);
|
||||
--color-bg: oklch(12% 0.005 350);
|
||||
|
||||
--color-accent: oklch(68% 0.23 350);
|
||||
--color-accent-hover: oklch(76% 0.23 350);
|
||||
--color-accent-dim: oklch(68% 0.23 350 / 0.15);
|
||||
--color-accent-soft: oklch(68% 0.23 350 / 0.25);
|
||||
|
||||
/* Framework category colors - Dark mode (muted backgrounds, brighter accents) */
|
||||
--cat-diagnostic-bg: #2d1f3d;
|
||||
--cat-diagnostic-border: #c084fc;
|
||||
--cat-diagnostic-text: #e879f9;
|
||||
|
||||
--cat-quality-bg: #14332a;
|
||||
--cat-quality-border: #4ade80;
|
||||
--cat-quality-text: #86efac;
|
||||
|
||||
--cat-intensity-bg: #362a1a;
|
||||
--cat-intensity-border: #fbbf24;
|
||||
--cat-intensity-text: #fcd34d;
|
||||
|
||||
--cat-adaptation-bg: #1e293b;
|
||||
--cat-adaptation-border: #60a5fa;
|
||||
--cat-adaptation-text: #93c5fd;
|
||||
|
||||
--cat-enhancement-bg: #3b1f32;
|
||||
--cat-enhancement-border: #f472b6;
|
||||
--cat-enhancement-text: #f9a8d4;
|
||||
|
||||
--cat-system-bg: #1c1917;
|
||||
--cat-system-border: #a8a29e;
|
||||
--cat-system-text: #d6d3d1;
|
||||
}
|
||||
|
||||
/* System preference fallback (when no explicit preference is set) */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
html:not(.light):not(.dark) {
|
||||
--color-ink: oklch(98% 0 0);
|
||||
--color-text: oklch(98% 0 0);
|
||||
--color-paper: oklch(10% 0 0);
|
||||
@@ -74,14 +141,84 @@
|
||||
--color-ash: oklch(65% 0 0);
|
||||
--color-mist: oklch(20% 0 0);
|
||||
--color-bg: oklch(12% 0.005 350);
|
||||
|
||||
|
||||
--color-accent: oklch(68% 0.23 350);
|
||||
--color-accent-hover: oklch(76% 0.23 350);
|
||||
--color-accent-dim: oklch(68% 0.23 350 / 0.15);
|
||||
--color-accent-soft: oklch(68% 0.23 350 / 0.25);
|
||||
|
||||
/* Framework category colors - Dark mode */
|
||||
--cat-diagnostic-bg: #2d1f3d;
|
||||
--cat-diagnostic-border: #c084fc;
|
||||
--cat-diagnostic-text: #e879f9;
|
||||
|
||||
--cat-quality-bg: #14332a;
|
||||
--cat-quality-border: #4ade80;
|
||||
--cat-quality-text: #86efac;
|
||||
|
||||
--cat-intensity-bg: #362a1a;
|
||||
--cat-intensity-border: #fbbf24;
|
||||
--cat-intensity-text: #fcd34d;
|
||||
|
||||
--cat-adaptation-bg: #1e293b;
|
||||
--cat-adaptation-border: #60a5fa;
|
||||
--cat-adaptation-text: #93c5fd;
|
||||
|
||||
--cat-enhancement-bg: #3b1f32;
|
||||
--cat-enhancement-border: #f472b6;
|
||||
--cat-enhancement-text: #f9a8d4;
|
||||
|
||||
--cat-system-bg: #1c1917;
|
||||
--cat-system-border: #a8a29e;
|
||||
--cat-system-text: #d6d3d1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Theme Toggle */
|
||||
.theme-toggle {
|
||||
position: fixed;
|
||||
bottom: var(--spacing-md);
|
||||
right: var(--spacing-md);
|
||||
z-index: 10001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--color-cream);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 100px;
|
||||
padding: 4px;
|
||||
gap: 2px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.theme-toggle-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
border-radius: 50%;
|
||||
color: var(--color-ash);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.theme-toggle-btn:hover {
|
||||
color: var(--color-charcoal);
|
||||
background: var(--color-mist);
|
||||
}
|
||||
|
||||
.theme-toggle-btn.active {
|
||||
color: var(--color-paper);
|
||||
background: var(--color-ink);
|
||||
}
|
||||
|
||||
.theme-toggle-btn svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
SKIP LINK (Accessibility)
|
||||
============================================ */
|
||||
@@ -119,23 +256,6 @@ html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
html.lenis, html.lenis body {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.lenis.lenis-smooth {
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
|
||||
.lenis.lenis-smooth [data-lenis-prevent] {
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.lenis.lenis-stopped {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -278,54 +398,52 @@ code {
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
HERO SECTION
|
||||
HERO SECTION - Combined Layout
|
||||
============================================ */
|
||||
|
||||
/* Hero shader viewport - first thing, full screen */
|
||||
.hero-shader {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
height: 100dvh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hero-shader canvas {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
/* Overlay content centered on shader */
|
||||
.hero-overlay-content {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 2;
|
||||
.hero-combined {
|
||||
min-height: 100vh;
|
||||
min-height: 100dvh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: var(--spacing-xl) var(--spacing-lg);
|
||||
background: var(--color-paper);
|
||||
}
|
||||
|
||||
.hero-combined-container {
|
||||
max-width: var(--width-max);
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--spacing-xl);
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.hero-combined-container {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-lg);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-combined-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-md);
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hero-badge {
|
||||
display: inline-block;
|
||||
padding: 0.35em 1em;
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-ink);
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
border: 1px solid var(--color-ink);
|
||||
backdrop-filter: blur(4px);
|
||||
@media (max-width: 1024px) {
|
||||
.hero-combined-left {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-title-overlay {
|
||||
.hero-title-combined {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(3.5rem, 12vw, 8rem);
|
||||
font-size: clamp(3.5rem, 10vw, 7rem);
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
line-height: 1;
|
||||
@@ -334,22 +452,40 @@ code {
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.hero-tagline-overlay {
|
||||
.hero-tagline-combined {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(1rem, 2.5vw, 1.5rem);
|
||||
font-size: clamp(1.125rem, 2.5vw, 1.75rem);
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
line-height: 1.4;
|
||||
line-height: 1.3;
|
||||
margin: 0;
|
||||
color: var(--color-ink);
|
||||
opacity: 0.8;
|
||||
max-width: 400px;
|
||||
color: var(--color-charcoal);
|
||||
}
|
||||
|
||||
.hero-cta-overlay {
|
||||
pointer-events: auto;
|
||||
.hero-problem-text {
|
||||
font-size: clamp(1rem, 1.5vw, 1.125rem);
|
||||
line-height: 1.6;
|
||||
color: var(--color-ash);
|
||||
max-width: 45ch;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.hero-cta-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-lg);
|
||||
margin-top: var(--spacing-sm);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.hero-cta-group {
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-md);
|
||||
}
|
||||
}
|
||||
|
||||
.hero-cta-combined {
|
||||
display: inline-block;
|
||||
margin-top: var(--spacing-md);
|
||||
padding: var(--spacing-sm) var(--spacing-xl);
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.9rem;
|
||||
@@ -360,225 +496,71 @@ code {
|
||||
color: var(--color-paper);
|
||||
background: var(--color-ink);
|
||||
border: none;
|
||||
transition: transform 0.2s ease, opacity 0.2s ease;
|
||||
transition: transform 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.hero-cta-overlay:hover {
|
||||
.hero-cta-combined:hover {
|
||||
transform: translateY(-2px);
|
||||
opacity: 0.9;
|
||||
background: var(--color-accent);
|
||||
color: var(--color-paper);
|
||||
}
|
||||
|
||||
/* Content section below shader */
|
||||
.hero-container {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
max-width: 1000px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: var(--spacing-2xl) var(--spacing-lg);
|
||||
background: var(--color-paper);
|
||||
}
|
||||
|
||||
.hero-section-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(1.5rem, 4vw, 2rem);
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
color: var(--color-ink);
|
||||
margin: 0 0 var(--spacing-lg) 0;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
.hero-logos-inline {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--spacing-xl);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hero-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.hero-eyebrow {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-accent);
|
||||
/* Animation handled by JS reveal.js */
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: clamp(3.5rem, 12vw, 8rem);
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.02em;
|
||||
margin: 0;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.hero-title-line {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hero-title-accent {
|
||||
font-style: italic;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: clamp(1rem, 2.5vw, 1.375rem);
|
||||
color: var(--color-charcoal);
|
||||
max-width: 45ch;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
.hero-providers {
|
||||
font-size: 0.8125rem;
|
||||
.hero-logos-inline .hero-logos-label {
|
||||
font-size: 0.6875rem;
|
||||
color: var(--color-ash);
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
.hero-tagline {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(1rem, 1.8vw, 1.25rem);
|
||||
font-style: italic;
|
||||
color: var(--color-ash);
|
||||
letter-spacing: 0.02em;
|
||||
margin-top: var(--spacing-sm);
|
||||
}
|
||||
|
||||
/* Hero Equation */
|
||||
.hero-equation {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: var(--spacing-md);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.equation-block {
|
||||
flex: 1;
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
border: 2px solid var(--color-ink);
|
||||
border-radius: 0;
|
||||
background: var(--color-cream);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.equation-label {
|
||||
display: inline-block;
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--color-cream);
|
||||
background: var(--color-ink);
|
||||
padding: 2px 8px;
|
||||
margin-bottom: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.equation-title {
|
||||
display: block;
|
||||
font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
|
||||
font-size: clamp(1.125rem, 2vw, 1.5rem);
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
margin-bottom: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.equation-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-charcoal);
|
||||
line-height: 1.6;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.equation-operator {
|
||||
.hero-logos-inline .hero-logos-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--font-display);
|
||||
font-size: 2.5rem;
|
||||
font-weight: 300;
|
||||
color: var(--color-accent);
|
||||
flex-shrink: 0;
|
||||
width: 48px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-equation {
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.equation-operator {
|
||||
font-size: 1.75rem;
|
||||
width: auto;
|
||||
padding: var(--spacing-xs) 0;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-logos {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.hero-logos-label {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-ash);
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
.hero-logos-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.hero-logos-row img {
|
||||
.hero-logos-inline .hero-logos-row img {
|
||||
border-radius: 4px;
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.hero-scroll-indicator {
|
||||
position: absolute;
|
||||
bottom: var(--spacing-lg);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
.hero-logos-inline .hero-logos-row img:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.hero-combined-right {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.hero-combined-right .split-comparison {
|
||||
max-width: 520px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hero-combined-right .split-container {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Bias tags at bottom of hero */
|
||||
.hero-bias-tags {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--spacing-xs);
|
||||
color: var(--color-ash);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
opacity: 0;
|
||||
/* Restore simple CSS animation */
|
||||
animation: fadeIn 1s var(--ease-out) 1.5s forwards, float 2s ease-in-out infinite 2s;
|
||||
}
|
||||
|
||||
/* Removed .revealed dependency for scroll indicator */
|
||||
|
||||
.hero-scroll-indicator svg {
|
||||
/* No separate bounce animation needed, handled by float */
|
||||
margin-top: var(--spacing-lg);
|
||||
padding-top: var(--spacing-md);
|
||||
border-top: 1px solid var(--color-mist);
|
||||
max-width: var(--width-max);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 100%;
|
||||
padding-bottom: var(--spacing-md);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
|
||||
+7
-12
@@ -139,7 +139,7 @@
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
padding: 5px 12px;
|
||||
background: var(--color-mist);
|
||||
background: var(--color-cream);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-bottom: none;
|
||||
border-radius: 6px 6px 0 0;
|
||||
@@ -201,14 +201,12 @@
|
||||
|
||||
/* Source Window Content */
|
||||
.source-window {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
background: var(--color-paper);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
box-shadow:
|
||||
0 20px 60px -10px rgba(0,0,0,0.15),
|
||||
0 0 0 1px rgba(255,255,255,0.5) inset;
|
||||
box-shadow: 0 20px 60px -10px rgba(0,0,0,0.15);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -216,7 +214,7 @@
|
||||
}
|
||||
|
||||
.source-header {
|
||||
background: rgba(0,0,0,0.02);
|
||||
background: var(--color-cream);
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -259,15 +257,12 @@
|
||||
}
|
||||
|
||||
.glass-terminal {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
/* Glass effect handled by backdrop-filter if supported */
|
||||
background: var(--color-paper);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
box-shadow:
|
||||
0 20px 60px -10px rgba(0,0,0,0.15),
|
||||
0 0 0 1px rgba(255,255,255,0.5) inset;
|
||||
box-shadow: 0 20px 60px -10px rgba(0,0,0,0.15);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -275,7 +270,7 @@
|
||||
}
|
||||
|
||||
.terminal-header {
|
||||
background: rgba(0,0,0,0.02);
|
||||
background: var(--color-cream);
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
+50
-87
@@ -38,81 +38,54 @@
|
||||
<!-- Grain Overlay -->
|
||||
<div class="grain-overlay" aria-hidden="true"></div>
|
||||
|
||||
<!-- 1. HERO -->
|
||||
<section id="hero">
|
||||
<!-- Shader viewport with overlayed content -->
|
||||
<div class="hero-shader" id="hero-shader">
|
||||
<div class="hero-overlay-content">
|
||||
<h1 class="hero-title-overlay">Impeccable</h1>
|
||||
<p class="hero-tagline-overlay">Design fluency for Claude Code, Codex, and more.</p>
|
||||
<a href="#downloads" class="hero-cta-overlay">Get Started</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Theme Toggle -->
|
||||
<div class="theme-toggle" role="group" aria-label="Theme switcher">
|
||||
<button class="theme-toggle-btn" data-theme="light" aria-label="Light theme" title="Light theme">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="theme-toggle-btn" data-theme="system" aria-label="System theme" title="System theme">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2"/>
|
||||
<path d="M8 21h8M12 17v4"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="theme-toggle-btn" data-theme="dark" aria-label="Dark theme" title="Dark theme">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Content below the shader -->
|
||||
<div class="hero-container">
|
||||
<div class="hero-content">
|
||||
<h2 class="hero-section-title" data-reveal>What's Included</h2>
|
||||
<!-- 1. HERO - Combined with Problem Section -->
|
||||
<section id="hero" class="hero-combined">
|
||||
<div class="hero-combined-container">
|
||||
<!-- Left: Title & Info -->
|
||||
<div class="hero-combined-left">
|
||||
<h1 class="hero-title-combined">Impeccable</h1>
|
||||
<p class="hero-tagline-combined">Design fluency for AI coding tools</p>
|
||||
|
||||
<!-- Visual Equation -->
|
||||
<div class="hero-equation" data-reveal>
|
||||
<div class="equation-block">
|
||||
<span class="equation-label">Enhanced Skill</span>
|
||||
<span class="equation-title">frontend-design</span>
|
||||
<ul class="equation-list">
|
||||
<li>Anthropic's original skill</li>
|
||||
<li>+ curated anti-patterns</li>
|
||||
<li>+ 7 deep reference guides</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p class="hero-problem-text">Every LLM learned from the same generic templates. Without explicit guidance, they converge on predictable defaults.</p>
|
||||
|
||||
<span class="equation-operator">+</span>
|
||||
|
||||
<div class="equation-block">
|
||||
<span class="equation-label">Steering Commands</span>
|
||||
<span class="equation-title">17 commands</span>
|
||||
<ul class="equation-list">
|
||||
<li>/polish, /audit, /simplify</li>
|
||||
<li>/bolder, /quieter, /animate</li>
|
||||
<li>and 11 more...</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom: Logos -->
|
||||
<div class="hero-footer" data-reveal>
|
||||
<div class="hero-logos">
|
||||
<div class="hero-cta-group">
|
||||
<a href="#downloads" class="hero-cta-combined">Get Started</a>
|
||||
<div class="hero-logos-inline">
|
||||
<span class="hero-logos-label">Works with</span>
|
||||
<div class="hero-logos-row">
|
||||
<img src="https://img.logo.dev/cursor.com?token=pk_dtRHfeTyRzG5zZInUc65Xw&size=64&format=png" alt="Cursor" width="30" height="30" loading="lazy">
|
||||
<img src="https://img.logo.dev/claude.ai?token=pk_dtRHfeTyRzG5zZInUc65Xw&size=64&format=png" alt="Claude Code" width="30" height="30" loading="lazy">
|
||||
<img src="https://img.logo.dev/gemini.google.com?token=pk_dtRHfeTyRzG5zZInUc65Xw&size=64&format=png" alt="Gemini CLI" width="24" height="24" loading="lazy">
|
||||
<img src="https://img.logo.dev/openai.com?token=pk_dtRHfeTyRzG5zZInUc65Xw&size=64&format=png" alt="Codex CLI" width="24" height="24" loading="lazy">
|
||||
<img src="https://img.logo.dev/cursor.com?token=pk_dtRHfeTyRzG5zZInUc65Xw&size=64&format=png" alt="Cursor" width="24" height="24" loading="lazy">
|
||||
<img src="https://img.logo.dev/claude.ai?token=pk_dtRHfeTyRzG5zZInUc65Xw&size=64&format=png" alt="Claude Code" width="24" height="24" loading="lazy">
|
||||
<img src="https://img.logo.dev/gemini.google.com?token=pk_dtRHfeTyRzG5zZInUc65Xw&size=64&format=png" alt="Gemini CLI" width="20" height="20" loading="lazy">
|
||||
<img src="https://img.logo.dev/openai.com?token=pk_dtRHfeTyRzG5zZInUc65Xw&size=64&format=png" alt="Codex CLI" width="20" height="20" loading="lazy">
|
||||
</div>
|
||||
</div>
|
||||
</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="site-content" id="main-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 explicit guidance, they converge on the same predictable defaults.</p>
|
||||
|
||||
<!-- Before/After Demo - The Hero -->
|
||||
<div class="split-comparison" id="lens-comparison" data-reveal>
|
||||
<!-- Right: Before/After Demo -->
|
||||
<div class="hero-combined-right">
|
||||
<div class="split-comparison" id="lens-comparison">
|
||||
<div class="split-container">
|
||||
<!-- Before: AI Slop -->
|
||||
<div class="split-before">
|
||||
@@ -160,26 +133,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Compact Bias Tags -->
|
||||
<div class="bias-tags" data-reveal>
|
||||
<span class="bias-tags-label">Common AI defaults:</span>
|
||||
<div class="bias-tags-list">
|
||||
<span class="bias-tag">Inter/Roboto fonts</span>
|
||||
<span class="bias-tag">Purple gradients</span>
|
||||
<span class="bias-tag">Cards on cards</span>
|
||||
<span class="bias-tag">Centered everything</span>
|
||||
<span class="bias-tag">Gray text on color</span>
|
||||
<span class="bias-tag">Decorative shadows</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. THE ANTIDOTE - Patterns & Anti-Patterns -->
|
||||
<main class="site-content" id="main-content">
|
||||
|
||||
<!-- 2. THE ANTIDOTE - Patterns & Anti-Patterns -->
|
||||
<section class="antidote-section" id="antidote">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">02</span>
|
||||
<span class="section-number">01</span>
|
||||
<h2 class="section-title">The Antidote</h2>
|
||||
</div>
|
||||
<div class="antidote-content">
|
||||
@@ -203,10 +166,10 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. THE SOLUTION - Two-part system -->
|
||||
<!-- 3. THE SOLUTION - Two-part system -->
|
||||
<section class="solution-section" id="solution">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">03</span>
|
||||
<span class="section-number">02</span>
|
||||
<h2 class="section-title">The Framework</h2>
|
||||
</div>
|
||||
<div class="solution-content">
|
||||
@@ -226,7 +189,7 @@
|
||||
<!-- 4. COMMANDS - Glass Terminal -->
|
||||
<section class="commands-section" id="commands-section">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">04</span>
|
||||
<span class="section-number">03</span>
|
||||
<h2 class="section-title">Commands in Action</h2>
|
||||
<p class="section-subtitle">See how commands transform your designs</p>
|
||||
</div>
|
||||
@@ -239,7 +202,7 @@
|
||||
<!-- 5. CASE STUDIES -->
|
||||
<section class="casestudies-section" id="casestudies">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">05</span>
|
||||
<span class="section-number">04</span>
|
||||
<h2 class="section-title">See It In Action</h2>
|
||||
<p class="section-subtitle">Sample projects transformed with Impeccable commands</p>
|
||||
</div>
|
||||
@@ -335,7 +298,7 @@
|
||||
<!-- 6. PLATFORMS -->
|
||||
<section class="platforms-section" id="downloads">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">06</span>
|
||||
<span class="section-number">05</span>
|
||||
<h2 class="section-title">Download for Your AI Harness</h2>
|
||||
<p class="section-subtitle">Same design intelligence, adapted for your workflow. Download and start using in seconds.</p>
|
||||
</div>
|
||||
@@ -438,7 +401,7 @@
|
||||
<!-- 7. FAQ -->
|
||||
<section class="faq-section" id="faq">
|
||||
<div class="section-header" data-reveal>
|
||||
<span class="section-number">07</span>
|
||||
<span class="section-number">06</span>
|
||||
<h2 class="section-title">Frequently Asked Questions</h2>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
|
||||
import { commandCategories, commandRelationships } from '../data.js';
|
||||
|
||||
// Colors now reference CSS custom properties for dark mode support
|
||||
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' }
|
||||
diagnostic: { bg: 'var(--cat-diagnostic-bg)', border: 'var(--cat-diagnostic-border)', text: 'var(--cat-diagnostic-text)' },
|
||||
quality: { bg: 'var(--cat-quality-bg)', border: 'var(--cat-quality-border)', text: 'var(--cat-quality-text)' },
|
||||
intensity: { bg: 'var(--cat-intensity-bg)', border: 'var(--cat-intensity-border)', text: 'var(--cat-intensity-text)' },
|
||||
adaptation: { bg: 'var(--cat-adaptation-bg)', border: 'var(--cat-adaptation-border)', text: 'var(--cat-adaptation-text)' },
|
||||
enhancement: { bg: 'var(--cat-enhancement-bg)', border: 'var(--cat-enhancement-border)', text: 'var(--cat-enhancement-text)' },
|
||||
system: { bg: 'var(--cat-system-bg)', border: 'var(--cat-system-border)', text: 'var(--cat-system-text)' }
|
||||
};
|
||||
|
||||
const categoryLabels = {
|
||||
|
||||
+10
-60
@@ -1,69 +1,17 @@
|
||||
import Lenis from "lenis";
|
||||
|
||||
// Check if user prefers reduced motion
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
export function initSmoothScroll() {
|
||||
// Skip smooth scroll entirely if user prefers reduced motion
|
||||
if (prefersReducedMotion) {
|
||||
// Still handle anchor links but with instant scroll
|
||||
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
|
||||
anchor.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(anchor.getAttribute("href"));
|
||||
if (target) {
|
||||
target.scrollIntoView({ behavior: 'auto', block: 'start' });
|
||||
}
|
||||
});
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
const lenis = new Lenis({
|
||||
duration: 1.2,
|
||||
easing: (t) => Math.min(1, 1.001 - 2 ** (-10 * t)),
|
||||
orientation: "vertical",
|
||||
gestureOrientation: "vertical",
|
||||
smoothWheel: true,
|
||||
wheelMultiplier: 1,
|
||||
touchMultiplier: 2,
|
||||
});
|
||||
|
||||
function raf(time) {
|
||||
lenis.raf(time);
|
||||
requestAnimationFrame(raf);
|
||||
}
|
||||
|
||||
requestAnimationFrame(raf);
|
||||
|
||||
// Handle anchor links
|
||||
// Instant anchor scroll - no smooth scrolling for better UX on long pages
|
||||
export function initAnchorScroll() {
|
||||
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
|
||||
anchor.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(anchor.getAttribute("href"));
|
||||
if (target) {
|
||||
lenis.scrollTo(target, { offset: -40 });
|
||||
// Instant jump with small offset for visual breathing room
|
||||
const offset = 40;
|
||||
const targetPosition = target.getBoundingClientRect().top + window.scrollY - offset;
|
||||
window.scrollTo({ top: targetPosition, behavior: 'auto' });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return lenis;
|
||||
}
|
||||
|
||||
export function initScrollIndicator() {
|
||||
const indicator = document.querySelector(".hero-scroll-indicator");
|
||||
if (!indicator) return;
|
||||
|
||||
function update() {
|
||||
if (window.scrollY > 20) {
|
||||
indicator.classList.add("hidden");
|
||||
} else {
|
||||
indicator.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", update, { passive: true });
|
||||
update();
|
||||
}
|
||||
|
||||
export function initHashTracking() {
|
||||
@@ -109,12 +57,14 @@ export function initHashTracking() {
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
// Handle initial hash on page load
|
||||
// Handle initial hash on page load - instant jump
|
||||
if (window.location.hash) {
|
||||
const target = document.querySelector(window.location.hash);
|
||||
if (target) {
|
||||
setTimeout(() => {
|
||||
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
const offset = 40;
|
||||
const targetPosition = target.getBoundingClientRect().top + window.scrollY - offset;
|
||||
window.scrollTo({ top: targetPosition, behavior: 'auto' });
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Theme toggle - supports light, dark, and system preference
|
||||
|
||||
const STORAGE_KEY = 'impeccable-theme';
|
||||
|
||||
function getStoredTheme() {
|
||||
return localStorage.getItem(STORAGE_KEY);
|
||||
}
|
||||
|
||||
function setStoredTheme(theme) {
|
||||
localStorage.setItem(STORAGE_KEY, theme);
|
||||
}
|
||||
|
||||
function applyTheme(theme) {
|
||||
const html = document.documentElement;
|
||||
|
||||
// Remove both classes first
|
||||
html.classList.remove('light', 'dark');
|
||||
|
||||
if (theme === 'light') {
|
||||
html.classList.add('light');
|
||||
} else if (theme === 'dark') {
|
||||
html.classList.add('dark');
|
||||
}
|
||||
// 'system' = no class, falls back to media query
|
||||
|
||||
// Update active state on buttons
|
||||
document.querySelectorAll('.theme-toggle-btn').forEach(btn => {
|
||||
btn.classList.toggle('active', btn.dataset.theme === theme);
|
||||
});
|
||||
}
|
||||
|
||||
export function initThemeToggle() {
|
||||
const toggle = document.querySelector('.theme-toggle');
|
||||
if (!toggle) return;
|
||||
|
||||
// Get stored theme or default to system
|
||||
const storedTheme = getStoredTheme() || 'system';
|
||||
applyTheme(storedTheme);
|
||||
|
||||
// Handle button clicks
|
||||
toggle.addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('.theme-toggle-btn');
|
||||
if (!btn) return;
|
||||
|
||||
const theme = btn.dataset.theme;
|
||||
setStoredTheme(theme);
|
||||
applyTheme(theme);
|
||||
});
|
||||
|
||||
// Listen for system preference changes (only matters when in 'system' mode)
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
||||
if (getStoredTheme() === 'system' || !getStoredTheme()) {
|
||||
applyTheme('system');
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user