/* ==========================================================================
   stop&loss — 로그인 · 회원가입 전용 스타일 (login.html · signup.html 공용)

   style.css 다음에 실린다. 토큰과 공용 부품(.input · .btn · .field · .field-error ·
   .checkbox · .spinner · 토스트 · 스킵 링크)은 style.css 것을 그대로 쓰고,
   이 파일에는 두 인증 문서에만 있는 것(전면 유체 배경 · 유리 카드 · 미니멀 셸 ·
   약관 동의 상자)만 둔다. 다른 문서는 이 파일을 싣지 않으므로, 여기를 지워도
   다른 페이지는 픽셀 하나 안 바뀐다.

   팔레트 — 새 색을 만들지 않았다. 전부 style.css 토큰과 히어로 색분산 계열이다.
     배경   #040407 (--bg)
     표면   #0d0d14 (--surface, 블러 미지원 카드 폴백)
     본문   #f7f7fa (--text) · rgba(255,255,255,.78) (--text-soft)
     보조   rgba(255,255,255,.52) (--muted)
     포인트 #3de9ff (--primary, 히어로 렌즈 색분산 청록) · 위험 #ff5c7a (--danger)
     염료   static/login.js 의 PALETTE — 청록 #3de9ff · 적 #ff2d5c · 보라 #b48cff · 흰빛
   ========================================================================== */

/* ---------- 1. 셸 ---------- */

.auth-body {
  min-height: 100vh;
  min-height: 100dvh;
  overflow-x: hidden;
}

.auth-frame {
  position: relative;
  z-index: 10;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ---------- 2. 유체 배경 ---------- */

/*
 * static/login.js 가 이 안의 캔버스에 WebGL 로 그린다. WebGL 이 없거나 셰이더가
 * 실패하면 캔버스는 투명하게 남고 이 배경 그라데이션이 그대로 보인다 —
 * 어떤 실패에서도 화면이 비지 않는다.
 *
 * 모션 최소화(prefers-reduced-motion)에서도 유체를 끄지 않는다. 성능 목적으로 창
 * 애니메이션을 꺼 둔 Windows PC 가 전부 reduce 로 보고되기 때문이다 — 메인 히어로
 * 셰이더(hero.css)와 같은 규칙이다. 대신 DOM 쪽 등장 애니메이션만 끈다(9절).
 */
.fluid-stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(720px 480px at 16% -10%, rgba(61, 233, 255, .1), transparent 64%),
    radial-gradient(720px 480px at 84% -12%, rgba(255, 45, 92, .09), transparent 64%),
    radial-gradient(640px 480px at 50% 112%, rgba(180, 140, 255, .08), transparent 70%),
    var(--bg);
}

.fluid-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 1.1s ease;
}

/* 첫 프레임이 실제로 나온 뒤에만 드러난다(login.js 가 is-live 를 단다).
   미리 켜면 빈 사각형이 한 번 번쩍인다. */
.fluid-stage.is-live .fluid-canvas { opacity: 1; }

/* 유체가 밝게 번져도 카드 글자가 묻히지 않게, 중앙이 살짝 더 어두운 베일 한 겹. */
.fluid-veil {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 92% 72% at 50% 46%,
    rgba(4, 4, 7, .5), rgba(4, 4, 7, .16) 58%, rgba(4, 4, 7, 0));
}

/* ---------- 3. 상단 바 ---------- */

/*
 * 로고 하나만 있는 줄이다.
 *
 * 예전에는 오른쪽에 '처음이신가요? 회원가입'이 있었다. 로그인하러 온 사람의 시선은
 * 카드 안에 머무는데, 화면 반대쪽 구석에 있으면 그 링크는 거의 읽히지 않는다.
 * 지금 회원가입 · 로그인 전환 링크는 카드 맨 아래(.auth-switch) 한 곳뿐이다.
 * 여기로 되살리지 말 것 — 같은 링크가 두 군데 있으면 한쪽만 고쳐지는 날이 온다.
 */
.auth-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 24px;
}

.auth-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.auth-brand-copy {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}

.auth-brand-copy b {
  color: #fff;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.03em;
}

.auth-brand-copy span {
  color: rgba(255, 255, 255, .45);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .16em;
}

/* ---------- 4. 중앙 카드 ---------- */

.auth-center {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 20px;
  /*
   * 등장 애니메이션은 카드가 아니라 여기에 건다. 카드에는 실패 시 shake 가 걸리는데
   * (아래 :has 규칙), 같은 요소에 두 animation 을 두면 shake 가 끝날 때 등장
   * 애니메이션이 되살아나 카드가 입력할 때마다 다시 떠오른다.
   */
  animation: auth-in .6s cubic-bezier(.22, 1, .36, 1) both;
}

@keyframes auth-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/*
 * 다크 글래스 카드.
 * 기본값은 불투명(--surface) — backdrop-filter 미지원 브라우저의 폴백이다.
 * 반투명 + 블러는 @supports 안에서만 켠다. 순서를 뒤집으면 미지원 환경에서
 * 유체가 글자 뒤로 그대로 비쳐 가독성이 무너진다.
 */
.auth-card {
  width: 100%;
  max-width: 420px;
  padding: 40px;
  background: var(--surface);
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 24px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, .55);
}

@supports ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .auth-card {
    background: rgba(10, 10, 17, .55);
    -webkit-backdrop-filter: blur(20px) saturate(1.15);
    backdrop-filter: blur(20px) saturate(1.15);
  }
}

/*
 * 로그인 · 가입 실패 → member.js 가 .auth-alert 의 hidden 을 걷는 순간 카드가
 * 짧게 흔들린다. :has 미지원 브라우저에서는 흔들림만 없다(알림은 그대로 보인다).
 * 알림이 숨겨졌다 다시 나타나면 선택자가 다시 매칭되어 애니메이션도 다시 돈다.
 */
.auth-card:has(.auth-alert:not([hidden])) {
  animation: auth-shake .22s ease;
}

@keyframes auth-shake {
  20% { transform: translateX(-6px); }
  45% { transform: translateX(5px); }
  70% { transform: translateX(-3px); }
  90% { transform: translateX(2px); }
}

/* ---------- 5. 카드 머리 ---------- */

.auth-head { margin-bottom: 22px; }

/* 영문 라벨(SIGN IN · CREATE ACCOUNT)은 지웠다. 제목이 이미 '로그인' · '회원가입'이라
   같은 말을 영어로 한 번 더 하는 셈이었다. 규칙은 남겨 둔다 — 다른 화면에서
   쓰게 될 수 있고, 안 쓰면 아무 영향도 없다. */
.auth-kicker {
  margin-bottom: 10px;
  color: rgba(255, 255, 255, .45);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .18em;
}

.auth-title {
  font-size: 25px;
  font-weight: 700;
  letter-spacing: -.03em;
  line-height: 1.3;
}

.auth-desc {
  margin-top: 8px;
  color: var(--muted);
  font-size: 13.5px;
  line-height: 1.65;
}

/* ---------- 6. 폼 ---------- */

.auth-form {
  display: grid;
  gap: 15px;
}

/* 포커스 표시는 사이트 공통(흰 링) 위에 포인트 색 전환을 얹는다. */
.auth-card .input {
  background: rgba(255, 255, 255, .05);
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}

.auth-card .input:focus {
  border-color: rgba(61, 233, 255, .6);
  background: rgba(61, 233, 255, .04);
  box-shadow: 0 0 0 3px rgba(61, 233, 255, .12);
}

.auth-card .input.is-invalid { border-color: var(--danger); }

/*
 * 다크 배경의 -webkit-autofill 흰 배경 보정.
 * 배경은 거대한 inset 그림자로 덮고, 배경색 전환은 사실상 무한대로 지연시킨다.
 */
.auth-card .input:-webkit-autofill,
.auth-card .input:-webkit-autofill:hover,
.auth-card .input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
  -webkit-box-shadow: 0 0 0 1000px #101019 inset;
  box-shadow: 0 0 0 1000px #101019 inset;
  transition: background-color 999999s ease-out;
}

.auth-card .input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 3px rgba(61, 233, 255, .12), 0 0 0 1000px #101019 inset;
  box-shadow: 0 0 0 3px rgba(61, 233, 255, .12), 0 0 0 1000px #101019 inset;
}

/* 비밀번호 입력 + 표시 토글(유리 알약 — 사이트 공통 문법) */
.password-field {
  position: relative;
  display: block;
}

.password-field .input {
  width: 100%;
  padding-right: 68px;
}

.password-toggle {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);
  padding: 6px 12px;
  background: rgba(255, 255, 255, .06);
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 9999px;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 600;
  transition: color .15s ease, background .15s ease, border-color .15s ease;
}

.password-toggle:hover,
.password-toggle:focus-visible {
  color: #fff;
  background: rgba(255, 255, 255, .12);
  border-color: rgba(255, 255, 255, .4);
}

/* Caps Lock 안내 — login.js 가 켜고 끈다. 로그인 실패의 가장 흔한 원인이라
   경고색을 준다(오류와 달리 입력을 막지는 않으므로 danger 가 아니라 warn). */
.caps-hint {
  color: var(--warn);
  font-size: 12.5px;
}

/* 아이디 규칙 같은 입력 도움말. 오류(.field-error)와 달리 늘 보인다. */
.field-hint {
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.6;
}

/* 서버 오류 알림(잘못된 비밀번호 · 레이트리밋 등) */
.auth-alert {
  margin-bottom: 16px;
  padding: 11px 14px;
  background: rgba(255, 92, 122, .12);
  border: 1px solid rgba(255, 92, 122, .38);
  border-radius: 12px;
  color: #ffb3c2;
  font-size: 13.5px;
  line-height: 1.55;
  animation: auth-alert-in .25s ease;
}

@keyframes auth-alert-in {
  from { opacity: 0; transform: translateY(-4px); }
}

.auth-note {
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.65;
  text-align: center;
}

.auth-note a {
  color: var(--primary);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.auth-note a:hover { color: #fff; }

/* 카드 하단 전환 링크 — 로그인 ↔ 회원가입.
   화면 폭과 상관없이 언제나 보인다. 예전에는 640px 이상에서 이것을 숨기고
   상단 오른쪽 링크를 대신 보여줬는데, 같은 링크가 두 벌이라 문구가 갈라졌다. */
.auth-switch {
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 13.5px;
  text-align: center;
}

.auth-switch a {
  color: var(--primary);
  font-weight: 600;
}

.auth-switch a:hover { color: #fff; }

/* ---------- 6-b. 약관 동의 (회원가입 전용) ---------- */

/*
 * 구조가 두 층이다.
 *   전체 동의 — 개별 항목을 한 번에 켜고 끄는 조작 도구. 저장되는 값이 아니다.
 *   개별 항목 — 필수 둘 · 선택 하나. 실제 판정은 이것만 본다(member.js).
 *
 * 상자로 묶는 이유: 이 다섯 줄이 하나의 결정이라는 것을 눈으로 알려야 한다.
 * 체크박스를 폼 필드들과 같은 간격으로 늘어놓으면 '입력 항목'처럼 보여서,
 * 전체 동의를 눌러 놓고도 아래가 켜졌는지 다시 확인하게 된다.
 */
.agree-box {
  padding: 14px 16px;
  background: rgba(255, 255, 255, .035);
  border: 1px solid var(--border);
  border-radius: 14px;
  transition: border-color .15s ease;
}

/* 필수 항목을 안 켜고 가입을 누른 상태. 오류 문구만으로는 어디를 봐야 하는지
   모른다 — 상자 자체가 붉어져야 시선이 그리로 간다. */
.agree-box.is-invalid { border-color: var(--danger); }

.agree-all {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
}

.agree-all input {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  accent-color: var(--primary);
  cursor: pointer;
}

.agree-all-copy {
  display: grid;
  gap: 3px;
  min-width: 0;
}

.agree-all-copy b {
  color: var(--text);
  font-size: 14.5px;
  font-weight: 700;
  letter-spacing: -.01em;
}

.agree-all-copy span {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
}

.agree-divider {
  height: 1px;
  margin: 13px 0;
  background: var(--border);
}

.agree-list {
  display: grid;
  gap: 11px;
}

.agree-item {
  display: grid;
  gap: 4px;
}

.agree-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--text-soft);
  font-size: 13.5px;
  line-height: 1.5;
  cursor: pointer;
}

.agree-row input {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin-top: 2px;
  accent-color: var(--primary);
  cursor: pointer;
}

/* '필수'와 '선택'은 글자 크기가 같으면 구분이 안 된다. 필수만 색을 준다 —
   선택까지 칠하면 둘 다 눈에 띄어 결국 아무것도 눈에 띄지 않는다. */
.agree-mark {
  margin-right: 4px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
}

.agree-mark.is-required { color: var(--primary); }

/* 약관 본문. 기본은 접혀 있다 — 펼친 채로 두면 카드가 두 배로 길어져
   정작 가입 버튼이 화면 밖으로 밀린다. */
.agree-detail { margin-left: 26px; }

.agree-detail > summary {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  width: fit-content;
  color: rgba(255, 255, 255, .45);
  font-size: 12px;
  list-style: none;
  cursor: pointer;
  transition: color .15s ease;
}

.agree-detail > summary::-webkit-details-marker { display: none; }
.agree-detail > summary::marker { content: ''; }

.agree-detail > summary::after {
  content: '⌄';
  font-size: 11px;
  line-height: 1;
  transform: translateY(-1px);
  transition: transform .15s ease;
}

.agree-detail[open] > summary::after { transform: translateY(1px) rotate(180deg); }

.agree-detail > summary:hover { color: #fff; }

.agree-detail-body {
  display: grid;
  gap: 6px;
  margin-top: 7px;
  padding: 11px 13px;
  background: rgba(255, 255, 255, .04);
  border-radius: 10px;
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.7;
}

.agree-detail-body b { color: var(--text-soft); font-weight: 600; }

.agree-detail-body a {
  color: var(--primary);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.agree-detail-body a:hover { color: #fff; }

/* ---------- 7. 하단 태그라인 ---------- */

.auth-foot {
  padding: 16px 24px 26px;
  text-align: center;
}

.auth-tagline {
  color: var(--muted);
  font-size: 13px;
}

.auth-copy {
  margin-top: 4px;
  color: rgba(255, 255, 255, .3);
  font-size: 12px;
}

/*
 * 저작권 옆의 처리방침 링크.
 *
 * 이 두 문서(로그인 · 회원가입)는 공용 푸터(.site-footer)를 쓰지 않아, 사이트에서
 * 유일하게 처리방침으로 가는 문이 없는 화면이었다. 「개인정보 보호법」 제30조
 * 제2항의 '정보주체가 언제든지 쉽게 확인할 수 있도록' 은 여기에도 그대로 걸린다 —
 * 가입 직전에 보는 화면이라 오히려 더 그렇다.
 *
 * 저작권보다 밝게 두는 것도 공용 푸터(.footer-policy, style.css 14-c)와 같은
 * 규칙이다. 같은 밝기면 저작권 문구의 일부처럼 읽혀 링크인 줄 모른다.
 */
/*
 * 누를 자리를 글자보다 크게 둔다.
 *
 * 12px 글자의 줄 상자는 16px 남짓이다. 휴대폰에서 손가락으로는 거의 맞출 수 없고
 * (WCAG 2.5.8 의 최소 24px 에 못 미친다), 사이트에서 가장 작은 표적이 하필
 * 법령이 '쉽게 확인할 수 있도록' 하라고 정한 문이었다.
 *
 * 세로 padding 만 준다. inline 요소의 세로 padding 은 줄 상자 높이를 바꾸지
 * 않으면서 누를 자리만 넓히므로 보이는 모양이 한 픽셀도 달라지지 않는다.
 * inline-block 으로 바꾸면 저작권 줄의 키가 함께 자라 태그라인과의 사이가 벌어진다.
 * 가로로도 넓히지 않는다 — 이미 96px 이고, 늘리면 옆의 가운뎃점과의 간격이 어긋난다.
 *
 * 밑줄을 그리는 이유: 이 줄의 본문은 rgba(…,.3) 이고 링크는 .58 이라 둘의 명도
 * 대비가 2.7:1 이다. WCAG 1.4.1 은 색만으로 링크를 가를 때 3:1 을 요구하므로
 * 굵기 차이 하나로는 모자란다. 사이트의 다른 본문 링크(.auth-note a ·
 * .agree-detail-body a)가 이미 쓰는 것과 같은 문법이다.
 */
.auth-copy a {
  padding: 9px 0;
  color: rgba(255, 255, 255, .58);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.auth-copy a:hover { color: #fff; }

.auth-copy-sep {
  margin: 0 7px;
  color: rgba(255, 255, 255, .18);
}

/* ---------- 8. 반응형 ---------- */

@media (max-width: 639px) {
  .auth-top { padding: 14px 18px; }
  .auth-card { padding: 32px 24px; }
  .agree-box { padding: 13px 14px; }
}

@media (max-width: 379px) {
  .auth-center { padding: 16px; }
  .auth-card { padding: 28px 20px; }
}

/* 세로가 짧은 화면(노트북 등)에서는 여백을 줄여 스크롤 없이 담는다.
   회원가입은 약관 상자 때문에 그래도 넘칠 수 있는데, 그때는 자연 스크롤에 맡긴다 —
   내용을 자르거나 약관을 감추는 것보다 낫다. */
@media (max-height: 820px) {
  .auth-top { padding-top: 12px; padding-bottom: 12px; }
  .auth-card { padding: 30px 32px; }
  .auth-head { margin-bottom: 16px; }
  .auth-form { gap: 12px; }
  .auth-switch { margin-top: 14px; padding-top: 12px; }
  .auth-foot { padding-bottom: 14px; }
}

/* ---------- 9. 접근성: 모션 최소화 ---------- */

/*
 * DOM 애니메이션(등장 · 흔들림)만 끈다. 유체 배경은 그대로 돈다 — 2절 주석 참조.
 * style.css 의 전역 축소 규칙이 이미 대부분을 잡지만, 명시해 둔다.
 */
@media (prefers-reduced-motion: reduce) {
  .auth-center,
  .auth-card,
  .auth-alert { animation: none; }
  .fluid-canvas { transition: none; }
}