first commit

This commit is contained in:
2026-06-16 17:12:08 +09:00
commit e1bc5a1dfc
257 changed files with 49823 additions and 0 deletions
+222
View File
@@ -0,0 +1,222 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>회원가입 — Relay</title>
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.css">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #f4f5f7; --panel: #ffffff; --border: #e6e8ec; --border-strong: #d7dae0;
--text: #16181d; --text-2: #5b626e; --text-3: #9298a3;
--accent: #4f46e5; --accent-hover: #4338ca; --accent-weak: #eef0fe; --accent-border: #c7ccfb;
--green: #1f9d57; --kakao: #FEE500; --kakao-text: #191600;
--radius: 8px; --radius-sm: 5px;
}
html, body { height: 100%; }
body { background: var(--bg); color: var(--text); font-family: "Pretendard", -apple-system, system-ui, sans-serif; font-size: 14px; line-height: 1.5; -webkit-font-smoothing: antialiased; }
.auth { display: flex; min-height: 100vh; }
/* brand panel */
.brand-panel { flex: 0 0 46%; max-width: 620px; position: relative; overflow: hidden; background: linear-gradient(155deg, #4f46e5 0%, #4338ca 52%, #2e2a8f 100%); color: #fff; padding: 44px 48px; display: flex; flex-direction: column; }
.brand-panel .blob { position: absolute; border-radius: 50%; pointer-events: none; }
.brand-panel .b1 { width: 360px; height: 360px; right: -120px; top: -90px; background: rgba(255,255,255,.10); }
.brand-panel .b2 { width: 260px; height: 260px; left: -90px; bottom: -70px; background: rgba(255,255,255,.07); }
.brand-panel .ring { position: absolute; right: 60px; bottom: 80px; width: 180px; height: 180px; border: 1.5px solid rgba(255,255,255,.14); border-radius: 50%; }
.brand-panel .ring::after { content: ""; position: absolute; inset: 34px; border: 1.5px solid rgba(255,255,255,.10); border-radius: 50%; }
.bp-logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 18px; letter-spacing: -.2px; position: relative; z-index: 1; }
.bp-logo .logo { width: 32px; height: 32px; border-radius: 9px; background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.22); display: grid; place-items: center; font-size: 17px; font-weight: 800; }
.bp-body { margin-top: auto; position: relative; z-index: 1; }
.bp-head { font-size: 34px; font-weight: 700; line-height: 1.32; letter-spacing: -.8px; text-wrap: balance; }
.bp-sub { margin-top: 18px; font-size: 15px; line-height: 1.7; color: rgba(255,255,255,.82); max-width: 400px; }
.bp-points { margin-top: 30px; display: flex; flex-direction: column; gap: 12px; }
.bp-point { display: flex; align-items: center; gap: 11px; font-size: 14px; color: rgba(255,255,255,.92); }
.bp-point .ic { width: 22px; height: 22px; border-radius: 50%; background: rgba(255,255,255,.16); display: grid; place-items: center; flex-shrink: 0; }
.bp-point .ic svg { width: 13px; height: 13px; }
.bp-foot { margin-top: 40px; font-size: 12.5px; color: rgba(255,255,255,.6); position: relative; z-index: 1; }
/* form panel */
.form-panel { flex: 1; display: flex; align-items: center; justify-content: center; padding: 40px 24px; }
.auth-card { width: 100%; max-width: 384px; }
.ac-logo { display: none; }
.ac-title { font-size: 24px; font-weight: 700; letter-spacing: -.5px; }
.ac-sub { color: var(--text-2); font-size: 14px; margin-top: 7px; }
.socials { display: flex; flex-direction: column; gap: 10px; margin-top: 26px; }
.sbtn { height: 46px; border-radius: var(--radius); border: 1px solid var(--border-strong); background: #fff; display: flex; align-items: center; justify-content: center; gap: 10px; cursor: pointer; font-family: inherit; font-size: 14.5px; font-weight: 600; color: var(--text); text-decoration: none; position: relative; transition: background .12s; }
.sbtn:hover { background: #f7f8fa; }
.sbtn .sico { position: absolute; left: 16px; display: grid; place-items: center; }
.sbtn.kakao { background: var(--kakao); border-color: var(--kakao); color: var(--kakao-text); }
.sbtn.kakao:hover { background: #f2d900; }
.divider { display: flex; align-items: center; gap: 14px; margin: 20px 0; color: var(--text-3); font-size: 12.5px; }
.divider::before, .divider::after { content: ""; height: 1px; background: var(--border); flex: 1; }
.field { margin-bottom: 13px; }
.flabel { font-size: 13px; font-weight: 600; color: var(--text-2); margin-bottom: 7px; display: block; }
.tinput { width: 100%; height: 44px; border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 0 13px; font-family: inherit; font-size: 14px; color: var(--text); background: #fff; }
.tinput:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); }
.tinput::placeholder { color: var(--text-3); }
.pw-wrap { position: relative; }
.pw-wrap .tinput { padding-right: 44px; }
.pw-toggle { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 34px; height: 34px; border: none; background: transparent; color: var(--text-3); display: grid; place-items: center; cursor: pointer; border-radius: 6px; }
.pw-toggle:hover { background: #f1f2f4; color: var(--text-2); }
.pw-toggle svg { width: 18px; height: 18px; }
.field-hint { font-size: 12px; color: var(--text-3); margin-top: 7px; display: flex; align-items: center; gap: 5px; }
.field-hint svg { width: 13px; height: 13px; flex-shrink: 0; }
.terms { display: flex; align-items: flex-start; gap: 9px; margin: 6px 0 18px; font-size: 13px; color: var(--text-2); cursor: pointer; user-select: none; line-height: 1.5; }
.terms .box { width: 18px; height: 18px; border-radius: 5px; border: 1.5px solid var(--border-strong); display: grid; place-items: center; background: #fff; flex-shrink: 0; margin-top: 1px; }
.terms .box.on { background: var(--accent); border-color: var(--accent); }
.terms .box svg { width: 12px; height: 12px; color: #fff; opacity: 0; }
.terms .box.on svg { opacity: 1; }
.terms a { color: var(--accent); font-weight: 600; text-decoration: none; }
.terms a:hover { text-decoration: underline; }
.submit { width: 100%; height: 46px; border-radius: var(--radius); border: none; background: var(--accent); color: #fff; font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer; box-shadow: 0 1px 2px rgba(79,70,229,.4); display: flex; align-items: center; justify-content: center; gap: 7px; }
.submit:hover { background: var(--accent-hover); }
.submit svg { width: 17px; height: 17px; }
.alt { margin-top: 22px; text-align: center; font-size: 13.5px; color: var(--text-2); }
.alt a { color: var(--accent); font-weight: 600; text-decoration: none; }
.alt a:hover { text-decoration: underline; }
/* verification sent state */
.verify { text-align: center; display: none; }
.verify .vicon { width: 66px; height: 66px; border-radius: 50%; background: var(--accent-weak); color: var(--accent); display: grid; place-items: center; margin: 0 auto 22px; }
.verify .vicon svg { width: 30px; height: 30px; }
.verify h1 { font-size: 23px; font-weight: 700; letter-spacing: -.4px; }
.verify .vtext { color: var(--text-2); font-size: 14px; line-height: 1.7; margin-top: 12px; }
.verify .vmail { display: inline-flex; align-items: center; gap: 6px; margin-top: 16px; padding: 9px 14px; background: #f7f8fa; border: 1px solid var(--border); border-radius: var(--radius); font-size: 14px; font-weight: 600; color: var(--text); }
.verify .vmail svg { width: 15px; height: 15px; color: var(--text-3); }
.verify .vspam { font-size: 12.5px; color: var(--text-3); margin-top: 18px; line-height: 1.6; }
.verify .vactions { margin-top: 26px; display: flex; flex-direction: column; gap: 10px; }
.btn-ghost { height: 44px; border-radius: var(--radius); border: 1px solid var(--border-strong); background: #fff; color: var(--text); font-family: inherit; font-size: 14px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 7px; text-decoration: none; }
.btn-ghost:hover { background: #f7f8fa; }
.btn-ghost svg { width: 16px; height: 16px; }
.vchange { background: none; border: none; font-family: inherit; font-size: 13px; color: var(--text-2); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.vchange:hover { color: var(--text); }
@media (max-width: 880px) {
.brand-panel { display: none; }
.ac-logo { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 17px; margin-bottom: 24px; }
.ac-logo .logo { width: 28px; height: 28px; border-radius: 8px; background: linear-gradient(135deg, #5b54f0, #4338ca); display: grid; place-items: center; color: #fff; font-size: 15px; font-weight: 800; }
}
</style>
</head>
<body>
<div class="auth">
<aside class="brand-panel">
<div class="blob b1"></div>
<div class="blob b2"></div>
<div class="ring"></div>
<div class="bp-logo"><span class="logo">R</span> Relay</div>
<div class="bp-body">
<div class="bp-head">팀에 합류하고<br>업무 지시를 시작하세요</div>
<div class="bp-sub">계정을 만들면 저장소에 초대되어, 받은 업무를 확인하고 직접 업무를 지시할 수 있습니다.</div>
<div class="bp-points">
<div class="bp-point"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span> 이메일로 1분이면 가입 완료</div>
<div class="bp-point"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span> 이메일 인증으로 안전한 가입</div>
<div class="bp-point"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span> 가입 후 바로 업무 흐름에 참여</div>
</div>
</div>
<div class="bp-foot">© 2026 Relay · 사내 업무 지시 플랫폼</div>
</aside>
<main class="form-panel">
<div class="auth-card">
<div class="ac-logo"><span class="logo">R</span> Relay</div>
<!-- ===== 상태 1: 가입 폼 ===== -->
<div class="signup-form">
<h1 class="ac-title">이메일로 회원가입</h1>
<p class="ac-sub">구글·카카오 계정은 <a href="로그인.html" style="color:var(--accent);font-weight:600;text-decoration:none">로그인 화면</a>에서 바로 시작할 수 있어요.</p>
<div class="field" style="margin-top:26px">
<label class="flabel">이름</label>
<input class="tinput" type="text" placeholder="홍길동" value="">
</div>
<div class="field">
<label class="flabel">이메일</label>
<input class="tinput" id="email" type="email" placeholder="name@acme.co" value="">
<div class="field-hint"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 6-10 7L2 6"/></svg> 가입 후 이 주소로 인증 메일이 발송됩니다.</div>
</div>
<div class="field">
<label class="flabel">비밀번호</label>
<div class="pw-wrap">
<input class="tinput" type="password" placeholder="비밀번호 입력" value="">
<button class="pw-toggle" type="button" title="비밀번호 표시"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></button>
</div>
<div class="field-hint"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg> 8자 이상, 영문과 숫자를 포함해주세요.</div>
</div>
<div class="field">
<label class="flabel">비밀번호 확인</label>
<div class="pw-wrap">
<input class="tinput" type="password" placeholder="비밀번호 다시 입력" value="">
<button class="pw-toggle" type="button" title="비밀번호 표시"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></button>
</div>
</div>
<label class="terms" id="terms">
<span class="box on"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span>
<span><a href="#">이용약관</a><a href="#">개인정보 처리방침</a>에 동의합니다. (필수)</span>
</label>
<button class="submit" type="button" id="submitBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 6-10 7L2 6"/></svg>
인증 메일 받고 가입하기
</button>
<div class="alt">이미 계정이 있으신가요? <a href="로그인.html">로그인</a></div>
</div>
<!-- ===== 상태 2: 인증 메일 전송됨 ===== -->
<div class="verify" id="verifyView">
<div class="vicon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 6-10 7L2 6"/></svg></div>
<h1>이메일을 확인해주세요</h1>
<div class="vtext">아래 주소로 인증 메일을 보냈습니다.<br>메일 속 링크를 클릭하면 가입이 완료됩니다.</div>
<div class="vmail"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 6-10 7L2 6"/></svg><span id="verifyEmail">name@acme.co</span></div>
<div class="vspam">메일이 보이지 않나요? 스팸함을 확인하거나 잠시 후 다시 시도해주세요.</div>
<div class="vactions">
<button class="btn-ghost" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg> 인증 메일 다시 보내기</button>
<button class="vchange" type="button" id="backBtn">다른 이메일로 가입하기</button>
</div>
</div>
</div>
</main>
</div>
<script>
// 비밀번호 표시 토글
document.querySelectorAll('.pw-toggle').forEach(function (btn) {
btn.addEventListener('click', function () {
var input = this.parentElement.querySelector('input');
input.type = input.type === 'password' ? 'text' : 'password';
});
});
// 약관 동의 토글
document.getElementById('terms').addEventListener('click', function (e) {
if (e.target.closest('a')) return;
e.preventDefault();
this.querySelector('.box').classList.toggle('on');
});
// 가입하기 → 인증 메일 전송 상태로 전환
document.getElementById('submitBtn').addEventListener('click', function () {
var email = document.getElementById('email').value.trim() || 'name@acme.co';
document.getElementById('verifyEmail').textContent = email;
document.querySelector('.signup-form').style.display = 'none';
document.getElementById('verifyView').style.display = 'block';
});
// 다른 이메일로 가입하기 → 폼으로 복귀
document.getElementById('backBtn').addEventListener('click', function () {
document.getElementById('verifyView').style.display = 'none';
document.querySelector('.signup-form').style.display = 'block';
});
</script>
</body>
</html>