From 53f160384d2157ce4a0607bb4da691934fd061f5 Mon Sep 17 00:00:00 2001 From: corpi Date: Wed, 25 Feb 2026 15:34:50 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/skills/color_system.md | 20 + docs/skills/frontend_architecture.md | 43 + src/app/(marketing)/page.tsx | 219 +++++ src/app/favicon.ico | Bin 25931 -> 0 bytes src/app/globals.css | 28 +- src/app/layout.tsx | 27 +- src/app/page.tsx | 65 -- src/shared/lib/apiClient.ts | 37 + test.css | 1112 ++++++++++++++++++++++++++ 9 files changed, 1446 insertions(+), 105 deletions(-) create mode 100644 docs/skills/color_system.md create mode 100644 docs/skills/frontend_architecture.md create mode 100644 src/app/(marketing)/page.tsx delete mode 100644 src/app/favicon.ico delete mode 100644 src/app/page.tsx create mode 100644 src/shared/lib/apiClient.ts create mode 100644 test.css diff --git a/docs/skills/color_system.md b/docs/skills/color_system.md new file mode 100644 index 0000000..97fa8ab --- /dev/null +++ b/docs/skills/color_system.md @@ -0,0 +1,20 @@ +# VibeRoom Color System (3-Color Palette) + +본 문서는 VibeRoom 웹앱의 UI/UX 일관성을 유지하기 위해 엄격하게 제한된 3가지 핵심 색상 시스템을 정의합니다. AI(Cursor, Cline 등) 코딩 시 **이 3가지 색상과 기본 무채색(white, slate-50) 범위를 벗어난 임의의 색상 사용을 엄격히 금지**합니다. + +## 1. 색상 정의 및 용도 +빌드 캐시 에러를 원천 차단하기 위해 Tailwind의 JIT 헥스(HEX) 주입 방식(예: `bg-[#63adf2]`)을 기본으로 사용합니다. + +| 색상 코드 | Tailwind 적용 예시 | 역할 (Role) | 주요 사용처 | +| :--- | :--- | :--- | :--- | +| `#304d6d` | `text-[#304d6d]`, `bg-[#304d6d]` | **딥 네이비 (메인 텍스트 & 다크 배경)** | 묵직하고 차분한 색상. 본문 글씨, 제목, 선(border), 푸터(Footer), 강조 요금제 카드 등에 사용되어 화면의 무게중심을 잡아줍니다. | +| `#63adf2` | `bg-[#63adf2]`, `text-[#63adf2]` | **소프트 코발트 (포인트 액션)** | 청명하고 기분 좋은 파란색. '무료로 시작하기', 추천 뱃지 등 유저가 액션을 취해야 하는 핵심 영역에만 포인트로 강조합니다. | +| `#a7cced` | `bg-[#a7cced]`, `border-[#a7cced]` | **파스텔 스카이 (소프트 서페이스)** | 아주 연하고 부드러운 파란색. 기능 소개 카드의 은은한 배경이나 체크마크(`✓`), 호버 상태 등 편안한 포인트 요소에 사용됩니다. | + +## 2. AI 바이브 코딩 시 주의사항 (스타일 가이드) +- **기본 배경:** 서비스의 기본 배경은 너무 파래서 답답하지 않도록 깨끗한 `slate-50`(`bg-slate-50`) 또는 `white`(`bg-white`)를 사용합니다. +- **투명도(Opacity) 활용:** 이 3가지 색상만으로 디자인을 구성하되, 농도를 조절해야 할 때는 Tailwind의 투명도 문법을 활용하세요. + - *예시 (텍스트 흐리게):* `text-[#304d6d]/70` + - *예시 (배경 옅게):* `bg-[#a7cced]/10` + - *예시 (테두리 연하게):* `border-[#304d6d]/20` +- **테두리(Border):** 부드러운 느낌을 위해 각진 모서리는 피하고(`rounded-2xl`, `rounded-full` 권장), 선의 굵기보다 색상의 농도 조절로 구분감을 줍니다. \ No newline at end of file diff --git a/docs/skills/frontend_architecture.md b/docs/skills/frontend_architecture.md new file mode 100644 index 0000000..b2407dd --- /dev/null +++ b/docs/skills/frontend_architecture.md @@ -0,0 +1,43 @@ +# VibeRoom 프론트엔드 아키텍처 규칙 (Lite FSD) + +본 문서는 VibeRoom 웹앱의 프론트엔드 코드 작성을 위한 핵심 지침서입니다. AI(Cursor, Cline, Gemini 등)를 통한 코딩 시 반드시 본 문서의 아키텍처 원칙을 준수해야 코드가 얽히고 망가지는(Code Rot) 현상을 방지할 수 있습니다. + +## 1. 아키텍처 핵심 사상 +이 프로젝트는 **'도메인/피처 기반(Feature-Driven) 아키텍처'**를 채택했습니다. 복잡한 FSD(Feature-Sliced Design)를 단순화하여 백엔드 개발자와 AI가 모두 이해하기 쉬운 구조입니다. + +**핵심 철학: "한 기능(Domain)에 관련된 코드는 무조건 하나의 `features` 폴더에 모아둔다."** + +## 2. 폴더 구조 설명 및 엄수 사항 + +```text +src/ +├── app/ # 진입점 (Routing & Pages) +├── features/ # 도메인 로직 묶음 (비즈니스 핵심) +├── shared/ # 공통 요소 (UI, Lib, Type - 도메인 종속성 0%) +└── store/ # 글로벌 상태 관리 (최소한으로 사용) +``` + +### 🚨 [규칙 1] `app/` 폴더는 멍청한 조립 공장이다. +- `app/**/page.tsx` 파일에는 절대 복잡한 비즈니스 로직(API 호출, 상태 관리)을 길게 작성하지 마세요. +- 오직 `features/`나 `shared/`에서 완성된 컴포넌트들을 `import` 해와서 배치(Layout)하는 역할만 수행합니다. +- 데이터 패칭이 필요하다면 SSR/RSC(React Server Components)의 장점을 살려 데이터를 가져온 후 하위 컴포넌트에 넘겨주는 선까지만 작성합니다. + +### 🚨 [규칙 2] `features/` 간의 상호 참조를 절대 금지한다. +- `src/features/timer` 내부의 파일이 `src/features/space` 내부의 파일을 직접 `import` 해서는 안 됩니다. +- 기능(도메인) 간의 결합도가 높아지면, AI가 한 도메인을 수정할 때 다른 도메인이 망가지는 나비효과가 발생합니다. +- 만약 두 기능이 서로 통신해야 한다면 1) 부모 페이지 컴포넌트(`app/`)에서 상태를 내려주거나 2) `store/`의 전역 상태를 활용하세요. + +### 🚨 [규칙 3] `shared/`는 도메인을 몰라야 한다. +- `src/shared/ui/Button.tsx`는 자기가 '로그인 버튼'인지, '타이머 시작 버튼'인지 절대 알면 안 됩니다. +- 오직 범용적인 디자인 컴포넌트, 유틸 함수, 전역 타입만 위치합니다. +- 이 폴더 안의 코드는 어떤 프로젝트에 복사/붙여넣기 해도 바로 동작할 만큼 순수(Pure)해야 합니다. + +### 🚨 [규칙 4] 컴포넌트 작성 시 '기능 중심' 사고방식 +- "버튼 하나 만들자" ➡️ `shared/ui`에 생성. +- "로그인 폼 만들자" ➡️ `features/auth/components`에 생성. +- "타이머 시작 함수 만들자" ➡️ `features/timer/api` 또는 `hooks`에 생성. +- "사용자 데이터를 여러 화면에서 공유하자" ➡️ `store/globalStore.ts` (Zustand) 생성. + +--- +**※ AI 에이전트 지시사항 ※** +코드를 생성하거나 리팩토링할 때 위 4가지 규칙 중 하나라도 위반하는 제안을 해서는 안 됩니다. 새로운 파일을 생성할 때는 반드시 이 폴더 트리 구조 중 어디에 속해야 하는지 명확히 설명하고 승인을 받으세요. \ No newline at end of file diff --git a/src/app/(marketing)/page.tsx b/src/app/(marketing)/page.tsx new file mode 100644 index 0000000..d2c0f1f --- /dev/null +++ b/src/app/(marketing)/page.tsx @@ -0,0 +1,219 @@ +import Link from "next/link"; + +export default function MarketingPage() { + return ( +
+ + {/* Navigation Bar */} +
+
+ + 🪴 VibeRoom + + + +
+
+ +
+ {/* Hero Section */} +
+
+
+

+ 함께하는 조용한 몰입,
+ VibeRoom +

+

+ 집중하기 어려운 순간, 당신을 다그치지 않는 편안한 공간으로 들어오세요. + 구조화된 코워킹 세션과 느슨한 연대가 당신의 페이스를 되찾아 줍니다. +

+
+ + 나만의 공간 만들기 + + + 더 알아보기 + +
+
+ + {/* Hero Illustration */} +
+
+
+
+
+
+
+
+
+
+
🧑‍💻
+
+
+
+
+
+
+
+
+ 45:00 남음 +
+
+
+
+
+
+ + {/* Features Section */} +
+
+
+

당신을 위한 다정한 몰입 장치

+

단순한 타이머가 아닙니다. 무리하지 않고 오래 지속할 수 있는 환경을 제공합니다.

+
+ +
+ {[ + { icon: "⏳", title: "구조화된 세션 타이머", desc: "부담 없이 시작할 수 있는 짧은 몰입과 확실한 휴식. 당신만의 작업 리듬을 부드럽게 설정하고 관리하세요." }, + { icon: "🌱", title: "다정한 연대와 코워킹", desc: "화면 너머 누군가와 함께하는 바디 더블링 효과. 감시가 아닌, 조용하지만 강력한 동기를 서로 나누어보세요." }, + { icon: "🛋️", title: "나만의 심미적 공간", desc: "비 오는 다락방, 햇살 드는 카페. 백색소음과 함께 내가 가장 편안함을 느끼는 가상 공간을 꾸미고 머무르세요." } + ].map((feature, idx) => ( +
+
+ {feature.icon} +
+

{feature.title}

+

+ {feature.desc} +

+
+ ))} +
+
+
+ + {/* Pricing Section */} +
+
+
+

나에게 맞는 공간 선택하기

+

개인의 가벼운 집중부터 프리랜서의 완벽한 워크스페이스까지.

+
+ +
+ {/* Starter Plan */} +
+

Starter

+

가벼운 집중이 필요한 분

+
+ 무료 +
+
    +
  • 기본 가상 공간 테마
  • +
  • 1:1 파트너 매칭 (주 3회)
  • +
  • 오픈 코워킹 룸 입장
  • +
+ + 무료로 시작하기 + +
+ + {/* Pro Plan */} +
+
+ 추천 +
+

Pro

+

방해 없는 완벽한 몰입 환경

+
+ ₩6,900 + /월 +
+
    +
  • 프리미엄 테마 무제한
  • +
  • 1:1 매칭 무제한
  • +
  • 고급 집중 통계 및 리포트
  • +
  • 공간 커스텀 아이템 제공
  • +
+ + Pro 시작하기 + +
+ + {/* Teams Plan */} +
+

Teams

+

리모트 워크 기업 및 팀

+
+ ₩12,000 + /인·월 +
+
    +
  • Pro 플랜의 모든 기능
  • +
  • 프라이빗 팀 스페이스
  • +
  • 팀 전체 생산성 대시보드
  • +
+ + 도입 문의하기 + +
+
+
+
+
+ + {/* Footer */} +
+
+
+
+ + 🪴 VibeRoom + +

+ 프리랜서와 온전한 집중이 필요한 분들을 위한 따뜻하고 구조화된 온라인 코워킹 스페이스입니다. +

+
+
+

제품

+ +
+ +
+
+ © 2026 VibeRoom. All rights reserved. +
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/app/favicon.ico b/src/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..756db9e 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,14 @@ @import "tailwindcss"; -:root { - --background: #ffffff; - --foreground: #171717; -} - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +@theme { + /* VibeRoom 4-Color System */ + --color-brand-bg: #eaf6ff; + --color-brand-primary: #009ffd; + --color-brand-secondary: #2a2a72; + --color-brand-dark: #232528; } body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + background-color: var(--color-brand-bg); + color: var(--color-brand-secondary); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..8f91e9f 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,20 +1,9 @@ -import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; -import "./globals.css"; - -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); +import type { Metadata } from 'next'; +import './globals.css'; export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: 'VibeRoom - 당신만의 편안한 몰입 공간', + description: '프리랜서와 온전한 집중이 필요한 분들을 위한 따뜻하고 구조화된 온라인 코워킹 스페이스. 작업 타이머, 세션 관리, 그리고 느슨한 연대를 통해 당신의 리듬을 찾아보세요.', }; export default function RootLayout({ @@ -23,12 +12,10 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - + + {children} ); -} +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx deleted file mode 100644 index 295f8fd..0000000 --- a/src/app/page.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import Image from "next/image"; - -export default function Home() { - return ( -
-
- Next.js logo -
-

- To get started, edit the page.tsx file. -

-

- Looking for a starting point or more instructions? Head over to{" "} - - Templates - {" "} - or the{" "} - - Learning - {" "} - center. -

-
- -
-
- ); -} diff --git a/src/shared/lib/apiClient.ts b/src/shared/lib/apiClient.ts new file mode 100644 index 0000000..0b4175c --- /dev/null +++ b/src/shared/lib/apiClient.ts @@ -0,0 +1,37 @@ +/** + * VibeRoom 공통 API 클라이언트 + * 환경 변수(NEXT_PUBLIC_API_BASE_URL)를 기반으로 자동으로 Base URL이 설정됩니다. + * + * - npm run dev 실행 시: https://api-dev.viberoom.io (from .env.development) + * - 빌드 후 운영 환경: https://api.viberoom.io (from .env.production) + */ + +const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8080'; + +export const apiClient = async ( + endpoint: string, + options: RequestInit = {} +): Promise => { + // 엔드포인트 앞의 슬래시(/) 중복 방지 + const url = `${API_BASE_URL}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`; + + const defaultHeaders = { + 'Content-Type': 'application/json', + }; + + const response = await fetch(url, { + ...options, + headers: { + ...defaultHeaders, + ...options.headers, + }, + }); + + if (!response.ok) { + // 향후 서비스 무드에 맞춰 "잠시 연결이 원활하지 않아요. 다시 시도해 주세요." 와 같이 + // 부드러운 에러 핸들링을 추가할 수 있는 진입점입니다. + throw new Error(`API 요청 실패: ${response.status}`); + } + + return response.json() as Promise; +}; diff --git a/test.css b/test.css new file mode 100644 index 0000000..a6eaafd --- /dev/null +++ b/test.css @@ -0,0 +1,1112 @@ +/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */ +@layer properties; +@layer theme, base, components, utilities; +@layer theme { + :root, :host { + --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", + "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", + "Courier New", monospace; + --color-stone-50: oklch(98.5% 0.001 106.423); + --color-stone-800: oklch(26.8% 0.007 34.298); + --color-white: #fff; + --spacing: 0.25rem; + --container-xs: 20rem; + --container-md: 28rem; + --container-xl: 36rem; + --container-2xl: 42rem; + --container-5xl: 64rem; + --container-6xl: 72rem; + --text-xs: 0.75rem; + --text-xs--line-height: calc(1 / 0.75); + --text-sm: 0.875rem; + --text-sm--line-height: calc(1.25 / 0.875); + --text-lg: 1.125rem; + --text-lg--line-height: calc(1.75 / 1.125); + --text-xl: 1.25rem; + --text-xl--line-height: calc(1.75 / 1.25); + --text-2xl: 1.5rem; + --text-2xl--line-height: calc(2 / 1.5); + --text-3xl: 1.875rem; + --text-3xl--line-height: calc(2.25 / 1.875); + --text-4xl: 2.25rem; + --text-4xl--line-height: calc(2.5 / 2.25); + --text-5xl: 3rem; + --text-5xl--line-height: 1; + --text-6xl: 3.75rem; + --text-6xl--line-height: 1; + --font-weight-medium: 500; + --font-weight-bold: 700; + --tracking-tight: -0.025em; + --tracking-wide: 0.025em; + --leading-tight: 1.25; + --leading-relaxed: 1.625; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --radius-2xl: 1rem; + --radius-3xl: 1.5rem; + --blur-md: 12px; + --aspect-video: 16 / 9; + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + --default-font-family: var(--font-sans); + --default-mono-font-family: var(--font-mono); + --color-brand-bg: #EAF6FF; + --color-brand-primary: #009FFD; + --color-brand-secondary: #2A2A72; + --color-brand-dark: #232528; + } +} +@layer base { + *, ::after, ::before, ::backdrop, ::file-selector-button { + box-sizing: border-box; + margin: 0; + padding: 0; + border: 0 solid; + } + html, :host { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + tab-size: 4; + font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); + font-feature-settings: var(--default-font-feature-settings, normal); + font-variation-settings: var(--default-font-variation-settings, normal); + -webkit-tap-highlight-color: transparent; + } + hr { + height: 0; + color: inherit; + border-top-width: 1px; + } + abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + } + h1, h2, h3, h4, h5, h6 { + font-size: inherit; + font-weight: inherit; + } + a { + color: inherit; + -webkit-text-decoration: inherit; + text-decoration: inherit; + } + b, strong { + font-weight: bolder; + } + code, kbd, samp, pre { + font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); + font-feature-settings: var(--default-mono-font-feature-settings, normal); + font-variation-settings: var(--default-mono-font-variation-settings, normal); + font-size: 1em; + } + small { + font-size: 80%; + } + sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + sub { + bottom: -0.25em; + } + sup { + top: -0.5em; + } + table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + } + :-moz-focusring { + outline: auto; + } + progress { + vertical-align: baseline; + } + summary { + display: list-item; + } + ol, ul, menu { + list-style: none; + } + img, svg, video, canvas, audio, iframe, embed, object { + display: block; + vertical-align: middle; + } + img, video { + max-width: 100%; + height: auto; + } + button, input, select, optgroup, textarea, ::file-selector-button { + font: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + letter-spacing: inherit; + color: inherit; + border-radius: 0; + background-color: transparent; + opacity: 1; + } + :where(select:is([multiple], [size])) optgroup { + font-weight: bolder; + } + :where(select:is([multiple], [size])) optgroup option { + padding-inline-start: 20px; + } + ::file-selector-button { + margin-inline-end: 4px; + } + ::placeholder { + opacity: 1; + } + @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { + ::placeholder { + color: currentcolor; + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, currentcolor 50%, transparent); + } + } + } + textarea { + resize: vertical; + } + ::-webkit-search-decoration { + -webkit-appearance: none; + } + ::-webkit-date-and-time-value { + min-height: 1lh; + text-align: inherit; + } + ::-webkit-datetime-edit { + display: inline-flex; + } + ::-webkit-datetime-edit-fields-wrapper { + padding: 0; + } + ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { + padding-block: 0; + } + ::-webkit-calendar-picker-indicator { + line-height: 1; + } + :-moz-ui-invalid { + box-shadow: none; + } + button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button { + appearance: button; + } + ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { + height: auto; + } + [hidden]:where(:not([hidden="until-found"])) { + display: none !important; + } +} +@layer utilities { + .absolute { + position: absolute; + } + .relative { + position: relative; + } + .sticky { + position: sticky; + } + .start { + inset-inline-start: var(--spacing); + } + .top-0 { + top: calc(var(--spacing) * 0); + } + .left-1\/2 { + left: calc(1 / 2 * 100%); + } + .z-10 { + z-index: 10; + } + .z-50 { + z-index: 50; + } + .container { + width: 100%; + @media (width >= 40rem) { + max-width: 40rem; + } + @media (width >= 48rem) { + max-width: 48rem; + } + @media (width >= 64rem) { + max-width: 64rem; + } + @media (width >= 80rem) { + max-width: 80rem; + } + @media (width >= 96rem) { + max-width: 96rem; + } + } + .mx-auto { + margin-inline: auto; + } + .mt-2 { + margin-top: calc(var(--spacing) * 2); + } + .mt-6 { + margin-top: calc(var(--spacing) * 6); + } + .mb-2 { + margin-bottom: calc(var(--spacing) * 2); + } + .mb-3 { + margin-bottom: calc(var(--spacing) * 3); + } + .mb-4 { + margin-bottom: calc(var(--spacing) * 4); + } + .mb-6 { + margin-bottom: calc(var(--spacing) * 6); + } + .mb-8 { + margin-bottom: calc(var(--spacing) * 8); + } + .mb-10 { + margin-bottom: calc(var(--spacing) * 10); + } + .mb-12 { + margin-bottom: calc(var(--spacing) * 12); + } + .mb-16 { + margin-bottom: calc(var(--spacing) * 16); + } + .block { + display: block; + } + .flex { + display: flex; + } + .grid { + display: grid; + } + .hidden { + display: none; + } + .aspect-square { + aspect-ratio: 1 / 1; + } + .h-2 { + height: calc(var(--spacing) * 2); + } + .h-3 { + height: calc(var(--spacing) * 3); + } + .h-10 { + height: calc(var(--spacing) * 10); + } + .h-12 { + height: calc(var(--spacing) * 12); + } + .h-14 { + height: calc(var(--spacing) * 14); + } + .h-16 { + height: calc(var(--spacing) * 16); + } + .h-full { + height: 100%; + } + .min-h-screen { + min-height: 100vh; + } + .w-3 { + width: calc(var(--spacing) * 3); + } + .w-14 { + width: calc(var(--spacing) * 14); + } + .w-16 { + width: calc(var(--spacing) * 16); + } + .w-full { + width: 100%; + } + .max-w-2xl { + max-width: var(--container-2xl); + } + .max-w-5xl { + max-width: var(--container-5xl); + } + .max-w-6xl { + max-width: var(--container-6xl); + } + .max-w-md { + max-width: var(--container-md); + } + .max-w-xl { + max-width: var(--container-xl); + } + .max-w-xs { + max-width: var(--container-xs); + } + .flex-1 { + flex: 1; + } + .-translate-x-1\/2 { + --tw-translate-x: calc(calc(1 / 2 * 100%) * -1); + translate: var(--tw-translate-x) var(--tw-translate-y); + } + .-translate-y-1\/2 { + --tw-translate-y: calc(calc(1 / 2 * 100%) * -1); + translate: var(--tw-translate-x) var(--tw-translate-y); + } + .transform { + transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); + } + .grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .flex-col { + flex-direction: column; + } + .items-baseline { + align-items: baseline; + } + .items-center { + align-items: center; + } + .justify-between { + justify-content: space-between; + } + .justify-center { + justify-content: center; + } + .gap-1 { + gap: calc(var(--spacing) * 1); + } + .gap-2 { + gap: calc(var(--spacing) * 2); + } + .gap-3 { + gap: calc(var(--spacing) * 3); + } + .gap-4 { + gap: calc(var(--spacing) * 4); + } + .gap-6 { + gap: calc(var(--spacing) * 6); + } + .gap-8 { + gap: calc(var(--spacing) * 8); + } + .gap-12 { + gap: calc(var(--spacing) * 12); + } + .gap-16 { + gap: calc(var(--spacing) * 16); + } + .space-y-3 { + :where(& > :not(:last-child)) { + --tw-space-y-reverse: 0; + margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse)); + margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse))); + } + } + .space-y-4 { + :where(& > :not(:last-child)) { + --tw-space-y-reverse: 0; + margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse)); + margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse))); + } + } + .overflow-hidden { + overflow: hidden; + } + .rounded-2xl { + border-radius: var(--radius-2xl); + } + .rounded-3xl { + border-radius: var(--radius-3xl); + } + .rounded-full { + border-radius: calc(infinity * 1px); + } + .rounded-lg { + border-radius: var(--radius-lg); + } + .rounded-xl { + border-radius: var(--radius-xl); + } + .border { + border-style: var(--tw-border-style); + border-width: 1px; + } + .border-t { + border-top-style: var(--tw-border-style); + border-top-width: 1px; + } + .border-b { + border-bottom-style: var(--tw-border-style); + border-bottom-width: 1px; + } + .border-brand-dark { + border-color: var(--color-brand-dark); + } + .border-brand-primary\/20 { + border-color: color-mix(in srgb, #009FFD 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-brand-primary) 20%, transparent); + } + } + .border-brand-secondary\/5 { + border-color: color-mix(in srgb, #2A2A72 5%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-brand-secondary) 5%, transparent); + } + } + .border-brand-secondary\/10 { + border-color: color-mix(in srgb, #2A2A72 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-brand-secondary) 10%, transparent); + } + } + .border-brand-secondary\/20 { + border-color: color-mix(in srgb, #2A2A72 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-brand-secondary) 20%, transparent); + } + } + .border-white\/10 { + border-color: color-mix(in srgb, #fff 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-white) 10%, transparent); + } + } + .bg-brand-bg { + background-color: var(--color-brand-bg); + } + .bg-brand-bg\/30 { + background-color: color-mix(in srgb, #EAF6FF 30%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-bg) 30%, transparent); + } + } + .bg-brand-bg\/50 { + background-color: color-mix(in srgb, #EAF6FF 50%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-bg) 50%, transparent); + } + } + .bg-brand-bg\/80 { + background-color: color-mix(in srgb, #EAF6FF 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-bg) 80%, transparent); + } + } + .bg-brand-dark { + background-color: var(--color-brand-dark); + } + .bg-brand-primary { + background-color: var(--color-brand-primary); + } + .bg-brand-primary\/10 { + background-color: color-mix(in srgb, #009FFD 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-primary) 10%, transparent); + } + } + .bg-brand-primary\/30 { + background-color: color-mix(in srgb, #009FFD 30%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-primary) 30%, transparent); + } + } + .bg-brand-secondary { + background-color: var(--color-brand-secondary); + } + .bg-brand-secondary\/20 { + background-color: color-mix(in srgb, #2A2A72 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-secondary) 20%, transparent); + } + } + .bg-stone-50 { + background-color: var(--color-stone-50); + } + .bg-white { + background-color: var(--color-white); + } + .bg-white\/40 { + background-color: color-mix(in srgb, #fff 40%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-white) 40%, transparent); + } + } + .bg-white\/50 { + background-color: color-mix(in srgb, #fff 50%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-white) 50%, transparent); + } + } + .p-4 { + padding: calc(var(--spacing) * 4); + } + .p-6 { + padding: calc(var(--spacing) * 6); + } + .p-8 { + padding: calc(var(--spacing) * 8); + } + .px-4 { + padding-inline: calc(var(--spacing) * 4); + } + .px-5 { + padding-inline: calc(var(--spacing) * 5); + } + .px-6 { + padding-inline: calc(var(--spacing) * 6); + } + .px-8 { + padding-inline: calc(var(--spacing) * 8); + } + .py-1 { + padding-block: calc(var(--spacing) * 1); + } + .py-2\.5 { + padding-block: calc(var(--spacing) * 2.5); + } + .py-3 { + padding-block: calc(var(--spacing) * 3); + } + .py-4 { + padding-block: calc(var(--spacing) * 4); + } + .py-24 { + padding-block: calc(var(--spacing) * 24); + } + .pt-8 { + padding-top: calc(var(--spacing) * 8); + } + .pt-16 { + padding-top: calc(var(--spacing) * 16); + } + .pt-24 { + padding-top: calc(var(--spacing) * 24); + } + .pb-8 { + padding-bottom: calc(var(--spacing) * 8); + } + .pb-32 { + padding-bottom: calc(var(--spacing) * 32); + } + .text-center { + text-align: center; + } + .font-sans { + font-family: var(--font-sans); + } + .text-2xl { + font-size: var(--text-2xl); + line-height: var(--tw-leading, var(--text-2xl--line-height)); + } + .text-3xl { + font-size: var(--text-3xl); + line-height: var(--tw-leading, var(--text-3xl--line-height)); + } + .text-4xl { + font-size: var(--text-4xl); + line-height: var(--tw-leading, var(--text-4xl--line-height)); + } + .text-lg { + font-size: var(--text-lg); + line-height: var(--tw-leading, var(--text-lg--line-height)); + } + .text-sm { + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + } + .text-xl { + font-size: var(--text-xl); + line-height: var(--tw-leading, var(--text-xl--line-height)); + } + .text-xs { + font-size: var(--text-xs); + line-height: var(--tw-leading, var(--text-xs--line-height)); + } + .leading-relaxed { + --tw-leading: var(--leading-relaxed); + line-height: var(--leading-relaxed); + } + .leading-tight { + --tw-leading: var(--leading-tight); + line-height: var(--leading-tight); + } + .font-bold { + --tw-font-weight: var(--font-weight-bold); + font-weight: var(--font-weight-bold); + } + .font-medium { + --tw-font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-medium); + } + .tracking-tight { + --tw-tracking: var(--tracking-tight); + letter-spacing: var(--tracking-tight); + } + .tracking-wide { + --tw-tracking: var(--tracking-wide); + letter-spacing: var(--tracking-wide); + } + .text-brand-dark { + color: var(--color-brand-dark); + } + .text-brand-primary { + color: var(--color-brand-primary); + } + .text-brand-secondary { + color: var(--color-brand-secondary); + } + .text-brand-secondary\/60 { + color: color-mix(in srgb, #2A2A72 60%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-brand-secondary) 60%, transparent); + } + } + .text-brand-secondary\/70 { + color: color-mix(in srgb, #2A2A72 70%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-brand-secondary) 70%, transparent); + } + } + .text-brand-secondary\/80 { + color: color-mix(in srgb, #2A2A72 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-brand-secondary) 80%, transparent); + } + } + .text-stone-800 { + color: var(--color-stone-800); + } + .text-white { + color: var(--color-white); + } + .text-white\/40 { + color: color-mix(in srgb, #fff 40%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-white) 40%, transparent); + } + } + .text-white\/60 { + color: color-mix(in srgb, #fff 60%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-white) 60%, transparent); + } + } + .text-white\/80 { + color: color-mix(in srgb, #fff 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-white) 80%, transparent); + } + } + .text-white\/90 { + color: color-mix(in srgb, #fff 90%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-white) 90%, transparent); + } + } + .antialiased { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + .shadow-sm { + --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + .shadow-xl { + --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + .backdrop-blur-md { + --tw-backdrop-blur: blur(var(--blur-md)); + -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); + backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); + } + .transition-colors { + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .transition-transform { + transition-property: transform, translate, scale, rotate; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .duration-300 { + --tw-duration: 300ms; + transition-duration: 300ms; + } + .selection\:bg-brand-primary\/20 { + & *::selection { + background-color: color-mix(in srgb, #009FFD 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-primary) 20%, transparent); + } + } + &::selection { + background-color: color-mix(in srgb, #009FFD 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-primary) 20%, transparent); + } + } + } + .hover\:-translate-y-1 { + &:hover { + @media (hover: hover) { + --tw-translate-y: calc(var(--spacing) * -1); + translate: var(--tw-translate-x) var(--tw-translate-y); + } + } + } + .hover\:bg-brand-bg\/80 { + &:hover { + @media (hover: hover) { + background-color: color-mix(in srgb, #EAF6FF 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-bg) 80%, transparent); + } + } + } + } + .hover\:bg-brand-primary\/90 { + &:hover { + @media (hover: hover) { + background-color: color-mix(in srgb, #009FFD 90%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-brand-primary) 90%, transparent); + } + } + } + } + .hover\:bg-white { + &:hover { + @media (hover: hover) { + background-color: var(--color-white); + } + } + } + .hover\:text-brand-primary { + &:hover { + @media (hover: hover) { + color: var(--color-brand-primary); + } + } + } + .hover\:shadow-md { + &:hover { + @media (hover: hover) { + --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + } + } + .sm\:block { + @media (width >= 40rem) { + display: block; + } + } + .sm\:flex-row { + @media (width >= 40rem) { + flex-direction: row; + } + } + .md\:col-span-2 { + @media (width >= 48rem) { + grid-column: span 2 / span 2; + } + } + .md\:mx-0 { + @media (width >= 48rem) { + margin-inline: calc(var(--spacing) * 0); + } + } + .md\:flex { + @media (width >= 48rem) { + display: flex; + } + } + .md\:aspect-video { + @media (width >= 48rem) { + aspect-ratio: var(--aspect-video); + } + } + .md\:max-w-full { + @media (width >= 48rem) { + max-width: 100%; + } + } + .md\:-translate-y-4 { + @media (width >= 48rem) { + --tw-translate-y: calc(var(--spacing) * -4); + translate: var(--tw-translate-x) var(--tw-translate-y); + } + } + .md\:grid-cols-3 { + @media (width >= 48rem) { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + } + .md\:grid-cols-4 { + @media (width >= 48rem) { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + } + .md\:flex-row { + @media (width >= 48rem) { + flex-direction: row; + } + } + .md\:justify-start { + @media (width >= 48rem) { + justify-content: flex-start; + } + } + .md\:text-left { + @media (width >= 48rem) { + text-align: left; + } + } + .md\:text-4xl { + @media (width >= 48rem) { + font-size: var(--text-4xl); + line-height: var(--tw-leading, var(--text-4xl--line-height)); + } + } + .md\:text-5xl { + @media (width >= 48rem) { + font-size: var(--text-5xl); + line-height: var(--tw-leading, var(--text-5xl--line-height)); + } + } + .md\:text-xl { + @media (width >= 48rem) { + font-size: var(--text-xl); + line-height: var(--tw-leading, var(--text-xl--line-height)); + } + } + .lg\:text-6xl { + @media (width >= 64rem) { + font-size: var(--text-6xl); + line-height: var(--tw-leading, var(--text-6xl--line-height)); + } + } +} +body { + background-color: var(--color-brand-bg); + color: var(--color-brand-secondary); +} +@property --tw-translate-x { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-translate-y { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-translate-z { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-rotate-x { + syntax: "*"; + inherits: false; +} +@property --tw-rotate-y { + syntax: "*"; + inherits: false; +} +@property --tw-rotate-z { + syntax: "*"; + inherits: false; +} +@property --tw-skew-x { + syntax: "*"; + inherits: false; +} +@property --tw-skew-y { + syntax: "*"; + inherits: false; +} +@property --tw-space-y-reverse { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-border-style { + syntax: "*"; + inherits: false; + initial-value: solid; +} +@property --tw-leading { + syntax: "*"; + inherits: false; +} +@property --tw-font-weight { + syntax: "*"; + inherits: false; +} +@property --tw-tracking { + syntax: "*"; + inherits: false; +} +@property --tw-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-inset-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-inset-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-inset-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-ring-color { + syntax: "*"; + inherits: false; +} +@property --tw-ring-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-inset-ring-color { + syntax: "*"; + inherits: false; +} +@property --tw-inset-ring-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-ring-inset { + syntax: "*"; + inherits: false; +} +@property --tw-ring-offset-width { + syntax: ""; + inherits: false; + initial-value: 0px; +} +@property --tw-ring-offset-color { + syntax: "*"; + inherits: false; + initial-value: #fff; +} +@property --tw-ring-offset-shadow { + syntax: "*"; + inherits: false; + initial-value: 0 0 #0000; +} +@property --tw-backdrop-blur { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-brightness { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-contrast { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-grayscale { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-hue-rotate { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-invert { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-opacity { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-saturate { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-sepia { + syntax: "*"; + inherits: false; +} +@property --tw-duration { + syntax: "*"; + inherits: false; +} +@layer properties { + @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { + *, ::before, ::after, ::backdrop { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-translate-z: 0; + --tw-rotate-x: initial; + --tw-rotate-y: initial; + --tw-rotate-z: initial; + --tw-skew-x: initial; + --tw-skew-y: initial; + --tw-space-y-reverse: 0; + --tw-border-style: solid; + --tw-leading: initial; + --tw-font-weight: initial; + --tw-tracking: initial; + --tw-shadow: 0 0 #0000; + --tw-shadow-color: initial; + --tw-shadow-alpha: 100%; + --tw-inset-shadow: 0 0 #0000; + --tw-inset-shadow-color: initial; + --tw-inset-shadow-alpha: 100%; + --tw-ring-color: initial; + --tw-ring-shadow: 0 0 #0000; + --tw-inset-ring-color: initial; + --tw-inset-ring-shadow: 0 0 #0000; + --tw-ring-inset: initial; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-offset-shadow: 0 0 #0000; + --tw-backdrop-blur: initial; + --tw-backdrop-brightness: initial; + --tw-backdrop-contrast: initial; + --tw-backdrop-grayscale: initial; + --tw-backdrop-hue-rotate: initial; + --tw-backdrop-invert: initial; + --tw-backdrop-opacity: initial; + --tw-backdrop-saturate: initial; + --tw-backdrop-sepia: initial; + --tw-duration: initial; + } + } +}