테마 적용
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import Link from "next/link";
|
||||
import { AUTH_ROUTES } from "@/features/auth/constants";
|
||||
import { Mail } from "lucide-react";
|
||||
|
||||
/**
|
||||
* [비밀번호 찾기 페이지]
|
||||
@@ -31,10 +32,10 @@ export default async function ForgotPasswordPage({
|
||||
<div className="relative z-10 w-full max-w-md animate-in fade-in slide-in-from-bottom-4 duration-700">
|
||||
{message && <FormMessage message={message} />}
|
||||
|
||||
<Card className="border-white/20 bg-white/70 shadow-2xl backdrop-blur-xl dark:border-white/10 dark:bg-gray-900/70">
|
||||
<Card className="border-brand-200/30 bg-white/80 shadow-2xl shadow-brand-500/5 backdrop-blur-xl dark:border-brand-800/30 dark:bg-brand-950/70">
|
||||
<CardHeader className="space-y-3 text-center">
|
||||
<div className="mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-2xl bg-linear-to-br from-gray-800 to-black shadow-lg dark:from-white dark:to-gray-200">
|
||||
<span className="text-sm font-semibold">MAIL</span>
|
||||
<div className="mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-2xl bg-linear-to-br from-brand-500 to-brand-700 shadow-lg shadow-brand-500/25">
|
||||
<Mail className="h-7 w-7 text-white" />
|
||||
</div>
|
||||
<CardTitle className="text-3xl font-bold tracking-tight">
|
||||
비밀번호 재설정
|
||||
@@ -59,13 +60,13 @@ export default async function ForgotPasswordPage({
|
||||
placeholder="name@example.com"
|
||||
autoComplete="email"
|
||||
required
|
||||
className="h-11 transition-all duration-200"
|
||||
className="h-11 transition-all duration-200 focus-visible:ring-brand-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
formAction={requestPasswordReset}
|
||||
className="h-11 w-full bg-linear-to-r from-gray-900 to-black font-semibold text-white shadow-lg transition-all hover:from-black hover:to-gray-800 hover:shadow-xl dark:from-white dark:to-gray-100 dark:text-black dark:hover:from-gray-100 dark:hover:to-white"
|
||||
className="h-11 w-full bg-linear-to-r from-brand-500 to-brand-700 font-semibold text-white shadow-lg shadow-brand-500/20 transition-all hover:from-brand-600 hover:to-brand-800 hover:shadow-xl hover:shadow-brand-500/25"
|
||||
>
|
||||
재설정 링크 보내기
|
||||
</Button>
|
||||
@@ -74,7 +75,7 @@ export default async function ForgotPasswordPage({
|
||||
<div className="text-center">
|
||||
<Link
|
||||
href={AUTH_ROUTES.LOGIN}
|
||||
className="text-sm font-medium text-gray-700 hover:text-black dark:text-gray-300 dark:hover:text-white"
|
||||
className="text-sm font-medium text-brand-600 transition-colors hover:text-brand-700 dark:text-brand-400 dark:hover:text-brand-300"
|
||||
>
|
||||
로그인 페이지로 돌아가기
|
||||
</Link>
|
||||
|
||||
@@ -12,17 +12,18 @@ export default async function AuthLayout({
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
return (
|
||||
<div className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden bg-linear-to-br from-gray-50 via-white to-gray-100 dark:from-black dark:via-gray-950 dark:to-gray-900">
|
||||
<div className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden bg-linear-to-br from-brand-50 via-white to-brand-100/60 dark:from-brand-950 dark:via-gray-950 dark:to-brand-900/40">
|
||||
{/* ========== 헤더 (홈 이동용) ========== */}
|
||||
<Header user={user} />
|
||||
|
||||
{/* ========== 배경 그라디언트 레이어 ========== */}
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top_right,var(--tw-gradient-stops))] from-gray-200/30 via-gray-100/15 to-transparent dark:from-gray-800/30 dark:via-gray-900/20" />
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom_left,var(--tw-gradient-stops))] from-gray-300/30 via-gray-200/15 to-transparent dark:from-gray-700/30 dark:via-gray-800/20" />
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top_right,var(--tw-gradient-stops))] from-brand-200/40 via-brand-100/20 to-transparent dark:from-brand-800/25 dark:via-brand-900/15" />
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom_left,var(--tw-gradient-stops))] from-brand-300/30 via-brand-200/15 to-transparent dark:from-brand-700/20 dark:via-brand-800/10" />
|
||||
|
||||
{/* ========== 애니메이션 블러 효과 ========== */}
|
||||
<div className="absolute left-1/4 top-1/4 h-64 w-64 animate-pulse rounded-full bg-gray-300/20 blur-3xl dark:bg-gray-700/20" />
|
||||
<div className="absolute bottom-1/4 right-1/4 h-64 w-64 animate-pulse rounded-full bg-gray-400/20 blur-3xl delay-700 dark:bg-gray-600/20" />
|
||||
<div className="absolute left-1/4 top-1/4 h-72 w-72 animate-pulse rounded-full bg-brand-300/25 blur-3xl dark:bg-brand-700/15" />
|
||||
<div className="absolute bottom-1/4 right-1/4 h-72 w-72 animate-pulse rounded-full bg-brand-400/20 blur-3xl delay-700 dark:bg-brand-600/15" />
|
||||
<div className="absolute right-1/3 top-1/3 h-48 w-48 animate-pulse rounded-full bg-brand-200/30 blur-2xl delay-1000 dark:bg-brand-800/20" />
|
||||
|
||||
{/* ========== 메인 콘텐츠 영역 (중앙 정렬) ========== */}
|
||||
<main className="z-10 flex w-full flex-1 flex-col items-center justify-center px-4 py-12">
|
||||
|
||||
@@ -7,13 +7,13 @@ import {
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import LoginForm from "@/features/auth/components/login-form";
|
||||
import { LogIn } from "lucide-react";
|
||||
|
||||
/**
|
||||
* [로그인 페이지 컴포넌트]
|
||||
*
|
||||
* Modern UI with glassmorphism effect (유리 형태 디자인)
|
||||
* - 투명 배경 + 블러 효과로 깊이감 표현
|
||||
* - 그라디언트 배경으로 생동감 추가
|
||||
* 브랜드 컬러 기반 글래스모피즘 카드 디자인
|
||||
* - 보라색 그라디언트 아이콘 배지
|
||||
* - shadcn/ui 컴포넌트로 일관된 디자인 시스템 유지
|
||||
*
|
||||
* @param searchParams - URL 쿼리 파라미터 (에러 메시지 전달용)
|
||||
@@ -23,36 +23,25 @@ export default async function LoginPage({
|
||||
}: {
|
||||
searchParams: Promise<{ message: string }>;
|
||||
}) {
|
||||
// URL에서 메시지 파라미터 추출 (로그인 실패 시 에러 메시지 표시)
|
||||
const { message } = await searchParams;
|
||||
|
||||
return (
|
||||
<div className="relative z-10 w-full max-w-md animate-in fade-in slide-in-from-bottom-4 duration-700">
|
||||
{/* 에러/성공 메시지 표시 영역 */}
|
||||
{/* URL 파라미터에 message가 있으면 표시됨 */}
|
||||
<FormMessage message={message} />
|
||||
|
||||
{/* ========== 로그인 카드 (Glassmorphism) ========== */}
|
||||
{/* bg-white/70: 70% 투명도의 흰색 배경 */}
|
||||
{/* backdrop-blur-xl: 배경 블러 효과 (유리 느낌) */}
|
||||
<Card className="border-white/20 bg-white/70 shadow-2xl backdrop-blur-xl dark:border-white/10 dark:bg-gray-900/70">
|
||||
{/* ========== 카드 헤더 영역 ========== */}
|
||||
<Card className="border-brand-200/30 bg-white/80 shadow-2xl shadow-brand-500/5 backdrop-blur-xl dark:border-brand-800/30 dark:bg-brand-950/70">
|
||||
<CardHeader className="space-y-3 text-center">
|
||||
{/* 아이콘 배경: 그라디언트 원형 */}
|
||||
<div className="mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-2xl bg-linear-to-br from-gray-800 to-black shadow-lg dark:from-white dark:to-gray-200">
|
||||
<span className="text-4xl">👋</span>
|
||||
<div className="mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-2xl bg-linear-to-br from-brand-500 to-brand-700 shadow-lg shadow-brand-500/25">
|
||||
<LogIn className="h-7 w-7 text-white" />
|
||||
</div>
|
||||
{/* 페이지 제목 */}
|
||||
<CardTitle className="text-3xl font-bold tracking-tight">
|
||||
환영합니다!
|
||||
</CardTitle>
|
||||
{/* 페이지 설명 */}
|
||||
<CardDescription className="text-base">
|
||||
서비스 이용을 위해 로그인해 주세요.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
{/* ========== 카드 콘텐츠 영역 (폼) ========== */}
|
||||
<CardContent>
|
||||
<LoginForm />
|
||||
</CardContent>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { createClient } from "@/utils/supabase/server";
|
||||
import { redirect } from "next/navigation";
|
||||
import { KeyRound } from "lucide-react";
|
||||
|
||||
/**
|
||||
* [비밀번호 재설정 페이지]
|
||||
@@ -39,10 +40,10 @@ export default async function ResetPasswordPage({
|
||||
<div className="relative z-10 w-full max-w-md animate-in fade-in slide-in-from-bottom-4 duration-700">
|
||||
{message && <FormMessage message={message} />}
|
||||
|
||||
<Card className="border-white/20 bg-white/70 shadow-2xl backdrop-blur-xl dark:border-white/10 dark:bg-gray-900/70">
|
||||
<Card className="border-brand-200/30 bg-white/80 shadow-2xl shadow-brand-500/5 backdrop-blur-xl dark:border-brand-800/30 dark:bg-brand-950/70">
|
||||
<CardHeader className="space-y-3 text-center">
|
||||
<div className="mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-2xl bg-linear-to-br from-gray-800 to-black shadow-lg dark:from-white dark:to-gray-200">
|
||||
<span className="text-sm font-semibold">PW</span>
|
||||
<div className="mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-2xl bg-linear-to-br from-brand-500 to-brand-700 shadow-lg shadow-brand-500/25">
|
||||
<KeyRound className="h-7 w-7 text-white" />
|
||||
</div>
|
||||
<CardTitle className="text-3xl font-bold tracking-tight">
|
||||
비밀번호 재설정
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { UserPlus } from "lucide-react";
|
||||
|
||||
export default async function SignupPage({
|
||||
searchParams,
|
||||
@@ -19,13 +20,12 @@ export default async function SignupPage({
|
||||
|
||||
return (
|
||||
<div className="relative z-10 w-full max-w-md animate-in fade-in slide-in-from-bottom-4 duration-700">
|
||||
{/* 메시지 알림 */}
|
||||
<FormMessage message={message} />
|
||||
|
||||
<Card className="border-white/20 bg-white/70 shadow-2xl backdrop-blur-xl dark:border-white/10 dark:bg-gray-900/70">
|
||||
<Card className="border-brand-200/30 bg-white/80 shadow-2xl shadow-brand-500/5 backdrop-blur-xl dark:border-brand-800/30 dark:bg-brand-950/70">
|
||||
<CardHeader className="space-y-3 text-center">
|
||||
<div className="mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-2xl bg-linear-to-br from-gray-800 to-black shadow-lg dark:from-white dark:to-gray-200">
|
||||
<span className="text-4xl">🚀</span>
|
||||
<div className="mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-2xl bg-linear-to-br from-brand-500 to-brand-700 shadow-lg shadow-brand-500/25">
|
||||
<UserPlus className="h-7 w-7 text-white" />
|
||||
</div>
|
||||
<CardTitle className="text-3xl font-bold tracking-tight">
|
||||
회원가입
|
||||
@@ -35,16 +35,14 @@ export default async function SignupPage({
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
{/* ========== 폼 영역 ========== */}
|
||||
<CardContent className="space-y-6">
|
||||
<SignupForm />
|
||||
|
||||
{/* ========== 로그인 링크 ========== */}
|
||||
<p className="text-center text-sm text-gray-600 dark:text-gray-400">
|
||||
<p className="text-center text-sm text-muted-foreground">
|
||||
이미 계정이 있으신가요?{" "}
|
||||
<Link
|
||||
href={AUTH_ROUTES.LOGIN}
|
||||
className="font-semibold text-gray-900 transition-colors hover:text-black dark:text-gray-100 dark:hover:text-white"
|
||||
className="font-semibold text-brand-600 transition-colors hover:text-brand-700 dark:text-brand-400 dark:hover:text-brand-300"
|
||||
>
|
||||
로그인 하러 가기
|
||||
</Link>
|
||||
|
||||
@@ -4,7 +4,15 @@
|
||||
*/
|
||||
|
||||
import Link from "next/link";
|
||||
import { ArrowRight, BarChart3, ShieldCheck, Sparkles, Zap } from "lucide-react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import {
|
||||
Activity,
|
||||
ArrowRight,
|
||||
ShieldCheck,
|
||||
Sparkles,
|
||||
TrendingUp,
|
||||
Zap,
|
||||
} from "lucide-react";
|
||||
import { Header } from "@/features/layout/components/header";
|
||||
import { AUTH_ROUTES } from "@/features/auth/constants";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -12,6 +20,85 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import ShaderBackground from "@/components/ui/shader-background";
|
||||
import { createClient } from "@/utils/supabase/server";
|
||||
|
||||
interface ValuePoint {
|
||||
value: string;
|
||||
label: string;
|
||||
detail: string;
|
||||
}
|
||||
|
||||
interface FeatureItem {
|
||||
icon: LucideIcon;
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
interface StartStep {
|
||||
step: string;
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
const VALUE_POINTS: ValuePoint[] = [
|
||||
{
|
||||
value: "3분",
|
||||
label: "초기 세팅 시간",
|
||||
detail: "복잡한 설정 대신 질문 기반으로 빠르게 시작합니다.",
|
||||
},
|
||||
{
|
||||
value: "24시간",
|
||||
label: "실시간 시장 관제",
|
||||
detail: "자리 비운 시간에도 규칙 기반으로 자동 대응합니다.",
|
||||
},
|
||||
{
|
||||
value: "0원",
|
||||
label: "가입 시작 비용",
|
||||
detail: "부담 없이 계정 생성 후 내 투자 스타일부터 점검합니다.",
|
||||
},
|
||||
];
|
||||
|
||||
const FEATURE_ITEMS: FeatureItem[] = [
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
eyebrow: "Risk Guard",
|
||||
title: "손실 방어를 먼저 설계합니다",
|
||||
description:
|
||||
"진입보다 중요한 것은 방어입니다. 손절 기준과 노출 한도를 먼저 세워 감정 개입을 줄입니다.",
|
||||
},
|
||||
{
|
||||
icon: TrendingUp,
|
||||
eyebrow: "Data Momentum",
|
||||
title: "데이터로 타점을 좁힙니다",
|
||||
description:
|
||||
"실시간 데이터 흐름을 읽어 조건이 맞을 때만 실행합니다. 초보도 납득 가능한 근거를 확인할 수 있습니다.",
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
eyebrow: "Auto Execution",
|
||||
title: "기회가 오면 즉시 자동 실행합니다",
|
||||
description:
|
||||
"규칙이 충족되면 지연 없이 주문이 실행됩니다. 잠자는 시간과 업무 시간에도 전략은 멈추지 않습니다.",
|
||||
},
|
||||
];
|
||||
|
||||
const START_STEPS: StartStep[] = [
|
||||
{
|
||||
step: "STEP 01",
|
||||
title: "계정 연결",
|
||||
description: "안내에 따라 거래 계정을 안전하게 연결합니다.",
|
||||
},
|
||||
{
|
||||
step: "STEP 02",
|
||||
title: "성향 선택",
|
||||
description: "공격형·균형형·안정형 중 내 스타일을 고릅니다.",
|
||||
},
|
||||
{
|
||||
step: "STEP 03",
|
||||
title: "자동 실행 시작",
|
||||
description: "선택한 전략으로 실시간 관제를 바로 시작합니다.",
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 홈 메인 랜딩 페이지
|
||||
* @returns 랜딩 UI
|
||||
@@ -24,138 +111,236 @@ export default async function HomePage() {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
// [CTA 분기] 로그인 여부에 따라 같은 위치에서 다른 행동으로 자연스럽게 전환합니다.
|
||||
const primaryCtaHref = user ? AUTH_ROUTES.DASHBOARD : AUTH_ROUTES.SIGNUP;
|
||||
const primaryCtaLabel = user ? "대시보드로 전략 실행하기" : "무료로 시작하고 첫 전략 받기";
|
||||
const secondaryCtaHref = user ? AUTH_ROUTES.DASHBOARD : AUTH_ROUTES.LOGIN;
|
||||
const secondaryCtaLabel = user ? "실시간 상태 확인하기" : "기존 계정으로 로그인";
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col overflow-x-hidden bg-transparent">
|
||||
<Header user={user} showDashboardLink={true} blendWithBackground={true} />
|
||||
|
||||
<main className="relative isolate flex-1 pt-16">
|
||||
<main className="relative isolate flex-1 overflow-hidden pt-16">
|
||||
{/* ========== SHADER BACKGROUND SECTION ========== */}
|
||||
<ShaderBackground opacity={1} className="-z-20" />
|
||||
<div aria-hidden="true" className="pointer-events-none absolute inset-0 -z-10 bg-black/45" />
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute -left-40 top-40 -z-10 h-96 w-96 rounded-full bg-brand-500/20 blur-3xl"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute -right-24 top-72 -z-10 h-[26rem] w-[26rem] rounded-full bg-brand-300/20 blur-3xl"
|
||||
/>
|
||||
|
||||
{/* ========== HERO SECTION ========== */}
|
||||
<section className="container mx-auto max-w-7xl px-4 pb-10 pt-16 md:pt-24">
|
||||
<div className="p-2 md:p-6">
|
||||
<div className="mx-auto max-w-4xl text-center">
|
||||
<span className="inline-flex items-center gap-2 rounded-full px-4 py-1.5 text-xs font-semibold text-brand-200 [text-shadow:0_2px_24px_rgba(0,0,0,0.65)]">
|
||||
<section className="container mx-auto max-w-7xl px-4 pb-14 pt-14 md:pt-24">
|
||||
<div className="grid gap-8 lg:grid-cols-12 lg:gap-10">
|
||||
<div className="lg:col-span-7">
|
||||
<span className="inline-flex animate-in fade-in-0 items-center gap-2 rounded-full border border-brand-400/40 bg-brand-500/15 px-4 py-1.5 text-xs font-semibold tracking-wide text-brand-100 backdrop-blur-md duration-700">
|
||||
<Sparkles className="h-3.5 w-3.5" />
|
||||
Shader Background Landing
|
||||
초보 투자자를 위한 전략 자동매매 파트너
|
||||
</span>
|
||||
|
||||
<h1 className="mt-5 text-4xl font-black tracking-tight text-white [text-shadow:0_4px_30px_rgba(0,0,0,0.6)] md:text-6xl">
|
||||
데이터로 판단하고
|
||||
<h1 className="mt-5 animate-in slide-in-from-bottom-4 text-4xl font-black tracking-tight text-white [text-shadow:0_6px_40px_rgba(0,0,0,0.55)] duration-700 md:text-6xl">
|
||||
감이 아닌 전략으로,
|
||||
<br />
|
||||
<span className="bg-linear-to-r from-brand-300 via-brand-400 to-brand-500 bg-clip-text text-transparent">
|
||||
자동으로 실행합니다
|
||||
<span className="bg-linear-to-r from-brand-100 via-brand-300 to-brand-500 bg-clip-text text-transparent">
|
||||
내 계좌의 성장 루틴을 만드세요
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<p className="mx-auto mt-5 max-w-2xl text-sm leading-relaxed text-white/80 [text-shadow:0_2px_16px_rgba(0,0,0,0.5)] md:text-lg">
|
||||
실시간 시세 확인, 전략 점검, 주문 연결까지 한 화면에서 이어지는 자동매매 환경을
|
||||
제공합니다. 복잡한 설정은 줄이고 실행 속도는 높였습니다.
|
||||
<p className="mt-5 max-w-2xl animate-in slide-in-from-bottom-4 text-sm leading-relaxed text-white/80 duration-700 md:text-lg">
|
||||
주린이는 보호와 성장의 균형을 먼저 설계합니다.
|
||||
<br />
|
||||
손실 방어 규칙, 데이터 신호, 자동 실행을 하나의 흐름으로 묶어 초보의 첫 수익 루틴을 만듭니다.
|
||||
</p>
|
||||
|
||||
<div className="mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row">
|
||||
{/* [분기 렌더] 로그인 사용자는 대시보드, 비로그인 사용자는 가입/로그인 동선을 노출합니다. */}
|
||||
{user ? (
|
||||
<Button asChild size="lg" className="h-12 rounded-full bg-primary px-8 text-base hover:bg-primary/90">
|
||||
<Link href={AUTH_ROUTES.DASHBOARD}>
|
||||
대시보드 바로가기
|
||||
<ArrowRight className="ml-1.5 h-4 w-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<Button asChild size="lg" className="h-12 rounded-full bg-primary px-8 text-base hover:bg-primary/90">
|
||||
<Link href={AUTH_ROUTES.SIGNUP}>
|
||||
무료로 시작하기
|
||||
<ArrowRight className="ml-1.5 h-4 w-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button
|
||||
asChild
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="h-12 rounded-full border-white/40 bg-transparent px-8 text-base text-white hover:bg-white/10 hover:text-white"
|
||||
>
|
||||
<Link href={AUTH_ROUTES.LOGIN}>로그인</Link>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<div className="mt-8 flex animate-in flex-col gap-3 duration-700 sm:flex-row">
|
||||
<Button
|
||||
asChild
|
||||
size="lg"
|
||||
className="group h-12 rounded-full bg-linear-to-r from-brand-500 via-brand-400 to-brand-600 px-8 text-base font-semibold text-white shadow-2xl shadow-brand-800/45 [background-size:200%_200%] animate-gradient-x hover:brightness-110"
|
||||
>
|
||||
<Link href={primaryCtaHref}>
|
||||
{primaryCtaLabel}
|
||||
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button
|
||||
asChild
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="h-12 rounded-full border-white/35 bg-black/30 px-8 text-base text-white backdrop-blur-md hover:bg-white/10 hover:text-white"
|
||||
>
|
||||
<Link href={secondaryCtaHref}>{secondaryCtaLabel}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex flex-wrap gap-3 text-xs text-white/70">
|
||||
<span className="rounded-full border border-white/20 bg-white/5 px-3 py-1 backdrop-blur-sm">
|
||||
가입 3분
|
||||
</span>
|
||||
<span className="rounded-full border border-white/20 bg-white/5 px-3 py-1 backdrop-blur-sm">
|
||||
카드 등록 없음
|
||||
</span>
|
||||
<span className="rounded-full border border-white/20 bg-white/5 px-3 py-1 backdrop-blur-sm">
|
||||
언제든 전략 변경 가능
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 grid gap-3 sm:grid-cols-3">
|
||||
<div className="rounded-2xl p-4 text-white [text-shadow:0_2px_12px_rgba(0,0,0,0.35)]">
|
||||
<p className="text-xs text-white/70">지연 시간 기준</p>
|
||||
<p className="mt-1 text-lg font-bold">Low Latency</p>
|
||||
</div>
|
||||
<div className="rounded-2xl p-4 text-white [text-shadow:0_2px_12px_rgba(0,0,0,0.35)]">
|
||||
<p className="text-xs text-white/70">모니터링</p>
|
||||
<p className="mt-1 text-lg font-bold">실시간 시세 반영</p>
|
||||
</div>
|
||||
<div className="rounded-2xl p-4 text-white [text-shadow:0_2px_12px_rgba(0,0,0,0.35)]">
|
||||
<p className="text-xs text-white/70">실행 환경</p>
|
||||
<p className="mt-1 text-lg font-bold">웹 기반 자동매매</p>
|
||||
<div className="relative lg:col-span-5">
|
||||
<div className="absolute -inset-px rounded-3xl bg-linear-to-br from-brand-300/50 via-brand-600/0 to-brand-600/60 blur-lg" />
|
||||
<div className="relative overflow-hidden rounded-3xl border border-white/15 bg-black/35 p-6 shadow-[0_30px_90px_-45px_rgba(0,0,0,0.85)] backdrop-blur-2xl">
|
||||
<div className="flex items-center justify-between border-b border-white/10 pb-4">
|
||||
<div>
|
||||
<p className="text-xs font-semibold tracking-wide text-brand-200">LIVE STRATEGY STATUS</p>
|
||||
<p className="mt-1 text-lg font-semibold text-white">실시간 자동매매 관제</p>
|
||||
</div>
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-brand-500/25 px-3 py-1 text-xs font-semibold text-brand-100">
|
||||
<Activity className="h-3.5 w-3.5" />
|
||||
안정 운영중
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* [신뢰 포인트] UI 안에서 가치 제안을 한눈에 보여 주기 위해 핵심 상태를 카드형으로 배치합니다. */}
|
||||
<div className="mt-5 grid gap-3">
|
||||
<div className="rounded-2xl border border-white/10 bg-white/5 px-4 py-3">
|
||||
<p className="text-xs text-white/65">리스크 룰 적용</p>
|
||||
<p className="mt-1 text-sm font-semibold text-white">손실 제한 + 분할 대응 활성화</p>
|
||||
</div>
|
||||
<div className="rounded-2xl border border-white/10 bg-white/5 px-4 py-3">
|
||||
<p className="text-xs text-white/65">데이터 신호 감시</p>
|
||||
<p className="mt-1 text-sm font-semibold text-white">시장 흐름 조건 충족 시 자동 진입</p>
|
||||
</div>
|
||||
<div className="rounded-2xl border border-white/10 bg-white/5 px-4 py-3">
|
||||
<p className="text-xs text-white/65">실행 상태</p>
|
||||
<p className="mt-1 text-sm font-semibold text-white">체결 지연 최소화, 규칙 기반 지속 운영</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 flex items-center gap-2 text-xs text-brand-100/90">
|
||||
<span className="inline-block h-2 w-2 rounded-full bg-brand-300" />
|
||||
당신의 전략은 설정한 원칙 안에서만 실행됩니다.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-10 grid gap-4 md:grid-cols-3">
|
||||
{VALUE_POINTS.map((point) => (
|
||||
<div
|
||||
key={point.label}
|
||||
className="rounded-2xl border border-white/10 bg-white/5 p-6 backdrop-blur-md transition-colors hover:bg-white/10"
|
||||
>
|
||||
<p className="text-2xl font-black text-brand-100">{point.value}</p>
|
||||
<p className="mt-2 text-sm font-semibold text-white">{point.label}</p>
|
||||
<p className="mt-2 text-xs leading-relaxed text-white/70">{point.detail}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ========== FEATURE SECTION ========== */}
|
||||
<section className="container mx-auto max-w-7xl px-4 pb-16 md:pb-24">
|
||||
<div className="grid gap-4 md:grid-cols-3">
|
||||
<Card className="border-0 bg-transparent text-white shadow-none">
|
||||
<CardHeader>
|
||||
<div className="mb-2 inline-flex h-10 w-10 items-center justify-center rounded-xl bg-brand-400/20 text-brand-200">
|
||||
<BarChart3 className="h-5 w-5" />
|
||||
</div>
|
||||
<CardTitle className="text-white [text-shadow:0_2px_12px_rgba(0,0,0,0.4)]">실시간 데이터 가시화</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-sm leading-relaxed text-white/75">
|
||||
시세 변화와 거래 흐름을 빠르게 확인할 수 있게 핵심 정보만 선별해 보여줍니다.
|
||||
</CardContent>
|
||||
</Card>
|
||||
<div className="mx-auto max-w-3xl text-center">
|
||||
<p className="text-xs font-semibold tracking-widest text-brand-200">WHY JURINI</p>
|
||||
<h2 className="mt-3 text-3xl font-black tracking-tight text-white md:text-4xl">
|
||||
초보에게 필요한 건 복잡함이 아니라
|
||||
<br />
|
||||
<span className="text-brand-200">기준이 분명한 자동매매</span>입니다
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<Card className="border-0 bg-transparent text-white shadow-none">
|
||||
<CardHeader>
|
||||
<div className="mb-2 inline-flex h-10 w-10 items-center justify-center rounded-xl bg-brand-400/20 text-brand-200">
|
||||
<Zap className="h-5 w-5" />
|
||||
</div>
|
||||
<CardTitle className="text-white [text-shadow:0_2px_12px_rgba(0,0,0,0.4)]">전략 실행 속도 최적화</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-sm leading-relaxed text-white/75">
|
||||
필요한 단계만 남긴 단순한 흐름으로 전략 테스트와 실행 전환 시간을 줄였습니다.
|
||||
</CardContent>
|
||||
</Card>
|
||||
<div className="mt-8 grid gap-6 md:grid-cols-3">
|
||||
{FEATURE_ITEMS.map((feature) => {
|
||||
const FeatureIcon = feature.icon;
|
||||
|
||||
<Card className="border-0 bg-transparent text-white shadow-none">
|
||||
<CardHeader>
|
||||
<div className="mb-2 inline-flex h-10 w-10 items-center justify-center rounded-xl bg-brand-400/20 text-brand-200">
|
||||
<ShieldCheck className="h-5 w-5" />
|
||||
return (
|
||||
<Card
|
||||
key={feature.title}
|
||||
className="group border-white/10 bg-black/25 text-white shadow-none backdrop-blur-md transition-all hover:-translate-y-1 hover:border-brand-400/40 hover:bg-black/35"
|
||||
>
|
||||
<CardHeader>
|
||||
<div className="mb-2 inline-flex h-12 w-12 items-center justify-center rounded-2xl bg-brand-500/20 text-brand-200 transition-transform group-hover:scale-110">
|
||||
<FeatureIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<p className="text-xs font-semibold tracking-wide text-brand-200">{feature.eyebrow}</p>
|
||||
<CardTitle className="text-xl leading-snug text-white">{feature.title}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-sm leading-relaxed text-white/75">
|
||||
{feature.description}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ========== START STEP SECTION ========== */}
|
||||
<section className="container mx-auto max-w-7xl px-4 pb-16">
|
||||
<div className="rounded-3xl border border-white/10 bg-white/5 p-6 backdrop-blur-xl md:p-10">
|
||||
<div className="flex flex-col justify-between gap-8 md:flex-row md:items-end">
|
||||
<div>
|
||||
<p className="text-xs font-semibold tracking-widest text-brand-200">GET STARTED</p>
|
||||
<h2 className="mt-3 text-3xl font-black tracking-tight text-white md:text-4xl">
|
||||
가입부터 자동 실행까지
|
||||
<br />
|
||||
<span className="text-brand-200">딱 3단계면 충분합니다</span>
|
||||
</h2>
|
||||
</div>
|
||||
<p className="max-w-sm text-sm leading-relaxed text-white/70">
|
||||
어려운 설정 화면 대신, 따라 하기 쉬운 단계로 바로 시작할 수 있게 구성했습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 grid gap-4 md:grid-cols-3">
|
||||
{START_STEPS.map((item) => (
|
||||
<div key={item.step} className="rounded-2xl border border-white/10 bg-black/30 p-5">
|
||||
<p className="text-xs font-semibold tracking-wide text-brand-200">{item.step}</p>
|
||||
<p className="mt-2 text-lg font-semibold text-white">{item.title}</p>
|
||||
<p className="mt-2 text-sm leading-relaxed text-white/70">{item.description}</p>
|
||||
</div>
|
||||
<CardTitle className="text-white [text-shadow:0_2px_12px_rgba(0,0,0,0.4)]">명확한 리스크 관리</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="text-sm leading-relaxed text-white/75">
|
||||
자동매매에서 중요한 손실 한도와 조건을 먼저 정의하고 일관되게 적용할 수 있습니다.
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ========== CTA SECTION ========== */}
|
||||
<section className="container mx-auto max-w-7xl px-4 pb-20">
|
||||
<div className="p-2 md:p-4">
|
||||
<div className="flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
|
||||
<div className="relative overflow-hidden rounded-3xl border border-brand-300/30 bg-linear-to-r from-brand-600/30 via-brand-500/20 to-brand-700/30 p-8 backdrop-blur-xl md:p-12">
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="absolute -right-20 -top-20 h-72 w-72 rounded-full bg-brand-200/25 blur-3xl"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="absolute -bottom-24 -left-16 h-72 w-72 rounded-full bg-brand-700/30 blur-3xl"
|
||||
/>
|
||||
|
||||
<div className="relative z-10 flex flex-col items-center justify-between gap-8 text-center md:flex-row md:text-left">
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-brand-200 [text-shadow:0_2px_18px_rgba(0,0,0,0.45)]">준비되면 바로 시작하세요</p>
|
||||
<h2 className="mt-1 text-2xl font-bold tracking-tight text-white [text-shadow:0_2px_18px_rgba(0,0,0,0.45)] md:text-3xl">
|
||||
AutoTrade에서 전략을 실행해 보세요
|
||||
<p className="text-sm font-semibold text-brand-100">수익의 시작은 빠를수록 좋습니다</p>
|
||||
<h2 className="mt-2 text-3xl font-black tracking-tight text-white md:text-4xl">
|
||||
지금 가입하고,
|
||||
<br />
|
||||
내 전략을 오늘부터 자동 실행하세요
|
||||
</h2>
|
||||
<p className="mt-3 text-sm text-white/75 md:text-base">
|
||||
주린이가 첫 설정부터 실행까지 함께 안내합니다.
|
||||
</p>
|
||||
</div>
|
||||
<Button asChild className="h-11 rounded-full bg-primary px-7 hover:bg-primary/90">
|
||||
<Link href={user ? AUTH_ROUTES.DASHBOARD : AUTH_ROUTES.SIGNUP}>
|
||||
{user ? "대시보드 열기" : "회원가입 시작"}
|
||||
<ArrowRight className="ml-1.5 h-4 w-4" />
|
||||
|
||||
<Button
|
||||
asChild
|
||||
size="lg"
|
||||
className="group h-14 rounded-full bg-white px-9 text-lg font-bold text-brand-700 shadow-xl shadow-black/35 hover:bg-white/90"
|
||||
>
|
||||
<Link href={primaryCtaHref}>
|
||||
지금 시작하기
|
||||
<ArrowRight className="ml-2 h-5 w-5" />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ export default async function MainLayout({
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col bg-zinc-50 dark:bg-black">
|
||||
<div className="flex min-h-screen flex-col bg-background">
|
||||
<Header user={user} />
|
||||
<div className="flex flex-1 pt-16">
|
||||
<Sidebar />
|
||||
|
||||
101
app/globals.css
101
app/globals.css
@@ -38,16 +38,16 @@
|
||||
--color-popover: var(--popover);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-card: var(--card);
|
||||
--color-brand-50: oklch(0.97 0.02 294);
|
||||
--color-brand-100: oklch(0.93 0.05 294);
|
||||
--color-brand-200: oklch(0.87 0.1 294);
|
||||
--color-brand-300: oklch(0.79 0.15 294);
|
||||
--color-brand-400: oklch(0.7 0.2 294);
|
||||
--color-brand-500: oklch(0.62 0.24 294);
|
||||
--color-brand-600: oklch(0.56 0.26 294);
|
||||
--color-brand-700: oklch(0.49 0.24 295);
|
||||
--color-brand-800: oklch(0.4 0.2 296);
|
||||
--color-brand-900: oklch(0.33 0.14 297);
|
||||
--color-brand-50: var(--brand-50);
|
||||
--color-brand-100: var(--brand-100);
|
||||
--color-brand-200: var(--brand-200);
|
||||
--color-brand-300: var(--brand-300);
|
||||
--color-brand-400: var(--brand-400);
|
||||
--color-brand-500: var(--brand-500);
|
||||
--color-brand-600: var(--brand-600);
|
||||
--color-brand-700: var(--brand-700);
|
||||
--color-brand-800: var(--brand-800);
|
||||
--color-brand-900: var(--brand-900);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
@@ -71,6 +71,41 @@
|
||||
}
|
||||
|
||||
:root {
|
||||
/* BRAND PALETTE CONTROL
|
||||
* 이 블록만 수정하면 랜딩/대시보드의 보라 톤이 함께 바뀝니다.
|
||||
*/
|
||||
/* 초기 브랜드 보라값(원본 기준) */
|
||||
--brand-50: oklch(0.97 0.02 294);
|
||||
--brand-100: oklch(0.93 0.05 294);
|
||||
--brand-200: oklch(0.87 0.1 294);
|
||||
--brand-300: oklch(0.79 0.15 294);
|
||||
--brand-400: oklch(0.7 0.2 294);
|
||||
--brand-500: oklch(0.62 0.24 294);
|
||||
--brand-600: oklch(0.56 0.26 294);
|
||||
--brand-700: oklch(0.49 0.24 295);
|
||||
--brand-800: oklch(0.4 0.2 296);
|
||||
--brand-900: oklch(0.33 0.14 297);
|
||||
|
||||
/* 차트(canvas): 봉 하락색은 요청대로 파란색 유지 */
|
||||
--brand-chart-background-light: #ffffff;
|
||||
--brand-chart-background-dark: #17131e;
|
||||
--brand-chart-text-light: #6b21a8;
|
||||
--brand-chart-text-dark: #e9d5ff;
|
||||
--brand-chart-border-light: #e9d5ff;
|
||||
--brand-chart-border-dark: rgba(216, 180, 254, 0.3);
|
||||
--brand-chart-grid-light: #f3e8ff;
|
||||
--brand-chart-grid-dark: rgba(216, 180, 254, 0.14);
|
||||
--brand-chart-crosshair-light: #c084fc;
|
||||
--brand-chart-crosshair-dark: rgba(233, 213, 255, 0.75);
|
||||
|
||||
--brand-chart-background: #ffffff;
|
||||
--brand-chart-down: #2563eb;
|
||||
--brand-chart-volume-down: rgba(37, 99, 235, 0.45);
|
||||
--brand-chart-text: #6b21a8;
|
||||
--brand-chart-border: var(--brand-chart-border-light);
|
||||
--brand-chart-grid: var(--brand-chart-grid-light);
|
||||
--brand-chart-crosshair: var(--brand-chart-crosshair-light);
|
||||
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
@@ -78,7 +113,7 @@
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.56 0.26 294);
|
||||
--primary: var(--brand-600);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
@@ -89,7 +124,7 @@
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.62 0.24 294);
|
||||
--ring: var(--brand-500);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
@@ -97,7 +132,7 @@
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.56 0.26 294);
|
||||
--sidebar-primary: var(--brand-600);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
@@ -106,37 +141,45 @@
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
/* 다크 모드 시인성 개선: 배경 대비는 유지하고, 카드/보더/보조 텍스트를 더 읽기 쉽게 조정 */
|
||||
--background: oklch(0.17 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card: oklch(0.235 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover: oklch(0.235 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.56 0.26 294);
|
||||
--primary: var(--brand-600);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary: oklch(0.285 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--muted: oklch(0.285 0 0);
|
||||
--muted-foreground: oklch(0.83 0 0);
|
||||
--accent: oklch(0.285 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.62 0.24 294);
|
||||
--border: oklch(1 0 0 / 18%);
|
||||
--input: oklch(1 0 0 / 22%);
|
||||
--ring: var(--brand-500);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar: oklch(0.235 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.56 0.26 294);
|
||||
--sidebar-primary: var(--brand-600);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent: oklch(0.285 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 18%);
|
||||
--sidebar-ring: oklch(0.78 0 0);
|
||||
|
||||
/* 다크 테마용 차트 배경/격자 대비 */
|
||||
--brand-chart-background: var(--brand-chart-background-dark);
|
||||
--brand-chart-text: var(--brand-chart-text-dark);
|
||||
--brand-chart-border: var(--brand-chart-border-dark);
|
||||
--brand-chart-grid: var(--brand-chart-grid-dark);
|
||||
--brand-chart-crosshair: var(--brand-chart-crosshair-dark);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
||||
@@ -33,8 +33,9 @@ const outfit = Outfit({
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "AutoTrade",
|
||||
description: "Automated Crypto Trading Platform",
|
||||
title: "Jurini - 감이 아닌 전략으로 시작하는 자동매매",
|
||||
description:
|
||||
"주린이를 위한 자동매매 파트너 Jurini. 손실 방어 규칙, 데이터 신호 분석, 실시간 자동 실행으로 초보의 첫 수익 루틴을 만듭니다.",
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user