Comprehensive style guide and design system implementation
Repo: jasonnovack/oneshot
Diff
diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md
new file mode 100644
index 0000000..43aebd7
--- /dev/null
+++ b/STYLE_GUIDE.md
@@ -0,0 +1,365 @@
+# Oneshot Brand Style Guide
+
+## Brand Essence
+
+**Oneshot** is a platform for verified AI code transformations. The visual identity balances:
+- **Clean minimalism** (Product Hunt influence) - Generous whitespace, clear hierarchy
+- **Retro web authenticity** (Hacker News influence) - Information density, functional simplicity
+- **Gallery-quality polish** (Dribbble influence) - Visual refinement, content-first presentation
+
+---
+
+## Color Palette
+
+### Primary Colors
+
+| Name | Hex | Usage |
+|------|-----|-------|
+| **Background** | `#0d0d0d` | Page background, depth |
+| **Surface** | `#141414` | Cards, elevated elements |
+| **Surface Elevated** | `#1a1a1a` | Hover states, inputs |
+| **Border** | `#262626` | Dividers, card borders |
+| **Border Subtle** | `#1f1f1f` | Subtle separations |
+
+### Text Colors
+
+| Name | Hex | Usage |
+|------|-----|-------|
+| **Text Primary** | `#fafafa` | Headlines, important text |
+| **Text Secondary** | `#a1a1a1` | Body text, descriptions |
+| **Text Muted** | `#737373` | Metadata, timestamps |
+| **Text Disabled** | `#525252` | Inactive states |
+
+### Accent Colors
+
+| Name | Hex | Usage |
+|------|-----|-------|
+| **Accent** | `#f97316` | Primary actions, links, highlights |
+| **Accent Hover** | `#fb923c` | Hover states |
+| **Accent Muted** | `rgba(249, 115, 22, 0.15)` | Backgrounds, badges |
+
+### Semantic Colors
+
+| Name | Hex | Usage |
+|------|-----|-------|
+| **Success** | `#22c55e` | Additions, positive states |
+| **Success Muted** | `rgba(34, 197, 94, 0.15)` | Diff additions |
+| **Error** | `#ef4444` | Deletions, errors |
+| **Error Muted** | `rgba(239, 68, 68, 0.15)` | Diff deletions |
+| **Warning** | `#eab308` | Warnings, stars |
+
+---
+
+## Typography
+
+### Font Stack
+
+```css
+--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+--font-mono: 'JetBrains Mono', 'SF Mono', Monaco, 'Cascadia Code', monospace;
+```
+
+### Type Scale
+
+| Name | Size | Weight | Line Height | Usage |
+|------|------|--------|-------------|-------|
+| **Display** | 2.5rem (40px) | 700 | 1.1 | Hero headlines |
+| **H1** | 1.75rem (28px) | 600 | 1.2 | Page titles |
+| **H2** | 1.25rem (20px) | 600 | 1.3 | Section headers, card titles |
+| **H3** | 1rem (16px) | 600 | 1.4 | Subsections |
+| **Body** | 0.9375rem (15px) | 400 | 1.6 | Primary content |
+| **Small** | 0.8125rem (13px) | 400 | 1.5 | Metadata, captions |
+| **Tiny** | 0.75rem (12px) | 500 | 1.4 | Badges, labels |
+
+### Typography Rules
+
+- Headlines use **-0.02em letter-spacing** for tightness
+- Body text uses **default letter-spacing** for readability
+- Uppercase labels use **0.05em letter-spacing** for clarity
+- Monospace code uses **0.875rem** base size
+
+---
+
+## Spacing System
+
+Base unit: **4px**
+
+| Token | Value | Usage |
+|-------|-------|-------|
+| `--space-1` | 4px | Tight gaps |
+| `--space-2` | 8px | Related elements |
+| `--space-3` | 12px | Component padding |
+| `--space-4` | 16px | Card padding, gaps |
+| `--space-5` | 20px | Section spacing |
+| `--space-6` | 24px | Large gaps |
+| `--space-8` | 32px | Section margins |
+| `--space-10` | 40px | Page sections |
+| `--space-12` | 48px | Major divisions |
+
+---
+
+## Border Radius
+
+| Token | Value | Usage |
+|-------|-------|-------|
+| `--radius-sm` | 4px | Badges, small elements |
+| `--radius-md` | 6px | Buttons, inputs |
+| `--radius-lg` | 8px | Cards, containers |
+| `--radius-xl` | 12px | Modals, large cards |
+| `--radius-full` | 9999px | Avatars, pills |
+
+---
+
+## Components
+
+### Cards
+
+```
+- Background: var(--surface)
+- Border: 1px solid var(--border)
+- Border Radius: var(--radius-lg)
+- Padding: var(--space-5)
+- Hover: border-color transitions to var(--accent)
+- Shadow: none (flat design)
+```
+
+**Card Hierarchy:**
+1. **Featured Card** - Larger padding, accent border-top
+2. **Standard Card** - Default styling
+3. **Compact Card** - Reduced padding for dense listings
+
+### Buttons
+
+**Primary Button:**
+```
+- Background: var(--accent)
+- Color: white
+- Padding: 10px 16px
+- Border Radius: var(--radius-md)
+- Font Weight: 500
+- Hover: background lightens 10%
+```
+
+**Secondary Button:**
+```
+- Background: transparent
+- Border: 1px solid var(--border)
+- Color: var(--text-secondary)
+- Hover: border-color var(--accent), color var(--accent)
+```
+
+**Ghost Button:**
+```
+- Background: transparent
+- Color: var(--text-muted)
+- Hover: color var(--text-primary)
+```
+
+### Badges/Tags
+
+```
+- Background: var(--surface-elevated)
+- Color: var(--text-secondary)
+- Padding: 4px 8px
+- Border Radius: var(--radius-sm)
+- Font Size: var(--text-tiny)
+- Font Weight: 500
+```
+
+**Badge Variants:**
+- **Default** - Neutral background
+- **Accent** - var(--accent-muted) background, var(--accent) text
+- **Success** - Green for additions
+- **Error** - Red for deletions
+
+### Links
+
+```
+- Color: var(--accent)
+- Text Decoration: none
+- Hover: underline or color lightens
+```
+
+**Link Types:**
+- **Inline Link** - Accent color, underline on hover
+- **Navigation Link** - Muted color, accent on hover
+- **Card Link** - Entire card clickable, subtle hover state
+
+### Form Inputs
+
+```
+- Background: var(--bg)
+- Border: 1px solid var(--border)
+- Color: var(--text-primary)
+- Padding: 10px 12px
+- Border Radius: var(--radius-md)
+- Focus: border-color var(--accent), subtle glow
+```
+
+---
+
+## Layout
+
+### Container Widths
+
+| Name | Width | Usage |
+|------|-------|-------|
+| **Narrow** | 640px | Forms, focused content |
+| **Default** | 900px | Shot detail pages |
+| **Wide** | 1200px | Gallery, dashboards |
+| **Full** | 100% | Edge-to-edge sections |
+
+### Grid System
+
+Gallery uses CSS Grid:
+```css
+grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
+gap: var(--space-5);
+```
+
+### Header
+
+```
+- Height: 60px
+- Background: var(--bg) with subtle border-bottom
+- Logo: Left-aligned, 1.25rem, font-weight 700
+- Navigation: Right-aligned, var(--space-6) gaps
+- Sticky positioning
+```
+
+---
+
+## Iconography
+
+- Style: Outlined, 1.5px stroke
+- Size: 16px (small), 20px (default), 24px (large)
+- Color: Inherits text color
+- Preferred set: Lucide Icons or Heroicons
+
+---
+
+## Motion & Animation
+
+### Transitions
+
+```css
+--transition-fast: 150ms ease;
+--transition-base: 200ms ease;
+--transition-slow: 300ms ease;
+```
+
+### Animation Principles
+
+- **Subtle** - Micro-interactions only, no flashy effects
+- **Purposeful** - Animation indicates state change
+- **Quick** - Under 300ms for UI feedback
+- **Reduced motion** - Respect prefers-reduced-motion
+
+### Common Animations
+
+- **Hover lift** - transform: translateY(-2px) on cards
+- **Color transitions** - border-color, background-color
+- **Fade in** - opacity 0 to 1 for lazy-loaded content
+
+---
+
+## Code & Diff Display
+
+### Code Blocks
+
+```
+- Background: #111111
+- Border Radius: var(--radius-md)
+- Padding: var(--space-4)
+- Font: var(--font-mono)
+- Font Size: 0.8125rem
+- Line Height: 1.6
+- Overflow: auto with custom scrollbar
+```
+
+### Diff Styling
+
+```
+- Addition: color #4ade80, bg rgba(74, 222, 128, 0.1)
+- Deletion: color #f87171, bg rgba(248, 113, 113, 0.1)
+- Line numbers: color var(--text-muted)
+- File headers: font-weight 600, border-bottom
+```
+
+---
+
+## Voice & Tone
+
+### Brand Voice
+
+- **Direct** - Say what you mean, no fluff
+- **Technical** - Speak to developers authentically
+- **Confident** - Verified transformations, proven results
+- **Welcoming** - Open source spirit, community-driven
+
+### Writing Guidelines
+
+- Use active voice
+- Keep sentences short
+- Avoid jargon unless necessary
+- Be specific with numbers and data
+- Headlines: Title case for major, sentence case for minor
+
+---
+
+## Logo Usage
+
+### Primary Logo
+
+- **Wordmark:** "Oneshot" in Inter Bold
+- **Lockup:** Optional crosshair/target icon + wordmark
+- **Minimum size:** 80px width
+- **Clear space:** 1x height on all sides
+
+### Color Variations
+
+- **Light on dark:** White wordmark on dark backgrounds
+- **Dark on light:** Black wordmark on light backgrounds
+- **Accent:** Orange wordmark for special uses
+
+---
+
+## Social & Marketing
+
+### Open Graph Images
+
+- Size: 1200x630px
+- Background: var(--bg) or gradient
+- Featured content: Screenshot thumbnail
+- Text: Shot title, author, Oneshot branding
+
+### Twitter Cards
+
+- Large image summary format
+- Include preview screenshot when available
+- Consistent branding bottom-right
+
+---
+
+## Accessibility
+
+- **Contrast:** Minimum 4.5:1 for text, 3:1 for large text
+- **Focus states:** Visible outline on all interactive elements
+- **Alt text:** Required for all images
+- **Keyboard navigation:** Full support
+- **Screen readers:** Semantic HTML, ARIA labels
+
+---
+
+## Implementation Checklist
+
+- [ ] Update CSS custom properties
+- [ ] Apply typography scale
+- [ ] Restyle header and navigation
+- [ ] Restyle shot cards in gallery
+- [ ] Restyle shot detail page
+- [ ] Restyle forms and inputs
+- [ ] Add hover states and transitions
+- [ ] Update badges and tags
+- [ ] Polish code/diff display
+- [ ] Add focus states for accessibility
diff --git a/packages/web/src/app/globals.css b/packages/web/src/app/globals.css
index ce755de..91d4d73 100644
--- a/packages/web/src/app/globals.css
+++ b/packages/web/src/app/globals.css
@@ -1,410 +1,876 @@
-* {
+/* ==========================================================================
+ Oneshot Design System
+ Based on: Clean minimalism + Retro web authenticity + Gallery-quality polish
+ ========================================================================== */
+
+/* --------------------------------------------------------------------------
+ CSS Custom Properties (Design Tokens)
+ -------------------------------------------------------------------------- */
+
+:root {
+ /* Colors - Background */
+ --bg: #0d0d0d;
+ --surface: #141414;
+ --surface-elevated: #1a1a1a;
+ --surface-hover: #1f1f1f;
+
+ /* Colors - Border */
+ --border: #262626;
+ --border-subtle: #1f1f1f;
+ --border-hover: #333333;
+
+ /* Colors - Text */
+ --text-primary: #fafafa;
+ --text-secondary: #a1a1a1;
+ --text-muted: #737373;
+ --text-disabled: #525252;
+
+ /* Colors - Accent */
+ --accent: #f97316;
+ --accent-hover: #fb923c;
+ --accent-muted: rgba(249, 115, 22, 0.12);
+ --accent-subtle: rgba(249, 115, 22, 0.08);
+
+ /* Colors - Semantic */
+ --success: #22c55e;
+ --success-muted: rgba(34, 197, 94, 0.12);
+ --error: #ef4444;
+ --error-muted: rgba(239, 68, 68, 0.12);
+ --warning: #eab308;
+ --warning-muted: rgba(234, 179, 8, 0.12);
+
+ /* Typography */
+ --font-sans: var(--font-inter), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ --font-mono: var(--font-jetbrains), 'SF Mono', Monaco, 'Cascadia Code', monospace;
+
+ /* Type Scale */
+ --text-display: 2.5rem;
+ --text-h1: 1.75rem;
+ --text-h2: 1.25rem;
+ --text-h3: 1rem;
+ --text-body: 0.9375rem;
+ --text-small: 0.8125rem;
+ --text-tiny: 0.75rem;
+
+ /* Spacing */
+ --space-1: 4px;
+ --space-2: 8px;
+ --space-3: 12px;
+ --space-4: 16px;
+ --space-5: 20px;
+ --space-6: 24px;
+ --space-8: 32px;
+ --space-10: 40px;
+ --space-12: 48px;
+
+ /* Border Radius */
+ --radius-sm: 4px;
+ --radius-md: 6px;
+ --radius-lg: 8px;
+ --radius-xl: 12px;
+ --radius-full: 9999px;
+
+ /* Transitions */
+ --transition-fast: 150ms ease;
+ --transition-base: 200ms ease;
+ --transition-slow: 300ms ease;
+
+ /* Shadows */
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
+
+ /* Container Widths */
+ --container-narrow: 640px;
+ --container-default: 900px;
+ --container-wide: 1200px;
+}
+
+/* --------------------------------------------------------------------------
+ Reset & Base Styles
+ -------------------------------------------------------------------------- */
+
+*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
-:root {
- --bg: #0a0a0a;
- --fg: #ededed;
- --muted: #888;
- --border: #333;
- --accent: #0070f3;
+html {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-rendering: optimizeLegibility;
}
body {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ font-family: var(--font-sans);
+ font-size: var(--text-body);
+ line-height: 1.6;
+ color: var(--text-secondary);
background: var(--bg);
- color: var(--fg);
+ min-height: 100vh;
+}
+
+/* --------------------------------------------------------------------------
+ Typography
+ -------------------------------------------------------------------------- */
+
+h1, h2, h3, h4 {
+ color: var(--text-primary);
+ font-weight: 600;
+ letter-spacing: -0.02em;
+ line-height: 1.3;
+}
+
+h1 {
+ font-size: var(--text-h1);
+ margin-bottom: var(--space-6);
+}
+
+h2 {
+ font-size: var(--text-h2);
+ margin-bottom: var(--space-4);
+}
+
+h3 {
+ font-size: var(--text-h3);
+ margin-bottom: var(--space-3);
+}
+
+p {
+ margin-bottom: var(--space-4);
+}
+
+a {
+ color: var(--accent);
+ text-decoration: none;
+ transition: color var(--transition-fast);
+}
+
+a:hover {
+ color: var(--accent-hover);
+}
+
+code {
+ font-family: var(--font-mono);
+ font-size: 0.875em;
+ background: var(--surface-elevated);
+ padding: 0.2em 0.4em;
+ border-radius: var(--radius-sm);
+}
+
+pre {
+ font-family: var(--font-mono);
+ font-size: var(--text-small);
+ background: var(--surface);
+ border: 1px solid var(--border-subtle);
+ border-radius: var(--radius-md);
+ padding: var(--space-4);
+ overflow-x: auto;
line-height: 1.6;
}
+pre code {
+ background: none;
+ padding: 0;
+}
+
+/* --------------------------------------------------------------------------
+ Layout
+ -------------------------------------------------------------------------- */
+
+main {
+ max-width: var(--container-wide);
+ margin: 0 auto;
+ padding: var(--space-8) var(--space-6);
+}
+
+/* --------------------------------------------------------------------------
+ Header
+ -------------------------------------------------------------------------- */
+
.header {
display: flex;
align-items: center;
justify-content: space-between;
- padding: 1rem 2rem;
- border-bottom: 1px solid var(--border);
+ padding: 0 var(--space-6);
+ height: 60px;
+ border-bottom: 1px solid var(--border-subtle);
+ background: var(--bg);
+ position: sticky;
+ top: 0;
+ z-index: 100;
}
.logo {
- font-size: 1.5rem;
+ font-size: var(--text-h2);
font-weight: 700;
- color: var(--fg);
+ color: var(--text-primary);
text-decoration: none;
+ letter-spacing: -0.03em;
+ transition: color var(--transition-fast);
+}
+
+.logo:hover {
+ color: var(--accent);
+}
+
+nav {
+ display: flex;
+ align-items: center;
+ gap: var(--space-6);
}
nav a {
- color: var(--muted);
+ color: var(--text-muted);
+ font-size: var(--text-small);
+ font-weight: 500;
text-decoration: none;
- margin-left: 2rem;
+ transition: color var(--transition-fast);
}
nav a:hover {
- color: var(--fg);
+ color: var(--text-primary);
}
-main {
- max-width: 1200px;
- margin: 0 auto;
- padding: 2rem;
+/* --------------------------------------------------------------------------
+ Buttons
+ -------------------------------------------------------------------------- */
+
+.btn {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: var(--space-2);
+ padding: 10px var(--space-4);
+ font-size: var(--text-small);
+ font-weight: 500;
+ font-family: inherit;
+ border-radius: var(--radius-md);
+ cursor: pointer;
+ transition: all var(--transition-fast);
+ border: none;
}
-h1 {
- font-size: 2rem;
- margin-bottom: 1.5rem;
+.btn-primary {
+ background: var(--accent);
+ color: white;
+}
+
+.btn-primary:hover:not(:disabled) {
+ background: var(--accent-hover);
+}
+
+.btn-secondary {
+ background: transparent;
+ border: 1px solid var(--border);
+ color: var(--text-secondary);
+}
+
+.btn-secondary:hover:not(:disabled) {
+ border-color: var(--accent);
+ color: var(--accent);
}
+.btn-ghost {
+ background: transparent;
+ color: var(--text-muted);
+}
+
+.btn-ghost:hover:not(:disabled) {
+ color: var(--text-primary);
+ background: var(--surface-hover);
+}
+
+.btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+/* Legacy button classes */
+.auth-btn {
+ background: transparent;
+ border: 1px solid var(--border);
+ color: var(--text-primary);
+ padding: var(--space-2) var(--space-4);
+ border-radius: var(--radius-md);
+ cursor: pointer;
+ font-size: var(--text-small);
+ font-weight: 500;
+ margin-left: var(--space-4);
+ transition: all var(--transition-fast);
+}
+
+.auth-btn:hover {
+ border-color: var(--accent);
+ color: var(--accent);
+}
+
+.filter-btn {
+ background: var(--accent);
+ border: none;
+ color: white;
+ padding: var(--space-2) var(--space-4);
+ border-radius: var(--radius-md);
+ font-size: var(--text-small);
+ font-weight: 500;
+ cursor: pointer;
+ transition: background var(--transition-fast);
+}
+
+.filter-btn:hover {
+ background: var(--accent-hover);
+}
+
+/* --------------------------------------------------------------------------
+ Badges & Tags
+ -------------------------------------------------------------------------- */
+
+.badge {
+ display: inline-flex;
+ align-items: center;
+ padding: var(--space-1) var(--space-2);
+ background: var(--surface-elevated);
+ color: var(--text-muted);
+ font-size: var(--text-tiny);
+ font-weight: 500;
+ border-radius: var(--radius-sm);
+ white-space: nowrap;
+}
+
+.badge-accent {
+ background: var(--accent-muted);
+ color: var(--accent);
+}
+
+.badge-success {
+ background: var(--success-muted);
+ color: var(--success);
+}
+
+.badge-error {
+ background: var(--error-muted);
+ color: var(--error);
+}
+
+/* --------------------------------------------------------------------------
+ Form Elements
+ -------------------------------------------------------------------------- */
+
+.search-input,
+.filter-select,
+.code-input,
+input[type="text"],
+input[type="email"],
+input[type="password"],
+textarea {
+ background: var(--bg);
+ border: 1px solid var(--border);
+ color: var(--text-primary);
+ padding: 10px var(--space-3);
+ border-radius: var(--radius-md);
+ font-size: var(--text-small);
+ font-family: inherit;
+ transition: border-color var(--transition-fast);
+ width: 100%;
+}
+
+.search-input:focus,
+.filter-select:focus,
+.code-input:focus,
+input:focus,
+textarea:focus {
+ outline: none;
+ border-color: var(--accent);
+}
+
+.search-input {
+ width: 220px;
+}
+
+.filter-select {
+ cursor: pointer;
+ width: auto;
+}
+
+textarea {
+ resize: vertical;
+ min-height: 100px;
+ line-height: 1.5;
+}
+
+/* --------------------------------------------------------------------------
+ Filters
+ -------------------------------------------------------------------------- */
+
+.filters {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--space-3);
+ margin-bottom: var(--space-8);
+ align-items: center;
+ padding-bottom: var(--space-6);
+ border-bottom: 1px solid var(--border-subtle);
+}
+
+.clear-btn {
+ color: var(--text-muted);
+ text-decoration: none;
+ font-size: var(--text-small);
+ transition: color var(--transition-fast);
+}
+
+.clear-btn:hover {
+ color: var(--text-primary);
+}
+
+/* --------------------------------------------------------------------------
+ Shot Cards (Gallery)
+ -------------------------------------------------------------------------- */
+
.shots-grid {
display: grid;
- gap: 1.5rem;
+ grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
+ gap: var(--space-5);
}
.shot-card {
+ background: var(--surface);
border: 1px solid var(--border);
- border-radius: 8px;
- padding: 1.5rem;
- transition: border-color 0.2s;
+ border-radius: var(--radius-lg);
+ overflow: hidden;
+ transition: all var(--transition-base);
}
.shot-card:hover {
- border-color: var(--accent);
+ border-color: var(--border-hover);
+ transform: translateY(-2px);
}
.shot-card a {
- color: var(--fg);
+ color: inherit;
text-decoration: none;
}
.shot-card h2 {
- font-size: 1.25rem;
- margin-bottom: 0.5rem;
+ font-size: var(--text-h2);
+ font-weight: 600;
+ color: var(--text-primary);
+ margin: 0 0 var(--space-3) 0;
+ padding: var(--space-4) var(--space-4) 0;
+ line-height: 1.3;
+}
+
+.shot-card h2:hover {
+ color: var(--accent);
+}
+
+/* Shot thumbnail */
+.shot-thumbnail-link {
+ display: block;
+ background: var(--surface-elevated);
+ overflow: hidden;
+}
+
+.shot-thumbnail {
+ width: 100%;
+ height: 200px;
+ object-fit: cover;
+ object-position: top;
+ display: block;
+ transition: transform var(--transition-base), opacity var(--transition-base);
}
+.shot-thumbnail-link:hover .shot-thumbnail {
+ transform: scale(1.02);
+ opacity: 0.9;
+}
+
+/* Shot meta */
.shot-meta {
- color: var(--muted);
- font-size: 0.875rem;
- margin-bottom: 1rem;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: var(--space-2);
+ padding: 0 var(--space-4) var(--space-4);
+ font-size: var(--text-small);
+ color: var(--text-muted);
}
.shot-meta span {
- margin-right: 1rem;
+ margin-right: 0;
}
-.diff-preview {
- background: #111;
- border-radius: 4px;
- padding: 1rem;
- font-family: 'SF Mono', Monaco, monospace;
- font-size: 0.8rem;
- overflow-x: auto;
- white-space: pre;
+.shot-date {
+ color: var(--text-muted);
+ font-size: var(--text-tiny);
}
-.diff-add {
- color: #4ade80;
+/* Author link with avatar */
+.author-link {
+ color: var(--accent);
+ font-weight: 500;
+ text-decoration: none;
+ transition: color var(--transition-fast);
}
-.diff-remove {
- color: #f87171;
+.author-link:hover {
+ color: var(--accent-hover);
}
-.prompt-box {
- background: #111;
- border-radius: 4px;
- padding: 1rem;
- margin-top: 1rem;
- font-size: 0.9rem;
+.author-with-avatar {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
}
-.prompt-label {
- color: var(--muted);
- font-size: 0.75rem;
- text-transform: uppercase;
- margin-bottom: 0.5rem;
+.author-avatar {
+ width: 20px;
+ height: 20px;
+ border-radius: var(--radius-full);
}
-.badge {
- display: inline-block;
- background: var(--border);
- padding: 0.25rem 0.5rem;
- border-radius: 4px;
- font-size: 0.75rem;
- margin-right: 0.5rem;
+.anonymous-author {
+ color: var(--text-muted);
+ font-style: italic;
}
-.shot-detail {
- max-width: 900px;
+/* Stats */
+.stats {
+ margin-left: auto;
+ display: flex;
+ gap: var(--space-3);
+ color: var(--text-muted);
+ font-size: var(--text-tiny);
}
-.shot-detail h1 {
- margin-bottom: 0.5rem;
+/* Diff preview in cards */
+.diff-preview-link {
+ display: block;
+ padding: 0 var(--space-4) var(--space-4);
}
-.full-diff {
- background: #111;
- border-radius: 4px;
- padding: 1.5rem;
- font-family: 'SF Mono', Monaco, monospace;
- font-size: 0.85rem;
+.diff-preview {
+ background: var(--bg);
+ border-radius: var(--radius-md);
+ padding: var(--space-3);
+ font-family: var(--font-mono);
+ font-size: 11px;
+ line-height: 1.5;
overflow-x: auto;
white-space: pre;
- margin: 1.5rem 0;
+ max-height: 160px;
+ overflow-y: hidden;
+ border: 1px solid var(--border-subtle);
}
-.recipe-panel {
- border: 1px solid var(--border);
- border-radius: 8px;
- padding: 1.5rem;
- margin-top: 2rem;
+.diff-add {
+ color: var(--success);
+ background: var(--success-muted);
+ display: block;
+ margin: 0 calc(var(--space-3) * -1);
+ padding: 0 var(--space-3);
}
-.recipe-panel h3 {
- margin-bottom: 1.5rem;
+.diff-remove {
+ color: var(--error);
+ background: var(--error-muted);
+ display: block;
+ margin: 0 calc(var(--space-3) * -1);
+ padding: 0 var(--space-3);
}
-.recipe-section {
- margin-bottom: 1.5rem;
+/* --------------------------------------------------------------------------
+ Shot Detail Page
+ -------------------------------------------------------------------------- */
+
+.shot-detail {
+ max-width: var(--container-default);
}
-.recipe-header {
+.shot-detail h1 {
+ font-size: var(--text-h1);
+ margin-bottom: var(--space-3);
+}
+
+.shot-header {
display: flex;
justify-content: space-between;
+ align-items: flex-start;
+ gap: var(--space-4);
+ padding-bottom: var(--space-6);
+ border-bottom: 1px solid var(--border-subtle);
+}
+
+.shot-info {
+ margin-top: var(--space-5);
+ color: var(--text-muted);
+ font-size: var(--text-small);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-2);
+}
+
+.shot-info a {
+ color: var(--accent);
+}
+
+/* Commit links */
+.commit-links {
+ display: flex;
align-items: center;
- margin-bottom: 0.5rem;
+ gap: var(--space-2);
+ flex-wrap: wrap;
}
-.recipe-label {
- color: var(--muted);
- font-size: 0.75rem;
- text-transform: uppercase;
- letter-spacing: 0.05em;
+.commit-links code {
+ background: var(--surface-elevated);
+ padding: 2px 6px;
+ border-radius: var(--radius-sm);
+ font-size: var(--text-tiny);
}
-.recipe-value {
- font-size: 0.95rem;
+.separator {
+ color: var(--text-disabled);
+ margin: 0 var(--space-1);
}
-.recipe-value code {
- background: #111;
- padding: 0.25rem 0.5rem;
- border-radius: 4px;
- font-size: 0.85rem;
+.github-diff-link {
+ color: var(--text-muted) !important;
+ font-size: var(--text-small);
}
-.copy-btn {
- background: transparent;
- border: 1px solid var(--border);
- color: var(--muted);
- padding: 0.25rem 0.5rem;
- border-radius: 4px;
- font-size: 0.75rem;
- cursor: pointer;
- transition: all 0.2s;
+.github-diff-link:hover {
+ color: var(--text-secondary) !important;
}
-.copy-btn:hover {
- border-color: var(--accent);
- color: var(--accent);
+/* Preview links */
+.preview-links {
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
}
-.toggle-btn {
- background: transparent;
- border: none;
- color: var(--accent);
- font-size: 0.75rem;
- cursor: pointer;
- padding: 0;
+.preview-link {
+ color: var(--success);
+ text-decoration: none;
+ font-weight: 500;
+ padding: var(--space-1) var(--space-2);
+ background: var(--success-muted);
+ border-radius: var(--radius-sm);
+ font-size: var(--text-small);
+ transition: background var(--transition-fast);
}
-.toggle-btn:hover {
- text-decoration: underline;
+.preview-link:hover {
+ background: rgba(34, 197, 94, 0.2);
+ color: var(--success);
}
-.raw-session {
- position: relative;
- margin-top: 0.5rem;
+/* Social links */
+.social-link {
+ color: var(--text-muted);
+ font-size: var(--text-tiny);
+ transition: color var(--transition-fast);
}
-.raw-session .copy-btn {
- position: absolute;
- top: 0.5rem;
- right: 0.5rem;
+.social-link:hover {
+ color: var(--accent);
}
-.raw-session pre {
- background: #111;
- border-radius: 4px;
- padding: 1rem;
- padding-top: 2.5rem;
- font-size: 0.75rem;
- overflow-x: auto;
- max-height: 300px;
- overflow-y: auto;
+/* Screenshot preview */
+.screenshot-preview {
+ margin-top: var(--space-8);
}
-.recipe-tip {
- margin-top: 1.5rem;
- padding: 1rem;
- background: rgba(0, 112, 243, 0.1);
- border-left: 3px solid var(--accent);
- border-radius: 0 4px 4px 0;
- font-size: 0.875rem;
- color: var(--muted);
+.screenshot-preview h3 {
+ margin-bottom: var(--space-4);
}
-.recipe-tip strong {
- color: var(--fg);
+.screenshot-container {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+ gap: var(--space-5);
}
-.auth-btn {
- background: transparent;
+.screenshot-item {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-2);
+}
+
+.screenshot-label {
+ font-size: var(--text-tiny);
+ text-transform: uppercase;
+ color: var(--text-muted);
+ letter-spacing: 0.05em;
+ font-weight: 500;
+}
+
+.screenshot-image {
+ width: 100%;
+ border-radius: var(--radius-lg);
border: 1px solid var(--border);
- color: var(--fg);
- padding: 0.5rem 1rem;
- border-radius: 4px;
- cursor: pointer;
- font-size: 0.875rem;
- margin-left: 1rem;
- transition: border-color 0.2s, background 0.2s;
+ transition: border-color var(--transition-base), transform var(--transition-base);
}
-.auth-btn:hover {
+.screenshot-item a:hover .screenshot-image {
border-color: var(--accent);
- background: rgba(0, 112, 243, 0.1);
+ transform: translateY(-2px);
}
-.user-header {
- display: flex;
- align-items: center;
- gap: 1.5rem;
- margin-bottom: 1rem;
+/* Full diff display */
+.full-diff {
+ background: var(--surface);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-lg);
+ padding: var(--space-5);
+ font-family: var(--font-mono);
+ font-size: var(--text-small);
+ line-height: 1.6;
+ overflow-x: auto;
+ white-space: pre;
+ margin: var(--space-5) 0;
}
-.avatar {
- width: 80px;
- height: 80px;
- border-radius: 50%;
+/* --------------------------------------------------------------------------
+ Recipe Panel
+ -------------------------------------------------------------------------- */
+
+.recipe-panel {
+ border: 1px solid var(--border);
+ border-radius: var(--radius-lg);
+ padding: var(--space-6);
+ margin-top: var(--space-8);
+ background: var(--surface);
}
-.user-header h1 {
- margin-bottom: 0.25rem;
+.recipe-panel h3 {
+ margin-bottom: var(--space-5);
+ color: var(--text-primary);
}
-.author-link {
- color: var(--accent);
- text-decoration: none;
- margin-right: 0.5rem;
+.recipe-section {
+ margin-bottom: var(--space-5);
}
-.author-link:hover {
- text-decoration: underline;
+.recipe-section:last-child {
+ margin-bottom: 0;
}
-.filters {
+.recipe-header {
display: flex;
- flex-wrap: wrap;
- gap: 0.75rem;
- margin-bottom: 2rem;
+ justify-content: space-between;
align-items: center;
+ margin-bottom: var(--space-2);
}
-.search-input {
- background: var(--bg);
- border: 1px solid var(--border);
- color: var(--fg);
- padding: 0.5rem 0.75rem;
- border-radius: 4px;
- font-size: 0.875rem;
- width: 200px;
+.recipe-label {
+ color: var(--text-muted);
+ font-size: var(--text-tiny);
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ font-weight: 500;
}
-.search-input:focus {
- outline: none;
- border-color: var(--accent);
+.recipe-value {
+ font-size: var(--text-body);
+ color: var(--text-secondary);
}
-.filter-select {
- background: var(--bg);
+.recipe-value code {
+ background: var(--surface-elevated);
+ padding: var(--space-1) var(--space-2);
+ border-radius: var(--radius-sm);
+ font-size: var(--text-small);
+}
+
+.copy-btn {
+ background: transparent;
border: 1px solid var(--border);
- color: var(--fg);
- padding: 0.5rem 0.75rem;
- border-radius: 4px;
- font-size: 0.875rem;
+ color: var(--text-muted);
+ padding: var(--space-1) var(--space-2);
+ border-radius: var(--radius-sm);
+ font-size: var(--text-tiny);
cursor: pointer;
+ transition: all var(--transition-fast);
}
-.filter-select:focus {
- outline: none;
+.copy-btn:hover {
border-color: var(--accent);
+ color: var(--accent);
}
-.filter-btn {
- background: var(--accent);
+.toggle-btn {
+ background: transparent;
border: none;
- color: white;
- padding: 0.5rem 1rem;
- border-radius: 4px;
- font-size: 0.875rem;
+ color: var(--accent);
+ font-size: var(--text-tiny);
cursor: pointer;
- transition: opacity 0.2s;
+ padding: 0;
+}
+
+.toggle-btn:hover {
+ text-decoration: underline;
}
-.filter-btn:hover {
- opacity: 0.9;
+.raw-session {
+ position: relative;
+ margin-top: var(--space-2);
}
-.clear-btn {
- color: var(--muted);
- text-decoration: none;
- font-size: 0.875rem;
+.raw-session .copy-btn {
+ position: absolute;
+ top: var(--space-2);
+ right: var(--space-2);
}
-.clear-btn:hover {
- color: var(--fg);
+.raw-session pre {
+ padding-top: var(--space-8);
+ max-height: 300px;
+ overflow-y: auto;
}
-/* Shot detail header */
-.shot-header {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- gap: 1rem;
+.recipe-tip {
+ margin-top: var(--space-5);
+ padding: var(--space-4);
+ background: var(--accent-subtle);
+ border-left: 3px solid var(--accent);
+ border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
+ font-size: var(--text-small);
+ color: var(--text-muted);
}
-.shot-info {
- margin-top: 1rem;
- color: var(--muted);
- font-size: 0.875rem;
+.recipe-tip strong {
+ color: var(--text-secondary);
}
-.shot-info a {
- color: var(--accent);
-}
+/* --------------------------------------------------------------------------
+ Star Button
+ -------------------------------------------------------------------------- */
-/* Star button */
.star-button {
display: flex;
align-items: center;
- gap: 0.5rem;
+ gap: var(--space-2);
background: transparent;
border: 1px solid var(--border);
- color: var(--muted);
- padding: 0.5rem 1rem;
- border-radius: 4px;
+ color: var(--text-muted);
+ padding: var(--space-2) var(--space-3);
+ border-radius: var(--radius-md);
cursor: pointer;
- font-size: 1rem;
- transition: all 0.2s;
+ font-size: var(--text-body);
+ transition: all var(--transition-fast);
}
.star-button:hover:not(:disabled) {
- border-color: #fbbf24;
- color: #fbbf24;
+ border-color: var(--warning);
+ color: var(--warning);
}
.star-button.starred {
- border-color: #fbbf24;
- color: #fbbf24;
+ border-color: var(--warning);
+ color: var(--warning);
+ background: var(--warning-muted);
}
.star-button:disabled {
@@ -413,60 +879,51 @@ h1 {
}
.star-icon {
- font-size: 1.25rem;
+ font-size: 1.125rem;
}
.star-count {
- font-size: 0.875rem;
+ font-size: var(--text-small);
+ font-weight: 500;
}
-/* Comments section */
+/* --------------------------------------------------------------------------
+ Comments Section
+ -------------------------------------------------------------------------- */
+
.comments-section {
- margin-top: 3rem;
- padding-top: 2rem;
+ margin-top: var(--space-10);
+ padding-top: var(--space-8);
border-top: 1px solid var(--border);
}
.comments-section h3 {
- margin-bottom: 1.5rem;
+ margin-bottom: var(--space-5);
}
.comment-form {
- margin-bottom: 2rem;
+ margin-bottom: var(--space-6);
}
.comment-form textarea {
- width: 100%;
- background: var(--bg);
- border: 1px solid var(--border);
- color: var(--fg);
- padding: 0.75rem;
- border-radius: 4px;
- font-size: 0.9rem;
- font-family: inherit;
- resize: vertical;
min-height: 80px;
-}
-
-.comment-form textarea:focus {
- outline: none;
- border-color: var(--accent);
+ margin-bottom: var(--space-3);
}
.comment-form button {
- margin-top: 0.75rem;
background: var(--accent);
- border: none;
color: white;
- padding: 0.5rem 1rem;
- border-radius: 4px;
- font-size: 0.875rem;
+ border: none;
+ padding: var(--space-2) var(--space-4);
+ border-radius: var(--radius-md);
+ font-size: var(--text-small);
+ font-weight: 500;
cursor: pointer;
- transition: opacity 0.2s;
+ transition: background var(--transition-fast);
}
.comment-form button:hover:not(:disabled) {
- opacity: 0.9;
+ background: var(--accent-hover);
}
.comment-form button:disabled {
@@ -475,47 +932,47 @@ h1 {
}
.sign-in-prompt {
- color: var(--muted);
- margin-bottom: 2rem;
-}
-
-.sign-in-prompt a {
- color: var(--accent);
+ color: var(--text-muted);
+ margin-bottom: var(--space-6);
+ font-size: var(--text-small);
}
.loading, .no-comments {
- color: var(--muted);
+ color: var(--text-muted);
+ font-size: var(--text-small);
}
.comments-list {
display: flex;
flex-direction: column;
- gap: 1.5rem;
+ gap: var(--space-4);
}
.comment {
- padding: 1rem;
- background: #111;
- border-radius: 4px;
+ padding: var(--space-4);
+ background: var(--surface);
+ border-radius: var(--radius-lg);
+ border: 1px solid var(--border-subtle);
}
.comment-header {
display: flex;
align-items: center;
- gap: 0.75rem;
- margin-bottom: 0.75rem;
+ gap: var(--space-3);
+ margin-bottom: var(--space-3);
}
.comment-avatar {
- width: 24px;
- height: 24px;
- border-radius: 50%;
+ width: 28px;
+ height: 28px;
+ border-radius: var(--radius-full);
}
.comment-author {
color: var(--accent);
text-decoration: none;
font-weight: 500;
+ font-size: var(--text-small);
}
.comment-author:hover {
@@ -523,288 +980,141 @@ h1 {
}
.comment-date {
- color: var(--muted);
- font-size: 0.75rem;
+ color: var(--text-muted);
+ font-size: var(--text-tiny);
}
.comment-content {
- color: var(--fg);
- line-height: 1.5;
+ color: var(--text-secondary);
+ line-height: 1.6;
white-space: pre-wrap;
+ font-size: var(--text-body);
}
-/* Stats on shot cards */
-.stats {
- margin-left: auto;
- display: flex;
- gap: 0.75rem;
- color: var(--muted);
- font-size: 0.8rem;
-}
-
-/* Device auth page */
-.device-auth {
- max-width: 400px;
- margin: 4rem auto;
- text-align: center;
-}
-
-.device-auth h1 {
- margin-bottom: 1rem;
-}
-
-.device-auth p {
- color: var(--muted);
- margin-bottom: 1rem;
-}
-
-.device-form {
- display: flex;
- flex-direction: column;
- gap: 1rem;
- margin: 2rem 0;
-}
-
-.code-input {
- background: var(--bg);
- border: 2px solid var(--border);
- color: var(--fg);
- padding: 1rem;
- border-radius: 8px;
- font-size: 1.5rem;
- font-family: 'SF Mono', Monaco, monospace;
- text-align: center;
- letter-spacing: 0.2em;
-}
-
-.code-input:focus {
- outline: none;
- border-color: var(--accent);
-}
-
-.success-message {
- color: #4ade80;
- font-size: 1.1rem;
-}
-
-.error-message {
- color: #f87171;
- margin-top: 1rem;
-}
-
-.signed-in-as {
- margin-top: 2rem;
- font-size: 0.875rem;
-}
-
-/* Getting started section */
-.getting-started {
- background: #111;
- border: 1px solid var(--border);
- border-radius: 8px;
- padding: 1.5rem 2rem;
- margin-bottom: 2rem;
-}
-
-.getting-started h2 {
- font-size: 1.1rem;
- margin-bottom: 1rem;
- color: var(--fg);
-}
-
-.getting-started ol {
- margin-left: 1.25rem;
- color: var(--fg);
-}
-
-.getting-started li {
- margin-bottom: 0.5rem;
-}
-
-.getting-started code {
- background: #1a1a1a;
- padding: 0.2rem 0.5rem;
- border-radius: 4px;
- font-size: 0.85rem;
- font-family: 'SF Mono', Monaco, monospace;
- color: #4ade80;
-}
+/* --------------------------------------------------------------------------
+ User Profile
+ -------------------------------------------------------------------------- */
-/* Commit links */
-.commit-links {
+.user-header {
display: flex;
align-items: center;
- gap: 0.5rem;
- flex-wrap: wrap;
-}
-
-.commit-links a {
- color: var(--accent);
- text-decoration: none;
-}
-
-.commit-links a:hover {
- text-decoration: underline;
-}
-
-.commit-links code {
- background: #111;
- padding: 0.2rem 0.4rem;
- border-radius: 3px;
- font-size: 0.85rem;
-}
-
-.separator {
- color: var(--muted);
- margin: 0 0.25rem;
+ gap: var(--space-5);
+ margin-bottom: var(--space-6);
+ padding-bottom: var(--space-6);
+ border-bottom: 1px solid var(--border-subtle);
}
-.github-diff-link {
- font-size: 0.875rem;
- color: var(--muted) !important;
+.avatar {
+ width: 80px;
+ height: 80px;
+ border-radius: var(--radius-full);
+ border: 2px solid var(--border);
}
-.github-diff-link:hover {
- color: var(--fg) !important;
+.user-header h1 {
+ margin-bottom: var(--space-1);
}
-/* User links */
.user-links {
display: flex;
- gap: 1rem;
- margin-top: 0.5rem;
+ gap: var(--space-4);
+ margin-top: var(--space-2);
}
.user-links a {
- color: var(--muted);
+ color: var(--text-muted);
text-decoration: none;
- font-size: 0.875rem;
+ font-size: var(--text-small);
+ transition: color var(--transition-fast);
}
.user-links a:hover {
color: var(--accent);
}
-/* Social links in shot meta */
-.social-link {
- color: var(--muted);
- text-decoration: none;
- font-size: 0.8rem;
- margin-right: 0.5rem;
-}
-
-.social-link:hover {
- color: var(--accent);
-}
-
-/* Shot date */
-.shot-date {
- color: var(--muted);
- font-size: 0.8rem;
-}
-
-/* Anonymous author */
-.anonymous-author {
- color: var(--muted);
- font-style: italic;
- margin-right: 0.5rem;
-}
-
-/* Preview links */
-.preview-links {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- margin-bottom: 0.5rem;
-}
-
-.preview-link {
- color: #4ade80;
- text-decoration: none;
- font-weight: 500;
- padding: 0.25rem 0.5rem;
- background: rgba(74, 222, 128, 0.1);
- border-radius: 4px;
- font-size: 0.875rem;
-}
-
-.preview-link:hover {
- background: rgba(74, 222, 128, 0.2);
- text-decoration: none;
-}
+/* --------------------------------------------------------------------------
+ Welcome Banner
+ -------------------------------------------------------------------------- */
-/* Welcome banner */
.welcome-banner {
- background: linear-gradient(135deg, rgba(0, 112, 243, 0.15) 0%, rgba(0, 112, 243, 0.05) 100%);
- border: 1px solid rgba(0, 112, 243, 0.3);
- border-radius: 12px;
- padding: 2rem;
- margin-bottom: 1.5rem;
+ background: linear-gradient(135deg, var(--accent-muted) 0%, var(--accent-subtle) 100%);
+ border: 1px solid rgba(249, 115, 22, 0.2);
+ border-radius: var(--radius-xl);
+ padding: var(--space-8);
+ margin-bottom: var(--space-8);
text-align: center;
position: relative;
}
.banner-close {
position: absolute;
- top: 0.75rem;
- right: 0.75rem;
+ top: var(--space-3);
+ right: var(--space-3);
background: none;
border: none;
- color: var(--muted);
- font-size: 1.5rem;
+ color: var(--text-muted);
+ font-size: 1.25rem;
cursor: pointer;
- padding: 0.25rem 0.5rem;
+ padding: var(--space-1) var(--space-2);
line-height: 1;
- border-radius: 4px;
- transition: color 0.2s, background 0.2s;
+ border-radius: var(--radius-sm);
+ transition: all var(--transition-fast);
}
.banner-close:hover {
- color: var(--fg);
+ color: var(--text-primary);
background: rgba(255, 255, 255, 0.1);
}
.welcome-banner h1 {
- font-size: 2rem;
- margin-bottom: 0.75rem;
- background: linear-gradient(135deg, var(--fg) 0%, var(--accent) 100%);
+ font-size: var(--text-display);
+ margin-bottom: var(--space-3);
+ background: linear-gradient(135deg, var(--text-primary) 0%, var(--accent) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.welcome-banner p {
- color: var(--muted);
+ color: var(--text-muted);
font-size: 1.1rem;
max-width: 600px;
margin: 0 auto;
}
-/* Submit page */
+/* --------------------------------------------------------------------------
+ Submit Page
+ -------------------------------------------------------------------------- */
+
.submit-page {
- max-width: 800px;
+ max-width: var(--container-default);
}
.submit-page .intro {
font-size: 1.1rem;
- color: var(--muted);
- margin-bottom: 2rem;
+ color: var(--text-muted);
+ margin-bottom: var(--space-8);
}
.submit-page .steps {
display: flex;
flex-direction: column;
- gap: 1.5rem;
- margin-bottom: 2rem;
+ gap: var(--space-4);
+ margin-bottom: var(--space-8);
}
.submit-page .step {
display: flex;
- gap: 1rem;
- padding: 1.5rem;
- background: var(--card);
+ gap: var(--space-4);
+ padding: var(--space-5);
+ background: var(--surface);
border: 1px solid var(--border);
- border-radius: 8px;
+ border-radius: var(--radius-lg);
+ transition: border-color var(--transition-base);
+}
+
+.submit-page .step:hover {
+ border-color: var(--border-hover);
}
.submit-page .step-number {
@@ -812,149 +1122,251 @@ h1 {
height: 32px;
background: var(--accent);
color: white;
- border-radius: 50%;
+ border-radius: var(--radius-full);
display: flex;
align-items: center;
justify-content: center;
- font-weight: bold;
+ font-weight: 600;
+ font-size: var(--text-small);
flex-shrink: 0;
}
.submit-page .step-content h3 {
- margin: 0 0 0.5rem 0;
- font-size: 1.1rem;
+ margin: 0 0 var(--space-2) 0;
+ font-size: var(--text-h3);
}
.submit-page .step-content p {
margin: 0;
- color: var(--muted);
+ color: var(--text-muted);
+ font-size: var(--text-body);
}
.submit-page .step-content ul {
- margin: 0.5rem 0 0 0;
- padding-left: 1.25rem;
+ margin: var(--space-2) 0 0 0;
+ padding-left: var(--space-5);
+ color: var(--text-secondary);
}
.submit-page .step-content li {
- margin-bottom: 0.25rem;
+ margin-bottom: var(--space-1);
}
.submit-page .step-content pre {
- margin: 0.75rem 0 0 0;
- padding: 0.75rem 1rem;
- background: var(--bg);
- border-radius: 6px;
- overflow-x: auto;
+ margin: var(--space-3) 0 0 0;
}
.submit-page .step-content code {
- font-family: 'SF Mono', Monaco, 'Courier New', monospace;
- font-size: 0.9rem;
+ color: var(--success);
}
.submit-page .step-content .note {
- font-size: 0.875rem;
- margin-top: 0.5rem;
+ font-size: var(--text-small);
+ margin-top: var(--space-2);
font-style: italic;
+ color: var(--text-muted);
}
.submit-page h2 {
- margin-top: 2rem;
- margin-bottom: 1rem;
- border-bottom: 1px solid var(--border);
- padding-bottom: 0.5rem;
+ margin-top: var(--space-8);
+ margin-bottom: var(--space-4);
+ padding-bottom: var(--space-3);
+ border-bottom: 1px solid var(--border-subtle);
}
.submit-page .shot-types ul,
.submit-page .verification ul {
- padding-left: 1.25rem;
+ padding-left: var(--space-5);
+ color: var(--text-secondary);
}
.submit-page .shot-types li,
.submit-page .verification li {
- margin-bottom: 0.5rem;
+ margin-bottom: var(--space-2);
}
.submit-page .cli-options pre {
- padding: 1rem;
- background: var(--card);
+ background: var(--surface);
border: 1px solid var(--border);
- border-radius: 8px;
- overflow-x: auto;
}
-/* Author avatar */
-.author-with-avatar {
- display: inline-flex;
- align-items: center;
- gap: 0.4rem;
-}
+/* --------------------------------------------------------------------------
+ Device Auth Page
+ -------------------------------------------------------------------------- */
-.author-avatar {
- width: 20px;
- height: 20px;
- border-radius: 50%;
- vertical-align: middle;
+.device-auth {
+ max-width: 400px;
+ margin: var(--space-12) auto;
+ text-align: center;
}
-/* Shot thumbnail in gallery */
-.shot-thumbnail-link {
- display: block;
- margin-bottom: 1rem;
- border-radius: 6px;
- overflow: hidden;
- background: #111;
+.device-auth h1 {
+ margin-bottom: var(--space-4);
}
-.shot-thumbnail {
- width: 100%;
- height: 180px;
- object-fit: cover;
- object-position: top;
- display: block;
- transition: opacity 0.2s;
+.device-auth p {
+ color: var(--text-muted);
+ margin-bottom: var(--space-4);
}
-.shot-thumbnail-link:hover .shot-thumbnail {
- opacity: 0.85;
+.device-form {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-4);
+ margin: var(--space-6) 0;
}
-/* Screenshot preview section */
-.screenshot-preview {
- margin-top: 2rem;
+.code-input {
+ background: var(--bg);
+ border: 2px solid var(--border);
+ color: var(--text-primary);
+ padding: var(--space-4);
+ border-radius: var(--radius-lg);
+ font-size: var(--text-h1);
+ font-family: var(--font-mono);
+ text-align: center;
+ letter-spacing: 0.2em;
}
-.screenshot-preview h3 {
- margin-bottom: 1rem;
+.code-input:focus {
+ border-color: var(--accent);
}
-.screenshot-container {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
- gap: 1.5rem;
+.success-message {
+ color: var(--success);
+ font-size: 1.1rem;
}
-.screenshot-item {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
+.error-message {
+ color: var(--error);
+ margin-top: var(--space-4);
}
-.screenshot-label {
- font-size: 0.75rem;
- text-transform: uppercase;
- color: var(--muted);
- letter-spacing: 0.05em;
+.signed-in-as {
+ margin-top: var(--space-6);
+ font-size: var(--text-small);
+ color: var(--text-muted);
}
-.screenshot-image {
- width: 100%;
- border-radius: 8px;
+/* --------------------------------------------------------------------------
+ Getting Started (Legacy)
+ -------------------------------------------------------------------------- */
+
+.getting-started {
+ background: var(--surface);
border: 1px solid var(--border);
- transition: border-color 0.2s, transform 0.2s;
+ border-radius: var(--radius-lg);
+ padding: var(--space-5) var(--space-6);
+ margin-bottom: var(--space-6);
}
-.screenshot-item a:hover .screenshot-image {
- border-color: var(--accent);
- transform: translateY(-2px);
+.getting-started h2 {
+ font-size: var(--text-h3);
+ margin-bottom: var(--space-4);
+ color: var(--text-primary);
+}
+
+.getting-started ol {
+ margin-left: var(--space-5);
+ color: var(--text-secondary);
+}
+
+.getting-started li {
+ margin-bottom: var(--space-2);
+}
+
+.getting-started code {
+ color: var(--success);
+}
+
+/* --------------------------------------------------------------------------
+ Scrollbar Styling
+ -------------------------------------------------------------------------- */
+
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--bg);
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--border);
+ border-radius: var(--radius-full);
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--border-hover);
+}
+
+/* --------------------------------------------------------------------------
+ Focus States (Accessibility)
+ -------------------------------------------------------------------------- */
+
+:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+}
+
+/* --------------------------------------------------------------------------
+ Responsive Adjustments
+ -------------------------------------------------------------------------- */
+
+@media (max-width: 768px) {
+ main {
+ padding: var(--space-5) var(--space-4);
+ }
+
+ .header {
+ padding: 0 var(--space-4);
+ }
+
+ nav {
+ gap: var(--space-4);
+ }
+
+ .shots-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .shot-header {
+ flex-direction: column;
+ }
+
+ .filters {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .search-input {
+ width: 100%;
+ }
+
+ .welcome-banner {
+ padding: var(--space-6);
+ }
+
+ .welcome-banner h1 {
+ font-size: var(--text-h1);
+ }
+
+ .submit-page .step {
+ flex-direction: column;
+ }
+}
+
+/* --------------------------------------------------------------------------
+ Reduced Motion
+ -------------------------------------------------------------------------- */
+
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ }
}
diff --git a/packages/web/src/app/layout.tsx b/packages/web/src/app/layout.tsx
index 0cace0e..586d641 100644
--- a/packages/web/src/app/layout.tsx
+++ b/packages/web/src/app/layout.tsx
@@ -1,8 +1,21 @@
import type { Metadata } from 'next'
+import { Inter, JetBrains_Mono } from 'next/font/google'
import { Providers } from './providers'
import { Header } from '@/components/Header'
import './globals.css'
+const inter = Inter({
+ subsets: ['latin'],
+ variable: '--font-inter',
+ display: 'swap',
+})
+
+const jetbrainsMono = JetBrains_Mono({
+ subsets: ['latin'],
+ variable: '--font-jetbrains',
+ display: 'swap',
+})
+
export const metadata: Metadata = {
title: 'Oneshot',
description: 'Showcase verified AI code transformations',
@@ -14,7 +27,7 @@ export default function RootLayout({
children: React.ReactNode
}) {
return (
- <html lang="en">
+ <html lang="en" className={`${inter.variable} ${jetbrainsMono.variable}`}>
<body>
<Providers>
<Header />
Recipe
Model
claude-opus-4-5-20251101Harness
Claude Code
Token Usage
Input:
17.2KOutput: 289.2KTotal: 306.4KCache Read: 191.1MPlugins
Frontend Design vclaude-plugins-officialGithub vclaude-plugins-officialFeature Dev vclaude-plugins-officialSwift Lsp vclaude-plugins-official
Prompt
Let's write a product spec for a web app called Oneshot. There is a huge amount of interest right now in AI model selection, harness selection, prompt engineering, context engineering, MCP, etc., etc. The goal is to create an app where users can showcase what they can do and how they do it. The idea is to let users showcase before/after and how they get amazing results with AI. I am thinking there are 3 key components: 1. we take a repo BEFORE state and host it somewhere, or accept a hosted version like a Vercel build that we can verify corresponds with the repo's BEFORE state. 2. users invoke AI, and we capture a VERIFIED set of attributes that allows full reproducibility of this AI action (model, harness, prompt, context, and anything else that's relevant). 3. we take a repo AFTER state and host it somewhere or accept a user-hosted version that we can verify corresponds with the repo's AFTER state. Once we have those 3 components, we build a simple database of all submitted examples, gallery app to discover and inspect them.
Config Files
Raw Session Data
Tip: Copy the prompt and adapt it for your own project. The key is understanding why this prompt worked, not reproducing it exactly.
Comments (0)
Sign in to leave a comment
Loading comments...