Initial commit: invest-copilot app
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
# Invest Copilot — Design System
|
||||
|
||||
> Dark-first, glassmorphic fintech aesthetic. Inspired by Linear, Stripe, Dribbble fintech.
|
||||
> Mobile-first responsive. OKLch color space.
|
||||
|
||||
---
|
||||
|
||||
## Design Tokens
|
||||
|
||||
### Colors (OKLch)
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Background */
|
||||
--bg-deep: oklch(0.08 0.02 260); /* near-black, slight blue tint */
|
||||
--bg-surface: oklch(0.12 0.03 260); /* card bg */
|
||||
--bg-raised: oklch(0.16 0.03 260); /* elevated card */
|
||||
--bg-overlay: oklch(0.10 0.02 260 / 0.85); /* glass overlay */
|
||||
|
||||
/* Borders & dividers */
|
||||
--border-subtle: oklch(0.22 0.02 260); /* very faint border */
|
||||
--border-default: oklch(0.30 0.03 260); /* visible border */
|
||||
|
||||
/* Text */
|
||||
--text-primary: oklch(0.96 0.005 260); /* white-ish */
|
||||
--text-secondary: oklch(0.65 0.02 260); /* gray */
|
||||
--text-tertiary: oklch(0.45 0.02 260); /* dim gray */
|
||||
--text-placeholder: oklch(0.35 0.02 260); /* placeholder text */
|
||||
|
||||
/* Accents — gradient pair */
|
||||
--accent-start: oklch(0.65 0.20 262); /* vibrant blue */
|
||||
--accent-end: oklch(0.60 0.25 290); /* vibrant purple */
|
||||
--accent-glow: oklch(0.65 0.20 262 / 0.25); /* blue glow */
|
||||
|
||||
/* Semantic — green (positive) */
|
||||
--positive: oklch(0.70 0.18 155); /* emerald */
|
||||
--positive-dim: oklch(0.70 0.18 155 / 0.12);
|
||||
|
||||
/* Semantic — red (negative) */
|
||||
--negative: oklch(0.60 0.22 25); /* red */
|
||||
--negative-dim: oklch(0.60 0.22 25 / 0.12);
|
||||
|
||||
/* Semantic — amber (warning) */
|
||||
--warning: oklch(0.72 0.18 70); /* amber */
|
||||
--warning-dim: oklch(0.72 0.18 70 / 0.12);
|
||||
|
||||
/* Semantic — teal (info) */
|
||||
--info: oklch(0.65 0.15 190); /* teal */
|
||||
--info-dim: oklch(0.65 0.15 190 / 0.12);
|
||||
}
|
||||
```
|
||||
|
||||
### Spacing (4px base)
|
||||
|
||||
```
|
||||
--space-1: 0.25rem (4px)
|
||||
--space-2: 0.5rem (8px)
|
||||
--space-3: 0.75rem (12px)
|
||||
--space-4: 1rem (16px)
|
||||
--space-5: 1.25rem (20px)
|
||||
--space-6: 1.5rem (24px)
|
||||
--space-8: 2rem (32px)
|
||||
--space-10: 2.5rem (40px)
|
||||
--space-12: 3rem (48px)
|
||||
--space-16: 4rem (64px)
|
||||
```
|
||||
|
||||
### Typography
|
||||
|
||||
| Level | Weight | Size | Family | Use |
|
||||
|-------|--------|------|--------|-----|
|
||||
| Display | 700 | 2.5rem (40px) | Inter | Page titles |
|
||||
| H1 | 700 | 2rem (32px) | Inter | Section headers |
|
||||
| H2 | 600 | 1.25rem (20px) | Inter | Sub-headers |
|
||||
| H3 | 600 | 1.125rem (18px) | Inter | Card titles |
|
||||
| Body | 400/500 | 1rem (16px) | Inter | Body text |
|
||||
| Body-sm | 400/500 | 0.875rem (14px) | Inter | Secondary text |
|
||||
| Caption | 500 | 0.75rem (12px) | Inter | Labels, timestamps |
|
||||
| Mono | 500 | 1rem (16px) | JetBrains Mono | Numbers, tickers |
|
||||
| Mono-sm | 500 | 0.875rem (14px) | JetBrains Mono | Small numbers |
|
||||
| Mono-xs | 500 | 0.6875rem (11px) | JetBrains Mono | Micro numbers |
|
||||
|
||||
### Shadows & Effects
|
||||
|
||||
```css
|
||||
--shadow-card: 0 1px 3px oklch(0 0 0 / 0.3), 0 0 1px oklch(0 0 0 / 0.5);
|
||||
--shadow-raised: 0 4px 12px oklch(0 0 0 / 0.4), 0 0 1px oklch(0 0 0 / 0.5);
|
||||
--shadow-glow-accent: 0 0 30px oklch(0.65 0.20 262 / 0.15);
|
||||
--shadow-glow-positive: 0 0 20px oklch(0.70 0.18 155 / 0.1);
|
||||
--blur-sm: blur(4px);
|
||||
--blur-md: blur(8px);
|
||||
--blur-lg: blur(16px);
|
||||
--glass-bg: bg with backdrop-filter: blur(12px) + semi-transparent bg;
|
||||
--gradient-accent: linear-gradient(135deg, var(--accent-start), var(--accent-end));
|
||||
```
|
||||
|
||||
### Border Radius
|
||||
|
||||
```
|
||||
--radius-sm: 0.5rem (8px) /* small elements, pills */
|
||||
--radius-md: 0.75rem (12px) /* cards, buttons */
|
||||
--radius-lg: 1rem (16px) /* large cards, modals */
|
||||
--radius-xl: 1.25rem (20px) /* hero sections */
|
||||
--radius-full: 9999px /* pills, badges */
|
||||
```
|
||||
|
||||
### Breakpoints
|
||||
|
||||
```
|
||||
sm: 375px (mobile base)
|
||||
md: 768px (tablet)
|
||||
lg: 1024px (desktop)
|
||||
xl: 1280px (large desktop)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Specifications
|
||||
|
||||
### Glass Card
|
||||
- bg: `--bg-surface` (oklch 0.12)
|
||||
- border: `1px solid --border-subtle`
|
||||
- border-radius: `--radius-lg` (12px)
|
||||
- shadow: `--shadow-card`
|
||||
- padding: `--space-6`
|
||||
- hover: lift slightly (translateY -2px), shadow increases
|
||||
|
||||
### Primary Button
|
||||
- bg: `--gradient-accent`
|
||||
- text: white, 500 weight
|
||||
- border-radius: `--radius-md`
|
||||
- padding: `--space-3` `--space-6`
|
||||
- hover: brightness 1.1, shadow `--shadow-glow-accent`
|
||||
- active: scale 0.98
|
||||
|
||||
### Stat Card (small card with icon)
|
||||
- bg: `--bg-raised`
|
||||
- border: `1px solid --border-subtle`
|
||||
- border-radius: `--radius-md`
|
||||
- icon: 36x36, bg with accent tint (opacity 0.15)
|
||||
- padding: `--space-4`
|
||||
|
||||
### Chart
|
||||
- Gradient area fill under line
|
||||
- Line: 2px stroke, gradient color
|
||||
- Dot on last point: 6px circle with glow
|
||||
- Grid lines: `--border-subtle`, dashed
|
||||
- Labels: `--text-tertiary`, mono font
|
||||
|
||||
### Nav Pill (tab selector)
|
||||
- bg: `--bg-raised`
|
||||
- border: `1px solid --border-subtle`
|
||||
- border-radius: `--radius-full` (pill shape)
|
||||
- active item: bg with `--accent-start`, text white
|
||||
|
||||
### Badge/Pill
|
||||
- border-radius: `--radius-full`
|
||||
- padding: `2px 10px`
|
||||
- font-size: `--caption`
|
||||
- bg: semantic tint (positive-dim, negative-dim, etc.)
|
||||
- text: semantic color
|
||||
|
||||
---
|
||||
|
||||
## Visual Design Principles
|
||||
|
||||
1. **Dark first** — all surfaces are dark, accents provide color
|
||||
2. **Glassmorphism** — translucent cards with blur, subtle borders
|
||||
3. **Gradient accents** — blue-to-purple gradients for primary actions and chart fills
|
||||
4. **Spacious** — generous padding, breathing room between elements
|
||||
5. **Data hierarchy** — numbers in monospace, large and prominent; labels smaller and dim
|
||||
6. **Semantic color** — green for positive, red for negative, blue/purple for brand
|
||||
7. **Glow effects** — subtle colored glows around key elements (charts, active states)
|
||||
8. **Smooth transitions** — 150-200ms ease-out for all interactive states
|
||||
@@ -0,0 +1,47 @@
|
||||
# Invest Copilot — Design System
|
||||
|
||||
Dark-first, glassmorphic fintech aesthetic. Inspired by Dribbble's top fintech dashboards (Linear, Stripe, trading apps).
|
||||
|
||||
## Preview
|
||||
|
||||
Open in browser:
|
||||
|
||||
```bash
|
||||
# Desktop Dashboard
|
||||
open design-systems/financial/dashboard.html
|
||||
|
||||
# Mobile Dashboard (PWA)
|
||||
open design-systems/financial/mobile-dashboard.html
|
||||
|
||||
# Stock Detail Page
|
||||
open design-systems/financial/stock-detail.html
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `DESIGN.md` | Complete design tokens: colors (OKLch), spacing, typography, components, effects |
|
||||
| `dashboard.html` | Desktop dashboard prototype (responsive 1400px max) |
|
||||
| `mobile-dashboard.html` | Mobile PWA prototype (375px base, safe areas) |
|
||||
| `stock-detail.html` | Stock detail page with stats, ownership, SEC filings |
|
||||
|
||||
## Visual Design
|
||||
|
||||
- **Theme:** Dark — near-black backgrounds (#0c0b14), deep blue-gray surfaces
|
||||
- **Cards:** Translucent with subtle borders, soft shadows
|
||||
- **Accents:** Blue-to-purple gradient (#6366f1 → #a855f7)
|
||||
- **Charts:** Gradient area fills, gradient lines, glowing endpoint dots
|
||||
- **Typography:** Inter (UI) + JetBrains Mono (numbers/tickers)
|
||||
- **Semantic color:** Emerald (positive), red (negative), amber (warning)
|
||||
- **Spacing:** Generous — breathing room between elements
|
||||
- **Effects:** Subtle glows on active elements, smooth 150-200ms transitions
|
||||
|
||||
## Mobile-First
|
||||
|
||||
All prototypes are mobile-first. The mobile dashboard uses:
|
||||
- Bottom navigation bar with glass effect
|
||||
- Scrollable content with safe area support
|
||||
- Touch-friendly tap targets (40px min)
|
||||
- Horizontal scroll for heatmap on small screens
|
||||
- PWA meta tags for installability
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,638 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name="theme-color" content="#0c0b14" />
|
||||
<title>Invest Copilot</title>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
:root {
|
||||
--bg-deep: #0c0b14;
|
||||
--bg-surface: #131220;
|
||||
--bg-raised: #1a1930;
|
||||
--bg-hover: #222140;
|
||||
--border-subtle: rgba(255,255,255,0.06);
|
||||
--border-default: rgba(255,255,255,0.10);
|
||||
--text-primary: #f1f0f7;
|
||||
--text-secondary: #8b87a3;
|
||||
--text-tertiary: #5c5878;
|
||||
--accent-start: #6366f1;
|
||||
--accent-end: #a855f7;
|
||||
--positive: #34d399;
|
||||
--positive-dim: rgba(52,211,153,0.10);
|
||||
--negative: #f87171;
|
||||
--negative-dim: rgba(248,113,113,0.10);
|
||||
--warning: #fbbf24;
|
||||
--warning-dim: rgba(251,191,36,0.10);
|
||||
--gradient-accent: linear-gradient(135deg, #6366f1, #a855f7);
|
||||
--gradient-positive: linear-gradient(135deg, #34d399, #22d3ee);
|
||||
--radius-sm: 8px;
|
||||
--radius-md: 12px;
|
||||
--radius-lg: 16px;
|
||||
--radius-xl: 20px;
|
||||
--radius-full: 9999px;
|
||||
}
|
||||
html { font-size: 16px; }
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, sans-serif;
|
||||
background: var(--bg-deep);
|
||||
color: var(--text-primary);
|
||||
line-height: 1.5;
|
||||
min-height: 100vh;
|
||||
min-height: 100dvh;
|
||||
padding-bottom: 76px;
|
||||
overflow-x: hidden;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.mono { font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
/* Header */
|
||||
.header {
|
||||
padding: 16px 20px 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.header__left { display: flex; align-items: center; gap: 12px; }
|
||||
.header__logo {
|
||||
width: 36px; height: 36px;
|
||||
background: var(--gradient-accent);
|
||||
border-radius: var(--radius-sm);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
box-shadow: 0 0 16px rgba(99,102,241,0.3);
|
||||
}
|
||||
.header__logo svg { width: 20px; height: 20px; }
|
||||
.header__title { font-size: 1.125rem; font-weight: 700; letter-spacing: -0.01em; }
|
||||
.header__actions { display: flex; gap: 8px; }
|
||||
.header__btn {
|
||||
width: 40px; height: 40px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.header__btn svg { width: 18px; height: 18px; }
|
||||
.header__btn .dot {
|
||||
position: absolute; top: 6px; right: 6px;
|
||||
width: 7px; height: 7px;
|
||||
background: var(--negative);
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--bg-surface);
|
||||
}
|
||||
|
||||
/* Search */
|
||||
.search {
|
||||
margin: 0 20px 20px;
|
||||
position: relative;
|
||||
}
|
||||
.search__input {
|
||||
width: 100%;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 12px 16px 12px 42px;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.875rem;
|
||||
font-family: 'Inter', sans-serif;
|
||||
outline: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
.search__input::placeholder { color: var(--text-tertiary); }
|
||||
.search__input:focus { border-color: var(--accent-start); }
|
||||
.search__icon {
|
||||
position: absolute; left: 14px; top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 16px; height: 16px;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.content {
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* Hero Card */
|
||||
.hero-card {
|
||||
background: linear-gradient(135deg, rgba(99,102,241,0.08), rgba(168,85,247,0.08));
|
||||
border: 1px solid rgba(99,102,241,0.15);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 24px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.hero-card__label { font-size: 0.75rem; color: var(--text-secondary); font-weight: 500; margin-bottom: 4px; }
|
||||
.hero-card__value {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
line-height: 1;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.hero-card__change {
|
||||
display: inline-flex; align-items: center; gap: 5px;
|
||||
padding: 5px 12px;
|
||||
border-radius: var(--radius-full);
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
background: var(--positive-dim);
|
||||
color: var(--positive);
|
||||
}
|
||||
.hero-card__change svg { width: 13px; height: 13px; }
|
||||
.hero-card__meta {
|
||||
display: flex; justify-content: center; gap: 28px; margin-top: 16px;
|
||||
}
|
||||
.hero-card__meta-item { text-align: center; }
|
||||
.hero-card__meta-val { font-size: 0.875rem; font-weight: 600; font-family: 'JetBrains Mono', monospace; }
|
||||
.hero-card__meta-label { font-size: 0.625rem; color: var(--text-tertiary); margin-top: 1px; }
|
||||
|
||||
/* Quick Actions */
|
||||
.quick-actions {
|
||||
display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
|
||||
}
|
||||
.quick-action {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 16px 12px;
|
||||
text-align: center;
|
||||
transition: transform 100ms, background 150ms;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.quick-action:active { transform: scale(0.96); background: var(--bg-raised); }
|
||||
.quick-action__icon {
|
||||
width: 40px; height: 40px;
|
||||
border-radius: var(--radius-sm);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
margin: 0 auto 8px;
|
||||
}
|
||||
.quick-action__icon svg { width: 18px; height: 18px; }
|
||||
.quick-action__icon--accent { background: rgba(99,102,241,0.12); color: var(--accent-start); }
|
||||
.quick-action__icon--positive { background: var(--positive-dim); color: var(--positive); }
|
||||
.quick-action__icon--warning { background: var(--warning-dim); color: var(--warning); }
|
||||
.quick-action__label { font-size: 0.6875rem; font-weight: 500; color: var(--text-secondary); }
|
||||
|
||||
/* Mini Chart */
|
||||
.chart-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 16px;
|
||||
}
|
||||
.chart-card__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
|
||||
.chart-card__title { font-size: 0.875rem; font-weight: 600; }
|
||||
.chart-card__badge {
|
||||
font-size: 0.625rem;
|
||||
padding: 3px 10px;
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--bg-raised);
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
.chart-card__svg { width: 100%; height: 120px; }
|
||||
.chart-card__svg line.grid { stroke: var(--border-subtle); stroke-width: 0.5; stroke-dasharray: 4 4; }
|
||||
.chart-card__svg text { fill: var(--text-tertiary); font-size: 9px; font-family: 'JetBrains Mono', monospace; }
|
||||
.chart-card__svg .area-fill { fill: url(#mChartGrad); opacity: 0.3; }
|
||||
.chart-card__svg .chart-line { fill: none; stroke: url(#mLineGrad); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
||||
|
||||
/* Section */
|
||||
.section-header { display: flex; justify-content: space-between; align-items: center; }
|
||||
.section-title { font-size: 0.9375rem; font-weight: 600; }
|
||||
.section-link { font-size: 0.6875rem; color: var(--accent-start); font-weight: 500; }
|
||||
|
||||
/* Watchlist */
|
||||
.watchlist { display: flex; flex-direction: column; gap: 8px; }
|
||||
.watchlist-item {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 14px;
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
transition: background 150ms;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.watchlist-item:active { background: var(--bg-raised); }
|
||||
.watchlist-item__icon {
|
||||
width: 36px; height: 36px;
|
||||
border-radius: var(--radius-sm);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 0.6875rem; font-weight: 700;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.watchlist-item__icon--green { background: var(--positive-dim); color: var(--positive); }
|
||||
.watchlist-item__icon--accent { background: rgba(99,102,241,0.12); color: var(--accent-start); }
|
||||
.watchlist-item__icon--purple { background: rgba(168,85,247,0.12); color: var(--accent-end); }
|
||||
.watchlist-item__info { flex: 1; min-width: 0; }
|
||||
.watchlist-item__name { font-size: 0.8125rem; font-weight: 600; }
|
||||
.watchlist-item__ticker { font-size: 0.625rem; color: var(--text-tertiary); font-family: 'JetBrains Mono', monospace; }
|
||||
.watchlist-item__price { text-align: right; flex-shrink: 0; }
|
||||
.watchlist-item__price-val { font-family: 'JetBrains Mono', monospace; font-size: 0.8125rem; font-weight: 600; }
|
||||
.change-pill {
|
||||
display: inline-flex; align-items: center; gap: 2px;
|
||||
padding: 2px 6px;
|
||||
border-radius: var(--radius-full);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
}
|
||||
.change-pill--positive { background: var(--positive-dim); color: var(--positive); }
|
||||
.change-pill--negative { background: var(--negative-dim); color: var(--negative); }
|
||||
.change-pill svg { width: 8px; height: 8px; }
|
||||
|
||||
/* Heatmap scroll */
|
||||
.heatmap-scroll {
|
||||
display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px;
|
||||
-webkit-overflow-scrolling: touch; scrollbar-width: none;
|
||||
}
|
||||
.heatmap-scroll::-webkit-scrollbar { display: none; }
|
||||
.heatmap-cell {
|
||||
min-width: 80px;
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 14px;
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center; gap: 2px;
|
||||
flex-shrink: 0;
|
||||
transition: transform 100ms;
|
||||
}
|
||||
.heatmap-cell:active { transform: scale(0.95); }
|
||||
.heatmap-cell .label { font-size: 0.6875rem; font-weight: 700; font-family: 'JetBrains Mono', monospace; }
|
||||
.heatmap-cell .value { font-size: 0.75rem; font-weight: 600; font-family: 'JetBrains Mono', monospace; }
|
||||
.heatmap-cell--strong-pos { background: rgba(52,211,153,0.15); color: var(--positive); }
|
||||
.heatmap-cell--pos { background: rgba(52,211,153,0.08); color: var(--positive); }
|
||||
.heatmap-cell--neutral { background: rgba(255,255,255,0.03); color: var(--text-secondary); }
|
||||
.heatmap-cell--neg { background: rgba(248,113,113,0.08); color: var(--negative); }
|
||||
.heatmap-cell--strong-neg { background: rgba(248,113,113,0.15); color: var(--negative); }
|
||||
|
||||
/* Alerts */
|
||||
.alert-item {
|
||||
display: flex; align-items: flex-start; gap: 10px;
|
||||
padding: 12px 14px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
transition: all 150ms;
|
||||
}
|
||||
.alert-item--unread { border-left: 3px solid var(--accent-start); }
|
||||
.alert-item__dot {
|
||||
width: 8px; height: 8px; border-radius: 50%; margin-top: 4px; flex-shrink: 0;
|
||||
}
|
||||
.alert-item__dot--accent { background: var(--accent-start); box-shadow: 0 0 6px rgba(99,102,241,0.4); }
|
||||
.alert-item__dot--warning { background: var(--warning); }
|
||||
.alert-item__dot--positive { background: var(--positive); }
|
||||
.alert-item__content { flex: 1; }
|
||||
.alert-item__title { font-size: 0.75rem; font-weight: 500; line-height: 1.3; }
|
||||
.alert-item__time { font-size: 0.5625rem; color: var(--text-tertiary); font-family: 'JetBrains Mono', monospace; white-space: nowrap; margin-top: 2px; }
|
||||
|
||||
/* Bottom Nav */
|
||||
.bottom-nav {
|
||||
position: fixed; bottom: 0; left: 0; right: 0;
|
||||
background: rgba(19,18,32,0.95);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border-top: 1px solid var(--border-subtle);
|
||||
padding: 8px 0;
|
||||
padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
|
||||
z-index: 100;
|
||||
}
|
||||
.bottom-nav__items { display: flex; justify-content: space-around; }
|
||||
.bottom-nav__item {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 3px;
|
||||
padding: 6px 16px;
|
||||
color: var(--text-tertiary);
|
||||
font-size: 0.5625rem; font-weight: 500;
|
||||
transition: color 150ms;
|
||||
}
|
||||
.bottom-nav__item svg { width: 22px; height: 22px; }
|
||||
.bottom-nav__item--active { color: var(--accent-start); }
|
||||
.bottom-nav__item:active { opacity: 0.6; }
|
||||
|
||||
/* Gradient defs */
|
||||
svg defs linearGradient { display: block; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header -->
|
||||
<header class="header">
|
||||
<div class="header__left">
|
||||
<div class="header__logo">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
|
||||
<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/>
|
||||
<polyline points="16 7 22 7 22 13"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="header__title">Invest Copilot</span>
|
||||
</div>
|
||||
<div class="header__actions">
|
||||
<button class="header__btn" style="position:relative" aria-label="Notifications">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
|
||||
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
||||
</svg>
|
||||
<span class="dot"></span>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Search -->
|
||||
<div class="search">
|
||||
<svg class="search__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
||||
</svg>
|
||||
<input class="search__input" type="text" placeholder="Search AAPL, NVDA, QQQ..." />
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="content">
|
||||
<!-- Hero -->
|
||||
<div class="hero-card">
|
||||
<div class="hero-card__label">Portfolio Value</div>
|
||||
<div class="hero-card__value">$147,832</div>
|
||||
<div class="hero-card__change">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"/></svg>
|
||||
+$2,341 (1.61%)
|
||||
</div>
|
||||
<div class="hero-card__meta">
|
||||
<div class="hero-card__meta-item">
|
||||
<div class="hero-card__meta-val" style="color:var(--positive)">+$1,204</div>
|
||||
<div class="hero-card__meta-label">Today</div>
|
||||
</div>
|
||||
<div class="hero-card__meta-item">
|
||||
<div class="hero-card__meta-val">12</div>
|
||||
<div class="hero-card__meta-label">Positions</div>
|
||||
</div>
|
||||
<div class="hero-card__meta-item">
|
||||
<div class="hero-card__meta-val" style="color:var(--warning)">3</div>
|
||||
<div class="hero-card__meta-label">Alerts</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<div class="quick-actions">
|
||||
<div class="quick-action">
|
||||
<div class="quick-action__icon quick-action__icon--accent">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="quick-action__label">Watchlist</span>
|
||||
</div>
|
||||
<div class="quick-action">
|
||||
<div class="quick-action__icon quick-action__icon--positive">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/>
|
||||
<polyline points="17 6 23 6 23 12"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="quick-action__label">Stocks</span>
|
||||
</div>
|
||||
<div class="quick-action">
|
||||
<div class="quick-action__icon quick-action__icon--warning">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2"/>
|
||||
<line x1="3" y1="9" x2="21" y2="9"/>
|
||||
<line x1="9" y1="21" x2="9" y2="9"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="quick-action__label">Sectors</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chart -->
|
||||
<div class="chart-card">
|
||||
<div class="chart-card__header">
|
||||
<span class="chart-card__title">Portfolio</span>
|
||||
<span class="chart-card__badge">3M</span>
|
||||
</div>
|
||||
<svg class="chart-card__svg" viewBox="0 0 320 120" preserveAspectRatio="none">
|
||||
<defs>
|
||||
<linearGradient id="mLineGrad" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style="stop-color:#6366f1"/>
|
||||
<stop offset="100%" style="stop-color:#a855f7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="mChartGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#6366f1;stop-opacity:0.3"/>
|
||||
<stop offset="100%" style="stop-color:#6366f1;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<line class="grid" x1="0" y1="30" x2="320" y2="30"/>
|
||||
<line class="grid" x1="0" y1="60" x2="320" y2="60"/>
|
||||
<line class="grid" x1="0" y1="90" x2="320" y2="90"/>
|
||||
<text x="8" y="26">155K</text>
|
||||
<text x="8" y="56">145K</text>
|
||||
<text x="8" y="86">135K</text>
|
||||
<path class="area-fill" d="M0,70 L40,64 80,58 120,52 160,44 200,40 240,34 280,30 320,24 L320,120 L0,120 Z"/>
|
||||
<path class="chart-line" d="M0,70 L40,64 80,58 120,52 160,44 200,40 240,34 280,30 320,24"/>
|
||||
<circle cx="320" cy="24" r="3" fill="#6366f1" stroke="#131220" stroke-width="2"/>
|
||||
<text x="290" y="116">Sep 26</text>
|
||||
<text x="8" y="116">May 26</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- Watchlist -->
|
||||
<div>
|
||||
<div class="section-header">
|
||||
<span class="section-title">Watchlist</span>
|
||||
<a href="#" class="section-link">View All →</a>
|
||||
</div>
|
||||
<div class="watchlist">
|
||||
<div class="watchlist-item">
|
||||
<div class="watchlist-item__icon watchlist-item__icon--green">A</div>
|
||||
<div class="watchlist-item__info">
|
||||
<div class="watchlist-item__name">Apple</div>
|
||||
<div class="watchlist-item__ticker">AAPL</div>
|
||||
</div>
|
||||
<div class="watchlist-item__price">
|
||||
<div class="watchlist-item__price-val">$189.43</div>
|
||||
<span class="change-pill change-pill--positive">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"/></svg>
|
||||
+2.4%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="watchlist-item">
|
||||
<div class="watchlist-item__icon watchlist-item__icon--accent">M</div>
|
||||
<div class="watchlist-item__info">
|
||||
<div class="watchlist-item__name">Microsoft</div>
|
||||
<div class="watchlist-item__ticker">MSFT</div>
|
||||
</div>
|
||||
<div class="watchlist-item__price">
|
||||
<div class="watchlist-item__price-val">$412.88</div>
|
||||
<span class="change-pill change-pill--positive">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"/></svg>
|
||||
+1.1%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="watchlist-item">
|
||||
<div class="watchlist-item__icon watchlist-item__icon--purple">N</div>
|
||||
<div class="watchlist-item__info">
|
||||
<div class="watchlist-item__name">NVIDIA</div>
|
||||
<div class="watchlist-item__ticker">NVDA</div>
|
||||
</div>
|
||||
<div class="watchlist-item__price">
|
||||
<div class="watchlist-item__price-val">$121.88</div>
|
||||
<span class="change-pill change-pill--negative">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>
|
||||
−0.3%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="watchlist-item">
|
||||
<div class="watchlist-item__icon watchlist-item__icon--accent">G</div>
|
||||
<div class="watchlist-item__info">
|
||||
<div class="watchlist-item__name">Alphabet</div>
|
||||
<div class="watchlist-item__ticker">GOOGL</div>
|
||||
</div>
|
||||
<div class="watchlist-item__price">
|
||||
<div class="watchlist-item__price-val">$141.26</div>
|
||||
<span class="change-pill change-pill--negative">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>
|
||||
−0.8%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="watchlist-item">
|
||||
<div class="watchlist-item__icon watchlist-item__icon--green">M</div>
|
||||
<div class="watchlist-item__info">
|
||||
<div class="watchlist-item__name">Meta</div>
|
||||
<div class="watchlist-item__ticker">META</div>
|
||||
</div>
|
||||
<div class="watchlist-item__price">
|
||||
<div class="watchlist-item__price-val">$502.30</div>
|
||||
<span class="change-pill change-pill--positive">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"/></svg>
|
||||
+0.5%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sector Heatmap -->
|
||||
<div>
|
||||
<div class="section-header">
|
||||
<span class="section-title">Sectors</span>
|
||||
<a href="#" class="section-link">View All →</a>
|
||||
</div>
|
||||
<div class="heatmap-scroll">
|
||||
<div class="heatmap-cell heatmap-cell--strong-pos">
|
||||
<span class="label">XLK</span>
|
||||
<span class="value">+8.2%</span>
|
||||
</div>
|
||||
<div class="heatmap-cell heatmap-cell--pos">
|
||||
<span class="label">XLF</span>
|
||||
<span class="value">+3.1%</span>
|
||||
</div>
|
||||
<div class="heatmap-cell heatmap-cell--pos">
|
||||
<span class="label">XLY</span>
|
||||
<span class="value">+2.8%</span>
|
||||
</div>
|
||||
<div class="heatmap-cell heatmap-cell--pos">
|
||||
<span class="label">XLI</span>
|
||||
<span class="value">+2.4%</span>
|
||||
</div>
|
||||
<div class="heatmap-cell heatmap-cell--pos">
|
||||
<span class="label">XLV</span>
|
||||
<span class="value">+1.5%</span>
|
||||
</div>
|
||||
<div class="heatmap-cell heatmap-cell--neutral">
|
||||
<span class="label">XLP</span>
|
||||
<span class="value">+0.3%</span>
|
||||
</div>
|
||||
<div class="heatmap-cell heatmap-cell--neg">
|
||||
<span class="label">XLU</span>
|
||||
<span class="value">−0.2%</span>
|
||||
</div>
|
||||
<div class="heatmap-cell heatmap-cell--neg">
|
||||
<span class="label">XLE</span>
|
||||
<span class="value">−1.8%</span>
|
||||
</div>
|
||||
<div class="heatmap-cell heatmap-cell--strong-neg">
|
||||
<span class="label">XLR</span>
|
||||
<span class="value">−3.4%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alerts -->
|
||||
<div>
|
||||
<div class="section-header">
|
||||
<span class="section-title">Alerts</span>
|
||||
<a href="#" class="section-link">View All →</a>
|
||||
</div>
|
||||
<div class="alert-list" style="display:flex;flex-direction:column;gap:8px;margin-top:12px;">
|
||||
<div class="alert-item alert-item--unread">
|
||||
<div class="alert-item__dot alert-item__dot--negative" style="background:var(--negative)"></div>
|
||||
<div class="alert-item__content">
|
||||
<div class="alert-item__title">NVDA below 200-day MA</div>
|
||||
<div class="alert-item__time">14:27 · Today</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert-item alert-item--unread">
|
||||
<div class="alert-item__dot alert-item__dot--warning"></div>
|
||||
<div class="alert-item__content">
|
||||
<div class="alert-item__title">Sector rotation: Tech → Energy</div>
|
||||
<div class="alert-item__time">13:45 · Today</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert-item">
|
||||
<div class="alert-item__dot alert-item__dot--positive"></div>
|
||||
<div class="alert-item__content">
|
||||
<div class="alert-item__title">AAPL insider buy — 5,000 shares</div>
|
||||
<div class="alert-item__time">11:20 · Today</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Nav -->
|
||||
<nav class="bottom-nav">
|
||||
<div class="bottom-nav__items">
|
||||
<a href="#" class="bottom-nav__item bottom-nav__item--active">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<rect x="3" y="3" width="7" height="7" rx="1"/>
|
||||
<rect x="14" y="3" width="7" height="7" rx="1"/>
|
||||
<rect x="3" y="14" width="7" height="7" rx="1"/>
|
||||
<rect x="14" y="14" width="7" height="7" rx="1"/>
|
||||
</svg>
|
||||
Home
|
||||
</a>
|
||||
<a href="#" class="bottom-nav__item">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
||||
</svg>
|
||||
Search
|
||||
</a>
|
||||
<a href="#" class="bottom-nav__item">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
|
||||
</svg>
|
||||
Watchlists
|
||||
</a>
|
||||
<a href="#" class="bottom-nav__item">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
|
||||
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
||||
</svg>
|
||||
Alerts
|
||||
</a>
|
||||
<a href="#" class="bottom-nav__item">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
||||
</svg>
|
||||
Settings
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,521 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name="theme-color" content="#0c0b14" />
|
||||
<title>Apple — AAPL</title>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
:root {
|
||||
--bg-deep: #0c0b14;
|
||||
--bg-surface: #131220;
|
||||
--bg-raised: #1a1930;
|
||||
--bg-hover: #222140;
|
||||
--border-subtle: rgba(255,255,255,0.06);
|
||||
--border-default: rgba(255,255,255,0.10);
|
||||
--text-primary: #f1f0f7;
|
||||
--text-secondary: #8b87a3;
|
||||
--text-tertiary: #5c5878;
|
||||
--accent-start: #6366f1;
|
||||
--accent-end: #a855f7;
|
||||
--positive: #34d399;
|
||||
--positive-dim: rgba(52,211,153,0.10);
|
||||
--negative: #f87171;
|
||||
--negative-dim: rgba(248,113,113,0.10);
|
||||
--warning: #fbbf24;
|
||||
--warning-dim: rgba(251,191,36,0.10);
|
||||
--gradient-accent: linear-gradient(135deg, #6366f1, #a855f7);
|
||||
--gradient-positive: linear-gradient(135deg, #34d399, #22d3ee);
|
||||
--radius-sm: 8px;
|
||||
--radius-md: 12px;
|
||||
--radius-lg: 16px;
|
||||
--radius-xl: 20px;
|
||||
--radius-full: 9999px;
|
||||
}
|
||||
html { font-size: 16px; }
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, sans-serif;
|
||||
background: var(--bg-deep);
|
||||
color: var(--text-primary);
|
||||
line-height: 1.5;
|
||||
min-height: 100vh;
|
||||
min-height: 100dvh;
|
||||
padding-bottom: 76px;
|
||||
overflow-x: hidden;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.mono { font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
/* Header */
|
||||
.header {
|
||||
padding: 12px 20px;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
}
|
||||
.header__left { display: flex; align-items: center; gap: 12px; }
|
||||
.header__back {
|
||||
width: 40px; height: 40px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.header__back svg { width: 18px; height: 18px; }
|
||||
.header__right { display: flex; gap: 8px; }
|
||||
.header__btn {
|
||||
width: 40px; height: 40px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.header__btn svg { width: 18px; height: 18px; }
|
||||
|
||||
/* Stock Info */
|
||||
.stock-info {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
.stock-info__ticker {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
}
|
||||
.stock-info__logo {
|
||||
width: 44px; height: 44px;
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--positive-dim);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 1.125rem; font-weight: 800; font-family: 'JetBrains Mono', monospace; color: var(--positive);
|
||||
}
|
||||
.stock-info__names { }
|
||||
.stock-info__name { font-size: 1.25rem; font-weight: 700; }
|
||||
.stock-info__sub { font-size: 0.75rem; color: var(--text-tertiary); }
|
||||
.stock-info__price-block {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.stock-info__price {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
line-height: 1;
|
||||
}
|
||||
.stock-info__change {
|
||||
display: inline-flex; align-items: center; gap: 5px;
|
||||
padding: 5px 12px;
|
||||
border-radius: var(--radius-full);
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
background: var(--positive-dim);
|
||||
color: var(--positive);
|
||||
margin-top: 8px;
|
||||
}
|
||||
.stock-info__change svg { width: 13px; height: 13px; }
|
||||
|
||||
/* Period Tabs */
|
||||
.period-tabs {
|
||||
padding: 0 20px 16px;
|
||||
display: flex; gap: 6px;
|
||||
}
|
||||
.period-tab {
|
||||
padding: 6px 14px;
|
||||
border-radius: var(--radius-full);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
color: var(--text-secondary);
|
||||
transition: all 150ms;
|
||||
}
|
||||
.period-tab--active {
|
||||
background: var(--gradient-accent);
|
||||
color: white;
|
||||
border-color: transparent;
|
||||
}
|
||||
.period-tab:active { transform: scale(0.95); }
|
||||
|
||||
/* Chart */
|
||||
.chart-section {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
.chart-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 16px;
|
||||
}
|
||||
.chart-card__svg { width: 100%; height: 160px; }
|
||||
.chart-card__svg line.grid { stroke: var(--border-subtle); stroke-width: 0.5; stroke-dasharray: 4 4; }
|
||||
.chart-card__svg text { fill: var(--text-tertiary); font-size: 9px; font-family: 'JetBrains Mono', monospace; }
|
||||
.chart-card__svg .area-fill { fill: url(#dChartGrad); opacity: 0.3; }
|
||||
.chart-card__svg .chart-line { fill: none; stroke: url(#dLineGrad); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
||||
|
||||
/* Stats Grid */
|
||||
.stats-section {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
.section-title { font-size: 0.9375rem; font-weight: 600; margin-bottom: 12px; }
|
||||
.stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
|
||||
.stat-cell {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 14px;
|
||||
}
|
||||
.stat-cell__label { font-size: 0.625rem; color: var(--text-tertiary); font-weight: 500; margin-bottom: 4px; }
|
||||
.stat-cell__value { font-size: 0.9375rem; font-weight: 600; font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
/* Tabs */
|
||||
.tabs {
|
||||
padding: 0 20px;
|
||||
display: flex; gap: 0;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
}
|
||||
.tab {
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
color: var(--text-tertiary);
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: all 150ms;
|
||||
}
|
||||
.tab--active { color: var(--accent-start); border-bottom-color: var(--accent-start); }
|
||||
|
||||
/* Institutional Ownership */
|
||||
.inst-section {
|
||||
padding: 20px;
|
||||
}
|
||||
.inst-bar {
|
||||
display: flex; align-items: center; gap: 12px; margin-bottom: 14px;
|
||||
}
|
||||
.inst-bar__label { font-size: 0.75rem; font-weight: 500; width: 80px; flex-shrink: 0; }
|
||||
.inst-bar__track {
|
||||
flex: 1; height: 8px; background: var(--bg-raised);
|
||||
border-radius: var(--radius-full); overflow: hidden;
|
||||
}
|
||||
.inst-bar__fill {
|
||||
height: 100%; border-radius: var(--radius-full);
|
||||
background: var(--gradient-accent);
|
||||
}
|
||||
.inst-bar__value { font-size: 0.75rem; font-weight: 600; font-family: 'JetBrains Mono', monospace; width: 44px; text-align: right; flex-shrink: 0; }
|
||||
|
||||
/* SEC Filings */
|
||||
.filing-section { padding: 0 20px 20px; }
|
||||
.filing-list { display: flex; flex-direction: column; gap: 8px; }
|
||||
.filing-item {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
padding: 14px;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
transition: background 150ms;
|
||||
}
|
||||
.filing-item:active { background: var(--bg-raised); }
|
||||
.filing-item__icon {
|
||||
width: 36px; height: 36px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: rgba(99,102,241,0.12);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
color: var(--accent-start);
|
||||
}
|
||||
.filing-item__icon svg { width: 16px; height: 16px; }
|
||||
.filing-item__info { flex: 1; }
|
||||
.filing-item__name { font-size: 0.8125rem; font-weight: 600; }
|
||||
.filing-item__date { font-size: 0.625rem; color: var(--text-tertiary); }
|
||||
.filing-item__tag {
|
||||
font-size: 0.5625rem;
|
||||
font-weight: 600;
|
||||
padding: 3px 8px;
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--positive-dim);
|
||||
color: var(--positive);
|
||||
}
|
||||
|
||||
/* Action Buttons */
|
||||
.action-bar {
|
||||
padding: 0 20px 12px;
|
||||
display: flex; gap: 10px;
|
||||
}
|
||||
.action-btn {
|
||||
flex: 1;
|
||||
padding: 14px;
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
font-family: 'Inter', sans-serif;
|
||||
text-align: center;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.action-btn--buy {
|
||||
background: var(--gradient-positive);
|
||||
color: #000;
|
||||
}
|
||||
.action-btn--watch {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* Bottom Nav */
|
||||
.bottom-nav {
|
||||
position: fixed; bottom: 0; left: 0; right: 0;
|
||||
background: rgba(19,18,32,0.95);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border-top: 1px solid var(--border-subtle);
|
||||
padding: 8px 0;
|
||||
padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
|
||||
z-index: 100;
|
||||
}
|
||||
.bottom-nav__items { display: flex; justify-content: space-around; }
|
||||
.bottom-nav__item {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 3px;
|
||||
padding: 6px 16px;
|
||||
color: var(--text-tertiary);
|
||||
font-size: 0.5625rem; font-weight: 500;
|
||||
}
|
||||
.bottom-nav__item svg { width: 22px; height: 22px; }
|
||||
.bottom-nav__item--active { color: var(--accent-start); }
|
||||
|
||||
/* Scroll */
|
||||
.content-scroll {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header -->
|
||||
<header class="header">
|
||||
<div class="header__left">
|
||||
<button class="header__back" aria-label="Back">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="header__right">
|
||||
<button class="header__btn" aria-label="Share">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
|
||||
<line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/>
|
||||
<line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="header__btn" aria-label="More">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Stock Info -->
|
||||
<div class="stock-info">
|
||||
<div class="stock-info__ticker">
|
||||
<div class="stock-info__logo">A</div>
|
||||
<div class="stock-info__names">
|
||||
<div class="stock-info__name">Apple Inc.</div>
|
||||
<div class="stock-info__sub">AAPL · NASDAQ · Tech · Consumer Electronics</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stock-info__price-block">
|
||||
<div class="stock-info__price">$189.43</div>
|
||||
<div class="stock-info__change">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"/></svg>
|
||||
+$4.42 (+2.39%)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Period Tabs -->
|
||||
<div class="period-tabs">
|
||||
<div class="period-tab">1D</div>
|
||||
<div class="period-tab">1W</div>
|
||||
<div class="period-tab">1M</div>
|
||||
<div class="period-tab period-tab--active">3M</div>
|
||||
<div class="period-tab">1Y</div>
|
||||
<div class="period-tab">5Y</div>
|
||||
</div>
|
||||
|
||||
<!-- Chart -->
|
||||
<div class="chart-section">
|
||||
<div class="chart-card">
|
||||
<svg class="chart-card__svg" viewBox="0 0 320 160" preserveAspectRatio="none">
|
||||
<defs>
|
||||
<linearGradient id="dLineGrad" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style="stop-color:#6366f1"/>
|
||||
<stop offset="100%" style="stop-color:#a855f7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="dChartGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#6366f1;stop-opacity:0.3"/>
|
||||
<stop offset="100%" style="stop-color:#6366f1;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<line class="grid" x1="0" y1="32" x2="320" y2="32"/>
|
||||
<line class="grid" x1="0" y1="64" x2="320" y2="64"/>
|
||||
<line class="grid" x1="0" y1="96" x2="320" y2="96"/>
|
||||
<line class="grid" x1="0" y1="128" x2="320" y2="128"/>
|
||||
<text x="8" y="28">195</text>
|
||||
<text x="8" y="60">185</text>
|
||||
<text x="8" y="92">175</text>
|
||||
<text x="8" y="124">165</text>
|
||||
<text x="40" y="156">Sep</text>
|
||||
<text x="130" y="156">Oct</text>
|
||||
<text x="230" y="156">Nov</text>
|
||||
<text x="290" y="156">Dec</text>
|
||||
<path class="area-fill" d="M0,96 L53,88 106,76 160,84 213,60 266,44 320,36 L320,160 L0,160 Z"/>
|
||||
<path class="chart-line" d="M0,96 L53,88 106,76 160,84 213,60 266,44 320,36"/>
|
||||
<circle cx="320" cy="36" r="3" fill="#6366f1" stroke="#131220" stroke-width="2"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Key Stats -->
|
||||
<div class="stats-section">
|
||||
<div class="section-title">Key Statistics</div>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-cell">
|
||||
<div class="stat-cell__label">Market Cap</div>
|
||||
<div class="stat-cell__value">$2.95T</div>
|
||||
</div>
|
||||
<div class="stat-cell">
|
||||
<div class="stat-cell__label">P/E Ratio</div>
|
||||
<div class="stat-cell__value">31.2</div>
|
||||
</div>
|
||||
<div class="stat-cell">
|
||||
<div class="stat-cell__label">52W High</div>
|
||||
<div class="stat-cell__value">$199.62</div>
|
||||
</div>
|
||||
<div class="stat-cell">
|
||||
<div class="stat-cell__label">52W Low</div>
|
||||
<div class="stat-cell__value">$142.45</div>
|
||||
</div>
|
||||
<div class="stat-cell">
|
||||
<div class="stat-cell__label">Avg Volume</div>
|
||||
<div class="stat-cell__value">54.2M</div>
|
||||
</div>
|
||||
<div class="stat-cell">
|
||||
<div class="stat-cell__label">EPS</div>
|
||||
<div class="stat-cell__value">$6.07</div>
|
||||
</div>
|
||||
<div class="stat-cell">
|
||||
<div class="stat-cell__label">Div Yield</div>
|
||||
<div class="stat-cell__value">0.51%</div>
|
||||
</div>
|
||||
<div class="stat-cell">
|
||||
<div class="stat-cell__label">Beta</div>
|
||||
<div class="stat-cell__value">1.29</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabs -->
|
||||
<div class="tabs" style="position:sticky; top:0; z-index:10; background:var(--bg-deep);">
|
||||
<div class="tab tab--active">Overview</div>
|
||||
<div class="tab">Ownership</div>
|
||||
<div class="tab">SEC</div>
|
||||
<div class="tab">Peers</div>
|
||||
</div>
|
||||
|
||||
<div class="content-scroll">
|
||||
<!-- Institutional Ownership -->
|
||||
<div class="inst-section">
|
||||
<div class="section-title">Institutional Ownership</div>
|
||||
<div class="inst-bar">
|
||||
<span class="inst-bar__label">Vanguard</span>
|
||||
<div class="inst-bar__track"><div class="inst-bar__fill" style="width:8.2%"></div></div>
|
||||
<span class="inst-bar__value">8.2%</span>
|
||||
</div>
|
||||
<div class="inst-bar">
|
||||
<span class="inst-bar__label">BlackRock</span>
|
||||
<div class="inst-bar__track"><div class="inst-bar__fill" style="width:6.5%"></div></div>
|
||||
<span class="inst-bar__value">6.5%</span>
|
||||
</div>
|
||||
<div class="inst-bar">
|
||||
<span class="inst-bar__label">Berkshire</span>
|
||||
<div class="inst-bar__track"><div class="inst-bar__fill" style="width:5.8%"></div></div>
|
||||
<span class="inst-bar__value">5.8%</span>
|
||||
</div>
|
||||
<div class="inst-bar">
|
||||
<span class="inst-bar__label">State Street</span>
|
||||
<div class="inst-bar__track"><div class="inst-bar__fill" style="width:4.1%"></div></div>
|
||||
<span class="inst-bar__value">4.1%</span>
|
||||
</div>
|
||||
<div class="inst-bar">
|
||||
<span class="inst-bar__label">Fidelity</span>
|
||||
<div class="inst-bar__track"><div class="inst-bar__fill" style="width:2.9%"></div></div>
|
||||
<span class="inst-bar__value">2.9%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEC Filings -->
|
||||
<div class="filing-section">
|
||||
<div class="section-title">Recent SEC Filings</div>
|
||||
<div class="filing-list">
|
||||
<div class="filing-item">
|
||||
<div class="filing-item__icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
|
||||
</div>
|
||||
<div class="filing-item__info">
|
||||
<div class="filing-item__name">Form 10-K — Annual Report</div>
|
||||
<div class="filing-item__date">Filed: Sep 28, 2024</div>
|
||||
</div>
|
||||
<span class="filing-item__tag">Annual</span>
|
||||
</div>
|
||||
<div class="filing-item">
|
||||
<div class="filing-item__icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
|
||||
</div>
|
||||
<div class="filing-item__info">
|
||||
<div class="filing-item__name">Form 10-Q — Q4 Report</div>
|
||||
<div class="filing-item__date">Filed: Oct 31, 2024</div>
|
||||
</div>
|
||||
<span class="filing-item__tag" style="background:var(--warning-dim);color:var(--warning)">Recent</span>
|
||||
</div>
|
||||
<div class="filing-item">
|
||||
<div class="filing-item__icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
||||
</div>
|
||||
<div class="filing-item__info">
|
||||
<div class="filing-item__name">Form 4 — Insider Trading</div>
|
||||
<div class="filing-item__date">Filed: Nov 15, 2024</div>
|
||||
</div>
|
||||
<span class="filing-item__tag" style="background:rgba(99,102,241,0.12);color:var(--accent-start)">Insider</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Bar -->
|
||||
<div class="action-bar">
|
||||
<button class="action-btn action-btn--watch">Add to Watchlist</button>
|
||||
<button class="action-btn action-btn--buy">Buy Stock</button>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Nav -->
|
||||
<nav class="bottom-nav">
|
||||
<div class="bottom-nav__items">
|
||||
<a href="#" class="bottom-nav__item">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
|
||||
Home
|
||||
</a>
|
||||
<a href="#" class="bottom-nav__item bottom-nav__item--active">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
||||
Search
|
||||
</a>
|
||||
<a href="#" class="bottom-nav__item">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></svg>
|
||||
Watchlist
|
||||
</a>
|
||||
<a href="#" class="bottom-nav__item">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
|
||||
Alerts
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user