/* 로그인 화면. 배경은 login-bg.js 가 캔버스에 그리는 블랙홀이고, 이 파일은 그 위에
   앉는 카드 하나만 입힌다. 배경 구도가 블랙홀을 오른쪽에 두므로(login-bg.js 의
   focus) 카드는 왼쪽, 좁은 화면에서는 블랙홀이 아래로 가므로 카드는 위로 간다. */

:root {
  color-scheme: dark;
  --accent: #2878d7;
  --accent-2: #7b61ff;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  color: rgba(255, 255, 255, 0.9);
  /* 캔버스가 못 뜨는 환경(WebGL 없음)의 바닥색. 배경 없이도 카드는 읽힌다. */
  background: #000;
  overflow: hidden;
}

#bg-host { position: fixed; inset: 0; }
#bg-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.login-card {
  position: fixed;
  z-index: 10;
  left: clamp(24px, 7vw, 110px);
  top: 50%;
  transform: translateY(-50%);
  /* 등장은 한 번뿐이다. fill-mode 가 backwards 인 것이 핵심: 끝난 뒤에는 애니메이션이
     아무 값도 남기지 않고 위 transform 이 그대로 화면을 잡는다. forwards 였다면 끝
     값이 계속 얹혀, 폭이 바뀌어 아래 모바일 규칙(translateX)으로 넘어갈 때 데스크톱의
     translateY(-50%) 가 그것을 덮는다 — 카드가 화면 밖으로 반쯤 나간다. */
  animation: card-rise 600ms cubic-bezier(0.22, 0.68, 0.31, 1) backwards;
  width: min(400px, calc(100vw - 48px));
  display: grid;
  gap: 20px;
  padding: 34px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 24px;
  background: rgba(10, 10, 14, 0.35);
  backdrop-filter: blur(12px);
}

.card-brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
.card-brand h1 {
  margin: 0;
  font-size: 26px;
  letter-spacing: -0.05em;
}
.card-brand p {
  margin: 5px 0 0;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.45);
}

.brand-mark {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 16px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #ffffff;
  font-weight: 850;
  font-size: 18px;
  letter-spacing: -0.04em;
}

/* 카드 등장. 끝 값은 위 .login-card 의 평상시 값과 **정확히 같아야** 한다 —
   한 픽셀이라도 다르면 애니메이션이 끝나는 프레임에 카드가 튄다. */
@keyframes card-rise {
  from {
    opacity: 0;
    transform: translateY(calc(-50% + 8px));
  }
  to {
    opacity: 1;
    transform: translateY(-50%);
  }
}

/* 타이핑 한 줄(login-fx.js). 글자가 늘었다 줄었다 하는 줄이라 폭이 아니라 **높이**가
   문제다: 줄 수가 바뀌면 카드 전체가 위아래로 출렁이고, 그 아래 구글 버튼이 손가락
   밑에서 움직인다. 그래서 높이를 min-height 로 못 박는다.

   몇 줄로 잡을지는 실제 폭으로 정한다. 카드 콘텐츠 폭은 min(400px, 100vw - 48px)
   에서 좌우 padding 34px 씩을 뺀 값이다 — 넓은 화면에서 332px. 가장 긴 문구
   ('CAN 신호와 카메라를 한 타임라인에 놓습니다')는 12.5px 모노스페이스에서 한글 17자가
   각각 약 1em, 라틴·공백 8자가 약 0.6em 이라 대략 275px 다. 332px 에는 한 줄로 들어가고,
   콘텐츠 폭이 그 아래로 내려가는 뷰포트(대략 391px 미만)에서만 두 줄이 된다.
   그 구간만 아래 미디어쿼리가 두 줄로 올린다 — 경계는 440px 로, 계산보다 넉넉히 잡는다.
   한글 글꼴 대체(모노스페이스에 한글 글리프가 없으면 다른 글꼴이 들어온다)로 실제 폭이
   추정보다 넓어질 수 있고, 그 어긋남은 '줄 수가 오락가락하는 구간'으로 나타난다.
   빈 한 줄을 더 두는 쪽이 카드가 출렁이는 것보다 낫다. */
.typed-line {
  --typed-line-height: 19px;
  margin: -6px 0 0;
  min-height: var(--typed-line-height);
  /* 스택 정본은 tokens.css 의 --mono 다(첫 stylesheet 로 로드됨). */
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: var(--typed-line-height);
  letter-spacing: -0.01em;
  color: rgba(255, 255, 255, 0.5);
}

/* 커서. 글자 높이만 한 세로 막대 하나가 깜빡인다. steps(1) 이라 밝기가 흐르지 않고
   딱 켜졌다 꺼진다 — 터미널 캐럿의 그림이다. */
.typed-caret {
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 3px;
  vertical-align: -0.14em;
  background: rgba(255, 255, 255, 0.72);
  animation: caret-blink 1.05s steps(1, end) infinite;
}
@keyframes caret-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.google-button {
  position: relative;
  /* 지나가는 빛(::after)을 버튼 모서리 안에 가둔다. 자기 box-shadow 는 바깥에
     그려지므로 이 클립에 걸리지 않는다. */
  overflow: hidden;
  min-height: 54px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 11px;
  border: 1px solid rgba(40, 120, 215, 0.5);
  border-radius: 15px;
  background: linear-gradient(135deg, var(--accent), #1c63b4);
  color: #ffffff;
  text-decoration: none;
  font-size: 15px;
  font-weight: 800;
  box-shadow: 0 18px 42px rgba(40, 120, 215, 0.35);
  transition: transform 140ms ease, box-shadow 140ms ease;
}
.google-button:hover {
  transform: translateY(-1px);
  box-shadow: 0 22px 50px rgba(40, 120, 215, 0.45);
}
/* 눌림. 떠 있던 1px 을 제자리로 내리고 그림자를 줄인다 — 버튼이 바닥에 닿는다. */
.google-button:active {
  transform: translateY(0);
  box-shadow: 0 8px 20px rgba(40, 120, 215, 0.3);
}
/* 버튼 위를 좌에서 우로 한 번 지나가는 빛. 글자 위를 덮지 않게 아래(z-index 0)에
   깔고, 내용은 위로 올린다. */
.google-button > * {
  position: relative;
  z-index: 1;
}
.google-button::after {
  content: "";
  position: absolute;
  z-index: 0;
  top: -60%;
  left: 0;
  width: 34%;
  height: 220%;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.28) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  transform: translateX(-140%) rotate(18deg);
  opacity: 0;
}
.google-button:hover::after {
  animation: button-shine 820ms ease-out;
}
@keyframes button-shine {
  from {
    opacity: 1;
    transform: translateX(-140%) rotate(18deg);
  }
  to {
    opacity: 0;
    transform: translateX(420%) rotate(18deg);
  }
}
.google-icon {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #ffffff;
  color: var(--accent);
  font-weight: 850;
}

.access-note {
  margin: 0;
  font-size: 12px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.35);
}
.access-note strong { color: rgba(255, 255, 255, 0.6); }

/* 좁은 화면: 블랙홀이 아래 1/3 로 내려가므로(login-bg.js 의 NARROW) 카드가 위로. */
@media (max-width: 767px) {
  .login-card {
    left: 50%;
    top: clamp(24px, 10vh, 96px);
    transform: translateX(-50%);
    /* 가로 중앙 정렬이 transform 으로 되어 있으므로 등장 애니메이션도 그 값을 품은
       것으로 갈아 끼운다. 데스크톱 키프레임을 그대로 쓰면 600ms 동안 카드가 왼쪽
       가장자리에 붙는다. */
    animation-name: card-rise-narrow;
  }
}
@keyframes card-rise-narrow {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(8px);
  }
  to {
    opacity: 1;
    /* 끝 값은 위 모바일 규칙의 transform 과 글자까지 같다. 빠진 translateY 는 브라우저가
       항등(translateY(0))으로 채워 보간한다. */
    transform: translateX(-50%);
  }
}

/* 카드 콘텐츠 폭이 가장 긴 문구보다 좁아지는 구간(위 .typed-line 주석의 산술).
   여기서는 두 줄이 나므로 자리를 미리 두 줄로 잡아 둔다. */
@media (max-width: 440px) {
  .typed-line {
    min-height: calc(var(--typed-line-height) * 2);
  }
}

/* 움직임을 원치 않는 사람에게는 움직이지 않는다. login-bg.js 가 같은 조건에서 한 장만
   그리고 멈추는 것과 같은 규약이고, 타이핑 자체를 걸지 않는 것은 login-fx.js 가 한다.
   여기서 끄는 것은 CSS 가 만드는 움직임 셋 — 카드 등장, 커서 깜빡임, 버튼 위를 지나는
   빛. 카드는 애니메이션 없이 곧바로 제자리에 보인다. */
@media (prefers-reduced-motion: reduce) {
  .login-card {
    animation: none;
  }
  .typed-caret {
    animation: none;
    opacity: 0.55;
  }
  .google-button::after {
    display: none;
  }
  .google-button:hover::after {
    animation: none;
  }
}
