diff --git a/.agents/skills/ce-plan/SKILL.md b/.agents/skills/ce-plan/SKILL.md index f087f12..f5897de 100644 --- a/.agents/skills/ce-plan/SKILL.md +++ b/.agents/skills/ce-plan/SKILL.md @@ -210,9 +210,10 @@ Based on the origin document, user signals, and local findings, decide whether e The repo-research-analyst output includes a structured Technology & Infrastructure summary. Use it to make sharper external research decisions: -- If specific frameworks and versions were detected (e.g., Next.js 16, NestJS 11, TypeORM 0.3), pass those exact identifiers to framework-docs-researcher so it fetches version-specific documentation +- If specific frameworks and versions were detected (e.g., Next.js 16, NestJS 11, Prisma 7), pass those exact identifiers to framework-docs-researcher so it fetches version-specific documentation - If the feature touches a technology layer the scan found well-established in the repo (e.g., existing NestJS providers, repositories, or Next.js route patterns), lean toward skipping external research -- local patterns are likely sufficient - If the feature touches a technology layer the scan found absent or thin (e.g., no existing proto files when planning a new gRPC service), lean toward external research -- there are no local patterns to follow +- If the plan touches Prisma in this repo, anchor the plan to `apps/api/package.json`, `apps/api/prisma.config.ts`, `apps/api/prisma/schema.prisma`, and `apps/api/src/prisma/prisma.service.ts`. Read `.agents/skills/prisma-cli/SKILL.md`, `.agents/skills/prisma-client-api/SKILL.md`, and `.agents/skills/prisma-database-setup/SKILL.md` before making ORM-specific recommendations - If the scan detected deployment infrastructure (Docker, K8s, serverless), note it in the planning context passed to downstream agents so they can account for deployment constraints - If the scan detected a monorepo and scoped to a specific service, pass that service's tech context to downstream research agents -- not the aggregate of all services. If the scan surfaced the workspace map without scoping, use the feature description to identify the relevant service before proceeding with research diff --git a/.agents/skills/ce-review/SKILL.md b/.agents/skills/ce-review/SKILL.md index ec4d12b..f8e538c 100644 --- a/.agents/skills/ce-review/SKILL.md +++ b/.agents/skills/ce-review/SKILL.md @@ -120,7 +120,7 @@ Focused TypeScript, frontend, API, reliability, and data-migration reviewers plu | `compound-engineering:review:security-reviewer` | Auth, public endpoints, user input, permissions | | `compound-engineering:review:performance-reviewer` | DB queries, data transforms, caching, async | | `compound-engineering:review:api-contract-reviewer` | Routes, serializers, type signatures, versioning | -| `compound-engineering:review:data-migrations-reviewer` | TypeORM migrations, entity/schema changes, backfills | +| `compound-engineering:review:data-migrations-reviewer` | Prisma migrations, schema changes, backfills, data service updates | | `compound-engineering:review:reliability-reviewer` | Error handling, retries, timeouts, background jobs | | `compound-engineering:review:adversarial-reviewer` | Diff >=50 changed non-test/non-generated/non-lockfile lines, or auth, payments, data mutations, external APIs | | `compound-engineering:review:previous-comments-reviewer` | Reviewing a PR that has existing review comments or threads | @@ -129,14 +129,14 @@ Focused TypeScript, frontend, API, reliability, and data-migration reviewers plu | Agent | Select when diff touches... | |-------|---------------------------| -| `compound-engineering:review:kieran-typescript-reviewer` | TypeScript components, services, hooks, utilities, shared types, Nest providers, TypeORM repositories | +| `compound-engineering:review:kieran-typescript-reviewer` | TypeScript components, services, hooks, utilities, shared types, Nest providers, Prisma-backed repository wrappers | | `compound-engineering:review:julik-frontend-races-reviewer` | React DOM events, timers, animations, or async UI flows | **CE conditional (migration-specific):** | Agent | Select when diff includes migration files | |-------|------------------------------------------| -| `compound-engineering:review:deployment-verification-agent` | Produces deployment checklist with TypeORM / data rollout verification steps | +| `compound-engineering:review:deployment-verification-agent` | Produces deployment checklist with Prisma migration / data rollout verification steps | ## Review Scope @@ -337,7 +337,7 @@ Read the diff and file list from Stage 1. The 4 always-on personas and 2 CE alwa Stack-specific personas are additive. A Next.js UI change may warrant `kieran-typescript` plus `julik-frontend-races`; a NestJS API diff may warrant `kieran-typescript` plus `api-contract` and `reliability`. -For CE conditional agents, check if the diff includes TypeORM migration files, entity/schema transitions, or data backfill scripts. +For CE conditional agents, check if the diff includes Prisma migration files under `apps/api/prisma/migrations/`, schema transitions in `apps/api/prisma/models/*.prisma`, `apps/api/src/prisma/prisma.service.ts`, or data backfill scripts. Announce the team before spawning: @@ -349,8 +349,8 @@ Review team: - project-standards (always) - learnings-researcher (always) - security -- new NestJS endpoint accepts a user-provided redirect URL -- data-migrations -- adds TypeORM migration `20260303-add-index-to-orders` -- deployment-verification-agent -- TypeORM migration or backfill files present +- data-migrations -- adds Prisma migration `apps/api/prisma/migrations/202604200001_add_feed_auto_refresh_state/migration.sql` +- deployment-verification-agent -- Prisma migration or backfill files present ``` This is progress reporting, not a blocking confirmation. @@ -406,7 +406,7 @@ Each persona sub-agent returns JSON matching the findings schema included below: **CE always-on agent** (`learnings-researcher`) is dispatched as a standard Agent call in parallel with the persona agents. Give it the same review context bundle the personas receive: entry mode, any PR metadata gathered in Stage 1, intent summary, review base branch name when known, `BASE:` marker, file list, diff, and `UNTRACKED:` scope notes. -**CE conditional agent** (`deployment-verification-agent`) is dispatched when the diff includes TypeORM migrations, data backfills, or risky entity/schema changes. Pass the same review context bundle plus the applicability reason. +**CE conditional agent** (`deployment-verification-agent`) is dispatched when the diff includes Prisma migrations, data backfills, or risky schema/data service changes. Pass the same review context bundle plus the applicability reason. ### Stage 5: Merge findings diff --git a/.agents/skills/ce-review/references/persona-catalog.md b/.agents/skills/ce-review/references/persona-catalog.md index 48926d1..8f23e09 100644 --- a/.agents/skills/ce-review/references/persona-catalog.md +++ b/.agents/skills/ce-review/references/persona-catalog.md @@ -46,16 +46,16 @@ These reviewers keep their original opinionated lens. They are additive with the ## CE Conditional Agents (migration-specific) -These CE-native agents provide specialized analysis beyond what the persona agents cover. Spawn them when the diff includes TypeORM migrations, entity/schema changes, or data backfills. +These CE-native agents provide specialized analysis beyond what the persona agents cover. Spawn them when the diff includes Prisma migrations, schema changes, or data backfills. | Agent | Focus | |-------|-------| -| `compound-engineering:review:deployment-verification-agent` | Produces rollout, rollback, and verification guidance for TypeORM migrations and data changes | +| `compound-engineering:review:deployment-verification-agent` | Produces rollout, rollback, and verification guidance for Prisma migrations and data changes | ## Selection rules 1. **Always spawn all 4 always-on personas** plus the 2 CE always-on agents. 2. **For each cross-cutting conditional persona**, the orchestrator reads the diff and decides whether the persona's domain is relevant. This is a judgment call, not a keyword match. 3. **For each stack-specific conditional persona**, use file types and changed patterns as a starting point, then decide whether the diff actually introduces meaningful work for that reviewer. Do not spawn language-specific reviewers just because one config or generated file happens to match the extension. -4. **For CE conditional agents**, spawn when the diff includes TypeORM migration files, entity/schema transitions, or data backfill scripts. +4. **For CE conditional agents**, spawn when the diff includes Prisma migration files, schema transitions, or data backfill scripts. 5. **Announce the team** before spawning with a one-line justification per conditional reviewer selected. diff --git a/.agents/skills/ckm-design-system/SKILL.md b/.agents/skills/ckm-design-system/SKILL.md deleted file mode 100644 index cfbcba0..0000000 --- a/.agents/skills/ckm-design-system/SKILL.md +++ /dev/null @@ -1,244 +0,0 @@ ---- -name: ckm:design-system -description: Token architecture, component specifications, and slide generation. Three-layer tokens (primitive→semantic→component), CSS variables, spacing/typography scales, component specs, strategic slide creation. Use for design tokens, systematic design, brand-compliant presentations. -argument-hint: "[component or token]" -license: MIT -metadata: - author: claudekit - version: "1.0.0" ---- - -# Design System - -Token architecture, component specifications, systematic design, slide generation. - -## When to Use - -- Design token creation -- Component state definitions -- CSS variable systems -- Spacing/typography scales -- Design-to-code handoff -- Tailwind theme configuration -- **Slide/presentation generation** - -## Token Architecture - -Load: `references/token-architecture.md` - -### Three-Layer Structure - -``` -Primitive (raw values) - ↓ -Semantic (purpose aliases) - ↓ -Component (component-specific) -``` - -**Example:** -```css -/* Primitive */ ---color-blue-600: #2563EB; - -/* Semantic */ ---color-primary: var(--color-blue-600); - -/* Component */ ---button-bg: var(--color-primary); -``` - -## Quick Start - -**Generate tokens:** -```bash -node scripts/generate-tokens.cjs --config tokens.json -o tokens.css -``` - -**Validate usage:** -```bash -node scripts/validate-tokens.cjs --dir src/ -``` - -## References - -| Topic | File | -|-------|------| -| Token Architecture | `references/token-architecture.md` | -| Primitive Tokens | `references/primitive-tokens.md` | -| Semantic Tokens | `references/semantic-tokens.md` | -| Component Tokens | `references/component-tokens.md` | -| Component Specs | `references/component-specs.md` | -| States & Variants | `references/states-and-variants.md` | -| Tailwind Integration | `references/tailwind-integration.md` | - -## Component Spec Pattern - -| Property | Default | Hover | Active | Disabled | -|----------|---------|-------|--------|----------| -| Background | primary | primary-dark | primary-darker | muted | -| Text | white | white | white | muted-fg | -| Border | none | none | none | muted-border | -| Shadow | sm | md | none | none | - -## Scripts - -| Script | Purpose | -|--------|---------| -| `generate-tokens.cjs` | Generate CSS from JSON token config | -| `validate-tokens.cjs` | Check for hardcoded values in code | -| `search-slides.py` | BM25 search + contextual recommendations | -| `slide-token-validator.py` | Validate slide HTML for token compliance | -| `fetch-background.py` | Fetch images from Pexels/Unsplash | - -## Templates - -| Template | Purpose | -|----------|---------| -| `design-tokens-starter.json` | Starter JSON with three-layer structure | - -## Integration - -**With brand:** Extract primitives from brand colors/typography -**With ui-styling:** Component tokens → Tailwind config - -**Skill Dependencies:** brand, ui-styling -**Primary Agents:** ui-ux-designer, frontend-developer - -## Slide System - -Brand-compliant presentations using design tokens + Chart.js + contextual decision system. - -### Source of Truth - -| File | Purpose | -|------|---------| -| `docs/brand-guidelines.md` | Brand identity, voice, colors | -| `assets/design-tokens.json` | Token definitions (primitive→semantic→component) | -| `assets/design-tokens.css` | CSS variables (import in slides) | -| `assets/css/slide-animations.css` | CSS animation library | - -### Slide Search (BM25) - -```bash -# Basic search (auto-detect domain) -python scripts/search-slides.py "investor pitch" - -# Domain-specific search -python scripts/search-slides.py "problem agitation" -d copy -python scripts/search-slides.py "revenue growth" -d chart - -# Contextual search (Premium System) -python scripts/search-slides.py "problem slide" --context --position 2 --total 9 -python scripts/search-slides.py "cta" --context --position 9 --prev-emotion frustration -``` - -### Decision System CSVs - -| File | Purpose | -|------|---------| -| `data/slide-strategies.csv` | 15 deck structures + emotion arcs + sparkline beats | -| `data/slide-layouts.csv` | 25 layouts + component variants + animations | -| `data/slide-layout-logic.csv` | Goal → Layout + break_pattern flag | -| `data/slide-typography.csv` | Content type → Typography scale | -| `data/slide-color-logic.csv` | Emotion → Color treatment | -| `data/slide-backgrounds.csv` | Slide type → Image category (Pexels/Unsplash) | -| `data/slide-copy.csv` | 25 copywriting formulas (PAS, AIDA, FAB) | -| `data/slide-charts.csv` | 25 chart types with Chart.js config | - -### Contextual Decision Flow - -``` -1. Parse goal/context - ↓ -2. Search slide-strategies.csv → Get strategy + emotion beats - ↓ -3. For each slide: - a. Query slide-layout-logic.csv → layout + break_pattern - b. Query slide-typography.csv → type scale - c. Query slide-color-logic.csv → color treatment - d. Query slide-backgrounds.csv → image if needed - e. Apply animation class from slide-animations.css - ↓ -4. Generate HTML with design tokens - ↓ -5. Validate with slide-token-validator.py -``` - -### Pattern Breaking (Duarte Sparkline) - -Premium decks alternate between emotions for engagement: -``` -"What Is" (frustration) ↔ "What Could Be" (hope) -``` - -System calculates pattern breaks at 1/3 and 2/3 positions. - -### Slide Requirements - -**ALL slides MUST:** -1. Import `assets/design-tokens.css` - single source of truth -2. Use CSS variables: `var(--color-primary)`, `var(--slide-bg)`, etc. -3. Use Chart.js for charts (NOT CSS-only bars) -4. Include navigation (keyboard arrows, click, progress bar) -5. Center align content -6. Focus on persuasion/conversion - -### Chart.js Integration - -```html - - - - -``` - -### Token Compliance - -```css -/* CORRECT - uses token */ -background: var(--slide-bg); -color: var(--color-primary); -font-family: var(--typography-font-heading); - -/* WRONG - hardcoded */ -background: #0D0D0D; -color: #FF6B6B; -font-family: 'Space Grotesk'; -``` - -### Reference Implementation - -Working example with all features: -``` -assets/designs/slides/claudekit-pitch-251223.html -``` - -### Command - -```bash -/slides:create "10-slide investor pitch for ClaudeKit Marketing" -``` - -## Best Practices - -1. Never use raw hex in components - always reference tokens -2. Semantic layer enables theme switching (light/dark) -3. Component tokens enable per-component customization -4. Use HSL format for opacity control -5. Document every token's purpose -6. **Slides must import design-tokens.css and use var() exclusively** diff --git a/.agents/skills/ckm-design-system/data/slide-backgrounds.csv b/.agents/skills/ckm-design-system/data/slide-backgrounds.csv deleted file mode 100644 index 1150484..0000000 --- a/.agents/skills/ckm-design-system/data/slide-backgrounds.csv +++ /dev/null @@ -1,11 +0,0 @@ -slide_type,image_category,overlay_style,text_placement,image_sources,search_keywords -hero,abstract-tech,gradient-dark,center,pexels:unsplash,technology abstract gradient dark -vision,future-workspace,gradient-brand,left,pexels:unsplash,futuristic office modern workspace -team,professional-people,gradient-dark,bottom,pexels:unsplash,business team professional diverse -testimonial,office-environment,blur-dark,center,pexels:unsplash,modern office workspace bright -cta,celebration-success,gradient-brand,center,pexels:unsplash,success celebration achievement -problem,frustration-pain,desaturate-dark,center,pexels:unsplash,stress frustration problem dark -solution,breakthrough-moment,gradient-accent,right,pexels:unsplash,breakthrough success innovation light -hook,attention-grabbing,gradient-dark,center,pexels:unsplash,dramatic abstract attention bold -social,community-connection,blur-dark,center,pexels:unsplash,community collaboration connection -demo,product-showcase,gradient-dark,left,pexels:unsplash,technology product showcase clean diff --git a/.agents/skills/ckm-design-system/data/slide-charts.csv b/.agents/skills/ckm-design-system/data/slide-charts.csv deleted file mode 100644 index 373648e..0000000 --- a/.agents/skills/ckm-design-system/data/slide-charts.csv +++ /dev/null @@ -1,26 +0,0 @@ -id,chart_type,keywords,best_for,data_type,when_to_use,when_to_avoid,max_categories,slide_context,css_implementation,accessibility_notes,sources -1,Bar Chart Vertical,"bar, vertical, comparison, categories, ranking",Comparing values across categories,Categorical discrete,"Comparing 3-12 categories, showing ranking, highlighting differences",Continuous time data trends,12,Traction metrics feature comparison,"Chart.js or CSS flexbox with height percentage bars",Always label axes include values,Atlassian Data Charts -2,Bar Chart Horizontal,"horizontal bar, ranking, long labels, categories",Categories with long names ranking,Categorical discrete,"Long category names, 5+ items, reading left-to-right natural",Few categories time series,15,Team performance competitor analysis,"CSS flexbox with width percentage bars",Natural reading direction for labels,Datylon Blog -3,Line Chart,"line, trend, time series, growth, change over time",Showing trends over continuous time,Time series continuous,"Time-based data, showing growth trajectory, 10+ data points",Categorical comparisons,50+ points,Revenue growth MRR user growth,"Chart.js line or SVG path element",Include data point markers for screen readers,Tableau Best Practices -4,Area Chart,"area, cumulative, volume, trend, filled line",Showing volume or magnitude over time,Time series cumulative,"Emphasizing magnitude, showing cumulative totals, comparing totals",Precise value comparison,3-4 series,Revenue breakdown market share over time,"Chart.js area or SVG path with fill",Use patterns not just colors for series,Data Visualization Guide -5,Pie Chart,"pie, composition, percentage, parts, whole",Showing parts of a whole,Proportional percentage,"2-5 slices, showing simple composition, adds to 100%",More than 6 categories precise comparison,6 max,Market share budget allocation simple splits,"CSS conic-gradient or Chart.js pie",Never use 3D always include percentages,FusionCharts Blog -6,Donut Chart,"donut, composition, percentage, center metric",Parts of whole with center highlight,Proportional percentage,"Like pie but need center space for key metric, 2-5 segments",Many categories,6 max,Composition with key stat in center,"CSS conic-gradient with inner circle",Same as pie include legend,Modern alternative to pie -7,Stacked Bar,"stacked, composition, comparison, breakdown",Comparing composition across categories,Categorical + proportional,"Showing composition AND comparison, segment contribution",Too many segments precise values,5 segments,Revenue by segment across quarters,"Chart.js stacked bar or CSS nested divs",Order segments consistently use legend,Atlassian Data Charts -8,Grouped Bar,"grouped, clustered, side by side, multi-series",Comparing multiple metrics per category,Multi-series categorical,"Direct comparison of 2-3 metrics per category",Too many groups (>4) or categories (>8),4 groups,Feature comparison pricing tiers,"Chart.js grouped bar CSS grid bars",Color code consistently across groups,Data Visualization Best Practices -9,100% Stacked Bar,"100%, proportion, normalized, percentage",Comparing proportions across categories,Proportional comparative,"Comparing percentage breakdown across categories, not absolute values",Showing absolute values,5 segments,Market share comparison percentage breakdown,"CSS flexbox 100% width segments",Clearly indicate percentage scale,Proportional analysis -10,Funnel Chart,"funnel, conversion, stages, drop-off, pipeline",Showing conversion or drop-off through stages,Sequential stage-based,"Sales funnel, conversion rates, sequential process with decreasing values",Non-sequential data equal stages,6-8 stages,User conversion sales pipeline,"CSS trapezoid shapes or SVG",Label each stage with count and percentage,Marketing/Sales standard -11,Gauge Chart,"gauge, progress, goal, target, kpi",Showing progress toward a goal,Single metric vs target,"Single KPI progress, goal completion, health scores",Multiple metrics,1 metric,Goal progress health score,"CSS conic-gradient or arc SVG",Include numeric value not just visual,Dashboard widgets -12,Sparkline,"sparkline, mini, inline, trend, compact",Showing trend in minimal space,Time series inline,"Inline metrics, table cells, compact trend indication",Detailed analysis,N/A,Metric cards with trend indicator,SVG path or canvas inline,Supplement with text for accessibility,Edward Tufte -13,Scatter Plot,"scatter, correlation, relationship, distribution",Showing relationship between two variables,Bivariate continuous,"Correlation analysis, pattern detection, outlier identification",Categorical data simple comparisons,100+ points,Correlation analysis segmentation,Canvas or SVG circles positioned,Include trend line if meaningful,Statistical visualization -14,Bubble Chart,"bubble, three variables, scatter, size",Showing three variables simultaneously,Trivariate continuous,"Three-variable comparison, population/size matters",Simple comparisons,30-50 bubbles,Market analysis with size dimension,"SVG circles with varying radius",Legend for size scale essential,Data Visualization Guide -15,Heatmap,"heatmap, matrix, intensity, correlation, grid",Showing intensity across two dimensions,Matrix intensity,"Large data matrices, time-day patterns, correlation matrices",Few data points,Unlimited grid,Usage patterns correlation matrices,CSS grid with background-color intensity,Use colorblind-safe gradients,Datylon Blog -16,Waterfall Chart,"waterfall, bridge, contribution, breakdown",Showing how values add to a total,Cumulative contribution,"Financial analysis, showing positive/negative contributions",Non-additive data,10-15 items,Revenue bridge profit breakdown,"CSS positioned bars with connectors",Clear positive/negative color coding,Financial reporting standard -17,Treemap,"treemap, hierarchy, nested, proportion",Showing hierarchical proportional data,Hierarchical proportional,"Nested categories, space-efficient proportions, 2 levels max",Simple comparisons few items,50+ items,Budget breakdown category analysis,"CSS grid with calculated areas",Include text labels on larger segments,Ben Shneiderman -18,Radar Chart,"radar, spider, multi-metric, profile",Comparing multiple metrics for single item,Multi-metric profile,"Comparing 5-8 metrics for one or two items, skill profiles",More than 3 items to compare,8 axes max,Feature profile skill assessment,SVG polygon on axes,Ensure scale is clear and consistent,Profile comparison -19,Bullet Chart,"bullet, target, actual, performance",Showing actual vs target with ranges,KPI with target,"Progress against target with qualitative ranges",Simple goal tracking,1-3 per slide,KPI performance with targets,"CSS layered bars with markers",Clearly label target and actual,Stephen Few -20,Timeline,"timeline, chronology, history, milestones",Showing events over time,Event-based temporal,"History roadmap milestones, showing progression",Quantitative comparison,10-15 events,Company history product roadmap,"CSS flexbox with positioned markers",Ensure logical reading order,Chronological visualization -21,Sankey Diagram,"sankey, flow, distribution, connections",Showing flow or distribution between nodes,Flow distribution,"Showing how values flow from source to destination",Simple distributions,15-20 nodes,User flow budget flow,D3.js or dedicated library,Alternative text description essential,Complex flow visualization -22,KPI Card,"kpi, metric, number, stat, scorecard",Highlighting single important metric,Single metric,"Dashboard hero metrics, emphasizing one key number",Showing trends or comparisons,1 number,Main KPI highlight,"Large font-size centered number",Include trend context if relevant,Dashboard design -23,Progress Bar,"progress, completion, percentage, bar",Showing completion percentage,Single percentage,"Simple progress indication, goal completion",Multiple goals comparison,1 per context,Project completion goal progress,"CSS width with percentage gradient",Include numeric percentage,UI/UX standard -24,Comparison Table,"table, comparison, matrix, features",Detailed feature or value comparison,Multi-attribute categorical,"Detailed comparison, many attributes, exact values matter",Visual impact storytelling,10-15 rows,Feature matrix pricing comparison,"HTML table with CSS styling",Proper table headers and scope,Information design -25,Icon Array,"icon array, pictogram, proportion, visual",Showing proportions with visual metaphor,Proportional visual,"Making statistics tangible (e.g. 1 in 10 people), visual impact",Precise values large numbers,100 icons,Statistics visualization impact slides,"CSS grid or flexbox with icons",Describe proportion in text,ISOTYPE Otto Neurath diff --git a/.agents/skills/ckm-design-system/data/slide-color-logic.csv b/.agents/skills/ckm-design-system/data/slide-color-logic.csv deleted file mode 100644 index d9481d6..0000000 --- a/.agents/skills/ckm-design-system/data/slide-color-logic.csv +++ /dev/null @@ -1,14 +0,0 @@ -emotion,background,text_color,accent_usage,use_full_bleed,gradient,card_style -frustration,dark-surface,foreground,minimal,false,none,subtle-border -hope,accent-bleed,dark,none,true,none,none -fear,dark-background,primary,stats-only,false,none,glow-primary -relief,surface,foreground,icons,false,none,accent-bar -trust,surface-elevated,foreground,metrics,false,none,subtle-border -urgency,gradient,white,cta-button,true,primary,none -curiosity,dark-glow,gradient-text,badge,false,glow,glow-secondary -confidence,surface,foreground,chart-accent,false,none,none -warmth,dark-surface,foreground,avatar-ring,false,none,none -evaluation,surface-elevated,foreground,highlight,false,none,comparison -narrative,dark-background,foreground-secondary,timeline-dots,false,none,none -clarity,surface,foreground,icons,false,none,feature-card -interest,dark-glow,foreground,demo-highlight,false,glow,none diff --git a/.agents/skills/ckm-design-system/data/slide-copy.csv b/.agents/skills/ckm-design-system/data/slide-copy.csv deleted file mode 100644 index ed448c0..0000000 --- a/.agents/skills/ckm-design-system/data/slide-copy.csv +++ /dev/null @@ -1,26 +0,0 @@ -id,formula_name,keywords,components,use_case,example_template,emotion_trigger,slide_type,source -1,AIDA,"aida, attention, interest, desire, action",Attention→Interest→Desire→Action,Lead-gen CTAs general persuasion,"{Attention hook} → {Interesting detail} → {Desirable outcome} → {Action step}",Curiosity→Engagement→Want→Urgency,CTA slides,Classic copywriting 1898 -2,PAS,"pas, problem, agitation, solution, dan kennedy",Problem→Agitate→Solution,Sales pages problem slides most reliable,"You're struggling with {problem}. It's costing you {agitation}. {Solution} fixes this.",Frustration→Fear→Relief,Problem slides,Dan Kennedy -3,4Ps,"4ps, promise, picture, proof, push, ray edwards",Promise→Picture→Proof→Push,Home pages lead-gen,"{Promise benefit} → {Picture future state} → {Proof it works} → {Push to act}",Hope→Vision→Trust→Action,Solution slides,Ray Edwards -4,Before-After-Bridge,"bab, before, after, bridge, transformation",Before→After→Bridge,Transformation case studies,"Before: {old state}. After: {new state}. Bridge: {how to get there}",Pain→Pleasure→Path,Before/after slides,Copywriting classic -5,QUEST,"quest, qualify, understand, educate, stimulate, transition",Qualify→Understand→Educate→Stimulate→Transition,Matching solution to prospect,"{Qualify audience} → {Show understanding} → {Educate on solution} → {Stimulate desire} → {Transition to CTA}",Recognition→Empathy→Learning→Excitement,Educational slides,Michel Fortin -6,Star-Story-Solution,"star, story, solution, narrative",Star→Story→Solution,Personality brands info products,"{Introduce character} → {Tell their struggle} → {Reveal their solution}",Connection→Empathy→Hope,Case study slides,CopyHackers -7,Feature-Advantage-Benefit,"fab, feature, advantage, benefit",Feature→Advantage→Benefit,Feature explanations product slides,"{Feature name}: {What it does} → {Why that matters} → {How it helps you}",Curiosity→Understanding→Desire,Feature slides,Sales training classic -8,What If,"what if, imagination, possibility, hook",What if + Possibility,Opening hooks vision slides,"What if you could {desirable outcome} without {common obstacle}?",Wonder→Possibility,Title problem slides,Headline formula -9,How To,"how to, tutorial, guide, instruction",How to + Specific outcome,Educational actionable content,"How to {achieve specific result} in {timeframe or steps}",Curiosity→Empowerment,Educational slides,Headline formula -10,Number List,"number, list, reasons, ways, tips",Number + Topic + Promise,Scannable benefit lists,"{Number} {Ways/Reasons/Tips} to {achieve outcome}",Curiosity→Completeness,Feature summary slides,Content marketing -11,Question Hook,"question, hook, curiosity, engagement",Question that implies answer,Opening engagement slides,"{Question that reader answers yes to}? Here's how.",Recognition→Curiosity,Opening slides,Rhetorical technique -12,Proof Stack,"proof, evidence, credibility, stats",Stat→Source→Implication,Building credibility trust,"{Impressive stat} (Source: {credible source}). This means {implication for audience}.",Trust→Validation,Traction proof slides,Social proof theory -13,Future Pacing,"future, vision, imagine, picture this",Imagine + Future state,Vision and aspiration slides,"Imagine: {desirable future scenario}. That's what {solution} delivers.",Aspiration→Desire,Solution CTA slides,NLP technique -14,Social Proof,"social proof, testimonial, customers, trust",Who + Result + Quote,Credibility through others,"{Customer name} increased {metric} by {amount}. '{Quote about experience}'",Trust→FOMO,Testimonial slides,Robert Cialdini -15,Scarcity Urgency,"scarcity, urgency, limited, deadline, fomo",Limited + Deadline + Consequence,Driving action urgency,"Only {quantity} available. Offer ends {date}. {Consequence of missing out}.",Fear of loss→Action,CTA closing slides,Cialdini influence -16,Cost of Inaction,"cost, inaction, consequence, loss",Current cost + Future cost + Comparison,Motivating change,"Every {timeframe} without {solution} costs you {quantified loss}. That's {larger number} per year.",Loss aversion→Urgency,Problem agitation slides,Loss aversion psychology -17,Simple Benefit,"benefit, value, outcome, result",You get + Specific benefit,Clear value communication,"{Solution}: You get {specific tangible benefit}.",Clarity→Desire,Any slide,Direct response -18,Objection Preempt,"objection, concern, but, however, faq",Objection + Response + Proof,"Handling concerns proactively","You might think {objection}. Actually, {counter with proof}.",Doubt→Resolution,FAQ objection slides,Sales training -19,Comparison Frame,"comparison, versus, than, better, alternative",Us vs Them + Specific difference,Competitive positioning,"{Competitor approach}: {limitation}. {Our approach}: {advantage}.",Evaluation→Preference,Comparison slides,Positioning strategy -20,Pain-Claim-Gain,"pcg, pain, claim, gain",Pain point→Bold claim→Specific gain,Concise value proposition,"{Pain point}? {Bold claim about solution}. Result: {specific gain}.",Frustration→Hope→Excitement,Problem/solution slides,Copywriting framework -21,One Thing,"one thing, single, focus, key",The one thing + Why it matters,Focus and clarity,"The #1 thing {audience} needs to {outcome} is {one thing}.",Focus→Clarity,Key message slides,Gary Keller concept -22,Riddle Open,"riddle, mystery, puzzle, question",Mystery + Reveal + Implication,Engagement through curiosity,"{Intriguing mystery or paradox}. The answer: {reveal}. For you: {implication}.",Mystery→Insight,Opening slides,Storytelling technique -23,Hero Journey,"hero, journey, transformation, story",Ordinary→Call→Challenge→Triumph,Narrative structure,"{Character in ordinary world} → {Discovers challenge} → {Overcomes with solution} → {Achieves transformation}",Identification→Tension→Triumph,Full deck structure,Joseph Campbell -24,Value Stack,"value, stack, bundle, worth",Component + Value → Total value,Justifying price/investment,"{Item 1} (Worth ${X}) + {Item 2} (Worth ${Y}) + ... = Total value ${Z}. Your investment: ${actual price}.",Value perception,Pricing offer slides,Info product marketing -25,Power Statement,"power, statement, bold, declaration",Bold declaration + Supporting fact,Authority and confidence,"{Bold declaration}. {Supporting evidence or fact}.",Confidence→Trust,Key message slides,Thought leadership diff --git a/.agents/skills/ckm-design-system/data/slide-layout-logic.csv b/.agents/skills/ckm-design-system/data/slide-layout-logic.csv deleted file mode 100644 index a673bec..0000000 --- a/.agents/skills/ckm-design-system/data/slide-layout-logic.csv +++ /dev/null @@ -1,16 +0,0 @@ -goal,emotion,layout_pattern,direction,visual_weight,break_pattern,use_bg_image -hook,curiosity,split-hero,visual-right,70-visual,false,true -problem,frustration,card-grid,centered,balanced,false,false -agitation,fear,full-bleed-stat,centered,100-text,true,false -solution,relief,split-feature,visual-left,50-50,false,true -proof,trust,metric-grid,centered,numbers-dominant,false,false -social,connection,quote-hero,centered,80-text,true,true -comparison,evaluation,split-compare,side-by-side,balanced,false,false -traction,confidence,chart-insight,chart-left,60-chart,false,false -cta,urgency,gradient-cta,centered,100-text,true,true -team,warmth,team-grid,centered,balanced,false,true -pricing,evaluation,pricing-cards,centered,balanced,false,false -demo,interest,split-demo,visual-left,60-visual,false,false -vision,hope,full-bleed-hero,centered,100-visual,true,true -timeline,narrative,timeline-flow,horizontal,balanced,false,false -features,clarity,feature-grid,centered,balanced,false,false diff --git a/.agents/skills/ckm-design-system/data/slide-layouts.csv b/.agents/skills/ckm-design-system/data/slide-layouts.csv deleted file mode 100644 index 708be11..0000000 --- a/.agents/skills/ckm-design-system/data/slide-layouts.csv +++ /dev/null @@ -1,26 +0,0 @@ -id,layout_name,keywords,use_case,content_zones,visual_weight,cta_placement,recommended_for,avoid_for,css_structure,card_variant,metric_style,quote_style,grid_columns,visual_treatment,animation_class -1,Title Slide,"title, cover, opening, intro, hero",Opening slide first impression,"Center: Logo + Title + Tagline, Bottom: Date/Presenter",Visual-heavy minimal text,None or subtle,All presentations,Never skip,"display:flex; flex-direction:column; justify-content:center; align-items:center; text-align:center",none,none,none,1,gradient-glow,animate-fade-up -2,Problem Statement,"problem, pain, challenge, issue",Establish the problem being solved,"Left: Problem headline, Right: Pain point bullets or icon grid",50/50 text visual balance,None,Pitch decks sales,Internal updates,"display:grid; grid-template-columns:1fr 1fr; gap:48px; align-items:center",icon-left,none,none,2,subtle-border,animate-stagger -3,Solution Overview,"solution, answer, approach, how",Introduce your solution,"Top: Solution headline, Center: Solution visual/diagram, Bottom: 3 key points",Visual-dominant,Subtle learn more,After problem slide,Without context,"display:flex; flex-direction:column; gap:32px",accent-bar,none,none,3,icon-top,animate-scale -4,Feature Grid,"features, grid, cards, capabilities, 3-column",Showcase multiple features,"Top: Section title, Grid: 3-6 feature cards with icon+title+description",Balanced grid,Bottom CTA optional,Product demos SaaS,Storytelling slides,"display:grid; grid-template-columns:repeat(3,1fr); gap:24px",accent-bar,none,none,3,icon-top,animate-stagger -5,Metrics Dashboard,"metrics, kpis, numbers, stats, data",Display key performance data,"Top: Context headline, Center: 3-4 large metric cards, Bottom: Trend context",Numbers-dominant,None,Traction slides QBRs,Early-stage no data,"display:grid; grid-template-columns:repeat(4,1fr); gap:16px",metric-card,gradient-number,none,4,none,animate-stagger-scale -6,Comparison Table,"comparison, vs, versus, table, matrix",Compare options or competitors,"Top: Comparison title, Center: Feature comparison table, Bottom: Conclusion",Table-heavy,Highlight winner row,Competitive analysis,Storytelling,"display:flex; flex-direction:column; table width:100%",comparison,none,none,2,highlight-winner,animate-fade-up -7,Timeline Flow,"timeline, roadmap, journey, steps, process",Show progression over time,"Top: Timeline title, Center: Horizontal timeline with milestones, Bottom: Current status",Visual timeline,End milestone CTA,Roadmaps history,Dense data,"display:flex; flex-direction:column; timeline:flex with arrows",none,none,none,1,timeline-dots,animate-stagger -8,Team Grid,"team, people, founders, leadership",Introduce team members,"Top: Team title, Grid: Photo + Name + Title + Brief bio cards",Photo-heavy,None or careers link,Investor decks about,Technical content,"display:grid; grid-template-columns:repeat(4,1fr); gap:24px",avatar-card,none,none,4,avatar-ring,animate-stagger -9,Quote Testimonial,"quote, testimonial, social proof, customer",Feature customer endorsement,"Center: Large quote text, Bottom: Photo + Name + Title + Company logo",Quote-dominant minimal UI,None,Sales case studies,Without real quotes,"display:flex; flex-direction:column; justify-content:center; font-size:large; font-style:italic",none,none,large-italic,1,author-avatar,animate-fade-up -10,Two Column Split,"split, two-column, side-by-side, comparison",Present two related concepts,"Left column: Content A, Right column: Content B",50/50 balanced,Either column bottom,Comparisons before/after,Single concept,display:grid; grid-template-columns:1fr 1fr; gap:48px,none,none,none,2,offset-image,animate-fade-up -11,Big Number Hero,"big number, stat, impact, headline metric",Emphasize one powerful metric,"Center: Massive number, Below: Context label and trend",Number-dominant,None,Impact slides traction,Multiple metrics,"display:flex; flex-direction:column; justify-content:center; align-items:center; font-size:120px",none,oversized,none,1,centered,animate-count -12,Product Screenshot,"screenshot, product, demo, ui, interface",Show product in action,"Top: Feature headline, Center: Product screenshot with annotations, Bottom: Key callouts",Screenshot-dominant,Try it CTA,Product demos,Abstract concepts,"display:flex; flex-direction:column; img max-height:60vh",none,none,none,1,screenshot-shadow,animate-scale -13,Pricing Cards,"pricing, plans, tiers, packages",Present pricing options,"Top: Pricing headline, Center: 2-4 pricing cards side by side, Bottom: FAQ or guarantee",Cards balanced,Each card has CTA,Sales pricing pages,Free products,"display:grid; grid-template-columns:repeat(3,1fr); gap:24px; .popular:scale(1.05)",pricing-card,none,none,3,popular-highlight,animate-stagger -14,CTA Closing,"cta, closing, call to action, next steps, final",Drive action end presentation,"Center: Bold headline + Value reminder, Center: Primary CTA button, Below: Secondary option",CTA-dominant,Primary center,All presentations,Middle slides,"display:flex; flex-direction:column; justify-content:center; align-items:center; text-align:center",none,none,none,1,gradient-bg,animate-pulse -15,Agenda Overview,"agenda, outline, contents, structure",Preview presentation structure,"Top: Agenda title, Center: Numbered list or visual timeline of sections",Text-light scannable,None,Long presentations,Short 3-5 slides,"display:flex; flex-direction:column; ol list-style-type:decimal",none,none,none,1,numbered-list,animate-stagger -16,Before After,"before, after, transformation, results, comparison",Show transformation impact,"Left: Before state (muted), Right: After state (vibrant), Center: Arrow or transition",50/50 high contrast,After column CTA,Case studies results,No transformation data,"display:grid; grid-template-columns:1fr 1fr; .before:opacity(0.7)",comparison,none,none,2,contrast-pair,animate-scale -17,Icon Grid Stats,"icons, stats, grid, key points, summary",Summarize key points visually,"Grid: 4-6 icon + stat + label combinations",Icons-dominant,None,Summary slides,Detailed explanations,"display:grid; grid-template-columns:repeat(3,1fr); gap:32px; text-align:center",icon-stat,sparkline,none,3,icon-top,animate-stagger -18,Full Bleed Image,"image, photo, visual, background, hero",Create visual impact,"Full background image, Overlay: Text with contrast, Corner: Logo",Image-dominant,Overlay CTA optional,Emotional moments,Data-heavy,background-size:cover; color:white; text-shadow for contrast,none,none,none,1,bg-overlay,animate-ken-burns -19,Video Embed,"video, demo, embed, multimedia",Show video content,"Top: Context headline, Center: Video player (16:9), Bottom: Key points if needed",Video-dominant,After video CTA,Demos testimonials,Reading-focused,"aspect-ratio:16/9; video controls",none,none,none,1,video-frame,animate-scale -20,Funnel Diagram,"funnel, conversion, stages, pipeline",Show conversion or process flow,"Top: Funnel title, Center: Funnel visualization with stage labels and metrics",Diagram-dominant,None,Sales marketing funnels,Non-sequential data,SVG or CSS trapezoid shapes,none,funnel-numbers,none,1,funnel-gradient,animate-chart -21,Quote Plus Stats,"quote, stats, hybrid, testimonial, metrics",Combine social proof with data,"Left: Customer quote with photo, Right: 3 supporting metrics",Balanced quote/data,None,Sales enablement,Without both elements,"display:grid; grid-template-columns:1.5fr 1fr; gap:48px",metric-card,gradient-number,side-quote,2,author-avatar,animate-stagger -22,Section Divider,"section, divider, break, transition",Transition between sections,"Center: Section number + Section title, Minimal design",Typography-only,None,Long presentations,Every slide,"display:flex; justify-content:center; align-items:center; font-size:48px",none,none,none,1,section-number,animate-fade-up -23,Logo Grid,"logos, clients, partners, trust, social proof",Display client or partner logos,"Top: Trust headline, Grid: 8-16 logos evenly spaced",Logos-only,None,Credibility slides,Few logos <6,"display:grid; grid-template-columns:repeat(4,1fr); gap:32px; filter:grayscale(1)",none,none,none,4,logo-grayscale,animate-stagger -24,Chart Focus,"chart, graph, data, visualization, analytics",Present data visualization,"Top: Chart title and context, Center: Single large chart, Bottom: Key insight",Chart-dominant,None,Data-driven slides,Poor data quality,"chart max-height:65vh; annotation for key point",none,sparkline,none,1,chart-left,animate-chart -25,Q&A Slide,"qa, questions, discussion, interactive",Invite audience questions,"Center: Q&A or Questions? text, Below: Contact info or submission method",Minimal text,None,End of presentations,Skip if no time,"display:flex; justify-content:center; align-items:center; font-size:64px",none,none,none,1,centered,animate-fade-up diff --git a/.agents/skills/ckm-design-system/data/slide-strategies.csv b/.agents/skills/ckm-design-system/data/slide-strategies.csv deleted file mode 100644 index 1aa2760..0000000 --- a/.agents/skills/ckm-design-system/data/slide-strategies.csv +++ /dev/null @@ -1,16 +0,0 @@ -id,strategy_name,keywords,slide_count,structure,goal,audience,tone,narrative_arc,key_metrics,sources,emotion_arc,sparkline_beats -1,YC Seed Deck,"yc, seed, startup, investor, funding, vc, venture","10-12","1.Title 2.Problem 3.Solution 4.Traction 5.Market 6.Product 7.Business Model 8.Team 9.Financials 10.Ask",Raise seed funding from VCs,Seed investors hunting asymmetric upside,Clear concise focused narrative,Problem→Solution→Evidence→Ask,MRR ARR growth rate user count,Y Combinator Library,"curiosity→frustration→hope→confidence→trust→urgency","hook|what-is|what-could-be|proof|proof|what-could-be|proof|trust|what-could-be|action" -2,Guy Kawasaki 10/20/30,"kawasaki, pitch, investor, 10 slides, venture","10","1.Title 2.Problem/Opportunity 3.Value Proposition 4.Underlying Magic 5.Business Model 6.Go-to-Market 7.Competition 8.Team 9.Projections 10.Status/Timeline/Ask",Pitch to investors in 20 min,VCs angel investors,Confident not arrogant,Hook→Magic→Proof→Ask,5yr projections milestones,Guy Kawasaki Blog,"curiosity→frustration→hope→confidence→trust→urgency","hook|what-is|what-could-be|what-could-be|proof|proof|evaluation|trust|proof|action" -3,Series A Deck,"series a, growth, scale, investor, traction","12-15","1.Title 2.Mission 3.Problem 4.Solution 5.Traction/Metrics 6.Product Demo 7.Market Size 8.Business Model 9.Competition 10.Team 11.Go-to-Market 12.Financials 13.Use of Funds 14.Ask",Raise Series A funding,Growth-stage VCs,Data-driven confident,Traction→Scale→Vision,Revenue growth LTV CAC cohorts,YC Library,"curiosity→hope→frustration→relief→confidence→trust→urgency","hook|what-could-be|what-is|what-could-be|proof|proof|proof|proof|evaluation|trust|proof|proof|what-could-be|action" -4,Product Demo,"demo, product, walkthrough, features, saas","5-8","1.Hook/Problem 2.Solution Overview 3.Live Demo/Screenshots 4.Key Features 5.Benefits 6.Pricing 7.CTA",Demonstrate product value,Prospects users,Enthusiastic helpful,Problem→See it work→Value,Conversion engagement time-saved,Product-led growth best practices,"curiosity→frustration→hope→confidence→urgency","hook|what-is|what-could-be|what-could-be|what-could-be|evaluation|action" -5,Sales Pitch,"sales, pitch, prospect, close, deal","7-10","1.Personalized Hook 2.Their Problem 3.Cost of Inaction 4.Your Solution 5.Proof/Case Studies 6.Differentiators 7.Pricing/ROI 8.Objection Handling 9.CTA 10.Next Steps",Close deal win customer,Qualified prospects,Consultative trustworthy,Pain→Agitate→Solve→Prove,ROI case study metrics,Sandler Sales Training,"connection→frustration→fear→hope→trust→confidence→urgency","hook|what-is|what-is|what-could-be|proof|what-could-be|evaluation|trust|action|action" -6,Nancy Duarte Sparkline,"duarte, sparkline, story, transformation, resonate","Varies","Alternate: What Is→What Could Be→What Is→What Could Be→New Bliss",Transform audience perspective,Any audience needing persuasion,Inspiring visionary,Tension→Release→Tension→Release→Resolution,Audience transformation,Nancy Duarte Resonate,"frustration→hope→frustration→hope→relief","what-is|what-could-be|what-is|what-could-be|new-bliss" -7,Problem-Solution-Benefit,"psb, simple, clear, benefit, value","3-5","1.Problem Statement 2.Solution Introduction 3.Key Benefits 4.Proof 5.CTA",Quick persuasion simple message,Time-pressed audience,Direct clear,Problem→Solution→Outcome,Core value metrics,Marketing fundamentals,"frustration→hope→confidence→urgency","what-is|what-could-be|what-could-be|proof|action" -8,Quarterly Business Review,"qbr, business review, internal, stakeholder","10-15","1.Executive Summary 2.Goals vs Results 3.Key Metrics 4.Wins 5.Challenges 6.Learnings 7.Customer Insights 8.Competitive Update 9.Next Quarter Goals 10.Resource Needs",Update stakeholders on progress,Internal leadership,Professional factual,Review→Analyze→Plan,KPIs OKRs progress %,Internal communications,"clarity→trust→confidence→evaluation→hope","summary|proof|proof|celebration|what-is|insight|trust|evaluation|what-could-be|action" -9,Team All-Hands,"all-hands, company, internal, culture, update","8-12","1.Opening/Energy 2.Company Wins 3.Metrics Dashboard 4.Team Spotlights 5.Product Updates 6.Customer Stories 7.Challenges/Learnings 8.Roadmap Preview 9.Q&A 10.Closing Motivation",Align and motivate team,All employees,Transparent inspiring,Celebrate→Update→Align→Energize,Company-wide KPIs,Internal communications,"warmth→confidence→trust→connection→hope→urgency","hook|celebration|proof|connection|what-could-be|trust|what-is|what-could-be|interaction|action" -10,Conference Talk,"conference, talk, keynote, public speaking, thought leadership","15-25","1.Hook/Story 2.Credibility 3.Big Idea 4.Point 1 + Evidence 5.Point 2 + Evidence 6.Point 3 + Evidence 7.Synthesis 8.Call to Action 9.Q&A Prep",Establish thought leadership,Conference attendees,Expert engaging,Story→Teach→Inspire,Audience engagement social shares,TED Talk guidelines,"curiosity→trust→hope→confidence→confidence→confidence→clarity→urgency","hook|trust|what-could-be|proof|proof|proof|synthesis|action|interaction" -11,Workshop Training,"workshop, training, education, how-to, tutorial","20-40","1.Welcome/Objectives 2.Agenda 3.Concept 1 4.Exercise 1 5.Concept 2 6.Exercise 2 7.Concept 3 8.Exercise 3 9.Synthesis 10.Resources 11.Q&A",Teach practical skills,Learners trainees,Patient instructive,Learn→Practice→Apply→Reflect,Skill acquisition completion,Adult learning principles,"warmth→clarity→confidence→confidence→confidence→confidence→clarity→hope","welcome|structure|teaching|practice|teaching|practice|teaching|practice|synthesis|resources|interaction" -12,Case Study Presentation,"case study, success story, customer, results","8-12","1.Customer Introduction 2.Their Challenge 3.Why They Chose Us 4.Implementation 5.Solution Details 6.Results/Metrics 7.Customer Quote 8.Lessons Learned 9.Applicability 10.CTA",Prove value through example,Prospects similar to case,Authentic factual,Challenge→Journey→Transformation,Before/after metrics ROI,Marketing case study best practices,"connection→frustration→trust→hope→confidence→celebration→trust→clarity→urgency","connection|what-is|trust|what-could-be|what-could-be|proof|trust|insight|what-could-be|action" -13,Competitive Analysis,"competitive, analysis, comparison, market","6-10","1.Market Landscape 2.Competitor Overview 3.Feature Comparison Matrix 4.Pricing Comparison 5.Strengths/Weaknesses 6.Our Differentiation 7.Market Positioning 8.Strategic Recommendations",Inform strategic decisions,Internal leadership,Analytical objective,Landscape→Analysis→Strategy,Market share feature gaps,Competitive intelligence,"clarity→evaluation→evaluation→evaluation→clarity→hope→confidence→urgency","overview|evaluation|comparison|comparison|analysis|what-could-be|proof|action" -14,Board Meeting Deck,"board, governance, investor update, quarterly","15-20","1.Agenda 2.Executive Summary 3.Financial Overview 4.Key Metrics 5.Product Update 6.Sales/Marketing 7.Operations 8.Team/Hiring 9.Risks/Challenges 10.Strategic Initiatives 11.Upcoming Milestones 12.Ask/Discussion",Update board on company status,Board members,Professional detailed,Report→Analyze→Discuss→Decide,All key business metrics,Board governance best practices,"clarity→confidence→trust→trust→confidence→confidence→trust→connection→evaluation→hope→confidence→urgency","structure|summary|proof|proof|proof|proof|proof|trust|what-is|what-could-be|proof|action" -15,Webinar Presentation,"webinar, online, education, lead gen","20-30","1.Welcome/Housekeeping 2.Presenter Intro 3.Agenda 4.Hook/Problem 5.Teaching Content 6.Case Study 7.Product Introduction 8.Demo 9.Offer/CTA 10.Q&A 11.Resources",Generate leads educate prospects,Webinar registrants,Educational helpful,Teach→Demonstrate→Offer,Registrations attendance conversion,Webinar marketing best practices,"warmth→trust→clarity→curiosity→confidence→trust→hope→confidence→urgency→connection→clarity","welcome|trust|structure|hook|teaching|trust|what-could-be|proof|action|interaction|resources" diff --git a/.agents/skills/ckm-design-system/data/slide-typography.csv b/.agents/skills/ckm-design-system/data/slide-typography.csv deleted file mode 100644 index 204243c..0000000 --- a/.agents/skills/ckm-design-system/data/slide-typography.csv +++ /dev/null @@ -1,15 +0,0 @@ -content_type,primary_size,secondary_size,accent_size,weight_contrast,letter_spacing,line_height -hero-statement,120px,32px,14px,700-400,tight,1.0 -metric-callout,96px,18px,12px,700-500,normal,1.1 -feature-grid,28px,16px,12px,600-400,normal,1.4 -quote-block,36px,18px,14px,400-italic,loose,1.5 -data-insight,48px,20px,14px,700-400,normal,1.2 -cta-action,64px,24px,16px,700-500,tight,1.1 -title-only,80px,24px,14px,700-400,tight,1.0 -subtitle-heavy,56px,28px,16px,600-400,normal,1.2 -body-focus,24px,18px,14px,500-400,normal,1.6 -comparison,32px,16px,12px,600-400,normal,1.3 -timeline,28px,16px,12px,500-400,normal,1.4 -pricing,48px,20px,14px,700-500,normal,1.2 -team,24px,16px,14px,600-400,normal,1.4 -testimonial,32px,20px,14px,400-italic,loose,1.5 diff --git a/.agents/skills/ckm-design-system/references/component-specs.md b/.agents/skills/ckm-design-system/references/component-specs.md deleted file mode 100644 index cc7821b..0000000 --- a/.agents/skills/ckm-design-system/references/component-specs.md +++ /dev/null @@ -1,236 +0,0 @@ -# Component Specifications - -Detailed specs for core components with states and variants. - -## Button - -### Variants - -| Variant | Background | Text | Border | Use Case | -|---------|------------|------|--------|----------| -| default | primary | white | none | Primary actions | -| secondary | gray-100 | gray-900 | none | Secondary actions | -| outline | transparent | foreground | border | Tertiary actions | -| ghost | transparent | foreground | none | Subtle actions | -| link | transparent | primary | none | Navigation | -| destructive | red-600 | white | none | Dangerous actions | - -### Sizes - -| Size | Height | Padding X | Padding Y | Font Size | Icon Size | -|------|--------|-----------|-----------|-----------|-----------| -| sm | 32px | 12px | 6px | 14px | 16px | -| default | 40px | 16px | 8px | 14px | 18px | -| lg | 48px | 24px | 12px | 16px | 20px | -| icon | 40px | 0 | 0 | - | 18px | - -### States - -| State | Background | Text | Opacity | Cursor | -|-------|------------|------|---------|--------| -| default | token | token | 1 | pointer | -| hover | darker | token | 1 | pointer | -| active | darkest | token | 1 | pointer | -| focus | token | token | 1 | pointer | -| disabled | muted | muted-fg | 0.5 | not-allowed | -| loading | token | token | 0.7 | wait | - -### Anatomy - -``` -┌─────────────────────────────────────┐ -│ [icon] Label Text [icon] │ -└─────────────────────────────────────┘ - ↑ ↑ - leading icon trailing icon -``` - ---- - -## Input - -### Variants - -| Variant | Description | -|---------|-------------| -| default | Standard text input | -| textarea | Multi-line text | -| select | Dropdown selection | -| checkbox | Boolean toggle | -| radio | Single selection | -| switch | Toggle switch | - -### Sizes - -| Size | Height | Padding | Font Size | -|------|--------|---------|-----------| -| sm | 32px | 8px 12px | 14px | -| default | 40px | 8px 12px | 14px | -| lg | 48px | 12px 16px | 16px | - -### States - -| State | Border | Background | Ring | -|-------|--------|------------|------| -| default | gray-300 | white | none | -| hover | gray-400 | white | none | -| focus | primary | white | primary/20% | -| error | red-500 | white | red/20% | -| disabled | gray-200 | gray-100 | none | - -### Anatomy - -``` -Label (optional) -┌─────────────────────────────────────┐ -│ [icon] Placeholder/Value [action] │ -└─────────────────────────────────────┘ -Helper text or error message -``` - ---- - -## Card - -### Variants - -| Variant | Shadow | Border | Use Case | -|---------|--------|--------|----------| -| default | sm | 1px | Standard card | -| elevated | lg | none | Prominent content | -| outline | none | 1px | Subtle container | -| interactive | sm→md | 1px | Clickable card | - -### Anatomy - -``` -┌─────────────────────────────────────┐ -│ Card Header │ -│ Title │ -│ Description │ -├─────────────────────────────────────┤ -│ Card Content │ -│ Main content area │ -│ │ -├─────────────────────────────────────┤ -│ Card Footer │ -│ Actions │ -└─────────────────────────────────────┘ -``` - -### Spacing - -| Area | Padding | -|------|---------| -| header | 24px 24px 0 | -| content | 24px | -| footer | 0 24px 24px | -| gap | 16px | - ---- - -## Badge - -### Variants - -| Variant | Background | Text | -|---------|------------|------| -| default | primary | white | -| secondary | gray-100 | gray-900 | -| outline | transparent | foreground | -| destructive | red-600 | white | -| success | green-600 | white | -| warning | yellow-500 | gray-900 | - -### Sizes - -| Size | Padding | Font Size | Height | -|------|---------|-----------|--------| -| sm | 4px 8px | 11px | 20px | -| default | 4px 10px | 12px | 24px | -| lg | 6px 12px | 14px | 28px | - ---- - -## Alert - -### Variants - -| Variant | Icon | Background | Border | -|---------|------|------------|--------| -| default | info | gray-50 | gray-200 | -| destructive | alert | red-50 | red-200 | -| success | check | green-50 | green-200 | -| warning | warning | yellow-50 | yellow-200 | - -### Anatomy - -``` -┌─────────────────────────────────────┐ -│ [icon] Title [×]│ -│ Description text │ -└─────────────────────────────────────┘ -``` - ---- - -## Dialog - -### Sizes - -| Size | Max Width | Use Case | -|------|-----------|----------| -| sm | 384px | Simple confirmations | -| default | 512px | Standard dialogs | -| lg | 640px | Complex forms | -| xl | 768px | Data-heavy dialogs | -| full | 100% - 32px | Full-screen on mobile | - -### Anatomy - -``` -┌───────────────────────────────────────┐ -│ Dialog Header [×]│ -│ Title │ -│ Description │ -├───────────────────────────────────────┤ -│ Dialog Content │ -│ Scrollable if needed │ -│ │ -├───────────────────────────────────────┤ -│ Dialog Footer │ -│ [Cancel] [Confirm]│ -└───────────────────────────────────────┘ -``` - ---- - -## Table - -### Row States - -| State | Background | Use Case | -|-------|------------|----------| -| default | white | Normal row | -| hover | gray-50 | Mouse over | -| selected | primary/10% | Selected row | -| striped | gray-50/white | Alternating | - -### Cell Alignment - -| Content Type | Alignment | -|--------------|-----------| -| Text | Left | -| Numbers | Right | -| Status/Badge | Center | -| Actions | Right | - -### Spacing - -| Element | Value | -|---------|-------| -| cell padding | 12px 16px | -| header padding | 12px 16px | -| row height (compact) | 40px | -| row height (default) | 48px | -| row height (comfortable) | 56px | diff --git a/.agents/skills/ckm-design-system/references/component-tokens.md b/.agents/skills/ckm-design-system/references/component-tokens.md deleted file mode 100644 index 912ab9d..0000000 --- a/.agents/skills/ckm-design-system/references/component-tokens.md +++ /dev/null @@ -1,214 +0,0 @@ -# Component Tokens - -Component-specific tokens referencing semantic layer. - -## Button Tokens - -```css -:root { - /* Default (Primary) */ - --button-bg: var(--color-primary); - --button-fg: var(--color-primary-foreground); - --button-hover-bg: var(--color-primary-hover); - --button-active-bg: var(--color-primary-active); - - /* Secondary */ - --button-secondary-bg: var(--color-secondary); - --button-secondary-fg: var(--color-secondary-foreground); - --button-secondary-hover-bg: var(--color-secondary-hover); - - /* Outline */ - --button-outline-border: var(--color-border); - --button-outline-fg: var(--color-foreground); - --button-outline-hover-bg: var(--color-accent); - - /* Ghost */ - --button-ghost-fg: var(--color-foreground); - --button-ghost-hover-bg: var(--color-accent); - - /* Destructive */ - --button-destructive-bg: var(--color-destructive); - --button-destructive-fg: var(--color-destructive-foreground); - --button-destructive-hover-bg: var(--color-destructive-hover); - - /* Sizing */ - --button-padding-x: var(--space-4); - --button-padding-y: var(--space-2); - --button-padding-x-sm: var(--space-3); - --button-padding-y-sm: var(--space-1-5); - --button-padding-x-lg: var(--space-6); - --button-padding-y-lg: var(--space-3); - - /* Shape */ - --button-radius: var(--radius-md); - --button-font-size: var(--font-size-sm); - --button-font-weight: var(--font-weight-medium); -} -``` - -## Input Tokens - -```css -:root { - /* Background & Border */ - --input-bg: var(--color-background); - --input-border: var(--color-input); - --input-fg: var(--color-foreground); - - /* Placeholder */ - --input-placeholder: var(--color-muted-foreground); - - /* Focus */ - --input-focus-border: var(--color-ring); - --input-focus-ring: var(--color-ring); - - /* Error */ - --input-error-border: var(--color-error); - --input-error-fg: var(--color-error); - - /* Disabled */ - --input-disabled-bg: var(--color-muted); - --input-disabled-fg: var(--color-muted-foreground); - - /* Sizing */ - --input-padding-x: var(--space-3); - --input-padding-y: var(--space-2); - --input-radius: var(--radius-md); - --input-font-size: var(--font-size-sm); -} -``` - -## Card Tokens - -```css -:root { - /* Background & Border */ - --card-bg: var(--color-card); - --card-fg: var(--color-card-foreground); - --card-border: var(--color-border); - - /* Shadow */ - --card-shadow: var(--shadow-default); - --card-shadow-hover: var(--shadow-md); - - /* Spacing */ - --card-padding: var(--space-6); - --card-padding-sm: var(--space-4); - --card-gap: var(--space-4); - - /* Shape */ - --card-radius: var(--radius-lg); -} -``` - -## Badge Tokens - -```css -:root { - /* Default */ - --badge-bg: var(--color-primary); - --badge-fg: var(--color-primary-foreground); - - /* Secondary */ - --badge-secondary-bg: var(--color-secondary); - --badge-secondary-fg: var(--color-secondary-foreground); - - /* Outline */ - --badge-outline-border: var(--color-border); - --badge-outline-fg: var(--color-foreground); - - /* Destructive */ - --badge-destructive-bg: var(--color-destructive); - --badge-destructive-fg: var(--color-destructive-foreground); - - /* Sizing */ - --badge-padding-x: var(--space-2-5); - --badge-padding-y: var(--space-0-5); - --badge-radius: var(--radius-full); - --badge-font-size: var(--font-size-xs); -} -``` - -## Alert Tokens - -```css -:root { - /* Default */ - --alert-bg: var(--color-background); - --alert-fg: var(--color-foreground); - --alert-border: var(--color-border); - - /* Destructive */ - --alert-destructive-bg: var(--color-destructive); - --alert-destructive-fg: var(--color-destructive-foreground); - - /* Spacing */ - --alert-padding: var(--space-4); - --alert-radius: var(--radius-lg); -} -``` - -## Dialog/Modal Tokens - -```css -:root { - /* Overlay */ - --dialog-overlay-bg: rgb(0 0 0 / 0.5); - - /* Content */ - --dialog-bg: var(--color-background); - --dialog-fg: var(--color-foreground); - --dialog-border: var(--color-border); - --dialog-shadow: var(--shadow-lg); - - /* Spacing */ - --dialog-padding: var(--space-6); - --dialog-radius: var(--radius-lg); - --dialog-max-width: 32rem; -} -``` - -## Table Tokens - -```css -:root { - /* Header */ - --table-header-bg: var(--color-muted); - --table-header-fg: var(--color-muted-foreground); - - /* Body */ - --table-row-bg: var(--color-background); - --table-row-hover-bg: var(--color-muted); - --table-row-fg: var(--color-foreground); - - /* Border */ - --table-border: var(--color-border); - - /* Spacing */ - --table-cell-padding-x: var(--space-4); - --table-cell-padding-y: var(--space-3); -} -``` - -## Usage Example - -```css -.button { - background: var(--button-bg); - color: var(--button-fg); - padding: var(--button-padding-y) var(--button-padding-x); - border-radius: var(--button-radius); - font-size: var(--button-font-size); - font-weight: var(--button-font-weight); - transition: background var(--duration-fast); -} - -.button:hover { - background: var(--button-hover-bg); -} - -.button.secondary { - background: var(--button-secondary-bg); - color: var(--button-secondary-fg); -} -``` diff --git a/.agents/skills/ckm-design-system/references/primitive-tokens.md b/.agents/skills/ckm-design-system/references/primitive-tokens.md deleted file mode 100644 index eb251a2..0000000 --- a/.agents/skills/ckm-design-system/references/primitive-tokens.md +++ /dev/null @@ -1,203 +0,0 @@ -# Primitive Tokens - -Raw design values - foundation of the design system. - -## Color Scales - -### Gray Scale - -```css -:root { - --color-gray-50: #F9FAFB; - --color-gray-100: #F3F4F6; - --color-gray-200: #E5E7EB; - --color-gray-300: #D1D5DB; - --color-gray-400: #9CA3AF; - --color-gray-500: #6B7280; - --color-gray-600: #4B5563; - --color-gray-700: #374151; - --color-gray-800: #1F2937; - --color-gray-900: #111827; - --color-gray-950: #030712; -} -``` - -### Primary Colors (Blue) - -```css -:root { - --color-blue-50: #EFF6FF; - --color-blue-100: #DBEAFE; - --color-blue-200: #BFDBFE; - --color-blue-300: #93C5FD; - --color-blue-400: #60A5FA; - --color-blue-500: #3B82F6; - --color-blue-600: #2563EB; - --color-blue-700: #1D4ED8; - --color-blue-800: #1E40AF; - --color-blue-900: #1E3A8A; -} -``` - -### Status Colors - -```css -:root { - /* Success - Green */ - --color-green-500: #22C55E; - --color-green-600: #16A34A; - - /* Warning - Yellow */ - --color-yellow-500: #EAB308; - --color-yellow-600: #CA8A04; - - /* Error - Red */ - --color-red-500: #EF4444; - --color-red-600: #DC2626; - - /* Info - Blue */ - --color-info: var(--color-blue-500); -} -``` - -## Spacing Scale - -4px base unit system. - -```css -:root { - --space-0: 0; - --space-px: 1px; - --space-0-5: 0.125rem; /* 2px */ - --space-1: 0.25rem; /* 4px */ - --space-1-5: 0.375rem; /* 6px */ - --space-2: 0.5rem; /* 8px */ - --space-2-5: 0.625rem; /* 10px */ - --space-3: 0.75rem; /* 12px */ - --space-3-5: 0.875rem; /* 14px */ - --space-4: 1rem; /* 16px */ - --space-5: 1.25rem; /* 20px */ - --space-6: 1.5rem; /* 24px */ - --space-7: 1.75rem; /* 28px */ - --space-8: 2rem; /* 32px */ - --space-9: 2.25rem; /* 36px */ - --space-10: 2.5rem; /* 40px */ - --space-12: 3rem; /* 48px */ - --space-14: 3.5rem; /* 56px */ - --space-16: 4rem; /* 64px */ - --space-20: 5rem; /* 80px */ - --space-24: 6rem; /* 96px */ -} -``` - -## Typography Scale - -```css -:root { - /* Font Sizes */ - --font-size-xs: 0.75rem; /* 12px */ - --font-size-sm: 0.875rem; /* 14px */ - --font-size-base: 1rem; /* 16px */ - --font-size-lg: 1.125rem; /* 18px */ - --font-size-xl: 1.25rem; /* 20px */ - --font-size-2xl: 1.5rem; /* 24px */ - --font-size-3xl: 1.875rem; /* 30px */ - --font-size-4xl: 2.25rem; /* 36px */ - --font-size-5xl: 3rem; /* 48px */ - - /* Line Heights */ - --leading-none: 1; - --leading-tight: 1.25; - --leading-snug: 1.375; - --leading-normal: 1.5; - --leading-relaxed: 1.625; - --leading-loose: 2; - - /* Font Weights */ - --font-weight-normal: 400; - --font-weight-medium: 500; - --font-weight-semibold: 600; - --font-weight-bold: 700; - - /* Letter Spacing */ - --tracking-tighter: -0.05em; - --tracking-tight: -0.025em; - --tracking-normal: 0; - --tracking-wide: 0.025em; - --tracking-wider: 0.05em; -} -``` - -## Border Radius - -```css -:root { - --radius-none: 0; - --radius-sm: 0.125rem; /* 2px */ - --radius-default: 0.25rem; /* 4px */ - --radius-md: 0.375rem; /* 6px */ - --radius-lg: 0.5rem; /* 8px */ - --radius-xl: 0.75rem; /* 12px */ - --radius-2xl: 1rem; /* 16px */ - --radius-3xl: 1.5rem; /* 24px */ - --radius-full: 9999px; -} -``` - -## Shadows - -```css -:root { - --shadow-none: none; - --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --shadow-default: 0 1px 3px 0 rgb(0 0 0 / 0.1), - 0 1px 2px -1px rgb(0 0 0 / 0.1); - --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), - 0 2px 4px -2px rgb(0 0 0 / 0.1); - --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), - 0 4px 6px -4px rgb(0 0 0 / 0.1); - --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), - 0 8px 10px -6px rgb(0 0 0 / 0.1); - --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); - --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); -} -``` - -## Motion / Duration - -```css -:root { - --duration-75: 75ms; - --duration-100: 100ms; - --duration-150: 150ms; - --duration-200: 200ms; - --duration-300: 300ms; - --duration-500: 500ms; - --duration-700: 700ms; - --duration-1000: 1000ms; - - /* Semantic durations */ - --duration-fast: var(--duration-150); - --duration-normal: var(--duration-200); - --duration-slow: var(--duration-300); -} -``` - -## Z-Index Scale - -```css -:root { - --z-auto: auto; - --z-0: 0; - --z-10: 10; - --z-20: 20; - --z-30: 30; - --z-40: 40; - --z-50: 50; - --z-dropdown: 1000; - --z-sticky: 1100; - --z-modal: 1200; - --z-popover: 1300; - --z-tooltip: 1400; -} -``` diff --git a/.agents/skills/ckm-design-system/references/semantic-tokens.md b/.agents/skills/ckm-design-system/references/semantic-tokens.md deleted file mode 100644 index b441010..0000000 --- a/.agents/skills/ckm-design-system/references/semantic-tokens.md +++ /dev/null @@ -1,215 +0,0 @@ -# Semantic Tokens - -Purpose-based aliases referencing primitive tokens. - -## Color Semantics - -### Background & Foreground - -```css -:root { - /* Page background */ - --color-background: var(--color-gray-50); - --color-foreground: var(--color-gray-900); - - /* Card/surface background */ - --color-card: white; - --color-card-foreground: var(--color-gray-900); - - /* Popover/dropdown */ - --color-popover: white; - --color-popover-foreground: var(--color-gray-900); -} -``` - -### Primary - -```css -:root { - --color-primary: var(--color-blue-600); - --color-primary-hover: var(--color-blue-700); - --color-primary-active: var(--color-blue-800); - --color-primary-foreground: white; -} -``` - -### Secondary - -```css -:root { - --color-secondary: var(--color-gray-100); - --color-secondary-hover: var(--color-gray-200); - --color-secondary-foreground: var(--color-gray-900); -} -``` - -### Muted - -```css -:root { - --color-muted: var(--color-gray-100); - --color-muted-foreground: var(--color-gray-500); -} -``` - -### Accent - -```css -:root { - --color-accent: var(--color-gray-100); - --color-accent-foreground: var(--color-gray-900); -} -``` - -### Destructive - -```css -:root { - --color-destructive: var(--color-red-600); - --color-destructive-hover: var(--color-red-700); - --color-destructive-foreground: white; -} -``` - -### Status Colors - -```css -:root { - --color-success: var(--color-green-600); - --color-success-foreground: white; - - --color-warning: var(--color-yellow-500); - --color-warning-foreground: var(--color-gray-900); - - --color-error: var(--color-red-600); - --color-error-foreground: white; - - --color-info: var(--color-blue-500); - --color-info-foreground: white; -} -``` - -### Border & Ring - -```css -:root { - --color-border: var(--color-gray-200); - --color-input: var(--color-gray-200); - --color-ring: var(--color-blue-500); -} -``` - -## Spacing Semantics - -```css -:root { - /* Component internal spacing */ - --spacing-component-xs: var(--space-1); - --spacing-component-sm: var(--space-2); - --spacing-component: var(--space-3); - --spacing-component-lg: var(--space-4); - - /* Section spacing */ - --spacing-section-sm: var(--space-8); - --spacing-section: var(--space-12); - --spacing-section-lg: var(--space-16); - - /* Page margins */ - --spacing-page-x: var(--space-4); - --spacing-page-y: var(--space-6); -} -``` - -## Typography Semantics - -```css -:root { - /* Headings */ - --font-heading: var(--font-size-2xl); - --font-heading-lg: var(--font-size-3xl); - --font-heading-xl: var(--font-size-4xl); - - /* Body */ - --font-body: var(--font-size-base); - --font-body-sm: var(--font-size-sm); - --font-body-lg: var(--font-size-lg); - - /* Labels & Captions */ - --font-label: var(--font-size-sm); - --font-caption: var(--font-size-xs); -} -``` - -## Interactive States - -```css -:root { - /* Focus ring */ - --ring-width: 2px; - --ring-offset: 2px; - --ring-color: var(--color-ring); - - /* Opacity for disabled */ - --opacity-disabled: 0.5; - - /* Transitions */ - --transition-colors: color, background-color, border-color; - --transition-transform: transform; - --transition-all: all; -} -``` - -## Dark Mode Overrides - -```css -.dark { - --color-background: var(--color-gray-950); - --color-foreground: var(--color-gray-50); - - --color-card: var(--color-gray-900); - --color-card-foreground: var(--color-gray-50); - - --color-popover: var(--color-gray-900); - --color-popover-foreground: var(--color-gray-50); - - --color-muted: var(--color-gray-800); - --color-muted-foreground: var(--color-gray-400); - - --color-secondary: var(--color-gray-800); - --color-secondary-foreground: var(--color-gray-50); - - --color-accent: var(--color-gray-800); - --color-accent-foreground: var(--color-gray-50); - - --color-border: var(--color-gray-800); - --color-input: var(--color-gray-800); -} -``` - -## Usage Patterns - -### Applying Semantic Tokens - -```css -/* Good - uses semantic tokens */ -.card { - background: var(--color-card); - color: var(--color-card-foreground); - border: 1px solid var(--color-border); -} - -/* Bad - uses primitive tokens directly */ -.card { - background: var(--color-gray-50); - color: var(--color-gray-900); -} -``` - -### Theme Switching - -Semantic tokens enable instant theme switching: - -```js -// Toggle dark mode -document.documentElement.classList.toggle('dark'); -``` diff --git a/.agents/skills/ckm-design-system/references/states-and-variants.md b/.agents/skills/ckm-design-system/references/states-and-variants.md deleted file mode 100644 index 64b808a..0000000 --- a/.agents/skills/ckm-design-system/references/states-and-variants.md +++ /dev/null @@ -1,241 +0,0 @@ -# States and Variants - -Component state definitions and variant patterns. - -## Interactive States - -### State Definitions - -| State | Trigger | Visual Change | -|-------|---------|---------------| -| default | None | Base appearance | -| hover | Mouse over | Slight color shift | -| focus | Tab/click | Focus ring | -| active | Mouse down | Darkest color | -| disabled | disabled attr | Reduced opacity | -| loading | Async action | Spinner + opacity | - -### State Priority - -When multiple states apply, priority (highest to lowest): - -1. disabled -2. loading -3. active -4. focus -5. hover -6. default - -### State Transitions - -```css -/* Standard transition for interactive elements */ -.interactive { - transition-property: color, background-color, border-color, box-shadow; - transition-duration: var(--duration-fast); - transition-timing-function: ease-in-out; -} -``` - -| Transition | Duration | Easing | -|------------|----------|--------| -| Color changes | 150ms | ease-in-out | -| Background | 150ms | ease-in-out | -| Transform | 200ms | ease-out | -| Opacity | 150ms | ease | -| Shadow | 200ms | ease-out | - -## Focus States - -### Focus Ring Spec - -```css -/* Standard focus ring */ -.focusable:focus-visible { - outline: none; - box-shadow: 0 0 0 var(--ring-offset) var(--color-background), - 0 0 0 calc(var(--ring-offset) + var(--ring-width)) var(--ring-color); -} -``` - -| Property | Value | -|----------|-------| -| Ring width | 2px | -| Ring offset | 2px | -| Ring color | primary (blue-500) | -| Offset color | background | - -### Focus Within - -```css -/* Container focus when child is focused */ -.container:focus-within { - border-color: var(--color-ring); -} -``` - -## Disabled States - -### Visual Treatment - -```css -.disabled { - opacity: var(--opacity-disabled); /* 0.5 */ - pointer-events: none; - cursor: not-allowed; -} -``` - -| Property | Disabled Value | -|----------|----------------| -| Opacity | 50% | -| Pointer events | none | -| Cursor | not-allowed | -| Background | muted | -| Color | muted-foreground | - -### Accessibility - -- Use `aria-disabled="true"` for semantic disabled -- Use `disabled` attribute for form elements -- Maintain sufficient contrast (3:1 minimum) - -## Loading States - -### Spinner Placement - -| Component | Spinner Position | -|-----------|------------------| -| Button | Replace icon or center | -| Input | Trailing position | -| Card | Center overlay | -| Page | Center of viewport | - -### Loading Treatment - -```css -.loading { - position: relative; - pointer-events: none; -} - -.loading::after { - content: ''; - /* spinner styles */ -} - -.loading > * { - opacity: 0.7; -} -``` - -## Error States - -### Visual Indicators - -```css -.error { - border-color: var(--color-error); - color: var(--color-error); -} - -.error:focus-visible { - box-shadow: 0 0 0 2px var(--color-background), - 0 0 0 4px var(--color-error); -} -``` - -| Element | Error Treatment | -|---------|-----------------| -| Input border | red-500 | -| Input focus ring | red/20% | -| Helper text | red-600 | -| Icon | red-500 | - -### Error Messages - -- Position below input -- Use error color -- Include icon for accessibility -- Clear on valid input - -## Variant Patterns - -### Color Variants - -```css -/* Pattern for color variants */ -.component { - --component-bg: var(--color-primary); - --component-fg: var(--color-primary-foreground); - background: var(--component-bg); - color: var(--component-fg); -} - -.component.secondary { - --component-bg: var(--color-secondary); - --component-fg: var(--color-secondary-foreground); -} - -.component.destructive { - --component-bg: var(--color-destructive); - --component-fg: var(--color-destructive-foreground); -} -``` - -### Size Variants - -```css -/* Pattern for size variants */ -.component { - --component-height: 40px; - --component-padding: var(--space-4); - --component-font: var(--font-size-sm); -} - -.component.sm { - --component-height: 32px; - --component-padding: var(--space-3); - --component-font: var(--font-size-xs); -} - -.component.lg { - --component-height: 48px; - --component-padding: var(--space-6); - --component-font: var(--font-size-base); -} -``` - -## Accessibility Requirements - -### Color Contrast - -| Element | Minimum Ratio | -|---------|---------------| -| Normal text | 4.5:1 | -| Large text (18px+) | 3:1 | -| UI components | 3:1 | -| Focus indicator | 3:1 | - -### State Indicators - -- Never rely on color alone -- Use icons, text, or patterns -- Ensure focus is visible -- Provide loading announcements - -### ARIA States - -```html - - - - - - - - -Error message -``` diff --git a/.agents/skills/ckm-design-system/references/tailwind-integration.md b/.agents/skills/ckm-design-system/references/tailwind-integration.md deleted file mode 100644 index c632788..0000000 --- a/.agents/skills/ckm-design-system/references/tailwind-integration.md +++ /dev/null @@ -1,251 +0,0 @@ -# Tailwind Integration - -Map design system tokens to Tailwind CSS configuration. - -## CSS Variables Setup - -### Base Layer - -```css -/* globals.css */ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - /* Primitives */ - --color-blue-600: 37 99 235; /* HSL: 217 91% 60% */ - - /* Semantic */ - --background: 0 0% 100%; - --foreground: 222 47% 11%; - --primary: 217 91% 60%; - --primary-foreground: 0 0% 100%; - --secondary: 220 14% 96%; - --secondary-foreground: 222 47% 11%; - --muted: 220 14% 96%; - --muted-foreground: 220 9% 46%; - --accent: 220 14% 96%; - --accent-foreground: 222 47% 11%; - --destructive: 0 84% 60%; - --destructive-foreground: 0 0% 100%; - --border: 220 13% 91%; - --input: 220 13% 91%; - --ring: 217 91% 60%; - --radius: 0.5rem; - } - - .dark { - --background: 222 47% 4%; - --foreground: 210 40% 98%; - --primary: 217 91% 60%; - --primary-foreground: 0 0% 100%; - --secondary: 217 33% 17%; - --secondary-foreground: 210 40% 98%; - --muted: 217 33% 17%; - --muted-foreground: 215 20% 65%; - --accent: 217 33% 17%; - --accent-foreground: 210 40% 98%; - --destructive: 0 62% 30%; - --destructive-foreground: 0 0% 100%; - --border: 217 33% 17%; - --input: 217 33% 17%; - --ring: 217 91% 60%; - } -} -``` - -## Tailwind Config - -### tailwind.config.ts - -```typescript -import type { Config } from 'tailwindcss' - -const config: Config = { - darkMode: ['class'], - content: ['./src/**/*.{ts,tsx}'], - theme: { - extend: { - colors: { - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))', - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))', - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))', - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))', - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))', - }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))', - }, - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)', - }, - }, - }, - plugins: [], -} - -export default config -``` - -## HSL Format Benefits - -Using HSL without function allows opacity modifiers: - -```tsx -// With HSL format (space-separated) -
// 50% opacity -
// 80% opacity - -// CSS output -background-color: hsl(217 91% 60% / 0.5); -``` - -## Component Classes - -### Button Example - -```css -@layer components { - .btn { - @apply inline-flex items-center justify-center - rounded-md font-medium - transition-colors - focus-visible:outline-none focus-visible:ring-2 - focus-visible:ring-ring focus-visible:ring-offset-2 - disabled:pointer-events-none disabled:opacity-50; - } - - .btn-default { - @apply bg-primary text-primary-foreground - hover:bg-primary/90; - } - - .btn-secondary { - @apply bg-secondary text-secondary-foreground - hover:bg-secondary/80; - } - - .btn-outline { - @apply border border-input bg-background - hover:bg-accent hover:text-accent-foreground; - } - - .btn-ghost { - @apply hover:bg-accent hover:text-accent-foreground; - } - - .btn-destructive { - @apply bg-destructive text-destructive-foreground - hover:bg-destructive/90; - } - - /* Sizes */ - .btn-sm { @apply h-8 px-3 text-xs; } - .btn-md { @apply h-10 px-4 text-sm; } - .btn-lg { @apply h-12 px-6 text-base; } -} -``` - -## Spacing Integration - -```typescript -// tailwind.config.ts -theme: { - extend: { - spacing: { - // Map to CSS variables if needed - 'section': 'var(--spacing-section)', - 'component': 'var(--spacing-component)', - } - } -} -``` - -## Animation Tokens - -```typescript -// tailwind.config.ts -theme: { - extend: { - transitionDuration: { - fast: '150ms', - normal: '200ms', - slow: '300ms', - }, - keyframes: { - 'accordion-down': { - from: { height: '0' }, - to: { height: 'var(--radix-accordion-content-height)' }, - }, - 'accordion-up': { - from: { height: 'var(--radix-accordion-content-height)' }, - to: { height: '0' }, - }, - }, - animation: { - 'accordion-down': 'accordion-down 0.2s ease-out', - 'accordion-up': 'accordion-up 0.2s ease-out', - }, - } -} -``` - -## Dark Mode Toggle - -```typescript -// Toggle dark mode -function toggleDarkMode() { - document.documentElement.classList.toggle('dark') -} - -// System preference -if (window.matchMedia('(prefers-color-scheme: dark)').matches) { - document.documentElement.classList.add('dark') -} -``` - -## shadcn/ui Alignment - -This configuration aligns with shadcn/ui conventions: - -- Same CSS variable naming -- Same HSL format -- Same color scale structure -- Compatible with `npx shadcn@latest add` commands - -### Using with shadcn/ui - -```bash -# Initialize (uses same token structure) -npx shadcn@latest init - -# Add components (styled with these tokens) -npx shadcn@latest add button card input -``` - -Components will automatically use your design system tokens. diff --git a/.agents/skills/ckm-design-system/references/token-architecture.md b/.agents/skills/ckm-design-system/references/token-architecture.md deleted file mode 100644 index e13ed2b..0000000 --- a/.agents/skills/ckm-design-system/references/token-architecture.md +++ /dev/null @@ -1,224 +0,0 @@ -# Token Architecture - -Three-layer token system for scalable, themeable design systems. - -## Layer Overview - -``` -┌─────────────────────────────────────────┐ -│ Component Tokens │ Per-component overrides -│ --button-bg, --card-padding │ -├─────────────────────────────────────────┤ -│ Semantic Tokens │ Purpose-based aliases -│ --color-primary, --spacing-section │ -├─────────────────────────────────────────┤ -│ Primitive Tokens │ Raw design values -│ --color-blue-600, --space-4 │ -└─────────────────────────────────────────┘ -``` - -## Why Three Layers? - -| Layer | Purpose | When to Change | -|-------|---------|----------------| -| Primitive | Base values (colors, sizes) | Rarely - foundational | -| Semantic | Meaning assignment | Theme switching | -| Component | Component customization | Per-component needs | - -## Layer 1: Primitive Tokens - -Raw design values without semantic meaning. - -```css -:root { - /* Colors */ - --color-gray-50: #F9FAFB; - --color-gray-900: #111827; - --color-blue-500: #3B82F6; - --color-blue-600: #2563EB; - - /* Spacing (4px base) */ - --space-1: 0.25rem; /* 4px */ - --space-2: 0.5rem; /* 8px */ - --space-4: 1rem; /* 16px */ - --space-6: 1.5rem; /* 24px */ - - /* Typography */ - --font-size-sm: 0.875rem; - --font-size-base: 1rem; - --font-size-lg: 1.125rem; - - /* Radius */ - --radius-sm: 0.25rem; - --radius-default: 0.5rem; - --radius-lg: 0.75rem; - - /* Shadows */ - --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.05); - --shadow-default: 0 1px 3px rgb(0 0 0 / 0.1); -} -``` - -## Layer 2: Semantic Tokens - -Purpose-based aliases that reference primitives. - -```css -:root { - /* Background */ - --color-background: var(--color-gray-50); - --color-foreground: var(--color-gray-900); - - /* Primary */ - --color-primary: var(--color-blue-600); - --color-primary-hover: var(--color-blue-700); - - /* Secondary */ - --color-secondary: var(--color-gray-100); - --color-secondary-foreground: var(--color-gray-900); - - /* Muted */ - --color-muted: var(--color-gray-100); - --color-muted-foreground: var(--color-gray-500); - - /* Destructive */ - --color-destructive: var(--color-red-600); - --color-destructive-foreground: white; - - /* Spacing */ - --spacing-component: var(--space-4); - --spacing-section: var(--space-6); -} -``` - -## Layer 3: Component Tokens - -Component-specific tokens referencing semantic layer. - -```css -:root { - /* Button */ - --button-bg: var(--color-primary); - --button-fg: white; - --button-hover-bg: var(--color-primary-hover); - --button-padding-x: var(--space-4); - --button-padding-y: var(--space-2); - --button-radius: var(--radius-default); - - /* Input */ - --input-bg: var(--color-background); - --input-border: var(--color-gray-300); - --input-focus-ring: var(--color-primary); - --input-padding: var(--space-2) var(--space-3); - - /* Card */ - --card-bg: var(--color-background); - --card-border: var(--color-gray-200); - --card-padding: var(--space-4); - --card-radius: var(--radius-lg); - --card-shadow: var(--shadow-default); -} -``` - -## Dark Mode - -Override semantic tokens for dark theme: - -```css -.dark { - --color-background: var(--color-gray-900); - --color-foreground: var(--color-gray-50); - --color-muted: var(--color-gray-800); - --color-muted-foreground: var(--color-gray-400); - --color-secondary: var(--color-gray-800); -} -``` - -## Naming Convention - -``` ---{category}-{item}-{variant}-{state} - -Examples: ---color-primary # category-item ---color-primary-hover # category-item-state ---button-bg-hover # component-property-state ---space-section-sm # category-semantic-variant -``` - -## Categories - -| Category | Examples | -|----------|----------| -| color | primary, secondary, muted, destructive | -| space | 1, 2, 4, 8, section, component | -| font-size | xs, sm, base, lg, xl | -| radius | sm, default, lg, full | -| shadow | sm, default, lg | -| duration | fast, normal, slow | - -## File Organization - -``` -tokens/ -├── primitives.css # Raw values -├── semantic.css # Purpose aliases -├── components.css # Component tokens -└── index.css # Imports all -``` - -Or single file with layer comments: - -```css -/* === PRIMITIVES === */ -:root { ... } - -/* === SEMANTIC === */ -:root { ... } - -/* === COMPONENTS === */ -:root { ... } - -/* === DARK MODE === */ -.dark { ... } -``` - -## Migration from Flat Tokens - -Before (flat): -```css ---button-primary-bg: #2563EB; ---button-secondary-bg: #F3F4F6; -``` - -After (three-layer): -```css -/* Primitive */ ---color-blue-600: #2563EB; ---color-gray-100: #F3F4F6; - -/* Semantic */ ---color-primary: var(--color-blue-600); ---color-secondary: var(--color-gray-100); - -/* Component */ ---button-bg: var(--color-primary); ---button-secondary-bg: var(--color-secondary); -``` - -## W3C DTCG Alignment - -Token JSON format (W3C Design Tokens Community Group): - -```json -{ - "color": { - "blue": { - "600": { - "$value": "#2563EB", - "$type": "color" - } - } - } -} -``` diff --git a/.agents/skills/ckm-design-system/scripts/embed-tokens.cjs b/.agents/skills/ckm-design-system/scripts/embed-tokens.cjs deleted file mode 100644 index 419c104..0000000 --- a/.agents/skills/ckm-design-system/scripts/embed-tokens.cjs +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env node -/** - * embed-tokens.cjs - * Reads design-tokens.css and outputs embeddable inline CSS. - * Use when generating standalone HTML files (infographics, slides, etc.) - * - * Usage: - * node embed-tokens.cjs # Output full CSS - * node embed-tokens.cjs --minimal # Output only commonly used tokens - * node embed-tokens.cjs --style # Wrap in `; - } else { - output = `/* Design Tokens (embedded for standalone HTML) */\n${output}`; - } - - console.log(output); -} catch (err) { - console.error(`Error reading tokens: ${err.message}`); - process.exit(1); -} diff --git a/.agents/skills/ckm-design-system/scripts/fetch-background.py b/.agents/skills/ckm-design-system/scripts/fetch-background.py deleted file mode 100644 index bcbd357..0000000 --- a/.agents/skills/ckm-design-system/scripts/fetch-background.py +++ /dev/null @@ -1,317 +0,0 @@ -#!/usr/bin/env python3 -""" -Background Image Fetcher -Fetches real images from Pexels for slide backgrounds. -Uses web scraping (no API key required) or WebFetch tool integration. -""" - -import json -import csv -import re -import sys -from pathlib import Path - -# Project root relative to this script -PROJECT_ROOT = Path(__file__).parent.parent.parent.parent.parent -TOKENS_PATH = PROJECT_ROOT / 'assets' / 'design-tokens.json' -BACKGROUNDS_CSV = Path(__file__).parent.parent / 'data' / 'slide-backgrounds.csv' - - -def resolve_token_reference(ref: str, tokens: dict) -> str: - """Resolve token reference like {primitive.color.ocean-blue.500} to hex value.""" - if not ref or not ref.startswith('{') or not ref.endswith('}'): - return ref # Already a value, not a reference - - # Parse reference: {primitive.color.ocean-blue.500} - path = ref[1:-1].split('.') # ['primitive', 'color', 'ocean-blue', '500'] - current = tokens - for key in path: - if isinstance(current, dict): - current = current.get(key) - else: - return None # Invalid path - # Return $value if it's a token object - if isinstance(current, dict) and '$value' in current: - return current['$value'] - return current - - -def load_brand_colors(): - """Load colors from assets/design-tokens.json for overlay gradients. - - Resolves semantic token references to actual hex values. - """ - try: - with open(TOKENS_PATH) as f: - tokens = json.load(f) - - colors = tokens.get('primitive', {}).get('color', {}) - semantic = tokens.get('semantic', {}).get('color', {}) - - # Try semantic tokens first (preferred) - resolve references - if semantic: - primary_ref = semantic.get('primary', {}).get('$value') - secondary_ref = semantic.get('secondary', {}).get('$value') - accent_ref = semantic.get('accent', {}).get('$value') - background_ref = semantic.get('background', {}).get('$value') - - primary = resolve_token_reference(primary_ref, tokens) - secondary = resolve_token_reference(secondary_ref, tokens) - accent = resolve_token_reference(accent_ref, tokens) - background = resolve_token_reference(background_ref, tokens) - - if primary and secondary: - return { - 'primary': primary, - 'secondary': secondary, - 'accent': accent or primary, - 'background': background or '#0D0D0D', - } - - # Fallback: find first color palette with 500 value (primary) - primary_keys = ['ocean-blue', 'coral', 'blue', 'primary'] - secondary_keys = ['golden-amber', 'purple', 'amber', 'secondary'] - accent_keys = ['emerald', 'mint', 'green', 'accent'] - - primary_color = None - secondary_color = None - accent_color = None - - for key in primary_keys: - if key in colors and isinstance(colors[key], dict): - primary_color = colors[key].get('500', {}).get('$value') - if primary_color: - break - - for key in secondary_keys: - if key in colors and isinstance(colors[key], dict): - secondary_color = colors[key].get('500', {}).get('$value') - if secondary_color: - break - - for key in accent_keys: - if key in colors and isinstance(colors[key], dict): - accent_color = colors[key].get('500', {}).get('$value') - if accent_color: - break - - background = colors.get('dark', {}).get('800', {}).get('$value', '#0D0D0D') - - return { - 'primary': primary_color or '#3B82F6', - 'secondary': secondary_color or '#F59E0B', - 'accent': accent_color or '#10B981', - 'background': background, - } - except (FileNotFoundError, KeyError, TypeError): - # Fallback defaults - return { - 'primary': '#3B82F6', - 'secondary': '#F59E0B', - 'accent': '#10B981', - 'background': '#0D0D0D', - } - - -def load_backgrounds_config(): - """Load background configuration from CSV.""" - config = {} - try: - with open(BACKGROUNDS_CSV, newline='') as f: - reader = csv.DictReader(f) - for row in reader: - config[row['slide_type']] = row - except FileNotFoundError: - print(f"Warning: {BACKGROUNDS_CSV} not found") - return config - - -def get_overlay_css(style: str, brand_colors: dict) -> str: - """Generate overlay CSS using brand colors from design-tokens.json.""" - overlays = { - 'gradient-dark': f"linear-gradient(135deg, {brand_colors['background']}E6, {brand_colors['background']}B3)", - 'gradient-brand': f"linear-gradient(135deg, {brand_colors['primary']}CC, {brand_colors['secondary']}99)", - 'gradient-accent': f"linear-gradient(135deg, {brand_colors['accent']}99, transparent)", - 'blur-dark': f"rgba(13,13,13,0.8)", - 'desaturate-dark': f"rgba(13,13,13,0.7)", - } - return overlays.get(style, overlays['gradient-dark']) - - -# Curated high-quality images from Pexels (free to use, pre-selected for brand aesthetic) -CURATED_IMAGES = { - 'hero': [ - 'https://images.pexels.com/photos/3861969/pexels-photo-3861969.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/2582937/pexels-photo-2582937.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/1089438/pexels-photo-1089438.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'vision': [ - 'https://images.pexels.com/photos/3183150/pexels-photo-3183150.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/3182812/pexels-photo-3182812.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/3184291/pexels-photo-3184291.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'team': [ - 'https://images.pexels.com/photos/3184418/pexels-photo-3184418.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/3184338/pexels-photo-3184338.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/3182773/pexels-photo-3182773.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'testimonial': [ - 'https://images.pexels.com/photos/3184465/pexels-photo-3184465.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/1181622/pexels-photo-1181622.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'cta': [ - 'https://images.pexels.com/photos/3184339/pexels-photo-3184339.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/3184298/pexels-photo-3184298.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'problem': [ - 'https://images.pexels.com/photos/3760529/pexels-photo-3760529.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/897817/pexels-photo-897817.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'solution': [ - 'https://images.pexels.com/photos/3184292/pexels-photo-3184292.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/3184644/pexels-photo-3184644.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'hook': [ - 'https://images.pexels.com/photos/2582937/pexels-photo-2582937.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/1089438/pexels-photo-1089438.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'social': [ - 'https://images.pexels.com/photos/3184360/pexels-photo-3184360.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/3184287/pexels-photo-3184287.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], - 'demo': [ - 'https://images.pexels.com/photos/1181675/pexels-photo-1181675.jpeg?auto=compress&cs=tinysrgb&w=1920', - 'https://images.pexels.com/photos/3861958/pexels-photo-3861958.jpeg?auto=compress&cs=tinysrgb&w=1920', - ], -} - - -def get_curated_images(slide_type: str) -> list: - """Get curated images for slide type.""" - return CURATED_IMAGES.get(slide_type, CURATED_IMAGES.get('hero', [])) - - -def get_pexels_search_url(keywords: str) -> str: - """Generate Pexels search URL for manual lookup.""" - import urllib.parse - return f"https://www.pexels.com/search/{urllib.parse.quote(keywords)}/" - - -def get_background_image(slide_type: str) -> dict: - """ - Get curated image matching slide type and brand aesthetic. - Uses pre-selected Pexels images (no API/scraping needed). - """ - brand_colors = load_brand_colors() - config = load_backgrounds_config() - - slide_config = config.get(slide_type) - overlay_style = 'gradient-dark' - keywords = slide_type - - if slide_config: - keywords = slide_config.get('search_keywords', slide_config.get('image_category', slide_type)) - overlay_style = slide_config.get('overlay_style', 'gradient-dark') - - # Get curated images - urls = get_curated_images(slide_type) - if urls: - return { - 'url': urls[0], - 'all_urls': urls, - 'overlay': get_overlay_css(overlay_style, brand_colors), - 'attribution': 'Photo from Pexels (free to use)', - 'source': 'pexels-curated', - 'search_url': get_pexels_search_url(keywords), - } - - # Fallback: provide search URL for manual selection - return { - 'url': None, - 'overlay': get_overlay_css(overlay_style, brand_colors), - 'keywords': keywords, - 'search_url': get_pexels_search_url(keywords), - 'available_types': list(CURATED_IMAGES.keys()), - } - - -def generate_css_for_background(result: dict, slide_class: str = '.slide-with-bg') -> str: - """Generate CSS for a background slide.""" - if not result.get('url'): - search_url = result.get('search_url', '') - return f"""/* No image scraped. Search manually: {search_url} */ -/* Overlay ready: {result.get('overlay', 'gradient-dark')} */ -""" - - return f"""{slide_class} {{ - background-image: url('{result['url']}'); - background-size: cover; - background-position: center; - position: relative; -}} - -{slide_class}::before {{ - content: ''; - position: absolute; - inset: 0; - background: {result['overlay']}; -}} - -{slide_class} .content {{ - position: relative; - z-index: 1; -}} - -/* {result.get('attribution', 'Pexels')} - {result.get('search_url', '')} */ -""" - - -def main(): - """CLI entry point.""" - import argparse - - parser = argparse.ArgumentParser(description='Get background images for slides') - parser.add_argument('slide_type', nargs='?', help='Slide type (hero, vision, team, etc.)') - parser.add_argument('--list', action='store_true', help='List available slide types') - parser.add_argument('--css', action='store_true', help='Output CSS for the background') - parser.add_argument('--json', action='store_true', help='Output JSON') - parser.add_argument('--colors', action='store_true', help='Show brand colors') - parser.add_argument('--all', action='store_true', help='Show all curated URLs') - - args = parser.parse_args() - - if args.colors: - colors = load_brand_colors() - print("\nBrand Colors (from design-tokens.json):") - for name, value in colors.items(): - print(f" {name}: {value}") - return - - if args.list: - print("\nAvailable slide types (curated images):") - for slide_type, urls in CURATED_IMAGES.items(): - print(f" {slide_type}: {len(urls)} images") - return - - if not args.slide_type: - parser.print_help() - return - - result = get_background_image(args.slide_type) - - if args.json: - print(json.dumps(result, indent=2)) - elif args.css: - print(generate_css_for_background(result)) - elif args.all: - print(f"\nAll images for '{args.slide_type}':") - for i, url in enumerate(result.get('all_urls', []), 1): - print(f" {i}. {url}") - else: - print(f"\nImage URL: {result['url']}") - print(f"Alternatives: {len(result.get('all_urls', []))} available (use --all)") - print(f"Overlay: {result['overlay']}") - - -if __name__ == '__main__': - main() diff --git a/.agents/skills/ckm-design-system/scripts/generate-slide.py b/.agents/skills/ckm-design-system/scripts/generate-slide.py deleted file mode 100644 index 228a50a..0000000 --- a/.agents/skills/ckm-design-system/scripts/generate-slide.py +++ /dev/null @@ -1,753 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -Slide Generator - Generates HTML slides using design tokens -ALL styles MUST use CSS variables from design-tokens.css -NO hardcoded colors, fonts, or spacing allowed -""" - -import argparse -import json -from pathlib import Path -from datetime import datetime - -# Paths -SCRIPT_DIR = Path(__file__).parent -DATA_DIR = SCRIPT_DIR.parent / "data" -TOKENS_CSS = Path(__file__).resolve().parents[4] / "assets" / "design-tokens.css" -TOKENS_JSON = Path(__file__).resolve().parents[4] / "assets" / "design-tokens.json" -OUTPUT_DIR = Path(__file__).resolve().parents[4] / "assets" / "designs" / "slides" - -# ============ BRAND-COMPLIANT SLIDE TEMPLATE ============ -# ALL values reference CSS variables from design-tokens.css - -SLIDE_TEMPLATE = ''' - - - - - {title} - - - - - - - - - - - -
- {slides_content} -
- - -''' - - -# ============ SLIDE GENERATORS ============ - -def generate_title_slide(data): - """Title slide with gradient headline""" - return f''' -
-
{data.get('badge', 'Pitch Deck')}
-

{data.get('title', 'Your Title Here')}

-

{data.get('subtitle', 'Your compelling subtitle')}

- - -
- ''' - - -def generate_problem_slide(data): - """Problem statement slide using PAS formula""" - return f''' -
-
The Problem
-

{data.get('headline', 'The problem your audience faces')}

-
-
-
01
-

{data.get('pain_1_title', 'Pain Point 1')}

-

{data.get('pain_1_desc', 'Description of the first pain point')}

-
-
-
02
-

{data.get('pain_2_title', 'Pain Point 2')}

-

{data.get('pain_2_desc', 'Description of the second pain point')}

-
-
-
03
-

{data.get('pain_3_title', 'Pain Point 3')}

-

{data.get('pain_3_desc', 'Description of the third pain point')}

-
-
- -
- ''' - - -def generate_solution_slide(data): - """Solution slide with feature highlights""" - return f''' -
-
The Solution
-

{data.get('headline', 'How we solve this')}

-
-
-
-
-
-

{data.get('feature_1_title', 'Feature 1')}

-

{data.get('feature_1_desc', 'Description of feature 1')}

-
-
-
-
-
-

{data.get('feature_2_title', 'Feature 2')}

-

{data.get('feature_2_desc', 'Description of feature 2')}

-
-
-
-
-
-

{data.get('feature_3_title', 'Feature 3')}

-

{data.get('feature_3_desc', 'Description of feature 3')}

-
-
-
-
-
-
-

Product screenshot or demo

-
-
-
- -
- ''' - - -def generate_metrics_slide(data): - """Traction/metrics slide with large numbers""" - metrics = data.get('metrics', [ - {'value': '10K+', 'label': 'Active Users'}, - {'value': '95%', 'label': 'Retention Rate'}, - {'value': '3x', 'label': 'Revenue Growth'}, - {'value': '$2M', 'label': 'ARR'} - ]) - - metrics_html = ''.join([f''' -
-
{m['value']}
-
{m['label']}
-
- ''' for m in metrics[:4]]) - - return f''' -
-
Traction
-

{data.get('headline', 'Our Growth')}

-
- {metrics_html} -
- -
- ''' - - -def generate_chart_slide(data): - """Chart slide with CSS bar chart""" - bars = data.get('bars', [ - {'label': 'Q1', 'value': 40}, - {'label': 'Q2', 'value': 60}, - {'label': 'Q3', 'value': 80}, - {'label': 'Q4', 'value': 100} - ]) - - bars_html = ''.join([f''' -
- {b.get('display', str(b['value']) + '%')} - {b['label']} -
- ''' for b in bars]) - - return f''' -
-
{data.get('badge', 'Growth')}
-

{data.get('headline', 'Revenue Growth')}

-
-
{data.get('chart_title', 'Quarterly Revenue')}
-
- {bars_html} -
-
- -
- ''' - - -def generate_testimonial_slide(data): - """Social proof slide""" - return f''' -
-
What They Say
-
-

"{data.get('quote', 'This product changed how we work. Incredible results.')}"

-

{data.get('author', 'Jane Doe')}

-

{data.get('role', 'CEO, Example Company')}

-
- -
- ''' - - -def generate_cta_slide(data): - """Closing CTA slide""" - return f''' -
-

{data.get('headline', 'Ready to get started?')}

-

{data.get('subheadline', 'Join thousands of teams already using our solution.')}

- - -
- ''' - - -# Slide type mapping -SLIDE_GENERATORS = { - 'title': generate_title_slide, - 'problem': generate_problem_slide, - 'solution': generate_solution_slide, - 'metrics': generate_metrics_slide, - 'traction': generate_metrics_slide, - 'chart': generate_chart_slide, - 'testimonial': generate_testimonial_slide, - 'cta': generate_cta_slide, - 'closing': generate_cta_slide -} - - -def generate_deck(slides_data, title="Pitch Deck"): - """Generate complete deck from slide data list""" - slides_html = "" - for slide in slides_data: - slide_type = slide.get('type', 'title') - generator = SLIDE_GENERATORS.get(slide_type) - if generator: - slides_html += generator(slide) - else: - print(f"Warning: Unknown slide type '{slide_type}'") - - # Calculate relative path to tokens CSS - tokens_rel_path = "../../../assets/design-tokens.css" - - return SLIDE_TEMPLATE.format( - title=title, - tokens_css_path=tokens_rel_path, - slides_content=slides_html - ) - - -def main(): - parser = argparse.ArgumentParser(description="Generate brand-compliant slides") - parser.add_argument("--json", "-j", help="JSON file with slide data") - parser.add_argument("--output", "-o", help="Output HTML file path") - parser.add_argument("--demo", action="store_true", help="Generate demo deck") - - args = parser.parse_args() - - if args.demo: - # Demo deck showcasing all slide types - demo_slides = [ - { - 'type': 'title', - 'badge': 'Investor Deck 2024', - 'title': 'ClaudeKit Marketing', - 'subtitle': 'Your AI marketing team. Always on.', - 'cta': 'Join Waitlist', - 'secondary_cta': 'See Demo', - 'company': 'ClaudeKit', - 'date': 'December 2024' - }, - { - 'type': 'problem', - 'headline': 'Marketing teams are drowning', - 'pain_1_title': 'Content Overload', - 'pain_1_desc': 'Need to produce 10x content with same headcount', - 'pain_2_title': 'Tool Fatigue', - 'pain_2_desc': '15+ tools that don\'t talk to each other', - 'pain_3_title': 'No Time to Think', - 'pain_3_desc': 'Strategy suffers when execution consumes all hours', - 'company': 'ClaudeKit', - 'page': '2' - }, - { - 'type': 'solution', - 'headline': 'AI agents that actually get marketing', - 'feature_1_title': 'Content Creation', - 'feature_1_desc': 'Blog posts, social, email - all on brand, all on time', - 'feature_2_title': 'Campaign Management', - 'feature_2_desc': 'Multi-channel orchestration with one command', - 'feature_3_title': 'Analytics & Insights', - 'feature_3_desc': 'Real-time optimization without the spreadsheets', - 'company': 'ClaudeKit', - 'page': '3' - }, - { - 'type': 'metrics', - 'headline': 'Early traction speaks volumes', - 'metrics': [ - {'value': '500+', 'label': 'Beta Users'}, - {'value': '85%', 'label': 'Weekly Active'}, - {'value': '4.9', 'label': 'NPS Score'}, - {'value': '50hrs', 'label': 'Saved/Week'} - ], - 'company': 'ClaudeKit', - 'page': '4' - }, - { - 'type': 'chart', - 'badge': 'Revenue', - 'headline': 'Growing month over month', - 'chart_title': 'MRR Growth ($K)', - 'bars': [ - {'label': 'Sep', 'value': 20, 'display': '$5K'}, - {'label': 'Oct', 'value': 40, 'display': '$12K'}, - {'label': 'Nov', 'value': 70, 'display': '$28K'}, - {'label': 'Dec', 'value': 100, 'display': '$45K'} - ], - 'company': 'ClaudeKit', - 'page': '5' - }, - { - 'type': 'testimonial', - 'quote': 'ClaudeKit replaced 3 tools and 2 contractors. Our content output tripled while costs dropped 60%.', - 'author': 'Sarah Chen', - 'role': 'Head of Marketing, TechStartup', - 'company': 'ClaudeKit', - 'page': '6' - }, - { - 'type': 'cta', - 'headline': 'Ship campaigns while you sleep', - 'subheadline': 'Early access available. Limited spots.', - 'cta': 'Join the Waitlist', - 'contact': 'hello@claudekit.ai', - 'website': 'claudekit.ai' - } - ] - - html = generate_deck(demo_slides, "ClaudeKit Marketing - Pitch Deck") - - OUTPUT_DIR.mkdir(parents=True, exist_ok=True) - output_path = OUTPUT_DIR / f"demo-pitch-{datetime.now().strftime('%y%m%d')}.html" - output_path.write_text(html, encoding='utf-8') - print(f"Demo deck generated: {output_path}") - - elif args.json: - with open(args.json, 'r') as f: - data = json.load(f) - - html = generate_deck(data.get('slides', []), data.get('title', 'Presentation')) - - output_path = Path(args.output) if args.output else OUTPUT_DIR / f"deck-{datetime.now().strftime('%y%m%d-%H%M')}.html" - output_path.parent.mkdir(parents=True, exist_ok=True) - output_path.write_text(html, encoding='utf-8') - print(f"Deck generated: {output_path}") - - else: - parser.print_help() - - -if __name__ == "__main__": - main() diff --git a/.agents/skills/ckm-design-system/scripts/generate-tokens.cjs b/.agents/skills/ckm-design-system/scripts/generate-tokens.cjs deleted file mode 100644 index 73cc7d7..0000000 --- a/.agents/skills/ckm-design-system/scripts/generate-tokens.cjs +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env node -/** - * Generate CSS variables from design tokens JSON - * - * Usage: - * node generate-tokens.cjs --config tokens.json -o tokens.css - * node generate-tokens.cjs --config tokens.json --format tailwind - */ - -const fs = require('fs'); -const path = require('path'); - -/** - * Parse command line arguments - */ -function parseArgs() { - const args = process.argv.slice(2); - const options = { - config: null, - output: null, - format: 'css' // css | tailwind - }; - - for (let i = 0; i < args.length; i++) { - if (args[i] === '--config' || args[i] === '-c') { - options.config = args[++i]; - } else if (args[i] === '--output' || args[i] === '-o') { - options.output = args[++i]; - } else if (args[i] === '--format' || args[i] === '-f') { - options.format = args[++i]; - } else if (args[i] === '--help' || args[i] === '-h') { - console.log(` -Usage: node generate-tokens.cjs [options] - -Options: - -c, --config Input JSON token file (required) - -o, --output Output file (default: stdout) - -f, --format Output format: css | tailwind (default: css) - -h, --help Show this help - `); - process.exit(0); - } - } - - return options; -} - -/** - * Resolve token references like {primitive.color.blue.600} - */ -function resolveReference(value, tokens) { - if (typeof value !== 'string' || !value.startsWith('{')) { - return value; - } - - const path = value.slice(1, -1).split('.'); - let result = tokens; - - for (const key of path) { - result = result?.[key]; - } - - if (result?.$value) { - return resolveReference(result.$value, tokens); - } - - return result || value; -} - -/** - * Convert token name to CSS variable name - */ -function toCssVarName(path) { - return '--' + path.join('-').replace(/\./g, '-'); -} - -/** - * Flatten tokens into CSS variables - */ -function flattenTokens(obj, tokens, prefix = [], result = {}) { - for (const [key, value] of Object.entries(obj)) { - const currentPath = [...prefix, key]; - - if (value && typeof value === 'object') { - if (value.$value !== undefined) { - // This is a token - const cssVar = toCssVarName(currentPath); - const resolvedValue = resolveReference(value.$value, tokens); - result[cssVar] = resolvedValue; - } else { - // Recurse into nested object - flattenTokens(value, tokens, currentPath, result); - } - } - } - - return result; -} - -/** - * Generate CSS output - */ -function generateCSS(tokens) { - const primitive = flattenTokens(tokens.primitive || {}, tokens, ['primitive']); - const semantic = flattenTokens(tokens.semantic || {}, tokens, []); - const component = flattenTokens(tokens.component || {}, tokens, []); - const darkSemantic = flattenTokens(tokens.dark?.semantic || {}, tokens, []); - - let css = `/* Design Tokens - Auto-generated */ -/* Do not edit directly - modify tokens.json instead */ - -/* === PRIMITIVES === */ -:root { -${Object.entries(primitive).map(([k, v]) => ` ${k}: ${v};`).join('\n')} -} - -/* === SEMANTIC === */ -:root { -${Object.entries(semantic).map(([k, v]) => ` ${k}: ${v};`).join('\n')} -} - -/* === COMPONENTS === */ -:root { -${Object.entries(component).map(([k, v]) => ` ${k}: ${v};`).join('\n')} -} -`; - - if (Object.keys(darkSemantic).length > 0) { - css += ` -/* === DARK MODE === */ -.dark { -${Object.entries(darkSemantic).map(([k, v]) => ` ${k}: ${v};`).join('\n')} -} -`; - } - - return css; -} - -/** - * Generate Tailwind config output - */ -function generateTailwind(tokens) { - const semantic = flattenTokens(tokens.semantic || {}, tokens, []); - - // Extract colors for Tailwind - const colors = {}; - for (const [key, value] of Object.entries(semantic)) { - if (key.includes('color')) { - const name = key.replace('--color-', '').replace(/-/g, '.'); - colors[name] = `var(${key})`; - } - } - - return `// Tailwind color config - Auto-generated -// Add to tailwind.config.ts theme.extend.colors - -module.exports = { - colors: ${JSON.stringify(colors, null, 2).replace(/"/g, "'")} -}; -`; -} - -/** - * Main - */ -function main() { - const options = parseArgs(); - - if (!options.config) { - console.error('Error: --config is required'); - process.exit(1); - } - - // Resolve config path - const configPath = path.resolve(process.cwd(), options.config); - - if (!fs.existsSync(configPath)) { - console.error(`Error: Config file not found: ${configPath}`); - process.exit(1); - } - - // Read and parse tokens - const tokens = JSON.parse(fs.readFileSync(configPath, 'utf-8')); - - // Generate output - let output; - if (options.format === 'tailwind') { - output = generateTailwind(tokens); - } else { - output = generateCSS(tokens); - } - - // Write output - if (options.output) { - const outputPath = path.resolve(process.cwd(), options.output); - fs.mkdirSync(path.dirname(outputPath), { recursive: true }); - fs.writeFileSync(outputPath, output); - console.log(`Generated: ${outputPath}`); - } else { - console.log(output); - } -} - -main(); diff --git a/.agents/skills/ckm-design-system/scripts/html-token-validator.py b/.agents/skills/ckm-design-system/scripts/html-token-validator.py deleted file mode 100644 index a722498..0000000 --- a/.agents/skills/ckm-design-system/scripts/html-token-validator.py +++ /dev/null @@ -1,327 +0,0 @@ -#!/usr/bin/env python3 -""" -HTML Design Token Validator -Ensures all HTML assets (slides, infographics, etc.) use design tokens. -Source of truth: assets/design-tokens.css - -Usage: - python html-token-validator.py # Validate all HTML assets - python html-token-validator.py --type slides # Validate only slides - python html-token-validator.py --type infographics # Validate only infographics - python html-token-validator.py path/to/file.html # Validate specific file - python html-token-validator.py --fix # Auto-fix issues (WIP) -""" - -import re -import json -import sys -from pathlib import Path -from typing import Dict, List, Tuple, Optional - -# Project root relative to this script -PROJECT_ROOT = Path(__file__).parent.parent.parent.parent.parent -TOKENS_JSON_PATH = PROJECT_ROOT / 'assets' / 'design-tokens.json' -TOKENS_CSS_PATH = PROJECT_ROOT / 'assets' / 'design-tokens.css' - -# Asset directories to validate -ASSET_DIRS = { - 'slides': PROJECT_ROOT / 'assets' / 'designs' / 'slides', - 'infographics': PROJECT_ROOT / 'assets' / 'infographics', -} - -# Patterns that indicate hardcoded values (should use tokens) -FORBIDDEN_PATTERNS = [ - (r'#[0-9A-Fa-f]{3,8}\b', 'hex color'), - (r'rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)', 'rgb color'), - (r'rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*[\d.]+\s*\)', 'rgba color'), - (r'hsl\([^)]+\)', 'hsl color'), - (r"font-family:\s*'[^v][^a][^r][^']*',", 'hardcoded font'), # Exclude var() - (r'font-family:\s*"[^v][^a][^r][^"]*",', 'hardcoded font'), -] - -# Allowed rgba patterns (brand colors with transparency - CSS limitation) -# These are derived from brand tokens but need rgba for transparency -ALLOWED_RGBA_PATTERNS = [ - r'rgba\(\s*59\s*,\s*130\s*,\s*246', # --color-primary (#3B82F6) - r'rgba\(\s*245\s*,\s*158\s*,\s*11', # --color-secondary (#F59E0B) - r'rgba\(\s*16\s*,\s*185\s*,\s*129', # --color-accent (#10B981) - r'rgba\(\s*20\s*,\s*184\s*,\s*166', # --color-accent alt (#14B8A6) - r'rgba\(\s*0\s*,\s*0\s*,\s*0', # black transparency (common) - r'rgba\(\s*255\s*,\s*255\s*,\s*255', # white transparency (common) - r'rgba\(\s*15\s*,\s*23\s*,\s*42', # --color-surface (#0F172A) - r'rgba\(\s*7\s*,\s*11\s*,\s*20', # --color-background (#070B14) -] - -# Allowed exceptions (external images, etc.) -ALLOWED_EXCEPTIONS = [ - 'pexels.com', 'unsplash.com', 'youtube.com', 'ytimg.com', - 'googlefonts', 'fonts.googleapis.com', 'fonts.gstatic.com', -] - - -class ValidationResult: - """Validation result for a single file.""" - def __init__(self, file_path: Path): - self.file_path = file_path - self.errors: List[str] = [] - self.warnings: List[str] = [] - self.passed = True - - def add_error(self, msg: str): - self.errors.append(msg) - self.passed = False - - def add_warning(self, msg: str): - self.warnings.append(msg) - - -def load_css_variables() -> Dict[str, str]: - """Load CSS variables from design-tokens.css.""" - variables = {} - if TOKENS_CSS_PATH.exists(): - content = TOKENS_CSS_PATH.read_text() - # Extract --var-name: value patterns - for match in re.finditer(r'(--[\w-]+):\s*([^;]+);', content): - variables[match.group(1)] = match.group(2).strip() - return variables - - -def is_inside_block(content: str, match_pos: int, open_tag: str, close_tag: str) -> bool: - """Check if position is inside a specific HTML block.""" - pre = content[:match_pos] - tag_open = pre.rfind(open_tag) - tag_close = pre.rfind(close_tag) - return tag_open > tag_close - - -def is_allowed_exception(context: str) -> bool: - """Check if the hardcoded value is in an allowed exception context.""" - context_lower = context.lower() - return any(exc in context_lower for exc in ALLOWED_EXCEPTIONS) - - -def is_allowed_rgba(match_text: str) -> bool: - """Check if rgba pattern uses brand colors (allowed for transparency).""" - return any(re.match(pattern, match_text) for pattern in ALLOWED_RGBA_PATTERNS) - - -def get_context(content: str, pos: int, chars: int = 100) -> str: - """Get surrounding context for a match position.""" - start = max(0, pos - chars) - end = min(len(content), pos + chars) - return content[start:end] - - -def validate_html(content: str, file_path: Path, verbose: bool = False) -> ValidationResult: - """ - Validate HTML content for design token compliance. - - Checks: - 1. design-tokens.css import present - 2. No hardcoded colors in CSS (except in '): - if verbose: - result.add_warning(f"Allowed in ",High,https://nuxt.com/docs/guide/concepts/nuxt-lifecycle -18,Lifecycle,Use onMounted for DOM access,Access DOM only after component is mounted,onMounted for DOM manipulation,Direct DOM access in setup,"onMounted(() => { document.getElementById('el') })","",High,https://nuxt.com/docs/api/composables/on-mounted -19,Lifecycle,Use nextTick for post-render access,Wait for DOM updates before accessing elements,await nextTick() after state changes,Immediate DOM access after state change,"count.value++; await nextTick(); el.value.focus()","count.value++; el.value.focus()",Medium,https://nuxt.com/docs/api/utils/next-tick -20,Lifecycle,Use onPrehydrate for pre-hydration logic,Run code before Nuxt hydrates the page,onPrehydrate for client setup,onMounted for hydration-critical code,"onPrehydrate(() => { console.log(window) })",onMounted for pre-hydration needs,Low,https://nuxt.com/docs/api/composables/on-prehydrate -21,Server,Use server/api for API routes,Create API endpoints in server/api directory,server/api/users.ts for /api/users,Manual Express setup,server/api/hello.ts -> /api/hello,app.get('/api/hello'),High,https://nuxt.com/docs/guide/directory-structure/server -22,Server,Use defineEventHandler for handlers,Define server route handlers,defineEventHandler for all handlers,export default function,"export default defineEventHandler((event) => { return { hello: 'world' } })","export default function(req, res) {}",High,https://nuxt.com/docs/guide/directory-structure/server -23,Server,Use server/routes for non-api routes,Routes without /api prefix,server/routes for custom paths,server/api for non-api routes,server/routes/sitemap.xml.ts,server/api/sitemap.xml.ts,Medium,https://nuxt.com/docs/guide/directory-structure/server -24,Server,Use getQuery and readBody for input,Access query params and request body,getQuery(event) readBody(event),Direct event access,"const { id } = getQuery(event)",event.node.req.query,Medium,https://nuxt.com/docs/guide/directory-structure/server -25,Server,Validate server input,Always validate input in server handlers,Zod or similar for validation,Trust client input,"const body = await readBody(event); schema.parse(body)",const body = await readBody(event),High,https://nuxt.com/docs/guide/directory-structure/server -26,State,Use useState for shared reactive state,SSR-friendly shared state across components,useState for cross-component state,ref for shared state,"const count = useState('count', () => 0)",const count = ref(0) in composable,High,https://nuxt.com/docs/api/composables/use-state -27,State,Use unique keys for useState,Prevent state conflicts with unique keys,Descriptive unique keys for each state,Generic or duplicate keys,"useState('user-preferences', () => ({}))",useState('data') in multiple places,Medium,https://nuxt.com/docs/api/composables/use-state -28,State,Use Pinia for complex state,Pinia for advanced state management,@pinia/nuxt for complex apps,Custom state management,useMainStore() with Pinia,Custom reactive store implementation,Medium,https://nuxt.com/docs/getting-started/state-management -29,State,Use callOnce for one-time async operations,Ensure async operations run only once,callOnce for store initialization,Direct await in component,"await callOnce(store.fetch)",await store.fetch() on every render,Medium,https://nuxt.com/docs/api/utils/call-once -30,SEO,Use useSeoMeta for SEO tags,Type-safe SEO meta tag management,useSeoMeta for meta tags,useHead for simple meta,"useSeoMeta({ title: 'Home', ogTitle: 'Home', description: '...' })","useHead({ meta: [{ name: 'description', content: '...' }] })",High,https://nuxt.com/docs/api/composables/use-seo-meta -31,SEO,Use reactive values in useSeoMeta,Dynamic SEO tags with refs or getters,Computed getters for dynamic values,Static values for dynamic content,"useSeoMeta({ title: () => post.value.title })","useSeoMeta({ title: post.value.title })",Medium,https://nuxt.com/docs/api/composables/use-seo-meta -32,SEO,Use useHead for non-meta head elements,Scripts styles links in head,useHead for scripts and links,useSeoMeta for scripts,"useHead({ script: [{ src: '/analytics.js' }] })","useSeoMeta({ script: '...' })",Medium,https://nuxt.com/docs/api/composables/use-head -33,SEO,Include OpenGraph tags,Add OG tags for social sharing,ogTitle ogDescription ogImage,Missing social preview,"useSeoMeta({ ogImage: '/og.png', twitterCard: 'summary_large_image' })",No OG configuration,Medium,https://nuxt.com/docs/api/composables/use-seo-meta -34,Middleware,Use defineNuxtRouteMiddleware,Define route middleware properly,defineNuxtRouteMiddleware wrapper,export default function,"export default defineNuxtRouteMiddleware((to, from) => {})","export default function(to, from) {}",High,https://nuxt.com/docs/guide/directory-structure/middleware -35,Middleware,Use navigateTo for redirects,Redirect in middleware with navigateTo,return navigateTo('/login'),router.push in middleware,"if (!auth) return navigateTo('/login')","if (!auth) router.push('/login')",High,https://nuxt.com/docs/api/utils/navigate-to -36,Middleware,Reference middleware in definePageMeta,Apply middleware to specific pages,middleware array in definePageMeta,Global middleware for page-specific,definePageMeta({ middleware: ['auth'] }),Global auth check for one page,Medium,https://nuxt.com/docs/guide/directory-structure/middleware -37,Middleware,Use .global suffix for global middleware,Apply middleware to all routes,auth.global.ts for app-wide auth,Manual middleware on every page,middleware/auth.global.ts,middleware: ['auth'] on every page,Medium,https://nuxt.com/docs/guide/directory-structure/middleware -38,ErrorHandling,Use createError for errors,Create errors with proper status codes,createError with statusCode,throw new Error,"throw createError({ statusCode: 404, statusMessage: 'Not Found' })",throw new Error('Not Found'),High,https://nuxt.com/docs/api/utils/create-error -39,ErrorHandling,Use NuxtErrorBoundary for local errors,Handle errors within component subtree,NuxtErrorBoundary for component errors,Global error page for local errors,"