/* =========================================================================
 * app.css — 골격 + 컴포넌트 14종. 정본은 DESIGN-SYSTEM.md §2·§5.
 * 2026-08-11 재디자인: Claude 디자인 언어(크림·코랄·넉넉한 여백·부드러운 곡률).
 *
 * ⚠️ 유지: 1024px 단일 분기 · 카드 고정높이 금지(rem) · 모션 150~200ms 스프링 금지 ·
 *          3상태 체크 · 추모 무채·모션0 · safe-area.
 * ========================================================================= */

* { margin: 0; padding: 0; box-sizing: border-box; }
/* ⚠️ 가로로는 절대 안 움직인다 — 2026-08-13 사용자 지시("폰으로 볼 때 슬라이딩이나
   화면 전체가 움직이는 상황은 최대한 없애줘"). 이건 **마지막 안전망**이지 해결책이
   아니다: 원인(가로 스크롤 칩·넘치는 그리드)은 각자 자리에서 고쳤고, 이 줄은 앞으로
   누가 넓은 요소를 넣어도 화면이 옆으로 밀리지 않게 잡아 두는 용도다.
   ⚠️ overflow-y 는 건드리지 않는다 — 세로 스크롤까지 막으면 긴 화면을 못 읽는다. */
html, body { max-width: 100%; overflow-x: hidden; overscroll-behavior-x: none; }
html { font-size: 16px; -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--sans);
  background: var(--bg); color: var(--ink);
  line-height: 1.65;
  min-height: 100dvh;
  padding-bottom: calc(4rem + env(safe-area-inset-bottom));
  -webkit-font-smoothing: antialiased;
  /* ⚠️ 한글은 어절 중간에서 끊으면 안 된다 — "바 뀝니다"·"이 안내는 초 안이에요" 방지.
     실제로 깨져 있던 것을 2026-08-12 전역으로 고침. */
  word-break: keep-all;
  overflow-wrap: break-word;   /* 단, 긴 URL·영문 연속은 넘치지 않게 */
  letter-spacing: -.003em;     /* Pretendard 는 아주 살짝 좁혀야 결이 산다 */
}
a { color: var(--primary); text-decoration: none; }
button { font: inherit; cursor: pointer; }
img { max-width: 100%; height: auto; }
/* ⚠️ 입력칸은 기본적으로 "20글자쯤"의 고유 너비를 가져서, flex:1 을 줘도 그 아래로는
   안 줄어든다. 좁은 폰에서 입력 두 개를 한 줄에 두면(기록·일정 화면이 그렇다) 줄이
   화면 밖으로 삐져나가 가로 스크롤이 생겼다. min-width:0 이 그걸 푼다. */
input, select, textarea { min-width: 0; max-width: 100%; }
.num { font-variant-numeric: tabular-nums; }

.wrap { max-width: 34rem; margin: 0 auto; padding: 1.25rem 1.25rem 2rem; }

/* ── 하단 탭바 ── */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: grid; grid-template-columns: repeat(5, 1fr);
  height: calc(4rem + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: saturate(140%) blur(12px);
  border-top: 1px solid var(--line);
}
/* 아이콘 — Solar(선형) 한 세트만. 획 두께는 1.5 로 고정(세트를 섞으면 여기가 어긋난다) */
.ico { width: 1.5rem; height: 1.5rem; flex: 0 0 auto; }

.tabbar a {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .18rem;
  /* ⚠️ ink-3 는 11.5px 라벨에서 3.63:1(AA 미달, 실측 2026-08-12) — 탭 라벨은 ink-2 하한 */
  font-size: .72rem; color: var(--ink-2); min-height: var(--tap);
  position: relative; transition: color var(--dur) var(--ease);
}
.tabbar a.on { color: var(--primary); font-weight: 600; }
.tabbar a.on::before {   /* 상단 코랄 인디케이터 — Claude 특유의 절제된 표식 */
  content: ""; position: absolute; top: 0; width: 1.5rem; height: 2px;
  border-radius: 999px; background: var(--primary);
}

/* 데스크톱 — 사이드바(1024px 단일 분기) */
@media (min-width: 1024px) {
  body { padding-bottom: 0; padding-left: 15rem; }
  /* ⚠️ **사이드바가 없는 화면은 그 자리를 비워 두면 안 된다.** 위 padding-left 는
     탭바(사이드바) 자리인데, 탭바를 안 그리는 화면(로그인·가입·아이 화면)에도 240px 이
     그대로 잡혀 내용이 **오른쪽으로 120px 밀려** 있었다(2026-08-14 데스크톱 실측:
     1440px 에서 main 이 400px 이 아니라 520px 에서 시작).
     ⚠️ 폰에서는 안 보이는 결함이다 — 이 media query 자체가 1024px 부터라서.
     ⚠️ `body.auth` 로 가르면 안 된다 — 온보딩·탈퇴처럼 **로그인한 auth 화면에는
        탭바가 있다.** 판정은 `ns_has_tabbar()` 한 곳(inc/view.php)이 하고,
        없을 때 `no-tabs` 를 붙인다. */
  body.no-tabs { padding-left: 0; }
  .tabbar {
    left: 0; right: auto; top: 3.75rem; bottom: 0; width: 15rem; height: auto;
    display: flex; flex-direction: column; padding: 1.25rem .75rem 0;
    border-top: none; border-right: 1px solid var(--line); background: var(--surface);
    backdrop-filter: none;
  }
  .tabbar a {   /* 데스크톱 사이드바 — 아이콘과 라벨을 가로로 */
    flex-direction: row; justify-content: flex-start; gap: .75rem;
    padding: .7rem 1rem; font-size: 1rem;
    border-radius: var(--radius); margin-bottom: .25rem;
  }
  .tabbar a.on { background: var(--primary-l); }
  .tabbar a.on::before { display: none; }
  .wrap { max-width: 40rem; padding-top: 2rem; }
}

/* ── 타이포 스케일 ── */
h1 { font-size: 1.55rem; font-weight: 700; line-height: 1.3; letter-spacing: -.015em; }
h2 { font-size: 1.15rem; font-weight: 600; line-height: 1.4; letter-spacing: -.01em; }
h3 { font-size: .8rem; font-weight: 600; line-height: 1.4; color: var(--ink-2);
     text-transform: none; letter-spacing: .01em; }
.display {
  font-family: var(--serif); font-size: 2rem; font-weight: 600;
  line-height: 1.2; letter-spacing: -.02em;
}
small, .caption { font-size: .78rem; line-height: 1.5; color: var(--ink-2); }

/* ── 버튼 — 부드러운 곡률, 코랄 액션 ── */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 0 2rem;   /* 명세: 좌우 32px — 손에 잡히는 크기 */
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font-weight: 500;
  white-space: nowrap;   /* ⚠️ 버튼 라벨은 절대 줄바꿈 금지("기 록"·"올 리 기" 방지) */
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.btn:hover { background: var(--surface-2); }
.btn:active { transform: scale(.98); }
.btn-primary {
  background: var(--primary); border-color: var(--primary); color: #fff;
  box-shadow: 0 1px 2px rgba(35,32,27,.08);
}
.btn-primary:hover { background: var(--primary-d); border-color: var(--primary-d); }
.btn-danger { background: var(--surface); border-color: var(--danger); color: var(--danger); }

/* ── 카드 — 크림 위 아이보리 + 층을 준 표면 ──
   ⚠️ 밋밋한 "1px 회색 테두리 + 검은 그림자" 금지. 경계는 배경색과 같은 계열로 두고,
   윗면에 아주 옅은 하이라이트(inset)를 얹어 빛이 위에서 오는 것처럼 만든다. */
.card {
  background: var(--surface);
  /* ⚠️ 명세 §Elevation — 카드에 그림자를 쓰지 않는다. 깊이는 색조 차이와 옅은 경계로 만든다.
     경계는 20~40% 불투명도라 "딱딱한 모서리"가 생기지 않는다. */
  border: 1px solid color-mix(in srgb, var(--line) 40%, transparent);
  border-radius: var(--radius-l); padding: 1.5rem; margin-bottom: 1rem;
  box-shadow: none;
}
.card .caption { display: block; margin-bottom: .35rem; color: var(--ink-2);
                 font-weight: 500; letter-spacing: .01em; }
.card h2 { margin-bottom: .35rem; font-family: var(--serif); font-weight: 500; }
/* quiet(기록 없음) — 그림자·경계 없이 면으로만. 다크에선 경계로 */
.card-quiet { background: var(--surface-2); border-color: transparent; box-shadow: none; }
:root[data-theme="dark"] .card-quiet { background: var(--surface); border-color: var(--line); }

/* ── 화면 제목 ── 2026-08-13. 모든 내용 화면이 같은 자리·같은 크기로 시작한다.
   ⚠️ 세리프 .display 를 안 쓴다 — 그건 로그인·등록완료 같은 순간용이다.
   매일 여는 화면마다 큰 세리프를 쓰면 강조가 흔해져 아무 데도 강조가 안 된다. */
.page-title { font-size: 1.55rem; font-weight: 700; line-height: 1.3;
              letter-spacing: -.015em; margin: .25rem 0 0; }
.page-sub { margin: .3rem 0 0; }
/* 제목 바로 뒤에 오는 칩은 위 여백을 줄인다(제목과 한 덩어리로 읽히게) */
.page-sub + .chips, .page-title + .chips { padding-top: .75rem; }
/* 제목 다음 첫 섹션 헤더는 위 여백을 줄인다 — 기본값(64px)은 제목과 너무 떨어진다 */
.page-title + .sec-head, .page-sub + .sec-head, .chips + .sec-head { margin-top: 1.5rem; }

/* 안내 본문 제목 — 화면 제목(h1)이 위에 따로 있어 이건 h2 다.
   다만 이 화면의 주인공이라 h2 기본값보다 크게 준다. */
.guide-title { font-size: 1.35rem; font-weight: 700; line-height: 1.35;
               letter-spacing: -.015em; margin-top: 1.25rem; }

/* ── 달력(월 격자) ── 2026-08-13.
   ⚠️ 7칸을 `1fr` 로만 나눈다(최소폭 금지) — 320px 폰에서 한 칸이 40px 남짓인데
   min-width 를 주는 순간 가로로 밀린다("가로로는 안 움직인다" 원칙). */
.cal-head { display: flex; align-items: center; justify-content: center; gap: 1rem; margin: .5rem 0 .75rem; }
.cal-head strong { font-size: 1.05rem; font-weight: 600; }
.cal-nav { display: inline-flex; align-items: center; justify-content: center;
           width: 2.5rem; height: 2.5rem; border-radius: 999px; color: var(--ink-2); font-size: 1.3rem; }
.cal-nav:hover { background: var(--surface-2); }

/* ⚠️ `1fr` 이 아니라 `minmax(0,1fr)` 이다. `1fr` 은 최소값이 auto(=콘텐츠 크기)라
   좁은 폰에서 앞쪽 칸들이 제 콘텐츠 폭을 우선 차지하고 **마지막 칸만 찌그러진다**
   (320px 실측: 40px×6 + 25.7px). minmax(0,…) 가 그 최소값을 0으로 풀어 7칸을 똑같이 나눈다.
   ⚠️ 요일 머리글은 **격자를 따로 쓴다** — 같은 격자에 넣으면 날짜 칸 행 높이가
   머리글과 엮여 한 줄만 키가 달라진다(실측: 한 칸이 96px). */
.cal, .cal-wds { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .15rem; }
.cal { grid-auto-rows: 2.75rem; }
.cal-wd { text-align: center; font-size: .72rem; color: var(--ink-3); padding: .25rem 0 .4rem; }
.cal-wd.sun, .cal-cell.sun .num { color: var(--primary); }
.cal-cell {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .12rem; min-height: 2.75rem; border-radius: var(--radius);
  color: var(--ink); font-size: .9rem; min-width: 0;
}
.cal-cell.empty { pointer-events: none; }
.cal-cell:hover { background: var(--surface-2); }
/* 오늘 = 은은한 테두리 / 고른 날 = 채움. 둘이 겹쳐도 읽힌다 */
.cal-cell.today { box-shadow: inset 0 0 0 1px var(--line); font-weight: 600; }
/* 기간이 걸친 날(시험·방학) — 점이 아니라 **면**으로 칠한다.
   ⚠️ 6주 방학을 점으로 찍으면 한 달이 점으로 뒤덮여 "무슨 날인지" 구분이 사라진다.
   ⚠️ .sel 보다 **먼저** 선언한다 — 고른 날은 채움색이 이겨야 한다. */
.cal-cell.span { background: var(--accent-l); }
.cal-cell.sel { background: var(--primary); color: #fff; font-weight: 600; }
.cal-cell.sel .num, .cal-cell.sel.sun .num { color: #fff; }
/* 점 — 할 게 남았으면 강조색, 다 끝났으면 옅게. ⚠️ 개수를 숫자로 쓰지 않는다(재촉이 된다) */
.cal-dot { width: .3rem; height: .3rem; border-radius: 999px; background: var(--accent); }
.cal-dot.done { background: var(--line); }
.cal-cell.sel .cal-dot { background: #fff; }

/* 안내 목록(학사 일정 등) — 카드 안에서 읽는 줄글. 점은 옅게, 줄간격은 넉넉히 */
.note-list { margin: .5rem 0 0; padding-left: 1.1rem; }
.note-list li { margin-bottom: .4rem; color: var(--ink-2); font-size: .92rem; line-height: 1.6; }
.note-list li::marker { color: var(--line); }

/* ── 자녀 열람 화면 ── 부모 화면의 축소판이 아니다. 탭바가 없어 아래 여백을 직접 준다. */
body.kid { padding-bottom: 3rem; }
.kid-wrap { max-width: 34rem; margin: 0 auto; }

/* ── 섹션 헤더 ── */
.sec-head { display: flex; align-items: baseline; gap: .75rem;
            margin: var(--stack-lg) .25rem 1rem; }
.sec-head h2 { font-size: .8rem; color: var(--ink-2); flex: 1; font-weight: 600;
               text-transform: uppercase; letter-spacing: .06em; }
.sec-act { font-size: .78rem; color: var(--primary); min-height: auto; font-weight: 500; }

/* ── 생년월일 년·월·일 드롭다운 ── 2026-08-13.
   모바일 기본 달력이 오늘 달부터 열려 먼 과거를 못 고른다는 제보로 신설(view.php 머리말). */
.ymd { display: flex; gap: .5rem; }
.ymd select {
  flex: 1; min-width: 0; min-height: 3rem; padding: 0 .5rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink); font: inherit;
}
.ymd select:first-child { flex: 1.4; }   /* 연도는 네 자리라 조금 넓게 */

/* ── 아이콘 타일 그리드(앱 화면) ──
   2026-08-13: "태아부터 청소년까지 통합할 수 있는 메뉴" 요청 + 코레일톡 이동·편의
   탭 참고 이미지. ⚠️ 하단 탭 5개는 그대로 두고(IA-SCREENS "탭 고정") 이 그리드는
   탭 안이 아니라 앱 화면 하나에서 기능 입구를 한눈에 모아 보여주는 용도다.
   (처음엔 더보기에 뒀다가 2026-08-13 앱 탭으로 옮겼다.) */
/* ⚠️ 4열이 아니라 3열이다 — 좁은 폰(320px)에서 4열은 타일이 눌려 라벨이 깨지고
   가로 스크롤을 만들 수 있다. 3열이면 타일 6개가 정확히 2줄로 떨어지기도 한다. */
.tilegrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem .5rem; margin: .5rem 0 var(--stack-lg); }
.tile { display: flex; flex-direction: column; align-items: center; gap: .45rem; text-align: center; color: var(--ink); }
.tile-ico {
  width: 3.25rem; height: 3.25rem; border-radius: 999px; background: var(--surface-2);
  display: flex; align-items: center; justify-content: center; color: var(--primary);
  transition: background var(--dur) var(--ease);
}
.tile:active .tile-ico { background: var(--primary-l); }
.tile span { font-size: .78rem; color: var(--ink-2); line-height: 1.3; }
/* 타일 모양의 **동작**(로그아웃) — 2026-08-14 사용자 지시("로그아웃도 해당 모양으로").
   ⚠️ <a> 가 아니라 <button> 이다. 로그아웃은 POST + CSRF 로만 받는다 — 링크로 두면
      남의 사이트에 심은 <img src=".../logout.php"> 하나로 로그아웃당한다.
      모양은 같게, 오는 길은 다르게. */
button.tile { border: 0; background: none; font: inherit; padding: 0; width: 100%; cursor: pointer; }

/* 작은 표식(일기 공개범위 등) — 강조가 아니라 사실 표기라 채도를 낮게 */
.pill { font-size: .7rem; padding: .1rem .5rem; border-radius: 999px;
        background: var(--info-l); color: var(--info); font-weight: 600; }

/* ── 일기 첨부 사진 ── 글에 딸린 것이라 크게 펼치지 않는다(글이 본체다) */
.diary-pics { display: flex; flex-wrap: wrap; gap: .4rem; width: 100%; margin-top: .15rem; }
.diary-pics img { width: 6.5rem; height: 6.5rem; object-fit: cover;
                  border-radius: var(--radius); border: 1px solid var(--line); }

/* 사진 한 장 + 지우기 — 2026-08-14.
   ⚠️ 사진 **위에 겹치는 X 단추를 안 쓴다.** 아이 얼굴 위에 삭제 아이콘이 얹히는 것도
      그렇고, 손가락이 큰 화면에서 사진을 보려다 잘못 누르기 쉽다. 사진 아래 조용한
      글씨 한 줄이면 실수로 눌릴 일이 없다.
   ⚠️ figure 의 기본 margin 을 0 으로 — 안 그러면 브라우저 기본 여백(1em 40px)이 붙어
      그리드가 통째로 벌어진다. */
.pic { margin: 0; display: flex; flex-direction: column; align-items: center; gap: .15rem; }
.pic-del { margin: 0; line-height: 1; }
.pic .cmt-del { font-size: .68rem; }

/* ── 일기 가족 댓글 ── 2026-08-13. 채팅이 아니라 "이 기록에 붙는 한마디"라서
   말풍선·시간·읽음표시를 만들지 않는다. 그런 걸 붙이는 순간 카톡 흉내가 된다. */
.cmts { width: 100%; margin-top: .5rem; padding-left: .75rem;
        border-left: 2px solid var(--line); display: flex; flex-direction: column; gap: .4rem; }
.cmt { display: flex; gap: .45rem; align-items: baseline; font-size: .88rem; }
.cmt-who { color: var(--ink-3); font-size: .78rem; flex: 0 0 auto; }
.cmt-body { color: var(--ink-2); flex: 1; }
.cmt-del { background: none; border: 0; color: var(--ink-3); font-size: .72rem;
           padding: 0 .2rem; text-decoration: underline; }
.cmt-form { display: flex; gap: .4rem; width: 100%; margin-top: .5rem; }
.cmt-form input {
  flex: 1; min-height: 2.5rem; padding: 0 .75rem; font-size: .88rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); color: var(--ink);
}
.cmt-form .btn { min-height: 2.5rem; padding: 0 .9rem; flex: 0 0 auto; }

/* ── 자녀 칩 ── ⚠️ 2026-08-13: 가로 스크롤(overflow-x:auto)을 걷어내고 줄바꿈으로.
   사용자 지시 "폰으로 볼 때 슬라이딩이나 화면 전체가 움직이는 상황은 최대한 없애줘".
   자녀가 여럿이면 칩이 옆으로 밀려 나가 손가락으로 밀어야 보였는데(안 밀면 뒤쪽
   자녀가 있는 줄도 모른다), 이제 다 보인다. guide.php 의 주차·시기 이동 nav 도
   같은 .chips 라 함께 고쳐진다. sticky 첫 칩도 뗀다 — 가로 스크롤이 없으면 붙일 이유가 없다. */
.chips { display: flex; flex-wrap: wrap; gap: .5rem; padding: .25rem 0 1rem; }
.chips a {
  flex: 0 0 auto; display: flex; align-items: center;
  min-height: 2.5rem; padding: 0 1.05rem;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink-2); font-size: .9rem; font-weight: 500;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.chips a.on { background: var(--primary); border-color: var(--primary); color: #fff; }

/* ── 일정 행 ── */
.sched { border: 1px solid color-mix(in srgb, var(--line) 40%, transparent);
         border-radius: var(--radius-l); background: var(--surface); overflow: hidden; }
.sched-row {
  display: flex; align-items: center; gap: .875rem;
  min-height: 3.75rem; padding: .75rem 1.25rem;
  /* 명세 §Lists — 구분선이 컨테이너를 가로지르지 않게 안쪽으로 들인다 */
  border-bottom: 1px solid transparent;
  background-image: linear-gradient(to right,
      color-mix(in srgb, var(--line) 55%, transparent),
      color-mix(in srgb, var(--line) 55%, transparent));
  background-size: calc(100% - 2.5rem) 1px;
  background-position: 1.25rem 100%;
  background-repeat: no-repeat;
}
.sched-row:last-child { background-image: none; }
.sched-row:hover { background: color-mix(in srgb, var(--surface-2) 50%, transparent); }
.sched-date { flex: 0 0 3.75rem; font-size: .82rem; color: var(--ink-2); font-weight: 500; }
.sched-title { flex: 1; }
/* 설정 목록 한 줄 — "라벨 … 값 ›". 2026-08-14 개인 관리를 목록+상세로 다시 짜면서.
   ⚠️ 값이 길면(메일 주소) 줄을 넘기지 말고 **잘라서 말줄임** — 넘기면 줄 높이가
      들쭉날쭉해져 목록이 목록으로 안 읽힌다. 전체 값은 누르고 들어가면 보인다. */
.row-label { flex: 0 0 auto; font-weight: 500; }
.row-val { flex: 1; min-width: 0; text-align: right; color: var(--ink-2);
           overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-val small { display: block; white-space: nowrap; }
/* 오른쪽 화살표 — i-back 을 뒤집어 쓴다(같은 세트·같은 획. icons.php 머리말 참고) */
.row-go { flex: 0 0 auto; width: 1.1rem; height: 1.1rem;
          color: var(--ink-3); transform: rotate(180deg); }
.sched-dday { font-size: .75rem; color: var(--primary); font-weight: 600;
              background: var(--primary-l); padding: .15rem .5rem; border-radius: 999px; }

/* ── 3상태 체크 ── */
.check3 { display: flex; gap: .5rem; margin-top: .875rem; }
.check3 button, .check3 form button {
  flex: 1; min-height: var(--tap);
  /* 아이콘이 들어와도 글자와 같은 줄에 가운데로 — 2026-08-13 설정 화면(밝게/어둡게) */
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2); font-weight: 500;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
/* 버튼 안 아이콘은 글자 크기에 맞춰 조금 작게(기본 1.5rem 은 라벨을 눌러 보인다) */
.check3 button .ico, .btn .ico { width: 1.15rem; height: 1.15rem; }
.btn { gap: .4rem; }
.check3 button:hover { background: var(--surface-2); }
.check3 button.on { background: var(--primary); border-color: var(--primary); color: #fff; }

/* 라디오를 같은 모양의 버튼으로 — 개인 관리의 보호자 구분(2026-08-14).
   ⚠️ 라디오를 `display:none` 으로 감추지 않는다 — 그러면 **탭 키로 못 고른다.**
      투명하게 겹쳐 두면 초점은 그대로 받는다(그래서 focus 표시도 따로 그린다).
   ⚠️ 선택 상태는 :has() 로 그린다. 못 쓰는 브라우저에서는 테두리가 안 바뀔 뿐
      고르는 것 자체는 된다(기능이 죽지 않는다). */
/* ⚠️ `.check3 label` 이 아니라 `label.opt` 다 — 아래 `.field label { display:block }` 이
   **나중에 나와서 이깄다.** 폼 안에 넣으면 라디오가 세로로 쌓여 버린다(같은 특이도면
   순서가 이긴다). 클래스를 하나 더 붙여 특이도로 못 박는다. */
.check3 label.opt {
  flex: 1; min-height: var(--tap); position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2); font-weight: 500; cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
label.opt input { position: absolute; opacity: 0; width: 1px; height: 1px; }
label.opt:has(input:checked) { background: var(--primary); border-color: var(--primary); color: #fff; }
label.opt:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }

/* ── 출처·면책 ── */
.src-note {
  margin-top: 1.25rem; padding-top: .875rem;
  border-top: 1px solid var(--line);
  font-size: .75rem; color: var(--ink-3); line-height: 1.6;
}

/* ── 빈 상태 — 넉넉한 여백 ── */
.empty { text-align: center; padding: 3rem 1.25rem; color: var(--ink-2); }
.empty p { margin-bottom: .5rem; font-size: 1.02rem; }
.empty .btn { margin: 1.25rem auto 0; max-width: 20rem; }

/* ── 주차 막대(StatBar) — 코랄 그라데이션 ── */
.statbar { height: .5rem; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.statbar > span {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--primary));
}

/* =========================================================================
 * 인사 히어로 — 이 서비스의 얼굴. 정체성 세 요소가 여기 모인다:
 *   ① 큰 세리프 주차 숫자(감정의 무게)  ② 여정 궤적 + 켜진 노드(로고와 같은 언어)
 *   ③ 넉넉한 여백(설렘은 여백과 타이포로 — 요건 그대로)
 * 2026-08-11 신설.
 * ======================================================================= */
.hero { padding: 1.25rem .25rem 1.75rem; }
/* 날짜 — ink-3 는 크림 배경 위 4.05:1 로 AA 미달(실측). ink-2 로 5.2:1 확보 */
.hero-date { color: var(--ink-2); font-size: .82rem; letter-spacing: .02em; margin-bottom: .85rem; }
.hero-greet {
  font-size: 1.85rem; font-weight: 700; line-height: 1.25; letter-spacing: -.02em; color: var(--ink);
}
.hero-greet span { font-weight: 400; color: var(--ink-2); }   /* "…를 기다리는 중" 은 약하게 */

/* 정체성 숫자 — 세리프 큰 주차. "주" 는 중간, "N일" 은 조용히 */
.hero-week {
  display: flex; align-items: baseline; gap: .3rem;
  margin-top: 1.05rem; font-family: var(--serif);
  font-size: 1.5rem; color: var(--primary); letter-spacing: -.01em;
}
.hero-week b { font-size: 4rem; font-weight: 600; line-height: .92; }
.hero-week em {
  font-style: normal; font-family: var(--sans); font-weight: 500;
  font-size: 1.25rem; color: var(--ink-2);
}

.hero-bar { margin-top: 1.15rem; height: .4rem; }
.hero-sub { margin-top: .95rem; color: var(--ink-2); font-size: .9rem; }

/* 여정 궤적의 '켜진 노드' — 로고와 같은 언어. 홈 히어로와 guide 상세가 공유(.trail).
   overflow 를 열어 노드가 막대 밖으로 나온다. */
.statbar.trail { overflow: visible; position: relative; }
.statbar.trail > span { position: relative; overflow: visible; }
.statbar.trail > span::after {
  content: ""; position: absolute; right: -.3rem; top: 50%; transform: translateY(-50%);
  width: .9rem; height: .9rem; border-radius: 999px;
  background: var(--primary); border: 3px solid var(--surface);
  box-shadow: 0 0 0 1px var(--line), 0 2px 7px rgba(187,90,56,.4);
}
/* guide 상세의 여정 궤적 — 캡션과 제목 사이 */
.trail-line { margin: .9rem 0 .3rem; }
.trail-cap { color: var(--ink-2); font-size: .8rem; margin-bottom: 1.25rem; }

/* 추모 모드 — 궤적 노드의 빛(그림자) 제거, 무채로 */
.memorial .statbar.trail > span::after { box-shadow: 0 0 0 1px var(--line); }

/* ── 피처 카드 본문(이번 시기) — 이 아이의 '다음 걸음'을 가장 또렷하게 ── */
.feature-body { margin-top: .3rem; color: var(--ink-2); line-height: 1.6; }
.feature-link {
  display: inline-flex; align-items: center; gap: .15rem;
  margin-top: .95rem; color: var(--primary); font-weight: 600; font-size: .9rem;
}

/* ── 안내 블록·플래시 ── */
.note-info {
  background: var(--info-l); border-left: 3px solid var(--info);
  padding: .875rem 1.15rem; border-radius: 0 var(--radius) var(--radius) 0;
  font-size: .86rem; margin: 1.25rem 0; line-height: 1.6;
}
.flash {
  background: var(--primary-l); color: var(--primary-d);
  padding: .875rem 1.15rem; border-radius: var(--radius); margin-bottom: 1.25rem;
  font-weight: 500; box-shadow: var(--shadow);
}

/* ── 폼 ── */
.field { margin-bottom: 1.5rem; }
.field label { display: block; font-weight: 600; margin-bottom: .5rem; font-size: .95rem; }
.field input, .field select {
  width: 100%; min-height: 3.5rem; padding: 0 1.1rem;
  font-size: 1.05rem; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.field input:focus, .field select:focus {
  /* 명세: 두꺼운 글로우 금지 — 테두리만 테라코타로 두꺼워진다 */
  outline: none; border-color: var(--accent); border-width: 2px;
  box-shadow: none;
}
/* ⚠️ .field 안팎 어디서든 쓴다 — 새 폼(일기·측정)은 .field 로 감싸지 않는다 */
.hint, .field .hint { font-size: .78rem; color: var(--ink-3); margin-top: .45rem; }
.field .live {
  margin-top: .875rem; padding: .875rem 1.15rem;
  background: var(--accent-l); color: var(--primary-d);
  border-radius: var(--radius); font-weight: 600; font-variant-numeric: tabular-nums;
}

/* ── 인증 화면 ── Earth and Cradle: 조용하게, 화면 세로 중앙에 둔다.
   ⚠️ 배경 사진·일러스트를 두지 않는다 — 첫 화면이 조용해야 서비스의 성격이 전해진다.
   2026-08-13: 고정 상단 여백(14dvh) 대신 진짜 세로 중앙 정렬로 — 화면 높이·내용
   길이(에러 문구 유무 등)가 달라도 항상 가운데 있어야 한다는 사용자 지시. */
/* ⚠️ 세로 중앙 정렬은 **로그인·추모 화면에만** 건다(`auth-center`).
   2026-08-13: 처음엔 `body.auth` 전체에 걸었는데("로그인 페이지는 세로 중앙"이라는
   지시를 auth 계열 전부로 넓혀 버렸다), 그 바람에 **온보딩·아이 등록 화면의 내용이
   화면 한가운데까지 밀려 내려갔다**(사용자 폰 스크린샷으로 확인).
   내용이 짧은 입력 화면은 위에서 시작해야 한다 — 다른 탭 화면(오늘·달력…)과 같은 틀이다. */
body.auth-center main.wrap { min-height: 100dvh; display: flex; flex-direction: column; justify-content: center; }
.auth-box { max-width: 22rem; margin: 0 auto; padding: 0 .5rem; }
/* ⚠️ 온보딩 입력 화면(보호자·내 정보·아이 등록) — 로그인보다 넓고 왼쪽 정렬이다.
   2026-08-13: 화면마다 `style="text-align:left; max-width:26rem;"` 을 손으로 반복하고
   있었고 첫 화면(보호자)만 그게 빠져 **혼자 좁았다**. 클래스 하나로 모은다. */
.auth-form { max-width: 26rem; margin: 0 auto; padding: 0 .5rem; text-align: left; }
.auth-mark { display: block; margin: 0 auto 1.25rem; }
.auth-title {
  font-family: var(--serif); font-size: 2.3rem; font-weight: 600;
  letter-spacing: -.02em; text-align: center; color: var(--ink);
}
.auth-sub {
  color: var(--ink-2); margin: .6rem 0 2.5rem; font-size: 1rem;
  text-align: center; line-height: 1.6;
}
.auth-btns { display: flex; flex-direction: column; gap: .75rem; }
.auth-err {
  color: var(--danger); font-size: .9rem; margin-bottom: 1.25rem; text-align: center;
  background: color-mix(in srgb, var(--danger) 7%, transparent);
  border-radius: var(--radius); padding: .75rem 1rem;
}
.btn-naver  { background: #03C75A; border-color: #03C75A; color: #fff; }
.btn-google { background: var(--surface); }

/* ── 접근성 ── */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ── 로그인 유지 체크 ── 기본 꺼짐이라 눈에 띄되 강요하지 않게 */
.keep-row {
  display: flex; align-items: flex-start; gap: .6rem;
  margin: 0 0 1.25rem; cursor: pointer; font-size: .95rem;
}
.keep-row input { width: 1.15rem; height: 1.15rem; margin-top: .18rem; accent-color: var(--primary); }
.keep-row em {   /* 공용기기 경고 — 체크 옆에 붙어 있어야 의미가 있다 */
  display: block; font-style: normal; font-size: .78rem; color: var(--ink-2); margin-top: .1rem;
}

/* =========================================================================
 * Earth and Cradle 시그니처 — "The Breath" (2026-08-12)
 * 명세 §Special Component: 기능 버튼이 하나도 없는 조용한 자리.
 * 대비를 낮추고 타이포만 크게 둔다. **이 서비스가 재촉하지 않는다는 증거**가 되는 칸이다.
 * ⚠️ 여기에 버튼·링크·수치를 넣지 말 것. 넣는 순간 성격이 사라진다.
 * ======================================================================= */
.breath {
  background: color-mix(in srgb, var(--info-l) 45%, transparent);
  border-top: 1px solid color-mix(in srgb, var(--line) 35%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 35%, transparent);
  border-radius: var(--radius-l);
  padding: 2rem 1.75rem;
  margin: var(--stack) 0;
  text-align: center;
}
.breath p {
  font-family: var(--serif); font-size: 1.15rem; font-weight: 500;
  line-height: 1.85; color: var(--ink-2); margin: 0;
}

/* ── 주차 여정 막대의 양 끝 라벨 ── 사장님이 좋다고 한 요소.
   "시작 · 40주 여정 중 23주째 · 40주" — 지금 어디쯤인지 한눈에 */
.trail-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  margin: 0 .25rem .5rem; font-size: .75rem; color: var(--ink-3);
}
.trail-head .now { color: var(--primary); font-weight: 600; font-size: .82rem; }

/* ── 카드 소제목에 붙는 작은 아이콘(아기·엄마) ── 면 색이라 --accent 를 쓴다 */
.card h2 .ico, .sec-ico {
  width: 1.35rem; height: 1.35rem; color: var(--accent);
  vertical-align: -.2rem; margin-right: .45rem;
}

/* ── 소셜 로그인 버튼(전체폭) ── 2026-08-12: 유일한 로그인 수단이 되면서
   작은 아이콘 원에서 라벨 있는 큰 버튼으로. 뭘 눌러야 하는지 한눈에 보여야 한다. */
.social-col { display: flex; flex-direction: column; gap: .625rem; }
/* ⚠️ 2026-08-14 실측: 아이콘이 130/124/124px 로 **어긋나 있었다**(가운데 정렬 +
   라벨 길이가 달라서). 세 버튼이 흐트러져 보이던 진짜 원인이 이것이다.
   → 3칸 격자로 바꿔 **아이콘은 왼쪽에 고정**하고, 오른쪽에 아이콘 폭만큼 빈 칸을 둬
     라벨이 진짜 가운데 오게 한다(구글·애플 로그인 버튼의 표준 배치). */
.social-btn {
  display: grid; grid-template-columns: 1.35rem 1fr 1.35rem;
  align-items: center; gap: .6rem;
  min-height: 3.25rem; padding: 0 1.125rem; border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  font-weight: 600; font-size: .98rem; letter-spacing: -.01em;
  transition: transform var(--dur) var(--ease);
}
.social-btn:active { transform: scale(.98); }
.social-btn .ico { width: 1.35rem; height: 1.35rem; }
.social-btn span { text-align: center; }
/* ⚠️ 구글 버튼은 흰색(#FFF)인데 바탕도 크림(#FFF8F5)이라 **테두리가 없으면 사라진다.**
   브랜드 규정상 배경색은 못 바꾸므로 테두리를 조금 더 준다. */
.social-btn[style*="#FFFFFF"] { border-color: color-mix(in srgb, var(--line) 95%, transparent); }
/* ⚠️ 아직 못 쓰는 곳은 흐리게 — 눌러도 되는 것처럼 보이면 안 된다 */
.social-btn.off { opacity: .45; }

/* ── 로고 로크업(로그인 화면) ── */
/* ⚠️ 2026-08-12: 15rem 이던 걸 키웠다 — 소셜 버튼(전체폭 21rem)보다 로고가
   작아 보인다는 지적. 컨테이너 폭(22rem)에 맞춰 로고가 화면의 주인공이 되게 한다.
   ⚠️ 2026-08-14 "세련되게" 요청으로 다시 봤을 때 **크기는 그대로 뒀다**(사용자 결정).
      실측: 화면 폭의 86%·세로의 28%. 문제는 크기가 아니라 **그 아래가 전부 작아서
      무게가 2단계(거대↔작음)뿐**이었던 것 — 그래서 문구를 중간 무게로 올렸다. */
/* ⚠️ 실측 4px 이었다 — 문구가 **로고의 일부**처럼 읽혔다. 로고와 문구는 다른 층위라
   (그림 / 말) 숨을 한 번 줘야 각자로 읽힌다. 이미지 자체 여백을 감안해 1rem. */
.auth-logo { display: block; width: 100%; max-width: 21rem; height: auto;
             margin: 0 auto 1rem; }

/* ── 로그인 리드 문구 ── 2026-08-14.
   ⚠️ 이 문구가 **이 서비스의 정체성 그 자체**다("지금 이 아이의 다음 걸음").
      그런데 16px 회색이라 로고 밑 각주처럼 읽혔다. 크기·색을 올려 로고와 버튼 사이의
      중간 무게를 만든다.
   ⚠️ 색은 --ink 다. --ink-2 로 두면 다시 각주가 된다.

   ⚠️⚠️ **--serif 를 지정하지만 한글에는 기대하지 말 것**(2026-08-14 실측).
      Literata·Georgia 는 **라틴 전용이라 한글 글리프가 없다** — 한글은 기기의 기본
      대체 글꼴로 떨어지고, 그게 명조인지 고딕인지는 **기기마다 다르다**(실제 렌더에서
      산세리프로 나왔다). 그러니 이 화면의 위계는 **세리프가 아니라 크기·굵기·색**이
      만든다. 라틴이 섞이면 그때만 세리프가 보인다.
      ⚠️ 이건 이 화면만의 문제가 아니다 — `.display`·`.auth-title`·`.breath p` 도
         같은 상태다. 한글 명조를 정말 쓰려면 웹폰트를 추가해야 하고, 그건 브랜드
         결정이라 여기서 혼자 정하지 않는다. */
/* ⚠️ 2026-08-14 문구가 한 줄("오늘의 한 걸음")로 짧아지면서 크기를 올렸다.
   두 줄일 땐 1.6rem 이 한계였다(더 키우면 세 줄로 넘어갔다) — 한 줄이면 그 제약이
   없어서, 이 화면의 위계를 **크기가** 만들 수 있다(한글에 세리프가 안 걸려 서체로는
   못 만든다, 위 주석). 로고 다음으로 큰 것이 이 한 줄이고 그다음이 로그인 단추다.
   ⚠️ letter-spacing 을 더 조인다 — 글자가 커질수록 자간이 벌어져 보인다. */
.auth-lead {
  font-family: var(--serif); font-size: 2rem; font-weight: 500;
  line-height: 1.35; letter-spacing: -.025em; color: var(--ink);
  text-align: center; margin: 0 0 var(--stack-lg);
  text-wrap: balance;                     /* 줄바꿈이 어색하게 갈리지 않게 */
}

/* ── 온보딩 진행 표시 ── 2026-08-13.
   ⚠️ 숫자("3/4")가 아니라 점이다 — 숫자는 세게 읽혀 재촉처럼 느껴진다.
   지난 단계는 옅게 채우고 지금만 길게 — 색은 하나(primary)만 쓴다. */
.steps { display: flex; gap: .3rem; align-items: center; margin: 0 0 1.25rem; }
.steps span {
  width: .375rem; height: .375rem; border-radius: 999px; background: var(--line);
  transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}
.steps span.done { background: var(--primary-l); }
.steps span.on   { width: 1.25rem; background: var(--primary); }

/* ── 온보딩 뒤로가기 ── auth 화면엔 상단 헤더가 없어 본문 안에 둔다 */
.onboard-back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.75rem; height: 2.75rem; margin: 0 0 .75rem -.6rem;
  border-radius: 999px; color: var(--ink-2);
  transition: background var(--dur) var(--ease);
}
.onboard-back:hover { background: var(--surface-2); }
.onboard-back .ico { width: 1.4rem; height: 1.4rem; }

/* ── 보호자 선택 — 버튼 자체가 폼(누르면 즉시 다음으로) ── */
.guardian-pick { display: flex; gap: 1rem; margin-top: 2rem; }
.guardian-pick form { flex: 1; }
.guardian-btn {
  width: 100%; min-height: 6rem; border-radius: var(--radius-l);
  border: 1px solid var(--line); background: var(--surface);
  font-size: 1.15rem; font-weight: 600; color: var(--ink);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.guardian-btn:active { transform: scale(.97); }
.guardian-btn:hover { border-color: var(--accent); }
.guardian-btn.on { border-color: var(--primary); background: var(--primary-l); color: var(--primary-d); }

/* ── 개발 서버 전용 신규가입 시험 버튼 ── 라이브엔 PHP 단에서부터 안 뜬다 */
.dev-signup { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px dashed var(--line); }
.dev-signup-cap { text-align: center; font-size: .72rem; color: var(--ink-3);
                   text-transform: uppercase; letter-spacing: .06em; margin-bottom: .6rem; }

/* ── 동의 체크 줄 (2026-08-13) ──────────────────────────────────────────────
   ⚠️ 필수/선택을 눈으로 갈라야 한다(개인정보 보호법 제22조 동의 구분). 한 덩어리로
      보이면 "선택을 거부할 자유"가 화면에서 사라진다. 그래서 줄마다 테두리를 준다. */
.consent-row { display: flex; gap: .625rem; align-items: flex-start;
  padding: .875rem 1rem; margin-top: .5rem; font-size: .9rem; line-height: 1.5;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.consent-row input[type="checkbox"] { width: auto; min-height: auto; margin-top: .2rem; flex: 0 0 auto; }
.consent-row a { text-decoration: underline; }

/* ── 법률 문서 ──────────────────────────────────────────────────────────────
   ⚠️ 읽으라고 만든 화면이라 본문 폭·행간을 앱 화면보다 넉넉하게 준다. */
.legal { font-size: .92rem; line-height: 1.75; color: var(--ink-2); }
.legal h2 { font-size: 1.02rem; color: var(--ink); margin: 1.75rem 0 .5rem; }
.legal h3 { font-size: .95rem; color: var(--ink); margin: 1.1rem 0 .35rem; }
.legal p, .legal ul { margin-bottom: .75rem; }
.legal ul { padding-left: 1.1rem; list-style: disc; }
.legal li { margin-bottom: .3rem; }
.legal strong { color: var(--ink); }
.legal a { text-decoration: underline; }
/* ⚠️ 표는 좁은 화면에서 가로로 밀리면 안 된다 — 칸을 쌓지 말고 폭을 나눈다 */
.legal-t { width: 100%; border-collapse: collapse; margin: .5rem 0 1rem; font-size: .87rem; }
.legal-t th, .legal-t td { border: 1px solid var(--line); padding: .5rem .625rem;
  text-align: left; vertical-align: top; word-break: keep-all; }
.legal-t th { background: var(--surface-2); color: var(--ink); font-weight: 600; width: 32%; }
.legal-note { padding: .75rem 1rem; border-radius: var(--radius);
  background: var(--surface-2); font-size: .87rem; }
.legal-ver { margin-top: 2rem; text-align: right; }

/* ── 앱 안 알림 (2026-08-13) ────────────────────────────────────────────────
   ⚠️ 알릴 게 없으면 아예 안 그린다(PHP 쪽에서). 빈 알림함은 소음이다.
   ⚠️ 색을 강하게 쓰지 않는다 — 이 앱은 재촉하지 않는 게 원칙이라, 알림이
      "빨간 뱃지"처럼 굴면 그 원칙과 충돌한다. 조용히 눈에 띄는 정도. */
.noti { margin: 0 0 1.25rem; border: 1px solid var(--line); border-radius: var(--radius-l);
        background: var(--surface); overflow: hidden; }
.noti-head { display: flex; align-items: center; justify-content: space-between;
             padding: .625rem 1rem; font-size: .82rem; font-weight: 600; color: var(--ink-2);
             background: var(--surface-2); }
.noti-head form button { background: none; border: 0; padding: 0; }
.noti-row { display: block; padding: .75rem 1rem; font-size: .9rem; color: var(--ink);
            border-top: 1px solid color-mix(in srgb, var(--line) 45%, transparent); }
.noti-row:first-of-type { border-top: 0; }
.noti-row:hover { background: color-mix(in srgb, var(--surface-2) 50%, transparent); }

/* ── 로그인 화면 마무리 (2026-08-14 "세련되게") ─────────────────────────────
   ⚠️ 여기서 "세련"은 화려함이 아니라 **덜어냄과 위계**다. 이 앱의 성격이
      "재촉하지 않음·조용함"이라, 그라데이션·그림자·모션을 더하면 성격과 싸운다.
      바꾼 것은 넷뿐: ①문구를 중간 무게로 ②아이콘 정렬 ③덩어리 사이 여백 ④군더더기 축소. */

/* 약관 줄 — ⚠️ 지우지 않는다(가입 전에 읽고 결정하는 문서다). 다만 두 줄 + 부연은
   첫 화면에서 무겁다. 한 줄로 줄이고 가장 낮은 대비로 내린다. */
.auth-legal {
  margin-top: var(--stack); text-align: center;
  font-size: .78rem; line-height: 1.7; color: var(--ink-3);
}
.auth-legal a { color: var(--ink-2); text-decoration: underline;
                text-underline-offset: .15em; }

/* 개발 서버 블록 — ⚠️ 라이브엔 안 뜬다. 그래도 **개발 중 첫인상을 매일 본다**.
   점선 상자에 큰 버튼이라 화면의 무게 중심을 가져갔다. 글자 링크 수준으로 낮춘다. */
/* ⚠️ 위(586줄)에 옛 규칙이 남아 있어 점선 테두리가 그대로 그려졌다 —
   여기서 명시적으로 끈다(둘을 합치지 않는 이유: 옛 규칙은 다른 화면에도 걸릴 수 있다). */
.dev-signup { margin-top: var(--stack); padding-top: 0; border-top: 0;
              text-align: center; opacity: .5; }
.dev-signup:hover { opacity: 1; }
.dev-signup-cap { font-size: .7rem; color: var(--ink-3); letter-spacing: .04em;
                  margin: 0 0 .35rem; }
.dev-signup .btn {
  min-height: auto; padding: .4rem .9rem; font-size: .8rem; font-weight: 500;
  background: none; border: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
  color: var(--ink-3); width: auto !important;
}

/* ── 가족 대화 (2026-08-14) ────────────────────────────────────────────────
   ⚠️ 말풍선을 화려하게 만들지 않는다. 이 앱은 조용한 앱이고, 대화창이 갑자기
      메신저처럼 굴면 나머지 화면과 다른 앱이 된다. 색은 두 가지(내 말/상대 말)뿐이고
      그림자·모션은 없다.
   ⚠️ 입력칸은 **고정**이다 — 화면 순서 규약("입력은 맨 아래")의 의도적 예외.
      대화는 읽으면서 바로 답하는 것이라 매번 스크롤해 내려가면 쓸 수가 없다. */
/* ⚠️ 고정 입력칸에 마지막 말이 가리지 않게 아래 여백. **대화가 없을 때도** 필요해서
   화면(body)에 건다 — 빈 화면의 안내 문구가 입력칸에 겹치던 것. */
body.chat-page main.wrap { padding-bottom: 5.5rem; }
.chat-log { display: flex; flex-direction: column; gap: .5rem; }

/* 날짜 구분 — ⚠️ 대화는 시간에 붙어 있어 "언제 한 말인지"가 내용만큼 중요하다 */
.chat-day { display: flex; align-items: center; gap: .75rem; margin: 1rem 0 .25rem; }
.chat-day::before, .chat-day::after {
  content: ''; flex: 1; height: 1px;
  background: color-mix(in srgb, var(--line) 45%, transparent);
}
.chat-day span { font-size: .75rem; color: var(--ink-3); }

/* ⚠️ 카카오톡식 배치(2026-08-14): 이름은 **묶음의 첫 줄에만**, 시간·읽음은 말풍선
   옆 아래. 연속으로 쓴 말은 이름을 생략한다 — 한 사람이 세 줄 쓰면 이름이 세 번 떠
   **세 사람이 말한 것처럼** 보이기 때문이다(미감이 아니라 읽기 속도의 문제). */
.chat-row { display: flex; flex-direction: column; max-width: 82%; }
.chat-row.me { align-self: flex-end; align-items: flex-end; }
.chat-row.grouped { margin-top: -.35rem; }   /* 묶인 줄은 더 붙인다 */
.chat-who { font-size: .74rem; color: var(--ink-2); margin: 0 0 .2rem .25rem; }
/* 말풍선 + 시간/읽음을 한 줄에 — 읽음은 말풍선 **바깥**이다(카톡과 같은 자리) */
.chat-line { display: flex; align-items: flex-end; gap: .35rem; }
.chat-row.me .chat-line { flex-direction: row-reverse; }
.chat-meta { display: flex; flex-direction: column; align-items: flex-end;
             gap: .05rem; flex: 0 0 auto; padding-bottom: .1rem; }
.chat-row.me .chat-meta { align-items: flex-start; }
/* 안 읽은 수 — 카카오톡의 "1". ⚠️ 0 이면 아예 안 그린다(0 을 보여주면 소음이다) */
.chat-unread { font-size: .68rem; color: var(--primary); font-weight: 700; line-height: 1; }
.chat-bubble {
  padding: .625rem .875rem; border-radius: 1rem;
  background: var(--surface); border: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  font-size: .94rem; line-height: 1.6; color: var(--ink);
  word-break: break-word; overflow-wrap: anywhere;   /* 긴 주소가 가로로 밀지 않게 */
}
/* 내 말 — ⚠️ --primary 면 글자가 흰색이라 대비는 되지만 화면이 강해진다.
   연한 primary-l 로 두면 "내 말"은 구분되면서 조용함이 유지된다. */
.chat-row.me .chat-bubble { background: var(--primary-l); border-color: transparent; }
/* 지워진 말 — 본문은 안 나온다. 자리만 남겨 흐름을 잇는다. */
.chat-bubble.gone { background: none; border-style: dashed; color: var(--ink-3);
                    font-size: .85rem; font-style: normal; }
.chat-time { font-size: .68rem; color: var(--ink-3); flex: 0 0 auto; margin-bottom: .15rem; }
/* 지우기 — ⚠️ 말풍선 바깥, 시간 옆. JS 가 있으면 평소엔 감춰 두고 내 말풍선을 누를
   때만 나온다(chat.js). display 를 주지 않는다 — 주면 hidden 이 안 먹는다(위 .emoji-pad 참고). */
.chat-del { margin: 0 0 .15rem; }
.chat-row .cmt-del { font-size: .68rem; }

/* 이전 대화 더 보기 — ⚠️ 단추처럼 안 만든다. 대화 위에 얹힌 조용한 한 줄이면 된다. */
.chat-more { text-align: center; margin: .25rem 0 .5rem; }
.chat-more a { font-size: .8rem; color: var(--ink-3); text-decoration: underline; }

/* 보내기 — 하단 탭바 바로 위에 고정 */
.chat-send {
  position: fixed; left: 0; right: 0;
  /* ⚠️ 탭바와 **같은 식**을 쓴다(.tabbar: 4rem + safe-area). 상수로 적으면 탭바 높이를
     고칠 때 여기만 남아 입력칸이 탭바에 겹치거나 뜬다. */
  bottom: calc(4rem + env(safe-area-inset-bottom));
  display: flex; gap: .5rem; align-items: flex-end;
  padding: .625rem var(--gap); background: var(--bg);
  border-top: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  /* ⚠️ 화면이 넓어져도 본문 폭 안에 머물게 — 데스크톱에서 좌우로 늘어지면 흉하다 */
  max-width: 40rem; margin: 0 auto;
}
.chat-send textarea {
  flex: 1; min-height: 2.75rem; max-height: 7.5rem; resize: none;
  padding: .625rem .875rem; font: inherit; font-size: .94rem; line-height: 1.5;
  border: 1px solid var(--line); border-radius: 1.25rem;
  background: var(--surface); color: var(--ink);
}
.chat-send .btn { min-height: 2.75rem; padding: 0 1rem; flex: 0 0 auto; }

/* ── 대화: 사진·이모지 (2026-08-14) ────────────────────────────────────────
   ⚠️ 사진만 보낸 말은 말풍선 배경을 안 씌운다(.pic-only) — 사진 둘레에 색면이 생기면
      액자처럼 보여 대화 흐름이 끊긴다. 카카오톡도 사진은 맨몸으로 둔다. */
.chat-bubble.pic-only { background: none; border: 0; padding: 0; }
.chat-pic { display: block; }
.chat-pic img {
  display: block; max-width: 100%; width: auto; max-height: 15rem;
  border-radius: .75rem; border: 1px solid color-mix(in srgb, var(--line) 40%, transparent);
}
/* 사진 + 글이 같이 온 경우 — 사진 아래에 글 */
.chat-bubble .chat-pic + span { display: block; margin-top: .4rem; }

/* 입력줄의 사진·이모지 단추 — ⚠️ 보내기보다 작고 조용하게. 입력이 주인공이다 */
.chat-attach, .chat-emoji {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.75rem; padding: 0; border: 0; background: none;
  color: var(--ink-3); cursor: pointer; font-size: 1.25rem; line-height: 1;
}
.chat-attach:active, .chat-emoji:active { color: var(--primary); }
.chat-attach .ico { width: 1.4rem; height: 1.4rem; }
.chat-picname {
  position: fixed; left: 0; right: 0; bottom: calc(7.5rem + env(safe-area-inset-bottom));
  margin: 0 auto; max-width: 40rem; padding: .35rem var(--gap);
  font-size: .78rem; color: var(--ink-2); background: var(--surface-2);
}

/* 이모지 팔레트 — ⚠️ 전체 픽커를 안 만든다. 폰 키보드에 이미 있고, 다시 만들면
   수백 개를 스크롤하게 된다. 육아 대화에서 실제로 쓰는 것 스물넷만. */
.emoji-pad {
  position: fixed; left: 0; right: 0; bottom: calc(7.25rem + env(safe-area-inset-bottom));
  margin: 0 auto; max-width: 40rem; z-index: 19;
  display: grid; grid-template-columns: repeat(8, 1fr); gap: .15rem;
  padding: .5rem var(--gap); background: var(--surface);
  border-top: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
}
.emoji-pad .emoji {
  border: 0; background: none; font-size: 1.4rem; line-height: 1;
  padding: .35rem 0; cursor: pointer; border-radius: .5rem;
}
.emoji-pad .emoji:active { background: var(--primary-l); }
/* ⚠️ **`display` 를 준 요소는 `hidden` 속성이 안 먹는다** — 브라우저 기본
   `[hidden]{display:none}` 보다 위 `.emoji-pad{display:grid}` 가 더 구체적이라
   이긴다. 그래서 팔레트가 **처음부터 펼쳐진 채로** 떠 있었다(2026-08-14 실측).
   display 를 주는 자리마다 이 짝을 같이 둘 것. */
.emoji-pad[hidden] { display: none; }

/* 아이가 체크한 줄 — 2026-08-14.
   ⚠️ 취소선을 **연하게만** 긋는다. 진하게 그으면 "지워진 것"처럼 보이는데, 아이가
      한 일은 지워진 게 아니라 **해낸 것**이다. 색도 --ink-3 까지만 내린다. */
.sched-title.done { color: var(--ink-3); text-decoration: line-through;
                    text-decoration-color: color-mix(in srgb, var(--ink-3) 45%, transparent); }

/* 비밀번호 보기 토글 — 2026-08-14 사용자 지시("uiux 기본은 다 만들어야").
   ⚠️ 왜 기본기인가: 가려진 칸은 **오타의 원인을 못 찾게 한다.** 아이는 왜 로그인이
      안 되는지 모르고, 부모는 자기가 뭘 쳤는지 모른다. 확인 재입력과 한 쌍이다.
   ⚠️ 칸 안에 겹쳐 놓지 않고 **오른쪽에 나란히** 둔다 — 겹치면 긴 비밀번호가 단추 밑으로
      들어가고, 폰에서 손가락이 칸을 누르려다 단추를 누른다. */
.pw-row { display: flex; gap: .5rem; align-items: stretch; }
.pw-row input { flex: 1; }
.pw-see {
  flex: 0 0 auto; min-width: 3.25rem; padding: 0 .6rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink-2); font-size: .8rem;
}
.pw-see:active { background: var(--surface-2); }

/* 사람 확인(캡챠) — 2026-08-14.
   ⚠️ 이미지와 "다시"를 한 줄에, 입력칸은 그 아래. 셋을 한 줄에 넣으면 좁은 폰에서
      입력칸이 손톱만 해진다. */
.cap-row { display: flex; align-items: center; gap: .6rem; margin-bottom: .5rem; }
.cap-img { border-radius: var(--radius); border: 1px solid var(--line); display: block; }
.cap-text { display: inline-flex; align-items: center; justify-content: center;
            width: 150px; height: 52px; background: var(--surface-2);
            font-size: 1.4rem; letter-spacing: .3em; color: var(--primary); }
.cap-again { font-size: .8rem; color: var(--ink-2); text-decoration: underline; }
