/* ============================================================
   ShinhanTrustPass 화면 공통 스타일
   화면설계서 3장(공통 틀),4장(화면별 정의),7장(디자인 기준)을 따른다.
   색,크기는 tokens.css 변수만 쓴다.
   상태 클래스(.is-*,.has-*)는 ui 스크립트가 붙이고 뗀다. 목록은 ui/README.md 3절.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  font-family: var(--font-primary);
  font-weight: 300;
  font-size: var(--tp-fs-body);
  line-height: 1.6;
  color: var(--text-primary);
  background: var(--bg-elevated);
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}
button, input { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: none; box-shadow: var(--focus-ring); }
[hidden] { display: none !important; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---------- 1. 공통 틀: 상단,가운데,하단 (3장) ---------- */
/* 상단과 하단은 고정하고 가운데만 스크롤한다. */
.app {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

/* 노치 자리만큼 위 여백을 더한다(3장 3항) */
.app-header {
  flex-shrink: 0;
  padding-top: env(safe-area-inset-top);
  background: var(--tp-fixed-bg);
}
.app-header__bar {
  height: var(--tp-header-h);
  padding: 0 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.app-title {
  margin: 0;
  font-size: var(--tp-fs-title);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.app-title--brand { display: flex; align-items: center; gap: 8px; min-width: 0; }
.app-title__icon { display: block; flex-shrink: 0; width: 28px; height: 28px; }

.app-main {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 16px;
}
.app-main--plain { padding: 48px 24px 24px; gap: 28px; background: var(--bg-elevated); }
.app-main--list { background: var(--bg-primary); }
.app-main--center { align-items: center; }

/* 잠금 전 화면의 하단: 주 버튼이나 숫자 자판. 홈 막대 자리만큼 아래 여백을 더한다. */
.app-footer {
  flex-shrink: 0;
  padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
  background: var(--tp-fixed-bg);
  border-top: 1px solid var(--border-default);
}
.app-footer--empty { padding: 0 0 env(safe-area-inset-bottom); min-height: 1px; }

/* 잠금 후 화면의 하단: 탭 3칸 */
.tabbar {
  flex-shrink: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--tp-fixed-bg);
  border-top: 1px solid var(--border-default);
}
.tabbar__item {
  height: var(--tp-tab-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  font-size: var(--tp-fs-tab);
  line-height: 1.2;
  color: var(--text-secondary);
}
.tabbar__item svg { width: 22px; height: 22px; }
.tabbar__item[aria-current="page"] { color: var(--tp-tab-active); font-weight: 500; }
/* 앱의 탭은 button이다(시안은 a). 브라우저 기본 버튼 테두리,바탕을 지운다(Phase 4) */
button.tabbar__item { padding: 0; border: 0; background: transparent; cursor: pointer; }
/* 직접입력에서 자판이 올라오면 탭을 숨긴다(3장 4항) */
.app.is-keyboard-open .tabbar { display: none; }

/* ---------- 2. 글자 ---------- */
.text { margin: 0; font-size: var(--tp-fs-body); line-height: 1.6; }
.text--muted { color: var(--text-secondary); }
.text--sub { font-size: var(--tp-fs-sub); line-height: 1.5; color: var(--text-secondary); }
.text--strong { font-weight: 500; color: var(--tp-strong); }
.text--center { text-align: center; }

.wordmark { margin: 0; line-height: 1; letter-spacing: -0.02em; white-space: nowrap; }
.wordmark__shinhan { font-weight: 300; color: var(--text-primary); }
.wordmark__pass { font-weight: 500; color: var(--shinhan-blue); }
.wordmark--brand { font-size: var(--tp-fs-brand); }

.brand { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.brand__icon { display: block; width: 80px; height: 80px; }

/* 검증미연동 표시 */
.badge {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  padding: 4px 8px;
  border-radius: 999px;
  background: var(--tp-key-bg);
  color: var(--tp-strong);
  font-size: var(--tp-fs-sub);
  font-weight: 500;
  line-height: 1.2;
}

/* ---------- 3. 버튼 ---------- */
/* 누르는 자리는 44px 이상(7장 7항) */
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 52px;
  padding: 0 16px;
  border: 0;
  border-radius: var(--radius-md);
  font-size: var(--tp-fs-body);
  font-weight: 500;
  line-height: 1.2;
  cursor: pointer;
  transition: transform 200ms var(--ease-out), background-color 200ms var(--ease-out);
}
.btn:active { transform: scale(0.98); }
.btn--primary { background: var(--shinhan-blue); color: var(--text-inverse); }
.btn--primary:active { background: var(--tp-pressed); }
.btn--secondary {
  min-height: 48px;
  background: var(--bg-elevated);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
}
.btn--danger { min-height: 48px; background: var(--tp-strong); color: var(--text-inverse); }

/* ---------- 4. 묶음 상자,아이콘 ---------- */
.panel {
  width: 100%;
  padding: 16px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--bg-primary);
}
.panel--status { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }

.guide { display: flex; align-items: center; gap: 12px; }
.icon-tile {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 40px; height: 40px;
  border-radius: var(--radius-lg);
  background: var(--shinhan-blue-50);
  color: var(--shinhan-blue);
}
.icon-tile svg { width: 22px; height: 22px; }

.icon-circle {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 72px; height: 72px;
  border-radius: 50%;
  background: var(--shinhan-blue-50);
  color: var(--shinhan-blue);
}
.icon-circle svg { width: 32px; height: 32px; }
.icon-circle--lg { width: 88px; height: 88px; }
.icon-circle--lg svg { width: 44px; height: 44px; }
.icon-circle--soft { color: var(--tp-sub-icon); }

/* 아이폰 설치 3단계(4.1) */
.steps {
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--bg-primary);
}
.steps__item {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-subtle);
}
.steps__item:last-child { border-bottom: 0; }
.steps__num {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--shinhan-blue-50);
  color: var(--tp-strong);
  font-size: var(--tp-fs-sub);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.steps__text { flex: 1 1 auto; font-size: var(--tp-fs-body); line-height: 1.5; }
.steps__pic {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 48px; height: 48px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--bg-elevated);
  color: var(--shinhan-blue);
}
.steps__pic svg { width: 24px; height: 24px; }
.steps__pic img { display: block; width: 32px; height: 32px; }

/* PIN 경고문: 연한 바탕에 진한 글자(4.3) */
.notice {
  width: 100%;
  margin: auto 0 0;
  padding: 12px 16px;
  border-radius: var(--radius-lg);
  background: var(--tp-fixed-bg);
  color: var(--tp-strong);
  font-size: var(--tp-fs-sub);
  line-height: 1.6;
}

/* ---------- 5. PIN 입력 점,숫자 자판 (4.3,4.4) ---------- */
.pin-dots { display: flex; gap: 16px; }
.pin-dot {
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 1.5px solid var(--border-strong);
  background: transparent;
}
.pin-dot.is-filled { border-color: var(--shinhan-blue); background: var(--shinhan-blue); }
.pin-dots.is-shake { animation: tp-shake 300ms var(--ease-out); }
@keyframes tp-shake {
  0%, 100% { transform: translateX(0); }
  20%, 60% { transform: translateX(-8px); }
  40%, 80% { transform: translateX(8px); }
}

.keypad { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.keypad__key {
  height: 56px;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--tp-key-bg);
  color: var(--text-primary);
  font-size: var(--tp-fs-key);
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
.keypad__key:active { background: var(--tp-pressed); color: var(--text-inverse); }
.keypad__key--del { background: transparent; font-size: var(--tp-fs-body); font-weight: 500; }
.keypad__key--del:active { background: var(--tp-key-bg); color: var(--text-primary); }
.keypad__blank { height: 56px; }
/* PIN 틀림 대기 중에는 자판을 흐리게 하고 막는다(4.4). 막는 일은 disabled가 하고 여기서는 보이기만 바꾼다(Phase 4) */
.keypad__key:disabled { opacity: var(--tp-disabled-opacity); cursor: default; }
/* 설정의 PIN변경은 자판을 가운데 구역 아래에 둔다(4.8,하단은 탭). 가운데 맞춤 안에서도 폭을 채운다(Phase 4) */
.app-main > .keypad { align-self: stretch; }

/* ---------- 6. 코드목록 (4.5) ---------- */
.otp-list { display: flex; flex-direction: column; gap: 12px; }
.otp-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  padding: 16px;
  text-align: left;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none; /* 길게 눌러 삭제를 쓰므로 기본 메뉴를 막는다 */
}
.otp-card__head { display: flex; flex-direction: column; gap: 2px; }
.otp-card__name { font-size: var(--tp-fs-body); font-weight: 500; line-height: 1.4; }
.otp-card__account { font-size: var(--tp-fs-sub); line-height: 1.4; color: var(--text-secondary); }
/* 숫자 폭을 고정해 코드가 바뀔 때 흔들리지 않게 한다(7장 5항) */
.otp-card__code {
  font-size: var(--tp-fs-otp);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
.otp-card__bar {
  display: block;
  height: 4px;
  border-radius: 2px;
  overflow: hidden;
  background: var(--shinhan-blue-100);
}
/* --remain : 남은 시간 비율 0~1. 스크립트가 1초마다 바꾼다. */
.otp-card__fill {
  display: block;
  height: 100%;
  width: calc(var(--remain, 1) * 100%);
  background: var(--shinhan-blue);
  transition: width 1s linear;
}
.otp-card.is-expiring .otp-card__fill { background: var(--tp-strong); }
.otp-hint { margin: 4px 0 0; text-align: center; font-size: var(--tp-fs-sub); line-height: 1.5; color: var(--text-secondary); }

.empty {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  text-align: center;
}
.empty__text { display: flex; flex-direction: column; align-items: center; gap: 4px; }
/* 빈 상태 첫 줄. 시안 마크업의 style 속성(font-weight 500)을 CSP 때문에 클래스로 옮겼다(지시서 2.8 R-29 행,Phase 5) */
.empty__title { font-weight: 500; }

/* "복사되었습니다." 1.5초 표시. 탭 바로 위에 띄운다. */
.toast {
  position: absolute;
  left: 50%;
  bottom: calc(var(--tp-tab-h) + env(safe-area-inset-bottom) + 16px);
  transform: translateX(-50%);
  z-index: 5;
  padding: 10px 16px;
  border-radius: var(--radius-lg);
  background: var(--shinhan-navy);
  color: var(--text-inverse);
  font-size: var(--tp-fs-sub);
  font-weight: 500;
  white-space: nowrap;
  box-shadow: var(--shadow-lg);
}

/* ---------- 7. 등록: 전환 버튼,촬영 틀,입력칸 (4.6,4.7) ---------- */
.segmented {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
  padding: 4px;
  border-radius: var(--radius-lg);
  background: var(--bg-tertiary);
}
.segmented__item {
  display: flex; align-items: center; justify-content: center;
  height: 44px;
  border-radius: var(--radius-md);
  font-size: var(--tp-fs-body);
  color: var(--text-secondary);
}
.segmented__item[aria-current="page"] {
  background: var(--bg-elevated);
  box-shadow: var(--shadow-xs);
  font-weight: 500;
  color: var(--text-primary);
}
/* 앱의 전환 버튼은 button이다(시안은 a). 브라우저 기본 버튼 테두리,바탕을 지운다(Phase 5,탭과 같다) */
button.segmented__item { width: 100%; padding: 0; border: 0; background: transparent; cursor: pointer; }
/* 카메라 권한 거부 때 직접입력 전환 버튼을 강조한다(5장) */
.segmented__item.is-emphasis {
  font-weight: 500;
  color: var(--shinhan-blue);
  box-shadow: inset 0 0 0 1.5px var(--shinhan-blue);
}

.scan-frame {
  align-self: center;
  width: min(304px, 100%);
  aspect-ratio: 1 / 1;
  padding: 6px;
  border: 2px dashed var(--shinhan-blue);
  border-radius: var(--radius-xl);
}
.scan-frame__view {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--shinhan-navy-deep);
  color: var(--text-quaternary);
  font-size: var(--tp-fs-sub);
}
.scan-frame__view video { width: 100%; height: 100%; object-fit: cover; }
.scan-guide { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }

.form { margin: 0; display: flex; flex-direction: column; gap: 16px; }
.form .btn { margin-top: 8px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field__label { font-size: var(--tp-fs-sub); font-weight: 500; }
.field__optional { font-weight: 300; color: var(--text-secondary); }
.field__input {
  height: 48px;
  padding: 0 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  font-size: var(--tp-fs-body);
  font-weight: 300;
}
.field__input::placeholder { color: var(--text-tertiary); }
.field__input--key { letter-spacing: 0.04em; }
.field__error { margin: 0; font-size: var(--tp-fs-sub); line-height: 1.5; color: var(--tp-strong); }
.field.has-error .field__input { border-color: var(--tp-strong); }
.form-note {
  margin: 0;
  display: flex; align-items: center; gap: 6px;
  font-size: var(--tp-fs-sub);
  line-height: 1.5;
  color: var(--text-secondary);
}
.form-note svg { flex-shrink: 0; width: 16px; height: 16px; }

/* ---------- 8. 설정,전체삭제 확인 창 (4.8) ---------- */
.app-main--settings { gap: 32px; }
.settings {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.settings__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 0 16px;
  border: 0;
  border-bottom: 1px solid var(--border-subtle);
  background: transparent;
  font-size: var(--tp-fs-body);
  text-align: left;
}
.settings__row:last-child { border-bottom: 0; }
button.settings__row, a.settings__row { cursor: pointer; }
.settings__value { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.settings__chevron { flex-shrink: 0; width: 18px; height: 18px; color: var(--text-tertiary); }
.settings__row--danger { font-weight: 500; color: var(--tp-strong); }
/* 저장 보호 줄 아래 경고 문구(4.8,5장 저장 보호 거절). 시안에 없어 Phase 4가 더했다. 경고 글자는 700 자리다(7장 표) */
.settings__note {
  margin: 0;
  padding: 0 16px 12px;
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--tp-fs-sub);
  line-height: 1.5;
  color: var(--tp-strong);
}
.settings__note:last-child { border-bottom: 0; }
/* 경고가 보일 때는 줄과 경고 사이 선을 지워 한 묶음으로 보인다 */
.settings__row:has(+ .settings__note:not([hidden])) { border-bottom: 0; }

.modal-backdrop {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 24px;
  background: var(--backdrop-modal);
}
.modal {
  width: 100%;
  max-width: 360px;
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 24px;
  border-radius: var(--radius-xl);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-xl);
}
/* 서비스 삭제 확인 창의 제목(서비스 이름,4.5). 시안이 없어 상단 화면 제목과 같은 크기,굵기로 둔다(Phase 5) */
.modal__title {
  margin: 0;
  font-size: var(--tp-fs-title);
  font-weight: 500;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.modal__text { margin: 0; font-size: var(--tp-fs-body); line-height: 1.6; }
.modal__actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }

@media (prefers-reduced-motion: reduce) {
  .btn, .otp-card__fill { transition: none; }
  .pin-dots.is-shake { animation: none; }
}
