diff --git a/AGENTS.md b/AGENTS.md index a3c8026..67993ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,3 +15,5 @@ - TypeScript는 `strict` 모드 기준으로 작성한다. `any`는 사용하지 않고, `as` 타입 단언도 꼭 필요한 경우가 아니면 지양한다. - SCSS는 nesting 기준으로 작성하되, 컴포넌트 클래스는 BEM 스타일의 `&__` / `&--` 형태를 우선 사용한다. 같은 블록 안에서 하위 요소는 일관된 네이밍으로 묶는다. - Nuxt, Vue 관련 코드 수정이 필요하면 `vue-expert` 서브 에이전트를 우선 사용한다. + +@DESIGN.md diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..f3a899a --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,881 @@ +--- +version: alpha +name: Notion +description: Notion presents itself as the all-in-one workspace through a confident, illustration-rich brand voice — anchored by a deep navy hero band ({colors.brand-navy}) decorated with brand-colored sticky-note dots and mesh wire illustrations, a signature purple pill primary CTA ({colors.primary}), and a rich palette of pastel-tinted feature cards that echo the colorful database properties of the live product. The system uses a Notion-Sans (Inter-based) typeface across every UI surface, anchors a 4-tier pricing comparison (Free / Plus / Business / Enterprise), and presents the live workspace UI mockup directly inside the hero band. Coverage spans homepage, Enterprise, Product AI, Product Agents, Startups, and Pricing surfaces. + +colors: + primary: "#5645d4" + primary-pressed: "#4534b3" + primary-deep: "#3a2a99" + on-primary: "#ffffff" + brand-navy: "#0a1530" + brand-navy-deep: "#070f24" + brand-navy-mid: "#1a2a52" + link-blue: "#0075de" + link-blue-pressed: "#005bab" + brand-orange: "#dd5b00" + brand-orange-deep: "#793400" + brand-pink: "#ff64c8" + brand-pink-deep: "#a02e6d" + brand-purple: "#7b3ff2" + brand-purple-300: "#d6b6f6" + brand-purple-800: "#391c57" + brand-teal: "#2a9d99" + brand-green: "#1aae39" + brand-yellow: "#f5d75e" + brand-brown: "#523410" + card-tint-peach: "#ffe8d4" + card-tint-rose: "#fde0ec" + card-tint-mint: "#d9f3e1" + card-tint-lavender: "#e6e0f5" + card-tint-sky: "#dcecfa" + card-tint-yellow: "#fef7d6" + card-tint-yellow-bold: "#f9e79f" + card-tint-cream: "#f8f5e8" + card-tint-gray: "#f0eeec" + canvas: "#ffffff" + surface: "#f6f5f4" + surface-soft: "#fafaf9" + hairline: "#e5e3df" + hairline-soft: "#ede9e4" + hairline-strong: "#c8c4be" + ink-deep: "#000000" + ink: "#1a1a1a" + charcoal: "#37352f" + slate: "#5d5b54" + steel: "#787671" + stone: "#a4a097" + muted: "#bbb8b1" + on-dark: "#ffffff" + on-dark-muted: "#a4a097" + semantic-success: "#1aae39" + semantic-warning: "#dd5b00" + semantic-error: "#e03131" + +typography: + hero-display: + fontFamily: Notion Sans + fontSize: 80px + fontWeight: 600 + lineHeight: 1.05 + letterSpacing: -2px + display-lg: + fontFamily: Notion Sans + fontSize: 56px + fontWeight: 600 + lineHeight: 1.10 + letterSpacing: -1px + heading-1: + fontFamily: Notion Sans + fontSize: 48px + fontWeight: 600 + lineHeight: 1.15 + letterSpacing: -0.5px + heading-2: + fontFamily: Notion Sans + fontSize: 36px + fontWeight: 600 + lineHeight: 1.20 + letterSpacing: -0.5px + heading-3: + fontFamily: Notion Sans + fontSize: 28px + fontWeight: 600 + lineHeight: 1.25 + heading-4: + fontFamily: Notion Sans + fontSize: 22px + fontWeight: 600 + lineHeight: 1.30 + heading-5: + fontFamily: Notion Sans + fontSize: 18px + fontWeight: 600 + lineHeight: 1.40 + subtitle: + fontFamily: Notion Sans + fontSize: 18px + fontWeight: 400 + lineHeight: 1.50 + body-md: + fontFamily: Notion Sans + fontSize: 16px + fontWeight: 400 + lineHeight: 1.55 + body-md-medium: + fontFamily: Notion Sans + fontSize: 16px + fontWeight: 500 + lineHeight: 1.55 + body-sm: + fontFamily: Notion Sans + fontSize: 14px + fontWeight: 400 + lineHeight: 1.50 + body-sm-medium: + fontFamily: Notion Sans + fontSize: 14px + fontWeight: 500 + lineHeight: 1.50 + caption: + fontFamily: Notion Sans + fontSize: 13px + fontWeight: 400 + lineHeight: 1.40 + caption-bold: + fontFamily: Notion Sans + fontSize: 13px + fontWeight: 600 + lineHeight: 1.40 + micro: + fontFamily: Notion Sans + fontSize: 12px + fontWeight: 500 + lineHeight: 1.40 + micro-uppercase: + fontFamily: Notion Sans + fontSize: 11px + fontWeight: 600 + lineHeight: 1.40 + letterSpacing: 1px + button-md: + fontFamily: Notion Sans + fontSize: 14px + fontWeight: 500 + lineHeight: 1.30 + +rounded: + xs: 4px + sm: 6px + md: 8px + lg: 12px + xl: 16px + xxl: 20px + xxxl: 24px + full: 9999px + +spacing: + xxs: 4px + xs: 8px + sm: 12px + md: 16px + lg: 20px + xl: 24px + xxl: 32px + xxxl: 40px + section-sm: 48px + section: 64px + section-lg: 96px + hero: 120px + +components: + button-primary: + backgroundColor: "{colors.primary}" + textColor: "{colors.on-primary}" + typography: "{typography.button-md}" + rounded: "{rounded.md}" + padding: "10px 18px" + button-primary-pressed: + backgroundColor: "{colors.primary-pressed}" + textColor: "{colors.on-primary}" + button-primary-disabled: + backgroundColor: "{colors.hairline}" + textColor: "{colors.muted}" + button-dark: + backgroundColor: "{colors.ink-deep}" + textColor: "{colors.on-dark}" + typography: "{typography.button-md}" + rounded: "{rounded.md}" + padding: "10px 18px" + button-secondary: + backgroundColor: "transparent" + textColor: "{colors.ink}" + typography: "{typography.button-md}" + rounded: "{rounded.md}" + padding: "10px 18px" + border: "1px solid {colors.hairline-strong}" + button-on-dark: + backgroundColor: "{colors.on-dark}" + textColor: "{colors.ink}" + typography: "{typography.button-md}" + rounded: "{rounded.md}" + padding: "10px 18px" + button-secondary-on-dark: + backgroundColor: "transparent" + textColor: "{colors.on-dark}" + typography: "{typography.button-md}" + rounded: "{rounded.md}" + padding: "10px 18px" + border: "1px solid {colors.on-dark-muted}" + button-ghost: + backgroundColor: "transparent" + textColor: "{colors.ink}" + typography: "{typography.button-md}" + rounded: "{rounded.sm}" + padding: "8px 12px" + button-link: + backgroundColor: "transparent" + textColor: "{colors.link-blue}" + typography: "{typography.body-sm-medium}" + padding: "0" + card-base: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.lg}" + padding: "{spacing.xl}" + border: "1px solid {colors.hairline}" + card-feature: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + border: "1px solid {colors.hairline}" + card-feature-yellow-bold: + backgroundColor: "{colors.card-tint-yellow-bold}" + textColor: "{colors.charcoal}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + card-feature-peach: + backgroundColor: "{colors.card-tint-peach}" + textColor: "{colors.charcoal}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + card-feature-rose: + backgroundColor: "{colors.card-tint-rose}" + textColor: "{colors.charcoal}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + card-feature-mint: + backgroundColor: "{colors.card-tint-mint}" + textColor: "{colors.charcoal}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + card-feature-sky: + backgroundColor: "{colors.card-tint-sky}" + textColor: "{colors.charcoal}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + card-feature-lavender: + backgroundColor: "{colors.card-tint-lavender}" + textColor: "{colors.charcoal}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + card-feature-yellow: + backgroundColor: "{colors.card-tint-yellow}" + textColor: "{colors.charcoal}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + card-feature-cream: + backgroundColor: "{colors.card-tint-cream}" + textColor: "{colors.charcoal}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + card-agent-tile: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.lg}" + padding: "{spacing.xl}" + border: "1px solid {colors.hairline}" + card-template: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.lg}" + padding: "{spacing.lg}" + border: "1px solid {colors.hairline}" + card-startup-perk: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.lg}" + padding: "{spacing.xl}" + border: "1px solid {colors.hairline}" + pricing-card: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + border: "1px solid {colors.hairline}" + pricing-card-featured: + backgroundColor: "{colors.surface}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + border: "2px solid {colors.primary}" + text-input: + backgroundColor: "{colors.canvas}" + textColor: "{colors.ink}" + typography: "{typography.body-md}" + rounded: "{rounded.md}" + padding: "{spacing.sm} {spacing.md}" + border: "1px solid {colors.hairline-strong}" + height: 44px + text-input-focused: + backgroundColor: "{colors.canvas}" + textColor: "{colors.ink}" + border: "2px solid {colors.primary}" + search-pill: + backgroundColor: "{colors.surface}" + textColor: "{colors.steel}" + typography: "{typography.body-md}" + rounded: "{rounded.md}" + padding: "{spacing.sm} {spacing.md}" + height: 44px + border: "1px solid {colors.hairline}" + pill-tab: + backgroundColor: "transparent" + textColor: "{colors.steel}" + typography: "{typography.body-sm-medium}" + rounded: "{rounded.full}" + padding: "{spacing.xs} {spacing.md}" + border: "1px solid {colors.hairline}" + pill-tab-active: + backgroundColor: "{colors.ink-deep}" + textColor: "{colors.on-dark}" + rounded: "{rounded.full}" + border: "1px solid {colors.ink-deep}" + segmented-tab: + backgroundColor: "transparent" + textColor: "{colors.steel}" + typography: "{typography.body-sm-medium}" + padding: "{spacing.sm} {spacing.md}" + border: "0 0 2px transparent solid" + segmented-tab-active: + backgroundColor: "transparent" + textColor: "{colors.ink}" + typography: "{typography.body-sm-medium}" + border: "0 0 2px {colors.ink} solid" + badge-purple: + backgroundColor: "{colors.primary}" + textColor: "{colors.on-primary}" + typography: "{typography.caption-bold}" + rounded: "{rounded.full}" + padding: "4px 10px" + badge-pink: + backgroundColor: "{colors.brand-pink}" + textColor: "{colors.on-primary}" + typography: "{typography.caption-bold}" + rounded: "{rounded.full}" + padding: "4px 10px" + badge-orange: + backgroundColor: "{colors.brand-orange}" + textColor: "{colors.on-primary}" + typography: "{typography.caption-bold}" + rounded: "{rounded.full}" + padding: "4px 10px" + badge-tag-purple: + backgroundColor: "{colors.card-tint-lavender}" + textColor: "{colors.brand-purple-800}" + typography: "{typography.caption-bold}" + rounded: "{rounded.sm}" + padding: "2px 8px" + badge-tag-orange: + backgroundColor: "{colors.card-tint-peach}" + textColor: "{colors.brand-orange-deep}" + typography: "{typography.caption-bold}" + rounded: "{rounded.sm}" + padding: "2px 8px" + badge-tag-green: + backgroundColor: "{colors.card-tint-mint}" + textColor: "{colors.brand-green}" + typography: "{typography.caption-bold}" + rounded: "{rounded.sm}" + padding: "2px 8px" + badge-popular: + backgroundColor: "{colors.primary}" + textColor: "{colors.on-primary}" + typography: "{typography.caption-bold}" + rounded: "{rounded.full}" + padding: "4px 10px" + promo-banner: + backgroundColor: "{colors.surface}" + textColor: "{colors.ink}" + typography: "{typography.body-sm-medium}" + padding: "{spacing.sm} {spacing.md}" + hero-band-dark: + backgroundColor: "{colors.brand-navy}" + textColor: "{colors.on-dark}" + rounded: "0" + padding: "{spacing.hero}" + workspace-mockup-card: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.lg}" + padding: "0" + border: "1px solid {colors.hairline}" + shadow: "rgba(15, 15, 15, 0.2) 0px 24px 48px -8px" + cta-banner-light: + backgroundColor: "{colors.surface}" + textColor: "{colors.ink}" + rounded: "{rounded.lg}" + padding: "{spacing.section}" + comparison-table: + backgroundColor: "{colors.canvas}" + textColor: "{colors.ink}" + typography: "{typography.body-sm}" + rounded: "{rounded.md}" + border: "1px solid {colors.hairline}" + comparison-row: + backgroundColor: "{colors.canvas}" + textColor: "{colors.ink}" + padding: "{spacing.md} {spacing.lg}" + border: "0 0 1px {colors.hairline-soft} solid" + testimonial-card: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.lg}" + padding: "{spacing.xxl}" + border: "1px solid {colors.hairline}" + logo-wall-item: + backgroundColor: "transparent" + textColor: "{colors.steel}" + typography: "{typography.body-md-medium}" + padding: "{spacing.lg}" + faq-accordion-item: + backgroundColor: "{colors.canvas}" + rounded: "{rounded.md}" + padding: "{spacing.xl}" + border: "0 0 1px {colors.hairline} solid" + stat-row: + backgroundColor: "{colors.surface}" + textColor: "{colors.ink}" + rounded: "{rounded.lg}" + padding: "{spacing.section-sm}" + footer-region: + backgroundColor: "{colors.canvas}" + textColor: "{colors.charcoal}" + typography: "{typography.body-sm}" + padding: "{spacing.section} {spacing.xxl}" + border: "1px solid {colors.hairline}" + footer-link: + backgroundColor: "transparent" + textColor: "{colors.steel}" + typography: "{typography.body-sm}" + padding: "{spacing.xxs} 0" +--- + +## Overview + +Notion presents itself as the all-in-one workspace through a confident, illustration-rich brand voice. The homepage opens with **"Meet the night shift."** rendered centered over a deep navy hero band ({colors.brand-navy}), decorated with brand-colored sticky-note dots and mesh wire illustrations scattered around the headline. The signature **purple pill primary CTA** ({colors.primary}) "Get Notion free" sits at the visual center, paired with an outlined "Request a demo" secondary. Below the buttons, a real Notion workspace UI mockup card (the "Ramp HQ" kanban board) breaks out of the hero band with a deep diffuse drop shadow. + +Below the hero, the page cycles through a distinctive sequence of feature sections: a dense sticky-note "Keep work moving 24/7" panel with red/blue/green/purple/teal status icons; a **bold yellow** ({colors.card-tint-yellow-bold}) "Ask your on-demand assistants" banner card flanked by orange/rose/mint pastel feature tiles showing assistant UI mockups; and a "Bring all your work together" 3-column grid with brand-colored mockups (sky-blue tutorial card, light Notion calendar, brown/rust testimonial slate). The pricing page renders 4 tiers (Free / Plus / Business / Enterprise) horizontally with one tier featured (purple-bordered) and a dense feature comparison table running below. + +The system uses a Notion-Sans typeface (Inter-based) across every UI surface — humanist-geometric character that pairs naturally with the colorful illustrations. Buttons are `{rounded.md}` (8px) rectangles, NOT pills — distinguishing Notion's sober rectangular geometry from competitors that use pills universally. Cards use `{rounded.lg}` (12px) consistently. + +**Key Characteristics:** + +- Deep navy hero band ({colors.brand-navy}) with scattered sticky-note dots + mesh wire decorative illustrations +- **Signature purple pill** ({colors.primary}) primary CTA — Notion's recognizable "Get Notion free" button color +- Real Notion workspace UI mockup card embedded in the hero with deep drop shadow +- Bold yellow feature banner ({colors.card-tint-yellow-bold}) for high-emphasis content sections +- Pastel feature card palette (peach, rose, mint, lavender, sky, yellow) echoing the live product database properties +- Notion-Sans (Inter-based) across every UI surface +- 8px-rounded buttons (NOT pills), 12px-rounded cards — sober editorial geometry +- 4-tier pricing comparison with dense feature table +- Centered hero layout (different from the left-aligned norm of most B2B SaaS) + +## Colors + +> Source pages: notion.com/ (homepage), /enterprise, /product/ai, /product/agents, /startups, /pricing. Token coverage was identical across all six pages. + +### Brand & Primary + +- **Notion Purple** ({colors.primary}): Signature primary CTA color — the unmistakable "Get Notion free" pill button. Reserved for the dominant CTA only. +- **Purple Pressed** ({colors.primary-pressed}): Pressed-state variant +- **Purple Deep** ({colors.primary-deep}): Deeper variant for emphasis +- **Brand Navy** ({colors.brand-navy}): Hero band background — deep navy +- **Brand Navy Deep** ({colors.brand-navy-deep}): Deeper navy for promo banner +- **Brand Navy Mid** ({colors.brand-navy-mid}): Mid-spectrum navy +- **Link Blue** ({colors.link-blue}): Inline text link blue (NOT primary CTA) +- **Link Blue Pressed** ({colors.link-blue-pressed}): Pressed-state link blue + +### Brand Color Spectrum (echoes live product database properties) + +- **Brand Pink** ({colors.brand-pink}): Pink accent +- **Brand Pink Deep** ({colors.brand-pink-deep}): Deeper pink +- **Brand Orange** ({colors.brand-orange}): Orange accent +- **Brand Orange Deep** ({colors.brand-orange-deep}): Deeper orange-rust +- **Brand Purple** ({colors.brand-purple}): Purple accent variant +- **Brand Purple 300** ({colors.brand-purple-300}): Light purple +- **Brand Purple 800** ({colors.brand-purple-800}): Deep purple for tag text +- **Brand Teal** ({colors.brand-teal}): Teal accent +- **Brand Green** ({colors.brand-green}): Bright green +- **Brand Yellow** ({colors.brand-yellow}): Soft yellow +- **Brand Brown** ({colors.brand-brown}): Brand brown for "earthy" tints + +### Card Tints (Pastel Feature Card Backgrounds) + +- **Tint Peach** ({colors.card-tint-peach}): Pale peach +- **Tint Rose** ({colors.card-tint-rose}): Pale rose-pink +- **Tint Mint** ({colors.card-tint-mint}): Pale mint-green +- **Tint Lavender** ({colors.card-tint-lavender}): Pale lavender +- **Tint Sky** ({colors.card-tint-sky}): Pale sky-blue +- **Tint Yellow** ({colors.card-tint-yellow}): Pale yellow +- **Tint Yellow Bold** ({colors.card-tint-yellow-bold}): Bold yellow for high-emphasis feature banners ("Ask your on-demand assistants") +- **Tint Cream** ({colors.card-tint-cream}): Cream tint +- **Tint Gray** ({colors.card-tint-gray}): Neutral surface + +### Surface + +- **Canvas White** ({colors.canvas}): Page background and primary card surface +- **Surface** ({colors.surface}): Subtle section backgrounds, search-pill rest, featured pricing tier +- **Surface Soft** ({colors.surface-soft}): Quieter section divisions +- **Hairline** ({colors.hairline}): 1px borders and primary dividers +- **Hairline Soft** ({colors.hairline-soft}): Quieter dividers +- **Hairline Strong** ({colors.hairline-strong}): Stronger 1px border for inputs + +### Text + +- **Ink Deep** ({colors.ink-deep}): Pure black for emphasis +- **Ink** ({colors.ink}): Primary headlines and body text +- **Charcoal** ({colors.charcoal}): Body emphasis (Notion's signature warm-charcoal) +- **Slate** ({colors.slate}): Secondary text +- **Steel** ({colors.steel}): Tertiary, footer links +- **Stone** ({colors.stone}): Muted labels +- **Muted** ({colors.muted}): Disabled, placeholders +- **On Dark** ({colors.on-dark}): White text on dark surfaces +- **On Dark Muted** ({colors.on-dark-muted}): Reduced-opacity white + +### Semantic + +- **Success** ({colors.semantic-success}): Confirmation green +- **Warning** ({colors.semantic-warning}): Mid-priority alerts (orange) +- **Error** ({colors.semantic-error}): Validation errors (red) + +## Typography + +### Font Family + +**Notion Sans** (primary): Notion's custom Inter-based variable typeface. Fallbacks: Inter, -apple-system, system-ui, 'Segoe UI', Helvetica, sans-serif. Humanist-geometric character used across every UI surface. + +### Hierarchy + +| Token | Size | Weight | Line Height | Letter Spacing | Use | +| ----------------------------- | ---- | ------ | ----------- | -------------- | ---------------------------------------------- | +| `{typography.hero-display}` | 80px | 600 | 1.05 | -2px | Hero ("Meet the night shift") | +| `{typography.display-lg}` | 56px | 600 | 1.10 | -1px | Section openers | +| `{typography.heading-1}` | 48px | 600 | 1.15 | -0.5px | Page-level headlines ("Try for free") | +| `{typography.heading-2}` | 36px | 600 | 1.20 | -0.5px | Subsection headlines ("Keep work moving 24/7") | +| `{typography.heading-3}` | 28px | 600 | 1.25 | 0 | Card titles | +| `{typography.heading-4}` | 22px | 600 | 1.30 | 0 | Feature tile titles | +| `{typography.heading-5}` | 18px | 600 | 1.40 | 0 | FAQ questions | +| `{typography.subtitle}` | 18px | 400 | 1.50 | 0 | Hero subtitle | +| `{typography.body-md}` | 16px | 400 | 1.55 | 0 | Primary body text | +| `{typography.body-md-medium}` | 16px | 500 | 1.55 | 0 | Body emphasis | +| `{typography.body-sm}` | 14px | 400 | 1.50 | 0 | Secondary body | +| `{typography.body-sm-medium}` | 14px | 500 | 1.50 | 0 | Active sidebar, button labels | +| `{typography.caption-bold}` | 13px | 600 | 1.40 | 0 | Badge labels | +| `{typography.button-md}` | 14px | 500 | 1.30 | 0 | Button labels | + +### Principles + +- Tight hero leading (1.05) on 80px display +- Negative letter-spacing on display sizes (-2px to -0.5px) +- Generous body leading (1.55) for documentation readability +- 600 weight for headlines + 500 for buttons; 400 body + +## Layout + +### Spacing System + +- **Base unit**: 4px (8px primary increment) +- **Tokens**: `{spacing.xxs}` (4px) through `{spacing.hero}` (120px) +- **Section rhythm**: Marketing pages use `{spacing.section-lg}` (96px); pricing tightens to `{spacing.section}` (64px) + +### Grid & Container + +- 1280px max-width with 32px gutters +- Pricing: 4-tier card row at desktop with dense comparison table +- Homepage: centered hero with workspace mockup below buttons; alternating colorful feature card sections + +### Whitespace Philosophy + +Marketing surfaces use generous breathing room between feature card bands. Workspace mockup card on hero gets full-width treatment with deep drop shadow. + +## Elevation & Depth + +| Level | Treatment | Use | +| ---------- | ------------------------------------------- | -------------------------- | +| 0 (flat) | No shadow; `{colors.hairline}` border | Default cards, table rows | +| 1 (subtle) | `rgba(15, 15, 15, 0.04) 0px 1px 2px 0px` | Hover-elevated tiles | +| 2 (card) | `rgba(15, 15, 15, 0.08) 0px 4px 12px 0px` | Feature cards | +| 3 (mockup) | `rgba(15, 15, 15, 0.20) 0px 24px 48px -8px` | Hero workspace mockup card | +| 4 (modal) | `rgba(15, 15, 15, 0.16) 0px 16px 48px -8px` | Modals, dropdowns | + +### Decorative Depth + +- Hero workspace mockup card uses deep diffuse drop shadow (Level 3) — significant elevation against the navy band +- Pastel feature cards carry their own visual weight via tint backgrounds +- Sticky-note dot illustrations and mesh wires add atmospheric decoration to navy hero + +## Shapes + +### Border Radius Scale + +| Token | Value | Use | +| ---------------- | ------ | --------------------------------------------------- | +| `{rounded.xs}` | 4px | Tag chips | +| `{rounded.sm}` | 6px | Type badges | +| `{rounded.md}` | 8px | Buttons, inputs, search-pill | +| `{rounded.lg}` | 12px | Cards, pricing tiers, agent tiles, workspace mockup | +| `{rounded.xl}` | 16px | Larger feature panels | +| `{rounded.xxl}` | 20px | Featured product showcases | +| `{rounded.xxxl}` | 24px | Larger feature cards | +| `{rounded.full}` | 9999px | Status badges, pill tabs (NOT regular buttons) | + +Notion's geometry is sober-editorial — `{rounded.md}` (8px) buttons distinguish it from pill-button-everywhere brands. + +## Components + +> Per the no-hover policy, hover states are NOT documented. + +### Buttons + +**`button-primary`** — Signature purple rectangular primary CTA, the dominant action. + +- Background `{colors.primary}`, text `{colors.on-primary}`, typography `{typography.button-md}`, padding `10px 18px`, rounded `{rounded.md}`. +- Pressed state `button-primary-pressed` deepens to `{colors.primary-pressed}`. +- Disabled state uses `{colors.hairline}` background. + +**`button-dark`** — Black rectangular CTA on light backgrounds. + +- Background `{colors.ink-deep}`, text `{colors.on-dark}`, typography `{typography.button-md}`, padding `10px 18px`, rounded `{rounded.md}`. + +**`button-secondary`** — Outlined rectangular for secondary actions ("Request a demo"). + +- Background transparent, text `{colors.ink}`, border `1px solid {colors.hairline-strong}`, typography `{typography.button-md}`, padding `10px 18px`, rounded `{rounded.md}`. + +**`button-on-dark`** — White button on dark hero bands. + +- Background `{colors.on-dark}`, text `{colors.ink}`, typography `{typography.button-md}`, padding `10px 18px`, rounded `{rounded.md}`. + +**`button-secondary-on-dark`** — Outlined button on dark. + +- Background transparent, text `{colors.on-dark}`, border `1px solid {colors.on-dark-muted}`, typography `{typography.button-md}`, padding `10px 18px`, rounded `{rounded.md}`. + +**`button-ghost`** — Quieter ghost button. + +- Background transparent, text `{colors.ink}`, typography `{typography.button-md}`, padding `8px 12px`, rounded `{rounded.sm}`. + +**`button-link`** — Inline blue text link (NOT primary purple). + +- Background transparent, text `{colors.link-blue}`, typography `{typography.body-sm-medium}`, padding `0`. + +### Cards & Containers + +**`card-base`** — Standard content card. + +- Background `{colors.canvas}`, rounded `{rounded.lg}`, padding `{spacing.xl}`, border `1px solid {colors.hairline}`. + +**`card-feature`** — Feature card with larger padding. + +- Background `{colors.canvas}`, rounded `{rounded.lg}`, padding `{spacing.xxl}`, border `1px solid {colors.hairline}`. + +**`card-feature-yellow-bold`** — Bold yellow feature banner for high-emphasis content ("Ask your on-demand assistants"). + +- Background `{colors.card-tint-yellow-bold}`, text `{colors.charcoal}`, rounded `{rounded.lg}`, padding `{spacing.xxl}`. + +**`card-feature-peach`** + **`card-feature-rose`** + **`card-feature-mint`** + **`card-feature-sky`** + **`card-feature-lavender`** + **`card-feature-yellow`** + **`card-feature-cream`** — Pastel-tinted feature cards. + +- Each variant uses its corresponding `card-tint-*` color as background, text `{colors.charcoal}`, rounded `{rounded.lg}`, padding `{spacing.xxl}`. + +**`card-agent-tile`** — Agent assistant tile. + +- Background `{colors.canvas}`, rounded `{rounded.lg}`, padding `{spacing.xl}`, border `1px solid {colors.hairline}`. + +**`card-template`** — Template thumbnail card. + +- Background `{colors.canvas}`, rounded `{rounded.lg}`, padding `{spacing.lg}`, border `1px solid {colors.hairline}`. + +**`card-startup-perk`** — Startup-program perk grid item. + +- Background `{colors.canvas}`, rounded `{rounded.lg}`, padding `{spacing.xl}`, border `1px solid {colors.hairline}`. + +**`pricing-card`** — Standard pricing tier card. + +- Background `{colors.canvas}`, rounded `{rounded.lg}`, padding `{spacing.xxl}`, border `1px solid {colors.hairline}`. + +**`pricing-card-featured`** — Featured pricing tier (Plus or Business — purple-bordered). + +- Background `{colors.surface}`, rounded `{rounded.lg}`, padding `{spacing.xxl}`, border `2px solid {colors.primary}`. + +### Inputs & Forms + +**`text-input`** — Standard text field. + +- Background `{colors.canvas}`, text `{colors.ink}`, border `1px solid {colors.hairline-strong}`, rounded `{rounded.md}`, padding `{spacing.sm} {spacing.md}`, height 44px. + +**`text-input-focused`** — Activated state. + +- Border switches to `2px solid {colors.primary}` (purple). + +**`search-pill`** — Search bar. + +- Background `{colors.surface}`, text `{colors.steel}`, typography `{typography.body-md}`, rounded `{rounded.md}`, height 44px, border `1px solid {colors.hairline}`. + +### Tabs + +**`pill-tab`** + **`pill-tab-active`** — Pill-style tab nav for top-level switching. + +- Inactive: text `{colors.steel}`, border `1px solid {colors.hairline}`, padding `{spacing.xs} {spacing.md}`, rounded `{rounded.full}`. +- Active: background `{colors.ink-deep}`, text `{colors.on-dark}`. + +**`segmented-tab`** + **`segmented-tab-active`** — Underline-style tab navigation. + +- Inactive: text `{colors.steel}`, no border. Active: text `{colors.ink}`, 2px bottom border in `{colors.ink}`. + +### Badges & Status + +**`badge-purple`** — Purple status badge (matches primary CTA). + +- Background `{colors.primary}`, text `{colors.on-primary}`, typography `{typography.caption-bold}`, rounded `{rounded.full}`, padding `4px 10px`. + +**`badge-pink`** — Pink accent badge. + +- Background `{colors.brand-pink}`, text `{colors.on-primary}`, typography `{typography.caption-bold}`, rounded `{rounded.full}`, padding `4px 10px`. + +**`badge-orange`** — Orange accent badge. + +- Background `{colors.brand-orange}`, text `{colors.on-primary}`, typography `{typography.caption-bold}`, rounded `{rounded.full}`, padding `4px 10px`. + +**`badge-tag-purple`** — Soft-purple feature tag chip. + +- Background `{colors.card-tint-lavender}`, text `{colors.brand-purple-800}`, typography `{typography.caption-bold}`, rounded `{rounded.sm}`, padding `2px 8px`. + +**`badge-tag-orange`** — Soft-orange feature tag. + +- Background `{colors.card-tint-peach}`, text `{colors.brand-orange-deep}`, typography `{typography.caption-bold}`, rounded `{rounded.sm}`, padding `2px 8px`. + +**`badge-tag-green`** — Soft-mint feature tag. + +- Background `{colors.card-tint-mint}`, text `{colors.brand-green}`, typography `{typography.caption-bold}`, rounded `{rounded.sm}`, padding `2px 8px`. + +**`badge-popular`** — "Most Popular" tier indicator. + +- Background `{colors.primary}`, text `{colors.on-primary}`, typography `{typography.caption-bold}`, rounded `{rounded.full}`, padding `4px 10px`. + +**`promo-banner`** — Light surface promo strip ABOVE the top nav. + +- Background `{colors.surface}`, text `{colors.ink}`, typography `{typography.body-sm-medium}`, padding `{spacing.sm} {spacing.md}`. ("Developers: Get a first look at our new Developer Platform on May 13.") + +### Tables + +**`comparison-table`** — Pricing feature comparison table. + +- Background `{colors.canvas}`, text `{colors.ink}`, typography `{typography.body-sm}`, rounded `{rounded.md}`, border `1px solid {colors.hairline}`. + +**`comparison-row`** — Individual feature row. + +- Background `{colors.canvas}`, text `{colors.ink}`, padding `{spacing.md} {spacing.lg}`, bottom border `1px solid {colors.hairline-soft}`. + +### Documentation Components + +**`workspace-mockup-card`** — Embedded Notion workspace UI mockup on hero band ("Ramp HQ" kanban board). + +- Background `{colors.canvas}`, rounded `{rounded.lg}`, border `1px solid {colors.hairline}`, deep shadow `rgba(15, 15, 15, 0.20) 0px 24px 48px -8px`. Carries actual Notion product UI mock. + +**`testimonial-card`** — Customer testimonial card. + +- Background `{colors.canvas}`, rounded `{rounded.lg}`, padding `{spacing.xxl}`, border `1px solid {colors.hairline}`. + +**`logo-wall-item`** — Customer logo wordmark cell. + +- Background transparent, text `{colors.steel}`, typography `{typography.body-md-medium}`, padding `{spacing.lg}`. + +**`faq-accordion-item`** — FAQ panel. + +- Background `{colors.canvas}`, rounded `{rounded.md}`, padding `{spacing.xl}`, bottom border `1px solid {colors.hairline}`. + +**`stat-row`** — Stats strip with bar chart visualization ("More productivity. Fewer tools."). + +- Background `{colors.surface}`, text `{colors.ink}`, rounded `{rounded.lg}`, padding `{spacing.section-sm}`. + +**`cta-banner-light`** — Light surface CTA banner. + +- Background `{colors.surface}`, text `{colors.ink}`, rounded `{rounded.lg}`, padding `{spacing.section}`. + +### Navigation + +**Top Navigation (Marketing)** — Sticky white bar. + +- Background `{colors.canvas}`, height ~64px, bottom border `1px solid {colors.hairline}`. +- Left: Notion "N" logo + "Product / AI / Solutions / Resources / Enterprise / Pricing / Request a demo" links. +- Right: "Get Notion free" purple button + "Log in" link. + +### Signature Components + +**`hero-band-dark`** — Deep navy hero band with embedded workspace mockup and decorative dots/wires. + +- Background `{colors.brand-navy}`, text `{colors.on-dark}`, padding `{spacing.hero}`. +- Layout: centered headline `{typography.hero-display}`, subtitle, button row (`button-primary` purple + `button-secondary-on-dark`), `workspace-mockup-card` below. +- Atmospheric decoration: scattered colorful sticky-note dots and mesh wire illustrations around the hero content (NOT a literal pattern fill — handled per-page via SVG/illustration). + +**`footer-region`** — Multi-column light footer. + +- Background `{colors.canvas}`, padding `{spacing.section} {spacing.xxl}`, top border `1px solid {colors.hairline}`. +- 6-column link grid (Product / Download / Resources / Notion for / Company / Legal). + +**`footer-link`** — Individual footer link. + +- Background transparent, text `{colors.steel}`, typography `{typography.body-sm}`, padding `{spacing.xxs} 0`. + +## Do's and Don'ts + +### Do + +- Use `{colors.primary}` (purple) as the dominant CTA across all surfaces — it's the brand's recognizable signal +- Pair deep navy hero bands ({colors.brand-navy}) with the purple button + decorative sticky-note dots +- Use pastel feature card tints (peach, rose, mint, lavender, sky, yellow) generously +- Use `{colors.card-tint-yellow-bold}` for high-emphasis "Ask the assistant"-style banner cards +- Apply `{rounded.md}` (8px) to buttons consistently — Notion uses rectangles, not pills +- Apply `{rounded.lg}` (12px) to all card families +- Maintain Notion-Sans across every UI surface +- Use the workspace mockup card on hero bands to show actual product UI + +### Don't + +- Don't use the purple for body text or large background surfaces +- Don't use pill-shaped buttons; Notion's geometry is rectangular-sober +- Don't mix link-blue ({colors.link-blue}) with primary-purple ({colors.primary}) — they have distinct roles +- Don't apply heavy shadows on flat documentation cards +- Don't replace Notion-Sans with a generic Inter + +## Responsive Behavior + +### Breakpoints + +| Name | Width | Key Changes | +| -------------- | ------------- | --------------------------------------- | +| Mobile (small) | < 480px | Single column. Hero 36px. Pricing 1-up. | +| Mobile (large) | 480 – 767px | Feature cards 2-up. Hero 48px. | +| Tablet | 768 – 1023px | 2-column feature grids. Hero 56px. | +| Desktop | 1024 – 1279px | 4-tier pricing card row. Hero 72px. | +| Wide Desktop | ≥ 1280px | Full 80px hero presentation. | + +### Touch Targets + +- Buttons render at 40–44px effective height +- Form inputs render at 44px height +- Pill tabs ~32px → 44px on mobile + +### Collapsing Strategy + +- **Promo banner** stays full-width; truncates at < 480px +- **Top nav** below 1024px collapses to hamburger +- **Hero band**: workspace mockup card moves below text/buttons on mobile +- **Pricing tiers**: 4-column → 2-column tablet → 1-column mobile +- **Feature cards**: 3-up desktop → 2-up tablet → 1-up mobile +- **Hero typography**: 80px → 56px → 48px → 36px +- **Footer**: 6-column desktop → 3-column tablet → accordion mobile + +### Image Behavior + +- Workspace mockup card maintains aspect ratio +- Pastel illustrations inside feature cards scale proportionally +- Customer logo wall: wordmarks at consistent 60–80px height + +## Iteration Guide + +1. Focus on ONE component at a time +2. Reference component names and tokens directly +3. Run `npx @google/design.md lint DESIGN.md` after edits +4. Add new variants as separate `components:` entries +5. Default to `{typography.body-md}` for body +6. Keep `{colors.primary}` (purple) as the primary CTA — distinct from `{colors.link-blue}` for inline links +7. Use `{rounded.md}` for buttons (rectangles), `{rounded.lg}` for cards, `{rounded.full}` for pill tabs/badges only + +## Known Gaps + +- Specific dark-mode token values not surfaced beyond hero bands +- Animation/transition timings not extracted; recommend 150–200ms ease +- Form validation success state not explicitly captured +- Pastel-tint mapping (which feature uses which tint) is observation-based — the actual brand library may have more entries diff --git a/README.md b/README.md index ba59743..c5ea831 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,14 @@ Nuxt 3 basic starter setup. +## Design System + +`DESIGN.md` is the source of truth for the repository's visual system. When the implementation and the design spec differ, update the code to follow [`DESIGN.md`](./DESIGN.md). + +```bash +npm run design:lint +``` + ## Setup ```bash diff --git a/assets/scss/components/about/_about-page.scss b/assets/scss/components/about/_about-page.scss index e7929bf..4c747f5 100644 --- a/assets/scss/components/about/_about-page.scss +++ b/assets/scss/components/about/_about-page.scss @@ -3,12 +3,16 @@ .about-page { display: grid; - gap: 28px; + gap: 32px; &__hero { display: grid; gap: 12px; - padding: 0 0 8px; + padding: 32px; + border: 1px solid $border-soft; + border-radius: $rounded-xl; + background: rgba(255, 255, 255, 0.9); + box-shadow: $shadow-card; } &__contact { @@ -61,7 +65,11 @@ &__section { display: grid; gap: 24px; - padding-top: 6px; + padding: 28px; + border: 1px solid $border-soft; + border-radius: $rounded-lg; + background: rgba(255, 255, 255, 0.86); + box-shadow: $shadow-card; } &__section-head { @@ -87,14 +95,6 @@ grid-template-columns: repeat(3, minmax(0, 1fr)); } - &__chip { - margin: 0; - padding: 14px 0; - color: $text-subtle; - font-size: 0.98rem; - font-weight: 700; - } - &__experience-list { display: grid; gap: 18px; @@ -144,6 +144,11 @@ } @media (max-width: 1024px) { + &__hero, + &__section { + padding: 24px 20px; + } + &__chips { grid-template-columns: 1fr; } diff --git a/assets/scss/components/base/_badge.scss b/assets/scss/components/base/_badge.scss new file mode 100644 index 0000000..cf0ae92 --- /dev/null +++ b/assets/scss/components/base/_badge.scss @@ -0,0 +1,47 @@ +@use '../../settings/tokens' as *; + +.base-badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 24px; + padding: 2px 8px; + border-radius: $rounded-sm; + background: $color-card-tint-lavender; + color: $color-brand-purple-800; + font-size: 0.8125rem; + font-weight: 600; + line-height: 1.4; + white-space: nowrap; + + &--purple { + padding: 4px 10px; + border-radius: $rounded-full; + background: $color-primary; + color: $color-on-primary; + } + + &--pink { + padding: 4px 10px; + border-radius: $rounded-full; + background: $color-card-tint-rose; + color: $color-brand-pink-deep; + } + + &--orange { + padding: 4px 10px; + border-radius: $rounded-full; + background: $color-card-tint-peach; + color: $color-brand-orange-deep; + } + + &--green { + background: $color-card-tint-mint; + color: $color-charcoal; + } + + &--lavender { + background: $color-card-tint-lavender; + color: $color-brand-purple-800; + } +} diff --git a/assets/scss/components/base/_button.scss b/assets/scss/components/base/_button.scss index d41a2d8..0a53ab7 100644 --- a/assets/scss/components/base/_button.scss +++ b/assets/scss/components/base/_button.scss @@ -5,55 +5,126 @@ display: inline-flex; align-items: center; justify-content: center; - gap: 8px; - min-height: 38px; - padding: 0 14px; - border: 1px solid $border-strong; - border-radius: $rounded-lg; - background: transparent; - color: $foreground; + gap: $space-xs; + min-height: 40px; + padding: 10px 18px; + border: 1px solid transparent; + border-radius: $rounded-md; + background: $color-primary; + color: $color-on-primary; font: inherit; - font-size: 0.95rem; - font-weight: 700; - line-height: 1; + font-size: 0.875rem; + font-weight: 500; + line-height: 1.3; cursor: pointer; text-decoration: none; transition: color 0.18s ease, - background 0.18s ease, - border-color 0.18s ease; - - &:hover:not(:disabled) { - background: rgba(53, 197, 240, 0.06); - border-color: $brand; - color: $brand-strong; - } + background-color 0.18s ease, + border-color 0.18s ease, + box-shadow 0.18s ease; &:focus-visible { @include focus-ring(); } - &:disabled { - opacity: 0.65; - cursor: wait; - box-shadow: none; + &:hover:not(:disabled):not([aria-disabled='true']) { + background: $color-primary-pressed; } + &:disabled, &[aria-disabled='true'] { - opacity: 0.65; + border-color: $color-hairline; + background: $color-hairline; + color: $color-muted; cursor: not-allowed; box-shadow: none; + text-decoration: none; + } + + &[aria-disabled='true'] { + pointer-events: none; + } + + &--primary { + background: $color-primary; + color: $color-on-primary; + + &.base-button--on-dark { + background: $color-on-dark; + color: $color-ink; + + &:hover:not(:disabled):not([aria-disabled='true']) { + background: $color-hairline-soft; + } + } } &--secondary { background: transparent; - color: $brand-strong; - border-color: $border-strong; - box-shadow: none; + color: $color-ink; + border-color: $color-hairline-strong; + + &:hover:not(:disabled):not([aria-disabled='true']) { + background: $color-surface-soft; + border-color: $color-ink; + color: $color-ink; + } + + &.base-button--on-dark { + color: $color-on-dark; + border-color: $color-on-dark-muted; + + &:hover:not(:disabled):not([aria-disabled='true']) { + background: rgba(255, 255, 255, 0.08); + border-color: $color-on-dark; + color: $color-on-dark; + } + } + } + + &--ghost { + padding: 8px 12px; + background: transparent; + color: $color-ink; + + &:hover:not(:disabled):not([aria-disabled='true']) { + background: $color-hairline-soft; + color: $color-ink; + } + + &.base-button--on-dark { + color: $color-on-dark; + + &:hover:not(:disabled):not([aria-disabled='true']) { + background: rgba(255, 255, 255, 0.08); + color: $color-on-dark; + } + } + } + + &--link { + min-height: auto; + padding: 0; + border-color: transparent; + background: transparent; + color: $color-link-blue; + font-size: 0.875rem; + text-decoration: none; + + &:hover:not(:disabled):not([aria-disabled='true']) { + background: transparent; + color: $color-link-blue-pressed; + text-decoration: underline; + text-underline-offset: 0.14em; + } + + &.base-button--on-dark { + color: $color-on-dark; - &:hover:not(:disabled) { - background: rgba(53, 197, 240, 0.04); - box-shadow: none; + &:hover:not(:disabled):not([aria-disabled='true']) { + color: $color-hairline-soft; + } } } } diff --git a/assets/scss/components/base/_card.scss b/assets/scss/components/base/_card.scss index 8f52030..0174d31 100644 --- a/assets/scss/components/base/_card.scss +++ b/assets/scss/components/base/_card.scss @@ -1,33 +1,101 @@ @use '../../settings/tokens' as *; .base-card { - padding: 0; - border-radius: 0; - background: transparent; - border: 0; - box-shadow: none; display: grid; - gap: 10px; + gap: $space-lg; + color: $color-charcoal; - &:hover { - background: transparent; + &--elevated { + padding: $space-xl; + border: 1px solid $color-hairline; + border-radius: $rounded-lg; + background: $color-canvas; + box-shadow: $shadow-card; } - &--elevated { + &--base { + padding: 0; + border: 0; + border-radius: 0; background: transparent; } + &--feature, + &--testimonial, + &--pricing { + padding: $space-xxl; + } + + &--template { + padding: $space-lg; + } + + &--feature { + gap: $space-lg; + } + + &--template { + gap: $space-sm; + } + + &--pricing { + gap: $space-xl; + } + + &--tone-peach { + background: $color-card-tint-peach; + color: $color-charcoal; + border-color: transparent; + } + + &--tone-rose { + background: $color-card-tint-rose; + color: $color-charcoal; + border-color: transparent; + } + + &--tone-mint { + background: $color-card-tint-mint; + color: $color-charcoal; + border-color: transparent; + } + + &--tone-lavender { + background: $color-card-tint-lavender; + color: $color-charcoal; + border-color: transparent; + } + + &--tone-sky { + background: $color-card-tint-sky; + color: $color-charcoal; + border-color: transparent; + } + + &--tone-yellow { + background: $color-card-tint-yellow; + color: $color-charcoal; + border-color: transparent; + } + + &--tone-cream { + background: $color-card-tint-cream; + color: $color-charcoal; + border-color: transparent; + } + &__header, + &__body, &__footer { display: grid; - gap: 8px; + gap: $space-md; } &__title { margin: 0; - color: $foreground; - font-size: 1rem; + color: inherit; + font-size: 1.08rem; line-height: 1.4; - font-weight: 700; + font-weight: 600; } } diff --git a/assets/scss/components/home/_home-page.scss b/assets/scss/components/home/_home-page.scss index 1a1dc9b..28f6995 100644 --- a/assets/scss/components/home/_home-page.scss +++ b/assets/scss/components/home/_home-page.scss @@ -3,31 +3,52 @@ .home-page { display: grid; - gap: 30px; + gap: 32px; &__hero { display: grid; - gap: 10px; - padding: 0 0 6px; + gap: 14px; + padding: 40px; + border-radius: $rounded-xl; + background: + radial-gradient(circle at top right, rgba(255, 100, 200, 0.18), transparent 24%), + radial-gradient(circle at bottom left, rgba(86, 69, 212, 0.22), transparent 28%), + $brand-navy; + box-shadow: $shadow-float; } &__eyebrow, &__section-eyebrow { - @include eyebrow(); + @include eyebrow(rgba(255, 255, 255, 0.72)); } &__title { @include page-title(clamp(2.4rem, 4.2vw, 3.7rem), 1); + max-width: 12ch; + color: #ffffff; } &__lead, &__summary { @include lead(66ch, 1.02rem); + color: rgba(255, 255, 255, 0.8); + } + + &__actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + padding-top: 4px; } &__section { display: grid; gap: 18px; + padding: 28px; + border: 1px solid $border-soft; + border-radius: $rounded-lg; + background: rgba(255, 255, 255, 0.86); + box-shadow: $shadow-card; } &__section-head { @@ -51,13 +72,14 @@ &__note-item { display: grid; - gap: 4px; + gap: 6px; + padding: 16px 18px; + border-radius: $rounded-lg; + background: $brand-lavender; } &__note-link { @include item-link; - text-decoration: underline; - text-underline-offset: 3px; } &__note-lead { @@ -66,5 +88,10 @@ @media (max-width: 1024px) { gap: 24px; + + &__hero, + &__section { + padding: 24px 20px; + } } } diff --git a/assets/scss/components/layout/_app-footer.scss b/assets/scss/components/layout/_app-footer.scss index 416cbb0..5131624 100644 --- a/assets/scss/components/layout/_app-footer.scss +++ b/assets/scss/components/layout/_app-footer.scss @@ -1,10 +1,48 @@ -@use '../../settings/tokens' as *; +@use "../../settings/tokens" as *; +@use "../../settings/mixins" as *; .app-footer { - padding: 12px 0 0; + border-top: 1px solid $border-soft; + background: $surface-elevated; color: $text-muted; + &__inner { + width: min(100%, 1080px); + margin: 0 auto; + display: flex; + align-items: center; + justify-content: space-between; + gap: $space-md; + padding: $space-xl $space-section-sm $space-section-sm; + } + &__text { margin: 0; + color: $text-muted; + font-size: 0.88rem; + line-height: 1.6; + } + + &__link { + color: $text-muted; + font-size: 0.88rem; + line-height: 1.5; + + &:hover { + color: $brand-strong; + } + + &:focus-visible { + @include focus-ring(); + color: $brand-strong; + } + } + + @media (max-width: 1024px) { + &__inner { + align-items: flex-start; + flex-direction: column; + padding: $space-lg $space-lg $space-xxxl; + } } } diff --git a/assets/scss/components/layout/_app-header.scss b/assets/scss/components/layout/_app-header.scss index 6ce3f6f..558adda 100644 --- a/assets/scss/components/layout/_app-header.scss +++ b/assets/scss/components/layout/_app-header.scss @@ -1,31 +1,34 @@ @use "../../settings/tokens" as *; @use "../../settings/mixins" as *; +$app-header-hover-border: rgba($color-primary, 0.12); +$app-header-active-border: rgba($color-primary, 0.18); + .app-header { position: sticky; top: 0; z-index: 20; display: grid; grid-template-rows: auto auto 1fr; - gap: 22px; + gap: $space-xl; align-content: start; - padding: 28px 22px 24px 24px; - background: #ffffff; + padding: $space-xl $space-lg $space-xl $space-xl; + background: $surface-soft; border-right: 1px solid $border-soft; height: 100dvh; overflow: auto; &__brand { display: grid; - gap: 6px; + gap: $space-xs; &-mark { display: inline-flex; align-items: center; - gap: 10px; + gap: $space-sm; font-size: 0.98rem; - font-weight: 800; - color: $foreground; + font-weight: 700; + color: $text-primary; &:focus-visible { @include focus-ring(); @@ -35,38 +38,44 @@ &-subtitle { font-size: 0.9rem; - color: $text-muted; + color: $text-subtle; + line-height: 1.6; } } &__nav { display: grid; - gap: 2px; - padding-top: 0; + gap: $space-xs; + padding-top: $space-sm; + border-top: 1px solid $border-soft; } &__link { @include nav-entry(0, 42px, 2px); - padding-left: 14px; + padding-left: $space-sm; + padding-right: $space-sm; display: flex; align-items: center; justify-content: space-between; &:hover { - background: rgba(53, 197, 240, 0.04); + background: $surface-elevated; color: $brand-strong; + border-color: $app-header-hover-border; } &.router-link-active, &.router-link-exact-active { color: $brand-strong; border-left-color: $brand; + border-color: $app-header-active-border; + background: $brand-lavender; } } &__accordion { display: grid; - gap: 4px; + gap: $space-xxs; } &__summary { @@ -82,7 +91,7 @@ content: ""; width: 16px; height: 16px; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23006780' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='lucide lucide-chevron-down-icon lucide-chevron-down'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234534b3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-size: contain; background-repeat: no-repeat; background-position: center; @@ -96,17 +105,18 @@ &__subnav { display: grid; - gap: 0; + gap: $space-xxs; + padding: $space-xxs 0 $space-xs; } &__subnav-section { display: grid; - gap: 4px; + gap: $space-xxs; } &__subnav-title { - margin: 0 0 2px; - padding-left: 14px; + margin: 0 0 $space-xxs; + padding-left: $space-sm; font-size: 0.76rem; font-weight: 800; letter-spacing: 0.08em; @@ -119,34 +129,38 @@ font-size: 0.92rem; &:hover { - background: rgba(53, 197, 240, 0.04); + background: $surface-elevated; color: $brand-strong; + border-color: $app-header-hover-border; } &.router-link-active, &.router-link-exact-active { color: $brand-strong; border-left-color: $brand; + border-color: $app-header-active-border; + background: $brand-lavender; } } &__subnav-divider { height: 1px; - margin: 10px 0 8px; + margin: $space-sm 0 $space-xs; background: $border-soft; } &__sidebar-note { display: grid; - gap: 8px; + gap: $space-xs; align-self: end; - padding-top: 16px; + padding-top: $space-lg; + border-top: 1px solid $border-soft; &-title { display: inline-flex; width: fit-content; font-size: 0.82rem; - font-weight: 800; + font-weight: 700; color: $brand-strong; letter-spacing: 0.08em; @@ -161,6 +175,10 @@ max-height: none; min-height: 0; top: auto; + height: auto; border-right: 0; + overflow: visible; + grid-template-rows: auto; + padding-bottom: $space-lg; } } diff --git a/assets/scss/components/notes/_notes-content-page.scss b/assets/scss/components/notes/_notes-content-page.scss index f302c66..5e4273a 100644 --- a/assets/scss/components/notes/_notes-content-page.scss +++ b/assets/scss/components/notes/_notes-content-page.scss @@ -27,6 +27,8 @@ &__article { @include prose-stack; + gap: 32px; + max-width: 74ch; color: $foreground; > :first-child { @@ -75,9 +77,10 @@ code { padding: 0.15em 0.4em; - border-radius: 4px; - background: rgba(53, 197, 240, 0.12); - color: $brand-strong; + border-radius: $rounded-sm; + background: rgba(86, 69, 212, 0.1); + color: $text-primary; + font-weight: 600; font-size: 0.95em; } @@ -85,27 +88,32 @@ overflow-x: auto; margin: 0; padding: 18px; - border-radius: 16px; - background: #f5fbfd; - color: $foreground; - line-height: 1.75; + border-radius: $rounded-lg; + border: 1px solid rgba(86, 69, 212, 0.16); + background: linear-gradient(180deg, #f7f4ff 0%, #f3f0ff 100%); + color: $text-primary; + line-height: 1.7; white-space: pre; + + code { + padding: 0; + border-radius: 0; + background: transparent; + color: inherit; + font-weight: 500; + } } blockquote { margin: 0; padding: 14px 18px; - border-left: 3px solid rgba(53, 197, 240, 0.35); + border-left: 3px solid rgba(86, 69, 212, 0.35); color: $text-subtle; - background: rgba(53, 197, 240, 0.04); + background: rgba(86, 69, 212, 0.04); } .base-card { - margin-top: 4px; - } - - .base-card + .base-card { - margin-top: 0; + margin-top: 24px; } } } diff --git a/assets/scss/components/notes/_notes-index-page.scss b/assets/scss/components/notes/_notes-index-page.scss index 94237df..ea8d13f 100644 --- a/assets/scss/components/notes/_notes-index-page.scss +++ b/assets/scss/components/notes/_notes-index-page.scss @@ -41,9 +41,10 @@ padding: 20px; border: 1px solid $border-soft; border-radius: $rounded-lg; - background: #fff; + background: $surface-elevated; color: inherit; text-decoration: none; + box-shadow: $shadow-card; transition: transform 0.18s ease, border-color 0.18s ease, @@ -52,13 +53,29 @@ &:hover { transform: translateY(-2px); border-color: $brand; - box-shadow: 0 12px 30px rgba(16, 24, 40, 0.08); + box-shadow: $shadow-float; } &:focus-visible { @include focus-ring(); border-color: $brand; - box-shadow: 0 12px 30px rgba(16, 24, 40, 0.08); + box-shadow: $shadow-float; + } + + &:nth-child(4n + 1) { + background: $brand-lavender; + } + + &:nth-child(4n + 2) { + background: $brand-peach; + } + + &:nth-child(4n + 3) { + background: $brand-mint; + } + + &:nth-child(4n + 4) { + background: $surface-soft; } } diff --git a/assets/scss/components/posts/_posts-archive-page.scss b/assets/scss/components/posts/_posts-archive-page.scss index 862aafb..cc3aaec 100644 --- a/assets/scss/components/posts/_posts-archive-page.scss +++ b/assets/scss/components/posts/_posts-archive-page.scss @@ -23,12 +23,17 @@ &__divider { height: 1px; margin: 4px 0 0; - background: transparent; + background: $border-soft; } &__section { display: grid; - gap: 14px; + gap: 18px; + padding: 24px; + border: 1px solid $border-soft; + border-radius: $rounded-lg; + background: rgba(255, 255, 255, 0.86); + box-shadow: $shadow-card; } &__section-title { @@ -41,10 +46,10 @@ &__list { display: grid; - gap: 18px; + gap: 14px; margin: 0; - padding-left: 22px; - list-style: disc; + padding: 0; + list-style: none; } &__item { @@ -56,8 +61,5 @@ @include item-link; font-size: 1.15rem; line-height: 1.45; - text-decoration: underline; - text-underline-offset: 3px; } } - diff --git a/assets/scss/components/posts/_posts-link-item.scss b/assets/scss/components/posts/_posts-link-item.scss index e1b731b..178e42c 100644 --- a/assets/scss/components/posts/_posts-link-item.scss +++ b/assets/scss/components/posts/_posts-link-item.scss @@ -3,7 +3,11 @@ .post-link-item { @include stack(8px); - padding: 0; + padding: 16px 18px; + border: 1px solid $border-soft; + border-radius: $rounded-lg; + background: $surface-elevated; + box-shadow: $shadow-card; &__head { display: flex; @@ -15,8 +19,6 @@ @include item-link; font-size: 1.08rem; line-height: 1.5; - text-decoration: underline; - text-underline-offset: 3px; } &__meta { diff --git a/assets/scss/components/posts/_posts-page.scss b/assets/scss/components/posts/_posts-page.scss index 1ef2879..13ab420 100644 --- a/assets/scss/components/posts/_posts-page.scss +++ b/assets/scss/components/posts/_posts-page.scss @@ -28,10 +28,15 @@ &__group { display: grid; - gap: 14px; + gap: 16px; + padding: 24px; + border: 1px solid $border-soft; + border-radius: $rounded-lg; + background: rgba(255, 255, 255, 0.86); + box-shadow: $shadow-card; &:not(:first-of-type) { - margin-top: 26px; + margin-top: 18px; } } @@ -45,7 +50,7 @@ &__group-outline { padding-left: 16px; - border-left: 1px solid $border-soft; + border-left: 2px solid $border-soft; } &__items { @@ -65,7 +70,7 @@ color: $text-muted; font-size: clamp(1rem, 1.25vw, 1.2rem); line-height: 1.6; - font-weight: 500; + font-weight: 600; text-decoration: none; white-space: normal; diff --git a/assets/scss/components/posts/_posts-queue-page.scss b/assets/scss/components/posts/_posts-queue-page.scss index d829233..68e9755 100644 --- a/assets/scss/components/posts/_posts-queue-page.scss +++ b/assets/scss/components/posts/_posts-queue-page.scss @@ -23,7 +23,7 @@ &__divider { height: 1px; margin: 4px 0 0; - background: transparent; + background: $border-soft; } &__categories { @@ -33,6 +33,11 @@ &__category { display: grid; gap: 16px; + padding: 24px; + border: 1px solid $border-soft; + border-radius: $rounded-lg; + background: rgba(255, 255, 255, 0.86); + box-shadow: $shadow-card; } &__category-title { diff --git a/assets/scss/layouts/_default.scss b/assets/scss/layouts/_default.scss index ced9b41..f0cb79b 100644 --- a/assets/scss/layouts/_default.scss +++ b/assets/scss/layouts/_default.scss @@ -5,21 +5,23 @@ position: relative; min-height: 100svh; display: grid; - grid-template-columns: 292px minmax(0, 1fr); + grid-template-columns: 304px minmax(0, 1fr); align-items: stretch; + background: $surface-soft; .skip-link { position: absolute; - left: 18px; - top: 12px; + left: $space-lg; + top: $space-sm; z-index: 40; - padding: 10px 14px; + padding: $space-sm $space-md; border: 1px solid $brand; + border-radius: $rounded-md; background: $surface-elevated; color: $brand-strong; font-size: 0.92rem; font-weight: 700; - transform: translateY(-180%); + transform: translateY(calc(-100% - #{$space-sm})); transition: transform 0.18s ease; &:focus-visible { @@ -31,15 +33,17 @@ .app-content { min-width: 0; display: grid; + grid-template-rows: minmax(0, 1fr) auto; gap: 0; align-content: start; + background: linear-gradient(180deg, $surface-soft 0%, $surface 100%); } .app-main { - width: 100%; - margin: 0; + width: min(100%, 1080px); + margin: 0 auto; min-width: 0; - padding: 48px 40px 56px; + padding: $space-section-sm $space-section-sm $space-section; } @media (max-width: 1024px) { @@ -47,8 +51,8 @@ padding: 0; .skip-link { - left: 12px; - top: 10px; + left: $space-sm; + top: $space-sm; } .app-content { @@ -56,7 +60,8 @@ } .app-main { - padding: 24px 18px 40px; + width: 100%; + padding: $space-xl $space-lg $space-section-sm; border-left: 0; } } diff --git a/assets/scss/layouts/_error.scss b/assets/scss/layouts/_error.scss index ac80a98..e5fb098 100644 --- a/assets/scss/layouts/_error.scss +++ b/assets/scss/layouts/_error.scss @@ -6,8 +6,8 @@ place-items: center; padding: 24px; background: - radial-gradient(circle at top, rgba(53, 197, 240, 0.16), transparent 36%), - linear-gradient(180deg, #f6faff 0%, #edf3f8 100%); + radial-gradient(circle at top, rgba(86, 69, 212, 0.18), transparent 34%), + linear-gradient(180deg, #fafaf9 0%, #f6f5f4 100%); } .error-card { diff --git a/assets/scss/main.scss b/assets/scss/main.scss index 349447a..ed53eb3 100644 --- a/assets/scss/main.scss +++ b/assets/scss/main.scss @@ -2,6 +2,7 @@ @use './layouts/default'; @use './layouts/error'; @use './components/base/button'; +@use './components/base/badge'; @use './components/base/icon'; @use './components/base/card'; @use './components/about/about-page'; @@ -19,10 +20,10 @@ :root { color-scheme: light; font-family: - 'Pretendard', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', + 'Inter', 'Pretendard', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; - background: #ffffff; - color: #171c20; + background: #f6f5f4; + color: #1a1a1a; } html, @@ -32,5 +33,7 @@ body, } body { - background: #ffffff; + background: + radial-gradient(circle at top left, rgba(86, 69, 212, 0.06), transparent 28%), + linear-gradient(180deg, #fafaf9 0%, #f6f5f4 100%); } diff --git a/assets/scss/settings/_mixins.scss b/assets/scss/settings/_mixins.scss index 671affd..39afeec 100644 --- a/assets/scss/settings/_mixins.scss +++ b/assets/scss/settings/_mixins.scss @@ -5,21 +5,36 @@ gap: $gap; } -@mixin eyebrow($color: $brand-strong, $size: 0.78rem) { +@mixin eyebrow($color: $text-muted, $size: 0.76rem) { margin: 0; color: $color; font-size: $size; - font-weight: 800; + font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; } @mixin page-title($size: clamp(2.4rem, 4vw, 3.6rem), $line-height: 1.08) { margin: 0; - color: $foreground; + color: $text-primary; font-size: $size; line-height: $line-height; - font-weight: 800; + font-weight: 600; + letter-spacing: 0; +} + +@mixin page-header($gap: $space-sm, $max-width: 72ch) { + display: grid; + gap: $gap; + max-width: $max-width; +} + +@mixin section-panel($padding: $space-xxl, $radius: $rounded-lg) { + border: 1px solid $border-soft; + border-radius: $radius; + background: $surface-elevated; + box-shadow: $shadow-card; + padding: $padding; } @mixin lead($max-width: 68ch, $size: 1rem) { @@ -27,26 +42,26 @@ max-width: $max-width; color: $text-subtle; font-size: $size; - line-height: 1.8; + line-height: 1.7; } @mixin meta { margin: 0; color: $text-muted; - font-size: 0.92rem; + font-size: 0.88rem; } @mixin focus-ring($offset: 2px) { - outline: 0; - outline: 2px solid $focus-ring; + outline: 2px solid transparent; outline-offset: $offset; + box-shadow: 0 0 0 3px $focus-ring; } @mixin item-link { - color: $foreground; + color: $text-primary; font-size: 1.05rem; - line-height: 1.6; - font-weight: 700; + line-height: 1.55; + font-weight: 600; &:hover { color: $brand-strong; @@ -81,15 +96,25 @@ line-height: 1.85; } +@mixin prose { + @include prose-stack; + + p, + li { + @include prose-text; + } +} + @mixin nav-entry($padding-left: 18px, $height: 42px, $border-width: 2px) { position: relative; min-height: $height; padding: 9px 10px 9px $padding-left; - border: 0; + border: 1px solid transparent; + border-radius: $rounded-md; border-left: $border-width solid transparent; background: transparent; color: $text-subtle; - font-weight: 700; + font-weight: 600; transition: color 0.18s ease, border-color 0.18s ease, @@ -97,7 +122,7 @@ &:focus-visible { @include focus-ring(); - background: rgba(53, 197, 240, 0.06); + background: rgba(86, 69, 212, 0.08); color: $brand-strong; } } @@ -112,7 +137,7 @@ height: $size; border-radius: 9999px; transform: translateY(-50%); - background: rgba(53, 197, 240, 0.2); + background: rgba(86, 69, 212, 0.16); transition: background 0.18s ease; } diff --git a/assets/scss/settings/_tokens.scss b/assets/scss/settings/_tokens.scss index 2470524..552dfc6 100644 --- a/assets/scss/settings/_tokens.scss +++ b/assets/scss/settings/_tokens.scss @@ -1,26 +1,105 @@ -$surface: #f6faff; -$surface-elevated: #ffffff; -$surface-card: #ffffff; -$surface-soft: #f0f4f9; -$surface-muted: #eaeef3; -$foreground: #171c20; -$text-primary: #2f3438; -$text-muted: #828c94; -$text-subtle: #5f6b72; -$rounded-sm: 0px; -$rounded-md: 2px; -$rounded-lg: 4px; -$rounded-xl: 6px; +$color-primary: #5645d4; +$color-primary-pressed: #4534b3; +$color-primary-deep: #3a2a99; +$color-on-primary: #ffffff; +$color-brand-navy: #0a1530; +$color-brand-navy-deep: #070f24; +$color-brand-navy-mid: #1a2a52; +$color-link-blue: #0075de; +$color-link-blue-pressed: #005bab; +$color-brand-orange: #dd5b00; +$color-brand-orange-deep: #793400; +$color-brand-pink: #ff64c8; +$color-brand-pink-deep: #a02e6d; +$color-brand-purple: #7b3ff2; +$color-brand-purple-300: #d6b6f6; +$color-brand-purple-800: #391c57; +$color-brand-teal: #2a9d99; +$color-brand-green: #1aae39; +$color-brand-yellow: #f5d75e; +$color-brand-brown: #523410; +$color-card-tint-peach: #ffe8d4; +$color-card-tint-rose: #fde0ec; +$color-card-tint-mint: #d9f3e1; +$color-card-tint-lavender: #e6e0f5; +$color-card-tint-sky: #dcecfa; +$color-card-tint-yellow: #fef7d6; +$color-card-tint-yellow-bold: #f9e79f; +$color-card-tint-cream: #f8f5e8; +$color-card-tint-gray: #f0eeec; +$color-canvas: #ffffff; +$color-surface: #f6f5f4; +$color-surface-soft: #fafaf9; +$color-hairline: #e5e3df; +$color-hairline-soft: #ede9e4; +$color-hairline-strong: #c8c4be; +$color-ink-deep: #000000; +$color-ink: #1a1a1a; +$color-charcoal: #37352f; +$color-slate: #5d5b54; +$color-steel: #787671; +$color-stone: #a4a097; +$color-muted: #bbb8b1; +$color-on-dark: #ffffff; +$color-on-dark-muted: #a4a097; +$color-semantic-success: #1aae39; +$color-semantic-warning: #dd5b00; +$color-semantic-error: #e03131; +$color-success: $color-semantic-success; +$color-warning: $color-semantic-warning; +$color-error: $color-semantic-error; + +$rounded-xs: 4px; +$rounded-sm: 6px; +$rounded-md: 8px; +$rounded-lg: 12px; +$rounded-xl: 16px; +$rounded-xxl: 20px; +$rounded-xxxl: 24px; $rounded-full: 9999px; -$border-soft: #eaecef; -$border-strong: #dfe4ea; -$shadow-card: none; -$shadow-float: none; -$shadow-inset: rgba(22, 28, 32, 0.02); -$brand: #35c5f0; -$brand-strong: #006780; -$brand-contrast: #ffffff; -$brand-soft: #f6faff; -$danger-bg: rgba(186, 26, 26, 0.08); -$danger-text: #ba1a1a; -$focus-ring: rgba(53, 197, 240, 0.28); + +$space-xxs: 4px; +$space-xs: 8px; +$space-sm: 12px; +$space-md: 16px; +$space-lg: 20px; +$space-xl: 24px; +$space-xxl: 32px; +$space-xxxl: 40px; +$space-section-sm: 48px; +$space-section: 64px; +$space-section-lg: 96px; +$space-hero: 120px; + +$shadow-card: 0 12px 24px -16px rgba(15, 15, 15, 0.18); +$shadow-float: 0 24px 48px -24px rgba(15, 15, 15, 0.28); +$shadow-hero: 0 32px 80px -36px rgba(7, 15, 36, 0.42); +$focus-ring: rgba(86, 69, 212, 0.24); + +$brand: $color-primary; +$brand-strong: $color-primary-pressed; +$brand-contrast: $color-on-primary; +$brand-soft: $color-card-tint-lavender; +$brand-navy: $color-brand-navy; +$brand-orange: $color-brand-orange; +$brand-orange-deep: $color-brand-orange-deep; +$brand-pink: $color-brand-pink; +$brand-pink-deep: $color-brand-pink-deep; +$brand-green: $color-brand-green; +$brand-lavender: $color-card-tint-lavender; +$brand-mint: $color-card-tint-mint; +$brand-peach: $color-card-tint-peach; + +$surface: $color-surface; +$surface-elevated: $color-canvas; +$surface-card: $color-canvas; +$surface-soft: $color-surface-soft; +$surface-muted: $color-hairline-soft; +$foreground: $color-ink; +$text-primary: $color-charcoal; +$text-muted: $color-steel; +$text-subtle: $color-slate; +$border-soft: $color-hairline; +$border-strong: $color-hairline-strong; +$danger-bg: rgba(224, 49, 49, 0.08); +$danger-text: $color-error; diff --git a/components/about/AboutPage.vue b/components/about/AboutPage.vue index c7d38f9..5ba8803 100644 --- a/components/about/AboutPage.vue +++ b/components/about/AboutPage.vue @@ -38,8 +38,10 @@
읽을 내용은 링크로, 정리는 메모로, 기록은 작업일지로 나눠서 관리합니다.
+ +