/* 가계부 — 흑백 미니멀
 *
 * 규칙 세 가지.
 *   1. 색은 검정·흰색·회색만. 강조는 색이 아니라 굵기와 크기로 한다.
 *   2. 상자와 그림자 대신 헤어라인과 여백으로 나눈다.
 *   3. 큰 글자는 화면에 하나. 나머지는 전부 그 숫자의 설명이다.
 */

:root {
  color-scheme: light;

  --bg: #ffffff;
  --ink: #0a0a0a;      /* 본문 */
  --ink-2: #707070;    /* 보조 */
  --ink-3: #a8a8a8;    /* 흐린 것 */
  --line: #e9e9e9;     /* 헤어라인 */
  --line-2: #f2f2f2;   /* 더 옅은 선, 막대 트랙 */

  --holiday: #ff4d3d;  /* 공휴일·일요일 날짜. 흑백의 유일한 예외 */
                       /* 흰 배경(lv1)부터 검은 배경(lv5)까지 한 색으로 읽히는 밝기 */

  --gutter: 20px;
  --radius: 4px;
}

* { box-sizing: border-box; }

/* display 를 지정하는 클래스 규칙은 UA 의 [hidden]{display:none} 보다 특이도가
 * 높다. 이 한 줄이 없으면 hidden 을 걸어도 계속 보인다. 실제로 당한 적 있다. */
[hidden] { display: none !important; }

/* 화면 전체를 고정 틀로 쓰고, 스크롤은 <main> 안에서만 일어나게 한다.
 *
 * 문서(body)가 직접 스크롤하면 탭을 옮길 때마다 문서 높이가 확 바뀌고,
 * 안드로이드 웹뷰는 그때 position:fixed 인 하단 탭을 한 프레임 늦게 옮긴다.
 * 그게 '탭을 누를 때마다 하단 탭이 내려갔다 올라오는' 증상이다.
 * 문서 높이를 화면 높이에 못 박으면 그 일이 아예 일어나지 않는다. */
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
}

body { overflow: hidden; }

body {
  font-family: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo",
               "Segoe UI", "Malgun Gothic", Roboto, "Noto Sans KR", sans-serif;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: contain;
  -webkit-tap-highlight-color: transparent;
}

main {
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  max-width: 560px;
  margin: 0 auto;
  padding: max(env(safe-area-inset-top), 14px) var(--gutter)
           calc(env(safe-area-inset-bottom) + 96px);
}

/* preview.html 의 폰 목업 안에서는 상태바가 화면 위를 덮는다. */
body.in-frame main {
  padding-top: 56px;
  padding-bottom: 100px;
}

/* 폰 목업 안에서는 홈 인디케이터가 맨 아래를 차지한다 */
body.in-frame .tabs { padding-bottom: 20px; }

/* ---------------------------------------------------------- 뷰 탭 (하단 고정) */

.tabs {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  max-width: 560px;
  margin: 0 auto;
  background: var(--bg);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
  /* 안드로이드 웹뷰는 문서 높이가 확 바뀌면(탭을 옮길 때가 그렇다) 고정 요소를
   * 한 프레임 늦게 옮긴다. 그래서 하단 탭이 잠깐 내려갔다 올라온다.
   * 별도 레이어로 올려 두면 문서 레이아웃과 따로 그려져 들썩이지 않는다. */
  transform: translateZ(0);
}

/* 선택 표시줄. 탭마다 따로 그리면 탭을 옮길 때 한쪽에서 사라지고 다른 쪽에
 * 나타나 '순간이동'한다. 하나만 두고 옮기면 미끄러진다. */
.tabs::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: calc(100% / 3);
  height: 1.5px;
  background: var(--ink);
  transform: translateX(calc(var(--tab, 0) * 100%));
  transition: transform .24s cubic-bezier(.2, .7, .3, 1);
}

.tab {
  position: relative;
  padding: 16px 0 15px;
  border: 0;
  background: none;
  color: var(--ink-3);
  font: inherit;
  font-size: 13.5px;
  /* 굵기는 세 탭이 항상 같아야 한다. 선택할 때만 600->700 으로 바꾸면
   * 글자 폭이 달라지면서 가운데 정렬이 다시 잡히고, 탭 세 개가 동시에
   * 들썩인다. 선택 표시는 색과 위쪽 선으로 충분하다. */
  font-weight: 700;
  letter-spacing: .01em;
  cursor: pointer;
  transition: color .16s;
}

.tab.is-on { color: var(--ink); }

/* ---------------------------------------------------------- 날짜 이동 */

.datebar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 0 10px;
}

.navbtn {
  flex: 0 0 44px;
  height: 44px;
  font-size: 22px;
  line-height: 1;
  color: var(--ink-3);
  background: none;
  border: 0;
  cursor: pointer;
}
.navbtn:active { color: var(--ink); }
.navbtn:disabled { opacity: .25; cursor: default; }

.datelabel {
  flex: 1 1 auto;
  min-height: 44px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  background: none;
  border: 0;
  color: var(--ink);
  font: inherit;
  font-weight: 700;
  font-size: 15px;
  /* 줄 높이를 못 박는다. 안 그러면 '9월 22일 (월)' 의 괄호가 '2026년 9월' 보다
   * 위아래로 더 뻗어서 날짜 칸 높이가 탭마다 달라지고, 그 아래 큰 숫자까지
   * 통째로 밀린다. 일별 글자가 더 커 보이던 것도 이것이다. */
  line-height: 1.3;
  letter-spacing: -.01em;
  cursor: pointer;
}

.datelabel > span { display: block; }

.datesub {
  font-size: 11px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: .04em;
  color: var(--ink-3);
}

/* ---------------------------------------------------------- 큰 숫자 */

/* 큰 숫자 한 덩이. 여기서 세로를 많이 먹으면 아래 내용이 전부 스크롤 밖으로
 * 밀려난다. 숫자는 여전히 화면에서 제일 크되, 앞뒤 여백을 아낀다. */
.hero {
  text-align: center;
  padding: 16px 0 20px;
}

.hero-label {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--ink-3);
}

.hero-amount {
  margin: 0;
  font-size: clamp(36px, 11.5vw, 48px);
  font-weight: 800;
  letter-spacing: -.045em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.hero-amount .won {
  font-size: .34em;
  font-weight: 600;
  margin-left: 4px;
  color: var(--ink-3);
  letter-spacing: 0;
}

.hero-meta {
  margin: 10px 0 0;
  min-height: 17px;
  font-size: 12.5px;
  color: var(--ink-3);
}
.hero-meta .up,
.hero-meta .down { color: var(--ink); font-weight: 700; }

/* ---------------------------------------------------------- 요약 칸 */

.cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: 30px;
}

.cards.three { grid-template-columns: repeat(3, 1fr); }

.card {
  padding: 14px 2px;
  text-align: center;
}

.card + .card { border-left: 1px solid var(--line); }

.card-label {
  margin: 0 0 6px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .03em;
  color: var(--ink-3);
}

.card-value {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.cards.three .card-value { font-size: 16px; }

.card-value i {
  font-style: normal;
  font-size: .6em;
  font-weight: 600;
  color: var(--ink-3);
  margin-left: 2px;
}

/* ---------------------------------------------------------- 블록 */

.block { margin-bottom: 34px; }

.block-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 18px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--ink-2);
}

.count {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--ink-3);
}

/* ---------------------------------------------------------- 카테고리 막대 */

.catlist { list-style: none; margin: 0; padding: 0; }

.catlist li { padding: 0 0 20px; }

.catrow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}

.catname {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -.01em;
}

.catamount {
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  white-space: nowrap;
}

.catpct {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink-3);
  margin-left: 7px;
}

/* ---------------------------------------------------------- 도넛 (월별) */

.donutwrap {
  display: flex;
  justify-content: center;
  padding: 2px 0 22px;
}

.donut {
  /* 세 개가 세로로 쌓이므로 너무 크면 월별 탭이 한없이 길어진다 */
  width: 148px;
  height: 148px;
  /* dashoffset 은 3시 방향부터 센다. 12시에서 시작하도록 돌린다. */
  transform: rotate(-90deg);
}

.donut circle {
  fill: none;
  stroke-width: 13;
}

/* 도넛이 있는 목록은 막대가 없으므로 줄 간격을 좁힌다 */
.donutwrap + .catlist li { padding-bottom: 14px; }
.donutwrap + .catlist li:last-child { padding-bottom: 0; }
.donutwrap + .catlist .catrow { margin-bottom: 0; }

.swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: 9px;
  /* 제일 밝은 조각이 흰 배경에 묻히지 않도록 */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}

.bar {
  height: 3px;
  background: var(--line-2);
  overflow: hidden;
}

.bar > span {
  display: block;
  height: 100%;
  background: var(--ink);
  transition: width .3s cubic-bezier(.2, .7, .3, 1);
}

/* ---------------------------------------------------------- 건별 */

.txlist { list-style: none; margin: 0; padding: 0; }

.tx {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.txlist li:first-child { border-top: 1px solid var(--line); }

.tx-time {
  flex: 0 0 auto;
  width: 40px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.tx-main { flex: 1 1 auto; min-width: 0; }

.tx-name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.015em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tx-sub {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 5px;
  min-width: 0;
  overflow: hidden;
  font-size: 11.5px;
  color: var(--ink-3);
}

.tx-sub > span:not(.chip) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}


/* 카드사 마크. 로고 이미지가 있으면 그걸, 없으면 글자 모노그램.
 * 테두리를 둘러 "표식"으로 읽히게 한다 — 배경 없는 맨 글씨는
 * 옆의 카테고리 이름과 섞여서 그냥 노이즈로 보인다. */
.mark {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 16px;
  padding: 0 4px;
  border: 1px solid var(--line);
  border-radius: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1;
  color: var(--ink-2);
  white-space: nowrap;
}

.mark.has-logo {
  border: 0;
  padding: 0;
  min-width: 0;
}

.mark img {
  width: 16px;
  height: 16px;
  object-fit: contain;
  display: block;
}

/* 칩은 배경 없이 글자만. 배경을 깔면 흑백에서 지저분해진다. */
.chip {
  flex: 0 0 auto;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--ink-2);
}

.chip.tag { color: var(--ink); }

.tx-amount {
  flex: 0 0 auto;
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.025em;
  white-space: nowrap;
}
/* 취소는 색 대신 흐리게 + 부호로 구분한다 */
.tx-amount.minus { color: var(--ink-3); }

.txlist.muted .tx { opacity: .5; }
.tx.tappable { cursor: pointer; }

.excluded-summary {
  cursor: pointer;
  list-style: none;
  padding: 10px 0;
  margin: -10px 0;
}
.excluded-summary::-webkit-details-marker { display: none; }
.excluded-summary::after {
  content: "+";
  margin-left: auto;
  font-size: 14px;
  color: var(--ink-3);
}
details[open] .excluded-summary::after { content: "\2212"; }

.empty {
  margin: 0;
  padding: 34px 0;
  text-align: center;
  font-size: 13.5px;
  color: var(--ink-3);
}

/* ---------------------------------------------------------- 달력 */

.cal-head,
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
}

.cal-grid { margin-bottom: 44px; }

.cal-head {
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

.cal-head span {
  text-align: center;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--ink-3);
}
.cal-head .sun { color: var(--holiday); }

.cal-cell {
  position: relative;
  aspect-ratio: 1 / 1.1;
  padding: 7px 2px 5px;
  border: 0;
  border-radius: var(--radius);
  background: var(--line-2);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  overflow: hidden;
}

/* 많이 쓴 날일수록 검어진다. lv1~lv5 는 분위수 단계.
 *
 * 연속 그라데이션 대신 다섯 단으로 끊는 이유: 흑백에서는 미세한 농도 차이를
 * 눈이 구분하지 못한다. 단이 뚜렷해야 한눈에 읽힌다.
 *
 * 농도는 글자 대비를 기준으로 골랐다. lv1~3 은 검은 글씨가, lv4~5 는
 * 흰 글씨가 읽히는 밝기다. 중간 회색을 쓰면 어느 쪽도 안 보인다.
 */
.cal-cell.lv1 { background: #ededed; }
.cal-cell.lv2 { background: #d4d4d4; }
.cal-cell.lv3 { background: #b4b4b4; }
.cal-cell.lv4 { background: #6e6e6e; }
.cal-cell.lv5 { background: #0a0a0a; }

/* 음영이 깔린 칸은 날짜도 진하게 — 기본 회색은 묻힌다 */
.cal-cell.spent .cal-day { color: var(--ink); }

.cal-cell.heavy .cal-day,
.cal-cell.heavy .cal-amount { color: #fff; }

.cal-cell.blank {
  visibility: hidden;
  cursor: default;
}

.cal-day {
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

/* 흑백에서 유일한 예외. 공휴일과 일요일의 날짜만 빨갛다.
 * 배경 농도와 무관하게 **항상 같은 빨강**을 쓴다 — 칸마다 색이 달라지면
 * 빨강이 지출 많고 적음을 뜻하는 것처럼 읽힌다. */
.cal-cell.holiday .cal-day { color: var(--holiday); }

.cal-amount {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: -.04em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  word-break: keep-all;
}

.cal-cell.today { box-shadow: inset 0 0 0 1.5px var(--ink); }

.cal-cell.future {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--line);
}
/* 공휴일 규칙보다 먼저 와야 미래의 일요일·공휴일도 빨갛게 남는다 */
.cal-cell.future .cal-day { color: var(--ink-3); }
.cal-cell.future.holiday .cal-day { color: var(--holiday); opacity: .55; }


/* ---------------------------------------------------------- 더보기 / 전체 내역 */

.morebtn {
  margin-left: auto;
  /* 전체 목록으로 가는 유일한 입구다. 손가락으로 눌러야 하므로 세로 여백을 준다 */
  padding: 12px 0 12px 16px;
  margin-top: -12px;
  margin-bottom: -12px;
  border: 0;
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .02em;
  cursor: pointer;
}
.morebtn::after {
  content: " ›";
  font-weight: 400;
}
.morebtn:active { color: var(--ink); }

/* 하루 전체 내역. 탭바까지 덮는 별도 화면. */
.sheet {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.sheet-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: max(env(safe-area-inset-top), 8px) var(--gutter) 12px;
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}

body.in-frame .sheet-head { padding-top: 54px; }

/* 뒤로가기는 한 손으로 누르는 버튼이다. 48dp 는 지켜야 한다. */
.backbtn {
  flex: 0 0 48px;
  height: 48px;
  margin-left: -14px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-bottom: 3px;   /* 꺾쇠 글리프의 시각적 중심 보정 */
  font-size: 28px;
  line-height: 1;
  color: var(--ink);
  background: none;
  border: 0;
  cursor: pointer;
}
.backbtn:active { opacity: .45; }

.sheet-heading { min-width: 0; }

.sheet-title {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -.02em;
}

.sheet-sub {
  margin: 3px 0 0;
  font-size: 12px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.sheet-body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 0 var(--gutter) calc(env(safe-area-inset-bottom) + 32px);
}

/* 헤더에 이미 선이 있으므로 첫 줄의 윗선은 겹친다 */
.sheet-body .txlist li:first-child { border-top: 0; }

.sheet-body .block { margin: 36px 0 0; }

/* ---------------------------------------------------------- 하단 */

.foot {
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  text-align: center;
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--ink-3);
}
.foot p { margin: 0 0 6px; }

.failed { color: var(--ink-2); font-weight: 600; }

/* ---------------------------------------------------------- 당겨서 새로고침 */

.pull {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  height: 0;
  overflow: hidden;
  z-index: 40;
  pointer-events: none;
  padding-bottom: 6px;
}

.pull-spinner {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid var(--line);
  border-top-color: var(--ink);
}

.pull.spin .pull-spinner { animation: spin .7s linear infinite; }

@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .pull.spin .pull-spinner { animation-duration: 1.6s; }
  .bar > span { transition: none; }
}


/* ---------------------------------------------------------- 화면 전환 */

/* 탭을 옮기면 새 화면이 진행 방향에서 밀려 들어온다.
 * 나가는 화면까지 같이 움직이려면 두 화면을 동시에 띄워야 해서
 * 높이가 출렁인다. 들어오는 쪽만 움직여도 방향은 충분히 읽힌다. */
@keyframes slide-from-right {
  from { transform: translateX(26px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

@keyframes slide-from-left {
  from { transform: translateX(-26px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

@keyframes slide-up {
  from { transform: translateY(14px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

.enter-right { animation: slide-from-right .2s cubic-bezier(.2, .7, .3, 1); }
.enter-left  { animation: slide-from-left  .2s cubic-bezier(.2, .7, .3, 1); }
.sheet.enter { animation: slide-up .18s cubic-bezier(.2, .7, .3, 1); }

@media (prefers-reduced-motion: reduce) {
  .enter-right, .enter-left, .sheet.enter { animation: none; }
  .tabs::after { transition: none; }
}

/* ---------------------------------------------------------- 토스트 */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom) + 24px);
  transform: translateX(-50%);
  max-width: calc(100% - 40px);
  padding: 12px 18px;
  background: var(--ink);
  color: #fff;
  font-size: 12.5px;
  font-weight: 600;
  z-index: 60;
  animation: rise .18s ease-out;
}

@keyframes rise {
  from { opacity: 0; transform: translate(-50%, 6px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
