/* =========================================================================
 * 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 는 아주 살짝 좁혀야 결이 산다 */
}
/* ⚠️ **`hidden` 이 우리 규칙에 지는 것을 막는다** (2026-08-16 사용자 제보 — 끝말잇기에서
   입력줄과 "다른 가족이 이어 줄 차례예요"가 **한꺼번에** 떴다).
   `hidden` 속성이 감추는 힘은 브라우저 기본 스타일의 `[hidden]{display:none}` 하나뿐이라,
   같은 요소에 `display` 를 주는 우리 규칙(`.word-send{display:flex}`) 하나면 조용히 뚫린다.
   **속성은 그대로 붙어 있는데 화면엔 보인다** — 그래서 `getAttribute('hidden')` 로 재는
   시험은 통과한다(실제로 통과했다).
   ⚠️ 이 사고가 **두 번째**다. 처음엔 `.emoji-pad` 에서 나서 그 자리만 막았는데(§이모지판),
      다음 컴포넌트에서 똑같이 났다. 컴포넌트마다 막는 대신 여기서 한 번에 막는다.
   ⚠️ `!important` 를 쓴다. 이건 취향이 아니라 **`hidden` 의 뜻이 "무조건 감춘다"**이기
      때문이다 — 여기서 지면 감춘 게 아니다. */
[hidden] { display: none !important; }
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;
  /* ⚠️ **개수를 박지 않는다**(2026-08-16). `repeat(5, 1fr)` 로 박아 뒀더니 게임 탭이
     늘면서 여섯째가 첫 줄 밖으로 밀려났다. 링크로 들어온 아이는 대화가 없어 하나 적기도
     하다 — 탭 수는 이미 상황마다 다르다(ns_tabs·ns_tabs_kid). 자동으로 나눈다. */
  display: grid; grid-auto-flow: column; grid-auto-columns: 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);
}

/* ── 데스크톱 좁은 창: **본문이 스크롤한다** ──
   2026-08-14 사용자 지적: "달력·대화에서 오른쪽 스크롤이 설정 옆으로까지 넘어온다".
   창이 스크롤하면 스크롤바가 **창 높이 전체**를 차지해서, 아래에 고정된 탭바 옆으로
   그대로 내려온다. 스크롤바는 브라우저가 그리는 것이라 우리 요소로 덮을 수도 없다.
   → 스크롤 주체를 **본문(body)** 으로 옮기고 그 높이를 탭바 위까지로 자른다.
      그러면 스크롤바가 탭바 **위에서 끝난다.**

   ⚠️ **마우스 쓰는 좁은 창에서만** 건다.
      · 폰(터치)은 그대로 창이 스크롤한다 — 안쪽 스크롤로 바꾸면 주소창 자동 숨김과
        관성 스크롤이 깨지고, 애초에 폰 스크롤바는 겹쳐 뜨는 방식이라 문제가 없다.
      · 1024px 이상은 탭바가 **왼쪽 사이드바**라 아래를 자를 이유가 없다.
   ⚠️ 스크롤 주체가 바뀌면 `window.scrollY` 를 쓰던 코드가 조용히 멈춘다 —
      대화(chat.js)가 그랬다. 거기도 같이 고쳤다(assets/chat.js 의 sc() 참고). */
@media (hover: hover) and (pointer: fine) and (max-width: 1023.98px) {
  html { height: 100%; overflow: hidden; }
  body {
    height: calc(100dvh - 4rem);   /* 4rem = 탭바 높이 */
    /* ⚠️ min-height 를 반드시 풀어 준다 — 기본값이 `min-height:100dvh` 라 그대로 두면
       **min 이 이겨서 높이가 안 줄어든다**(스크롤바가 그대로 탭바 옆까지 내려온다).
       2026-08-14 실측으로 잡았다: 창 907 일 때 843 이어야 할 body 가 907 로 나왔다. */
    min-height: 0;
    overflow-y: auto;
    padding-bottom: 1rem;          /* 아래 padding 은 이제 탭바 자리가 아니다 */
  }
  /* 탭바가 없는 화면(로그인 등)은 자를 이유가 없다 */
  body.no-tabs { height: auto; overflow: visible; }

  /* ⚠️ 대화는 **탭바 위에 보내기 칸이 하나 더** 있다(.chat-send 는 bottom:4rem 고정).
     탭바만 빼면 스크롤바가 보내기 칸 뒤로 지나가 거기까지 내려온 것처럼 보인다
     (2026-08-14 사용자 지적 "대화의 스크롤은 보내기 버튼 틀 위까지 되도록").
     ⚠️ 보내기 칸 높이는 **글이 길어지면 늘어난다**(textarea 최대 7.5rem) — 상수로 적으면
        여러 줄을 쓰는 순간 어긋난다. 그래서 chat.js 가 실제 높이를 재서 --compose-h 로 준다.
     ⚠️ 기본값(4.25rem)은 한 줄일 때의 높이다 — JS 가 막혀도 얼추 맞게. */
  body.chat-page { height: calc(100dvh - 4rem - var(--compose-h, 4.25rem)); }
  /* ⚠️ 본문 아래 여백을 줄이는 규칙은 **이 파일 뒤쪽**에 있다(.chat-page 여백 항목).
     여기 두면 뒤쪽의 같은 특정도 규칙(body.chat-page main.wrap)에 져서 **한 번도 안 먹는다** —
     실제로 그랬다(2026-08-15 실측: PC 에서 88px 죽은 여백). CSS 는 특정도가 같으면
     **나중 것이 이긴다** — 그래서 순서가 곧 규칙이다. */
}

/* 데스크톱 — 사이드바(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;
  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-19 사장님 지적("1982 뒤의 년과 10 뒤의 월이 잘려", 갤럭시 실물).
   원인 둘:
   ① **세기 싸움에서 졌다.** 위 `.ymd select` 와 아래 `.field select`(633줄 근처)는
      세기가 같은데(클래스 1 + 요소 1) `.field select` 가 **뒤에 있어 이긴다.**
      그래서 여백이 의도한 .5rem 이 아니라 **1.1rem** 으로 잡혔다(실측 17.6px).
      ⚠️ 위 규칙만 고치면 또 진다 — 세기를 올려야 한다.
   ② **기본 드롭다운 화살표가 글자를 덮는다.** 화살표는 여백 안쪽에 그려지는데
      브라우저마다 크기가 다르다 — 데스크톱 Chromium 에선 안 잘리고 갤럭시에서만 잘렸다.
      그래서 **오른쪽에 화살표 자리를 따로 비운다**(1.7rem). 왼쪽은 좁혀 글자 자리를 번다.
   ⚠️ 내 화면에서 멀쩡하다고 넘어가면 안 되는 자리다. 사장님 폰이 정본이다. */
.field .ymd select,
.ymd select {
  /* ⚠️ **기본 화살표를 안 쓴다**(appearance:none) — 2026-08-19 두 번째 손질.
     처음엔 오른쪽 여백만 넓혀 화살표 자리를 비웠는데, 그건 **화살표 크기를 짐작한 것**이다.
     기본 화살표는 브라우저·기기마다 다르게 그려지고 **내 화면에선 재현이 안 된다** —
     사장님 갤럭시에선 잘리는데 데스크톱 Chromium 에선 멀쩡했다.
     짐작으로 여백을 맞추는 대신 **변수를 없앤다**: 우리가 그린 화살표만 쓴다.
     그러면 어느 기기에서 열든 같은 그림이고, 자리도 정확히 우리가 아는 만큼만 먹는다. */
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding: 0 2rem 0 .75rem;     /* 오른쪽 2rem = 우리 화살표(.6rem) + 여백 */
  font-size: 1rem;
  width: auto;                  /* .field select 의 width:100% 를 되돌린다(flex 가 정한다) */
  text-overflow: ellipsis;      /* 그래도 좁으면 조용히 자르지 말고 …으로 알린다 */
  background-image: var(--sel-arrow);
  background-repeat: no-repeat;
  background-position: right .7rem center;
  background-size: .62rem .62rem;
}
/* ⚠️ 화살표 색은 테마마다 다르다 — 배경 이미지엔 currentColor 가 안 먹어서 두 벌을 둔다.
   ⚠️ 한쪽만 고치면 다른 테마에서 화살표가 배경에 묻힌다(밝은 화면의 흰 화살표처럼). */
:root { --sel-arrow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path d='M2 4.5L6 8.5L10 4.5' fill='none' stroke='%237E6763' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>"); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --sel-arrow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path d='M2 4.5L6 8.5L10 4.5' fill='none' stroke='%23A08D87' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>"); }
}
:root[data-theme="dark"] { --sel-arrow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path d='M2 4.5L6 8.5L10 4.5' fill='none' stroke='%23A08D87' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>"); }

/* ── 아이콘 타일 그리드(앱 화면) ──
   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 사용자 지시("메뉴에 대한 설명이 있었으면").
   ⚠️ 라벨보다 **작고 옅게**. 같은 크기면 두 줄짜리 라벨로 읽혀 무엇이 이름인지 흐려진다.
   ⚠️ 3열 그리드라 길면 접힌다 — 짧게 쓰는 건 문구 쪽 규칙이고(apps.php 주석),
      그래도 넘칠 때를 대비해 줄바꿈은 허용한다(잘라내면 뜻이 사라진다). */
/* 타일 배지(느낌표) — 2026-08-14 사용자 지시("수정사항이 있으면 오른쪽 위에 느낌표").
   ⚠️ **알림이 가리키는 화면에만** 붙인다 — 아무 데나 붙이면 배지가 흔해져 아무 뜻이 없다.
   ⚠️ 숫자를 안 쓴다. 몇 건인지는 오늘 화면의 "새로운 소식"이 말하고, 여기서는
      "볼 것이 있다"만 알리면 된다(같은 정보를 두 곳에서 세면 언젠가 어긋난다). */
.tile-ico { position: relative; }
.tile-dot {
  position: absolute; top: -.15rem; right: -.15rem;
  min-width: 1.15rem; height: 1.15rem; padding: 0 .25rem;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px; background: var(--primary); color: #fff;
  font-size: .72rem; font-weight: 700; line-height: 1;
  border: 2px solid var(--bg);   /* 배경과 떨어져 보이게 — 아이콘 원에 붙으면 얼룩처럼 보인다 */
}
.tile-sub { font-size: .66rem; color: var(--ink-3); line-height: 1.25; margin-top: -.2rem;
            word-break: keep-all; }
/* 타일 모양의 **동작**(로그아웃) — 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 개인 관리를 목록+상세로 다시 짜면서.
   ⚠️ 값이 길면(메일 주소) 줄을 넘기지 말고 **잘라서 말줄임** — 넘기면 줄 높이가
      들쭉날쭉해져 목록이 목록으로 안 읽힌다. 전체 값은 누르고 들어가면 보인다. */
/* ⚠️ 줄 전체가 <a> 라 기본 링크색(코랄)이 따라온다 — 그대로 두면 라벨 다섯 개가
   전부 강조색이 되어 **무엇이 중요한지 안 보인다**(2026-08-14 화면 실측).
   누를 수 있다는 신호는 오른쪽 화살표가 이미 하고 있다. */
a.sched-row { color: var(--ink); }
.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; }
/* 고친 말 표시 — ⚠️ **시간 앞**에 둔다(카카오톡과 같은 자리). 뒤에 두면 시간과 붙어
   "17:34 수정됨"이 한 덩어리로 읽혀 몇 시에 고쳤다는 말처럼 보인다.
   ⚠️ 옅게 — 사실 표기지 강조가 아니다. */
.chat-edited { font-size: .68rem; color: var(--ink-3); }
/* 고치는 중 — 입력칸 바로 위. 왜 옛 글이 들어와 있는지 말해 준다 */
/* ── 고치는 중 알림줄 ── 입력칸 바로 위. 카카오톡의 "메시지 수정" 줄과 같은 자리.
   ⚠️ 2026-08-14 사용자 지적("고치는 중 · 그만두기는 뭐야?")으로 다시 짰다 —
      그만두기가 **글자 링크**라 눌러야 할 것으로 안 보였고, 무엇을 고치는 중인지도
      안 보였다. 지금은 ✕ 단추로 두고, 고치는 말은 위에서 .chat-row.editing 이 짚는다. */
.chat-editing { position: fixed; left: 0; right: 0; z-index: 11;
  bottom: calc(4rem + env(safe-area-inset-bottom) + var(--compose-h, 4.25rem));
  max-width: 40rem; margin: 0 auto; padding: .35rem .5rem;
  background: var(--primary-l); color: var(--ink-2); font-size: .78rem;
  display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
/* ⚠️ 손가락으로 누르는 것이라 글자 크기와 별개로 2rem 을 확보한다 */
.chat-editing-x { flex: none; width: 2rem; height: 2rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-2); text-decoration: none; font-size: .9rem; line-height: 1; }
.chat-editing-x:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }

/* 지금 고치는 중인 말 — 어느 것인지 눈으로 짚어 준다(위 알림줄과 한 쌍이다).
   ⚠️ 배경색을 바꾸지 않는다. 내 말/남의 말 색이 이미 의미를 지고 있어서, 거기에
      또 색을 얹으면 "지워진 말"·"안 읽음"과 뒤섞인다. 테두리만 두른다. */
.chat-row.editing .chat-bubble {
  outline: 2px solid var(--primary); outline-offset: 2px; }

/* ── 사진 크게 보기 ── 2026-08-14. 대화의 사진을 **떠나지 않고** 크게 본다.
   ⚠️ 배경을 아주 어둡게 한다 — 사진을 보는 자리라 주변이 밝으면 눈이 분산된다.
   ⚠️ 닫기 단추는 **오른쪽 위 고정**. 사진 크기가 제각각이라 사진에 붙이면 자리가 매번 다르다. */
dialog.lightbox {
  border: 0; padding: 0; background: transparent;
  width: 100vw; height: 100dvh; max-width: 100vw; max-height: 100dvh;
}
/* ⚠️ **`display` 는 열렸을 때만 준다.** 닫힌 <dialog> 는 브라우저 기본값
   `display:none` 으로 숨는데, 여기에 `display:flex` 를 무조건 걸면 그 기본값을 이겨서
   **닫아도 사진이 그대로 남는다**(2026-08-14 사용자 제보 "X를 눌러도 사진만 남아있어").
   ⚠️ 이모지 팔레트에서 겪은 것과 **같은 함정**이다 — 그때는 `hidden` 을 `display:grid` 가
      이겼다(.emoji-pad[hidden] 참고). 감추는 기본값을 덮어쓰는 속성은 늘 이 사고를 낸다. */
dialog.lightbox[open] { display: flex; align-items: center; justify-content: center; }
dialog.lightbox::backdrop { background: rgba(0, 0, 0, .88); }
dialog.lightbox img { max-width: 96vw; max-height: 88dvh; object-fit: contain; border-radius: var(--radius); }
.lightbox-x {
  position: fixed; top: calc(.75rem + env(safe-area-inset-top)); right: .75rem;
  width: 2.5rem; height: 2.5rem; border: 0; border-radius: 999px;
  background: rgba(255, 255, 255, .16); color: #fff; font-size: 1.1rem; line-height: 1;
}

/* ── 팝업(바텀시트) ── 2026-08-14 사용자 지시("버튼을 누를 경우 팝업이 떠서 변경").
   ⚠️ 네이티브 <dialog> 를 쓴다 — 배경 비활성·Esc·초점 가두기를 브라우저가 해 준다.
      직접 만들면 그 셋 중 하나는 반드시 빠지고, 빠진 게 접근성이다.
   ⚠️ 폰에서는 **아래에 붙인다**(바텀시트). 손가락이 닿는 곳이 아래쪽이고, 가운데에
      띄우면 키보드가 올라올 때 팝업이 위로 밀려 제목이 화면 밖으로 나간다. */
dialog.sheet {
  border: 0; padding: 0; background: transparent;
  width: 100%; max-width: 34rem; max-height: 92dvh;
  margin: auto auto 0;                 /* 아래 붙임 */
}
dialog.sheet::backdrop { background: rgba(35, 32, 27, .45); }
.sheet-box {
  background: var(--surface); color: var(--ink);
  border-radius: var(--radius-l) var(--radius-l) 0 0;
  padding: 1.25rem 1.25rem calc(1.5rem + env(safe-area-inset-bottom));
  max-height: 92dvh; overflow-y: auto;
}
.sheet-head { display: flex; align-items: center; justify-content: space-between;
              gap: 1rem; margin-bottom: 1.25rem; }
.sheet-head h2 { font-size: 1.2rem; }
.sheet-x { border: 0; background: none; color: var(--ink-2);
           font-size: 1.1rem; line-height: 1; padding: .5rem; margin: -.5rem; }
/* ⚠️ **아래에 붙이는 것은 "폰일 때"만이다**(2026-08-14 사용자 지적 "일부러 저렇게 아래에
   뜨게 해둔거야?" — 959px 창에서 좁은 카드가 화면 아래에 붙어 있었다).
   바텀시트의 근거는 **엄지**다. 마우스로 쓰는 폭에서는 근거가 사라지고, 넓은 화면 아래쪽에
   좁은 카드만 붙어 있으면 잘린 것처럼 보인다.
   ⚠️ 이 앱은 분기를 1024px 하나로 쓰는데(DESIGN-SYSTEM) 여기만 640px 을 더 둔다 —
      1024px 은 **사이드바가 생기는 폭**이고, 이 판단의 기준은 **손이 닿는 폭**이라
      같은 선을 쓸 이유가 없다. 실제로 그 사이(640~1024)가 어긋나 있었다. */
@media (min-width: 640px) {
  dialog.sheet { margin: auto; max-width: 26rem; }
  .sheet-box { border-radius: var(--radius-l); }
}
/* 데스크톱 — 사이드바 자리를 빼고 가운데.
   ⚠️ **뷰포트가 아니라 "내용 칸" 가운데다.** 데스크톱은 왼쪽 15rem 이 사이드바라,
      뷰포트 기준으로 가운데를 잡으면 팝업이 **사이드바 쪽으로 120px 밀려** 내가 누른
      줄과 어긋난 자리에 뜬다(2026-08-14 사용자 지적 "팝업 위치가 이상한데?").
   ⚠️ 2026-08-14 로그인 화면이 오른쪽으로 밀렸던 것과 **똑같은 함정**이다 —
      그때는 사이드바 자리를 안 비워서, 이번엔 비운 자리를 안 빼서. 15rem 이 등장하는
      곳(body.padding-left · .tabbar.width · 여기)은 늘 같이 움직여야 한다.
   ⚠️ 탭바가 없는 화면(body.no-tabs)에는 그 자리가 없으니 되돌린다 — 지금 팝업은
      account.php 에만 있어 해당이 없지만, 다음에 로그인 계열 화면에 팝업을 두면 걸린다. */
@media (min-width: 1024px) {
  dialog.sheet { left: 15rem; right: 0; }
  body.no-tabs dialog.sheet { left: 0; }
}
/* 오른쪽 화살표 — 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);
}
/* "만" — 나이 앞의 한정어. ⚠️ 큰 숫자와 같은 크기로 두면 flex 한 칸을 차지해
   숫자가 왼쪽 끝에서 밀린다. 태아 화면은 주차가 왼쪽 끝에서 시작하는데, 칩으로
   아이를 바꿀 때마다 그 시작점이 어긋나 보인다. 작고 조용하게 두어 큰 숫자가
   왼쪽을 잡게 한다(2026-08-16). */
.hero-week i {
  font-style: normal; font-family: var(--sans); font-weight: 500;
  font-size: .95rem; color: var(--ink-2); align-self: center;
}

/* "전체" 화면의 **무엇까지인가** — 큰 숫자 위에 조용히 놓인다(2026-08-16).
   ⚠️ 아이별 화면의 `.hero-sub`(숫자 아래)와 자리가 반대다. 여기선 "콩이 · 만날 날까지"를
      먼저 읽어야 아래 숫자가 무슨 뜻인지 안다 — 숫자부터 보면 137이 뭔지 모른다. */
.hero-next { margin-top: 1.05rem; color: var(--ink-2); font-size: .9rem; }
.hero-next + .hero-week { margin-top: .15rem; }

.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;
}
/* ── 음력·윤달 체크칸 (2026-08-18) ──────────────────────────────────────────
   ⚠️ 사장님 지적: "본인의 생년월일을 알려주세요 밑에 음력과 윤달 체크가 이상하게 표기돼".
   원인은 이 위젯(`ns_lunar_fields()`)이 `<div class="field">` **안에** 있는데
   그 안의 규칙이 **체크박스에까지 걸린 것**이다:
     · `.field input { width:100%; min-height:3.5rem; border… }` → 체크박스가 **화면 폭짜리 상자**
     · `.field label { display:block; font-weight:600 }`         → 라벨이 굵게 **세로로** 쌓임
   `.check` 에는 CSS 가 **하나도 없어서**(kidlogin.php 만 인라인 style 로 때우고 있었다)
   아무도 이걸 되돌리지 않고 있었다. 여기서 되돌린다.
   ⚠️ `.field ...` 선택자를 같이 두는 이유 — `.field input` 이 더 구체적이라 그것보다 세야 한다. */
.lunar-pick { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin-top: .6rem; }
.lunar-pick label.check,
.field .lunar-pick label.check {
  display: inline-flex; align-items: center; gap: .45rem;
  margin: 0; font-weight: 400; font-size: .95rem; cursor: pointer;
}
.lunar-pick input[type="checkbox"],
.field .lunar-pick input[type="checkbox"] {
  width: 1.15rem; height: 1.15rem; min-height: 0;
  padding: 0; margin: 0; flex: 0 0 auto; accent-color: var(--primary);
}
/* 설명 줄은 두 체크칸 아래로 — 같은 줄에 끼면 셋이 뒤엉킨다 */
.lunar-pick .hint { flex: 1 0 100%; margin-top: .1rem; }

/* ⚠️ .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-18 사용자 지시) ─────────────────────────────
   "구글/네이버/카카오로 시작하기를 동그란 모양으로, 동그라미 안에 아이콘이 있도록.
    그리고 아이 로그인 동그란 버튼이 있어서 누르면 아이 id pw 입력."

   ⚠️ **아이콘만 남기면 글자 없는 단추가 된다** — 화면낭독기에는 아무것도 안 들린다.
      그래서 ①동그라미마다 `aria-label` 을 달고 ②동그라미 **아래에 작은 이름**을 남긴다.
      이름을 지우면 색으로만 구분해야 하는데, 색각이 다른 사람에겐 넷이 같은 원이다.
   ⚠️ 손가락이 닿는 크기를 3.75rem 으로 잡았다 — 권장 최소(44px)보다 넉넉하다.
      아이가 누르는 단추라 더 크게 잡을 이유가 있다. */
.auth-circles {
  display: flex; justify-content: center; align-items: flex-start;
  gap: 1.1rem; flex-wrap: wrap; margin: .25rem 0 1.5rem;
}
.circle-item { display: flex; flex-direction: column; align-items: center; gap: .45rem; width: 4.25rem; }
.circle-btn {
  width: 3.75rem; height: 3.75rem; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  transition: transform var(--dur) var(--ease);
  cursor: pointer;
}
.circle-btn:active { transform: scale(.94); }
.circle-btn .ico { width: 1.8rem; height: 1.8rem; }
/* 구글은 흰 동그라미라 크림 바탕에서 사라진다 — 테두리를 조금 더(위 .social-btn 와 같은 이유) */
.circle-btn[style*="#FFFFFF"] { border-color: color-mix(in srgb, var(--line) 95%, transparent); }
.circle-btn.off { opacity: .4; }
.circle-cap { font-size: .76rem; line-height: 1.3; color: var(--ink-2); text-align: center; }

/* 아이 동그라미 — ⚠️ 2026-08-18 스크린샷이 잡았다: **색이 없으면 '준비 안 됨'으로 읽힌다.**
   소셜 셋이 브랜드 색을 쓰니 맨 동그라미 하나만 혼자 꺼져 보였다.
   앱 색(--primary)을 줘서 **넷 중 유일하게 '우리 것'** 으로 보이게 한다. */
.kid-circle {
  background: var(--primary); color: #fff;
  border-color: var(--primary);
}
.kid-circle[aria-expanded="true"] { box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 25%, transparent); }

/* ── 로고 로크업(로그인 화면) ── */
/* ⚠️ 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; }
/* ⚠️ 줄이 **눌러서 가는 것**임을 보인다 — 머리의 "모두 읽음"과 하는 일이 달라서,
   화살표가 없으면 둘 다 그냥 글씨로 보인다(2026-08-14 제보의 절반이 이 혼동이었다). */
.noti-go { width: 1rem; height: 1rem; flex: 0 0 auto; color: var(--ink-3);
           transform: rotate(180deg); margin-left: auto; }
.noti-row { display: flex; align-items: center; gap: .5rem;
            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)에 건다 — 빈 화면의 안내 문구가 입력칸에 겹치던 것.
   ⚠️ **상수(5.5rem)로는 모자랐다**(2026-08-15 폰 폭 실측: 마지막 말이 66px 가려졌다).
      비켜야 할 것이 둘이다 — 탭바(4rem, .chat-send 의 bottom 값)와 **입력칸 자신의 높이**.
      입력칸 높이는 글이 길어지면 늘어나므로(textarea 최대 7.5rem) 상수로 적을 수가 없다.
      그래서 chat.js 가 재서 주는 --compose-h 를 그대로 쓴다(위 미디어쿼리와 같은 값).
   ⚠️ 기본값 4.25rem 은 한 줄일 때의 높이 — JS 가 막혀도 얼추 맞게. */
/* ⚠️ **산수를 버리고 잰 값을 쓴다.** 예전엔 `4rem(탭바) + 입력칸 높이` 로 계산했는데
   실기기에서 안 맞았다(2026-08-15 사용자 사진 — 마지막 말이 입력칸에서 한참 떴다).
   안전영역·브라우저 주소창·기기 내비게이션 바가 기기마다 다르게 끼어들기 때문이다.
   `--compose-gap` 은 chat.js 가 **화면 바닥부터 입력줄 윗변까지**를 실제로 잰 값이라
   그 전부가 이미 들어 있다. 여기에 숨 쉴 틈 .5rem 만 더한다.
   ⚠️ 기본값(8.5rem)은 JS 가 막혔을 때만 쓰인다 — 넉넉한 쪽으로 잡는다(가리는 것보다 낫다). */
body.chat-page main.wrap { padding-bottom: calc(var(--compose-gap, 8.5rem) + .5rem); }
/* ⚠️ **데스크톱 좁은 창에서는 그 여백이 죽은 공간이다.** 거기서는 body 를
   `100dvh - 탭바 - 보내기칸` 으로 이미 잘라 놨기 때문에(위 미디어쿼리), 5.5rem 이
   그대로 남아 마지막 말과 입력칸 사이에 **88px 빈 자리**가 생긴다
   (2026-08-15 사용자 지적 "보내고 나면 글이 이상한 자리에 보인다" — PC 에서 재현).
   ⚠️ **조건은 위 미디어쿼리와 같아야 한다.** 한쪽만 고치면 자른 화면과 여백이 어긋난다.
   ⚠️ 폰(hover 없음)에서는 5.5rem 이 **맞다** — 거기선 입력칸이 본문 위에 떠 있어서
      그 여백이 없으면 마지막 말이 입력칸에 가린다. 지우면 안 된다. */
@media (hover: hover) and (pointer: fine) and (max-width: 1023.98px) {
  body.chat-page main.wrap { padding-bottom: 1rem; }
}

/* ── 말이 적으면 **아래에서부터** 쌓인다 (2026-08-15 사용자 사진) ──────────────
   ⚠️ 여기까지 고친 건 전부 "가리지 않게 하는" 여백이었는데, 사용자가 보낸 사진의
      문제는 **정반대**였다 — 말이 몇 개뿐이라 위쪽에 붙어 있고 입력칸은 화면 바닥에
      고정이라, 그 사이가 통째로 빈 것이다("마지막 글이 보내기 버튼이랑 너무 멀어").
      여백을 아무리 잘 재도 이건 안 고쳐진다. **정렬의 문제**지 여백의 문제가 아니다.
   ⚠️ 메신저(카카오톡)는 전부 아래 정렬이다 — 대화는 **최근 것이 눈높이**에 있어야 한다.
   방법: 화면(body)을 세로 flex 로 두고 본문이 남는 자리를 다 먹게(flex:1) 한 뒤,
        말 목록에 `margin-top:auto` 를 준다. 말이 화면보다 길어지면 남는 자리가 없어
        이 규칙은 **저절로 꺼진다**(스크롤 동작은 그대로).
   ⚠️ 고정 요소(.chat-send·.emoji-pad·.tabbar·.devmark)는 flex 항목이 아니다 —
      position:fixed 는 흐름에서 빠지므로 이 정렬에 끼어들지 않는다.
   ⚠️ `padding-bottom:0` 이 필요하다: 화면 기본값이 탭바 자리 4rem 인데, 아래 여백은
      이미 `--compose-gap`(바닥부터 입력줄 윗변까지, 탭바를 **포함해** 잰 값)이 다 갖고
      있다. 둘을 겹쳐 두면 그만큼(실측 72px) 또 뜬다. */
body.chat-page { display: flex; flex-direction: column; padding-bottom: 0; }
/* ⚠️ `width:100%` 가 꼭 있어야 한다. 화면(body)을 세로 flex 로 바꾸는 순간, `margin:0 auto`
   가 붙은 본문은 **stretch 를 잃고 내용 폭으로 쪼그라든다**(flex 규칙: 가로 auto 마진이
   있으면 늘리지 않는다). 1440px 실측에서 1024px 이어야 할 칼럼이 **505px** 로 좁아져
   있었다 — 아래 정렬을 넣으면서 조용히 생긴 부작용이고, 폰에서는 어차피 화면이 좁아
   안 보였다. `width:100%` 로 예전처럼 "채우고 max-width 로 자르기"를 되돌린다. */
body.chat-page main.wrap { flex: 1 1 auto; display: flex; flex-direction: column; width: 100%; }
body.chat-page .chat-log { margin-top: auto; }
/* ⚠️ **아이 대화는 한 겹이 더 있다** (2026-08-16 사용자 지시 "지금 어른 대화창과 동일한
   여백으로"). 아이 화면은 `<main class="wrap">` 안에 `<section class="kid-wrap">` 을 한 겹
   더 두는데, 위 두 줄이 `main.wrap` 과 `.chat-log` 만 잡아서 **가운데 한 겹이 흐름을 끊었다** —
   `.chat-log` 의 부모가 flex 가 아니니 `margin-top:auto` 가 아무 일도 안 했고, 말이 위에
   붙은 채 밑이 통째로 비었다. 여백을 아무리 재도 안 보이던 이유다(가로는 실측상 같았다).
   ⚠️ `max-width` 도 같이 맞춘다 — 아이 기본값은 34rem, 어른 대화는 40rem 이라 **넓은
      화면에서만** 칼럼이 어긋났다. 폰에서는 둘 다 화면보다 넓어 티가 안 난다.
   ⚠️ 대화일 때만이다. 다른 아이 화면은 34rem 이 맞다(읽는 화면이라 좁은 게 낫다). */
body.chat-page .kid-wrap {
  flex: 1 1 auto; display: flex; flex-direction: column; width: 100%; max-width: 40rem;
}

/* ── 좌우 여백을 줄인다 (2026-08-15 사용자 지적 "왼쪽 오른쪽 가로 너비가 너무 많아") ──
   ⚠️ 대화는 **다른 화면과 여백 규칙이 다르다.** 나머지 화면은 읽는 화면이라 넉넉한
      여백이 글을 읽기 좋게 하지만, 대화는 **말풍선 자체가 여백을 만든다**(오른쪽 말은
      왼쪽이 비고, 왼쪽 말은 오른쪽이 빈다). 거기에 화면 여백까지 얹으면 두 겹이 된다.
   실측(390px 폰, 고치기 전): 긴 말의 말풍선이 **250px = 화면의 64%** 밖에 못 썼고
   왼쪽에 120px 이 통째로 비었다. 메신저는 보통 75% 안팎이다.
   ⚠️ 셋을 **같이** 고쳐야 한다 — 하나만 줄이면 줄 끝이 서로 어긋나 더 지저분해진다:
      ① 본문 여백(1.25rem→.75rem) ② 말풍선 상한(82%→88%) ③ 입력줄 여백(--gap 24px→.75rem)
   ⚠️ 본문 상한을 40rem 으로 올린 이유는 미감이 아니다 — `.chat-send` 가 이미 40rem 이라,
      544~1024px 구간에서 **입력줄만 넓고 말은 좁은** 어긋남이 있었다. 둘을 같은 값으로. */
/* ⚠️ 좌우는 **카카오톡 수준으로** 좁힌다(.5rem=8px). 여기서 더 줄이면 말풍선이 화면
   가장자리에 붙어 답답하고, 늘리면 말풍선이 쓸 자리가 그만큼 준다. */
body.chat-page main.wrap { max-width: 40rem; padding-left: .5rem; padding-right: .5rem; }
body.chat-page .chat-row { max-width: 90%; }
/* ③(입력줄·고치는중 줄·이모지판)은 **각자의 규칙 안에서** 고쳤다 — 여기에 적으면
   뒤에 오는 `padding` 단축 속성에 져서 안 먹는다(이 파일에서 이미 한 번 겪은 함정). */

.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;
  /* ⚠️ 좌우는 본문(main.wrap)과 **같은 값**이어야 한다(.75rem) — 다르면 말풍선 줄 끝과
     입력줄 끝이 어긋난다. 2026-08-15 --gap(24px) 에서 내렸다. */
  padding: .625rem .5rem; 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);
}
/* ⚠️ 보내기는 **작게**(2026-08-15 사용자 지적 "보내기 버튼이 너무 커").
   390px 폰에서 재 보니 75px 로 입력줄의 19% 를 먹고 있었다(입력칸은 163px).
   이 줄의 주인공은 **입력칸**이다 — 단추가 넓으면 쓸 자리가 그만큼 줄어든다.
   ⚠️ **높이는 안 줄인다**(2.75rem 유지). 이유 둘:
      ① 입력칸 min-height 와 같아야 두 칸이 나란히 맞는다.
      ② 이 줄 높이가 `--compose-h` 로 대화 스크롤 계산에 들어간다(app.css 위쪽) —
         높이를 건드리면 오늘 맞춘 스크롤이 다시 어긋난다.
   ⚠️ 그래서 **폭과 글자만** 줄인다. 손가락이 닿는 면적은 높이가 지킨다. */
.chat-send .btn {
  min-height: 2.75rem; padding: 0 .7rem; flex: 0 0 auto;
  font-size: .88rem; border-radius: 1.25rem;   /* 입력칸(1.25rem)과 같은 둥글기 */
}

/* ── 대화: 사진·이모지 (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 .5rem; 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; }

/* ── 개발 표시 ── 2026-08-14. 스테이징에만 그려진다(inc/view.php 의 NS_STAGING).
   ⚠️ **자리를 안 먹는다**(fixed) — 흐름에 넣으면 오늘 맞춘 대화 화면 스크롤 높이가
      어긋난다. ⚠️ pointer-events:none — 밑에 있는 것을 못 누르게 만들면 안 된다.
   ⚠️ 처음엔 모서리에 **비스듬한 리본**으로 넣었는데, 회전시키니 글자가 화면 밖으로
      잘려 "개발"이 안 읽혔다(실측 top=-15 left=-28). 딱지는 읽히라고 다는 것이라
      **회전을 버리고 납작한 라벨**로 바꿨다 — 멋보다 읽히는 게 먼저다.
   ⚠️ 왼쪽 위. 오른쪽 위는 화면마다 단추가 오는 자리라 겹친다.
   ⚠️ `--danger` 를 안 쓴다. 그 토큰은 **파괴적 동작 전용**이라고 tokens.css 에 못
      박혀 있고(지우기·탈퇴), 무대 표시는 파괴가 아니다. 더구나 다크모드에서 --danger 는
      연분홍(#FFB4AB)이라 흰 글씨가 묻힌다 — 값을 직접 박아 두 테마에서 같게 만든다. */
.devmark {
  position: fixed; top: 0; left: 0; z-index: 60; pointer-events: none;
  padding: .2rem .6rem .25rem; border-bottom-right-radius: .5rem;
  background: #8E1B1B; color: #fff;
  font-size: .7rem; font-weight: 700; letter-spacing: .06em; line-height: 1;
  box-shadow: 0 1px 4px rgba(0,0,0,.25);
}

/* ── 게임 시간 (2026-08-15) ─────────────────────────────────────────────────
   ⚠️ 이 화면의 주인공은 **숫자 하나**다. 카드·설명·단추가 시계보다 크면 "몇 분 남았지"에
      한 박자가 더 걸린다 — 그 한 박자를 없애려고 만든 화면이다.
   ⚠️ 숫자는 **자리가 안 흔들려야 한다**(tabular-nums). 안 그러면 1초마다 폭이 달라져
      옆 글자가 들썩인다. */
.game-card { margin-top: 1.25rem; text-align: center; }
.game-clock {
  font-size: 3.2rem; font-weight: 600; line-height: 1.1; color: var(--primary);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em; margin: .1rem 0 .2rem;
}
/* 아직 시작 전 — ⚠️ 옅게 둔다. 안 도는 시계가 도는 것처럼 보이면 안 된다 */
.game-clock.off { color: var(--ink-3); }
/* 마지막 1분 — ⚠️ 소리를 못 듣는 상황이 실제로 많아 **눈으로도** 알린다.
   ⚠️ `--danger` 를 쓰지 않는다(tokens.css: 파괴적 동작 전용). 시간이 얼마 안 남은 것은
      경고가 아니다 — 아이 화면에서 빨강은 "잘못했다"로 읽힌다. 굵기로만 말한다. */
.game-clock.soon { font-weight: 700; }
.game-clock.over { color: var(--ink-3); }
.game-done { margin-top: .5rem; font-weight: 600; color: var(--primary); }
/* 빠른 단추 — ⚠️ 4칸 고정. 개수가 늘면 여기 숫자도 같이 고쳐야 한다(줄이 접힌다) */
.game-presets { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; }
.game-preset { padding: 0 .25rem; font-size: .9rem; }

/* ── 알림 받기 상자 (2026-08-15) ──
   ⚠️ 눈에 띄되 **재촉하지 않는다** — 알림 허락은 한 번 거절당하면 되돌리기 어려워서
      (브라우저가 다시 안 물어본다) 크게 강조해 얼떨결에 누르게 만들면 안 된다. */
.pushbox { margin-top: .5rem; }
.pushbox .btn { width: 100%; }
.pushbox .push-say { margin-top: .35rem; min-height: 1.1em; }

/* ── 데스크톱: 대화가 창을 채운다 (2026-08-16 사용자 지적 "좌우 여백이 너무 넓어, 카톡처럼") ──
   두 가지가 걸려 있었다.
   ⚠️ ① **입력줄이 말풍선과 안 맞았다.** `.chat-send` 는 `position:fixed` 라 body 의
        사이드바 자리(padding-left:15rem)를 **못 본다** — 본문은 사이드바 오른쪽에서
        가운데를 잡고, 입력줄은 **창 전체**에서 가운데를 잡았다.
        1440px 실측: 말풍선 587~1093 vs 입력줄 400~1040 — **187px 어긋남.**
        고정 요소는 흐름 밖이라 부모의 padding 이 안 먹는다는 걸 잊으면 늘 이렇게 된다.
   ⚠️ ② 대화가 **좁은 띠**로 남았다(1440 에서 505px). 대화는 읽는 화면이 아니라 주고받는
        화면이라, 나머지 화면과 같은 폭 규칙(읽기 좋은 34~40rem)이 안 어울린다.
        메신저는 창을 채운다.
   ⚠️ 대신 **말풍선은 따로 묶는다** — 칼럼을 넓히면서 말풍선까지 같이 넓히면 한 줄이
      900px 이 되어 눈이 줄을 못 따라간다. 넓어지는 건 '자리'고, 말풍선은 읽는 폭을 지킨다. */
@media (min-width: 1024px) {
  body.chat-page main.wrap { max-width: 64rem; }
  /* ⚠️ 셋 다 같이 옮긴다 — 하나만 두면 고치는 중 알림줄·이모지판이 딴 데 뜬다 */
  body.chat-page .chat-send,
  body.chat-page .chat-editing,
  body.chat-page .emoji-pad { left: 15rem; max-width: 64rem; }
  /* 창은 넓어져도 한 줄은 읽을 수 있는 길이로.
     ⚠️ 70% = 1008px 칼럼에서 말풍선 ~660px ≈ 한글 50자 안팎이다(읽기 좋은 45~75자 안).
        60% 로 뒀더니 칼럼의 절반밖에 못 써서 여백이 다시 넓어 보였다(실측 50%). */
  body.chat-page .chat-row { max-width: 70%; }
}

/* ── 수유 기록 (2026-08-16) ──
   ⚠️ 이 화면의 주인공은 **"마지막으로 먹은 지 얼마나 됐나"** 한 줄이다. 게임 시간의
      시계와 같은 자리·같은 크기 — 새벽에 한 팔로 안고 보는 화면이라 한 박자라도 줄여야 한다.
   ⚠️ 다만 **초를 세지 않는다**(게임 시간과 다른 점). 1초마다 바뀌면 재촉처럼 보인다. */
.feed-card { margin-top: 1.25rem; text-align: center; }
.feed-ago {
  font-size: 2.4rem; font-weight: 600; line-height: 1.15; color: var(--primary);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em; margin: .1rem 0 .2rem;
}
.feed-ago.off { font-size: 1.5rem; color: var(--ink-3); }
/* ⚠️ 한 손으로 누른다 — 폭을 다 쓰고 높이도 넉넉히 */
.feed-now { width: 100%; min-height: 3.5rem; font-size: 1.05rem; }

/* ══ 끝말잇기 입력줄 ══ 2026-08-16 사용자 지시("이어진 말이 계속될수록 글 넣는 창이
   계속 밑으로 내려가지 않도록"). 말이 쌓이면 폼이 화면 밖으로 밀려 매번 스크롤해야 했다.
   ⚠️ **대화(.chat-send)와 같은 식**을 쓴다 — 같은 문제를 이미 그렇게 풀었고, 두 벌로
      갈라 두면 탭바 높이를 고칠 때 한쪽만 남는다.
   ⚠️ 좌우·최대폭도 본문과 같은 값이어야 줄 끝이 안 어긋난다(대화에서 겪은 그대로). */
.word-send {
  position: fixed; left: 0; right: 0;
  bottom: calc(4rem + env(safe-area-inset-bottom));   /* 탭바와 같은 식 */
  display: flex; gap: .5rem; align-items: center;
  padding: .625rem 1.25rem; background: var(--bg);
  border-top: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  max-width: 34rem; margin: 0 auto; z-index: 15;
}
.word-send .field { flex: 1 1 auto; margin: 0; }
.word-send .field label { display: block; margin-bottom: .15rem; }
.word-send .btn { flex: 0 0 auto; }
/* ⚠️ 고정 줄에 가리지 않게 본문 아래를 비운다. 라벨이 한 줄 더 있어 대화보다 조금 높다. */
body.word-page main.wrap { padding-bottom: 9rem; }
@media (min-width: 1024px) {
  /* ⚠️ position:fixed 는 사이드바를 모른다 — 대화와 같은 값으로 비켜 준다 */
  body.word-page .word-send { left: 15rem; max-width: 40rem; }
  body.word-page main.wrap { padding-bottom: 8rem; }
}

/* ══ 초성게임 ══ 2026-08-17. 결재 #75 1순위.
   ⚠️ **초성이 화면의 주인공**이다. 글자 몇 개가 문제의 전부라, 작으면 화면이 무슨 화면인지
      알 수가 없다. (처음엔 "온 가족이 한 화면을 본다"가 이유였는데 2026-08-17 온라인화로
      각자 폰을 보게 됐다 — 그래도 크기는 그대로가 맞다.)
   ⚠️ **점수·별·등수 자리가 아직 없다.** 막던 원칙 9 는 2026-08-18 폐기됐으니 이제 금지가
      아니라 **안 만든 것**이다 — 붙이려면 여기에 클래스를 새로 만들게 되고, 그때 이 줄을 본다. */
.cho-board {
  text-align: center; padding: 2rem 1rem; margin-top: 1rem;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
}
.cho-letters {
  font-size: 3rem; font-weight: 600; letter-spacing: .35em;
  /* ⚠️ letter-spacing 은 **오른쪽에** 붙는다 — 안 밀어 주면 가운데가 왼쪽으로 치우친다 */
  text-indent: .35em;
  line-height: 1.2; color: var(--ink);
}
.cho-answer { font-size: 2rem; font-weight: 600; color: var(--primary); margin-top: .75rem; }
/* ⚠️ 단추 둘을 나란히. "정답 보기"가 없을 때도 "다음 문제"가 같은 자리에 있어야
   손이 헤매지 않는다(그래서 flex-end 가 아니라 stretch 로 나눈다). */
.cho-acts { display: flex; gap: .5rem; margin-top: 1rem; }
.cho-acts form { flex: 1 1 0; }
.cho-acts .btn { width: 100%; }

/* ⚠️ 스무고개 — 질문 줄에 붙는 예·아니요 단추. 2026-08-17 온라인화.
   ⚠️ 단추가 셋이라 줄바꿈이 생기기 쉽다 — 질문이 길어도 단추가 **한 덩이로** 붙어 있게
      wrap 을 막고, 대신 질문 쪽이 줄어든다(읽는 건 두 줄이 돼도 되지만 단추가 흩어지면
      어느 질문의 답인지 알 수 없다). */
.say-ans { display: flex; gap: .25rem; flex: 0 0 auto; white-space: nowrap; }
.say-ans .cmt-del { padding: .2rem .5rem; }

/* ⚠️ 스무고개의 **출제자 이름**은 초성이 아니다. `.cho-letters` 를 그대로 썼더니
   자간 .35em 이 먹어 "아 빠"로 벌어졌다(2026-08-17 화면 실측) — 초성은 글자를 하나씩
   떼어 보여야 하고 이름은 붙어 있어야 한다. 크기만 물려받고 자간은 되돌린다. */
.guess-who { font-size: 2.2rem; font-weight: 600; line-height: 1.2; color: var(--ink);
             letter-spacing: -.02em; text-indent: 0; }

/* ⚠️ 놀이 입력줄의 단추가 **입력칸과 안 맞았다**(2026-08-18 사장님 지적 "넣기 사이즈가
   이상해"). 실측(390px): 입력칸 56px 높이인데 단추는 48px, 게다가 `align-items:center` 라
   **라벨까지 포함한 한가운데**에 떠 있어 위로 10px 어긋나 있었다 — 입력칸 옆에 있는데
   입력칸과 아귀가 안 맞으니 크기가 이상해 보인다.
   ⚠️ 라벨이 한 줄이라 눈에 잘 안 띄는 종류다. 두 화면(끝말잇기·떠오르는 말 잇기)이 같은
      `.word-send` 를 써서 한 번에 고쳐진다. */
.word-send .btn { align-self: flex-end; min-height: 3.5rem; }

/* ⚠️ 맞힌 말 — **눈에 띄되 상 같지는 않게**(확정 원칙 9(2026-08-18 폐기)). 색만 살짝 바뀐다.
   별·트로피·크기 키우기를 안 쓰는 것이 그 선이다. */
.say-hit { background: color-mix(in srgb, var(--primary) 8%, transparent); border-radius: var(--radius); }

/* ══ 이어쓰기 이야기 ══ 2026-08-18.
   ⚠️ **이야기는 목록이 아니라 글이다.** 다른 놀이처럼 줄마다 칸을 나누면(누가·무엇) 읽을 때
      이야기가 안 이어진다 — 문장을 잇대어 놓고 이름은 작게 옆에 둔다.
   ⚠️ 그래서 `.sched` 를 안 쓴다. 같은 폴링 코드가 여기만 다른 모양으로 그린다
      (assets/wordchain.js 의 KIND === 'story'). 한쪽만 고치면 **폴링으로 온 문장만
      모양이 다르다** — 새로고침하면 멀쩡해지는, 제일 찾기 어려운 종류의 어긋남이다. */
.story-log { line-height: 1.9; font-size: 1.05rem; }
.story-line { margin: 0 0 .35rem; }
.story-who { font-size: .75rem; color: var(--ink-3); white-space: nowrap; }

/* ══ 복약 ══ 2026-08-18. 진료에서 떼어내며 신설.
   ⚠️ **오늘 칸이 이 화면의 주인공**이다 — 여기 온 사람의 질문은 "오늘 아침 약 먹였나?"
      하나다. 그래서 칸이 크고, 누른 것과 안 누른 것이 멀리서도 갈린다.
   ⚠️ **누른 칸을 상처럼 꾸미지 않는다** — 색만 바뀐다. 별·체크마크·크기 키우기를 안 쓴다.
      이건 성취가 아니라 사실이다(약을 먹인 것은 잘한 일이 아니라 한 일이다).
   ⚠️ 아이 화면은 같은 모양을 **span 으로** 그린다(누를 수 없다) — 눌러도 아무 일이
      없으면 그게 더 답답해서, 아예 단추가 아니게 만든다. */
.med-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .875rem 1rem; margin-bottom: .625rem;
}
.med-head { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; }
.med-name { font-weight: 600; }
/* ⚠️ 칸이 여섯까지 온다(하루 6번) — 줄바꿈을 막지 않는다. 좁은 폰에서 한 줄에 욱여넣으면
   글자가 잘리고, 약 이름이 잘리는 것보다 나쁜 것은 시각이 잘리는 것이다. */
.med-slots { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .5rem; }
/* ⚠️ 2026-08-18 사장님 지적("아침 점심 저녁 칸이 너무 작게 되어있어").
   원인은 **칸을 나눠 갖는 것이 단추가 아니라 폼**이라는 것이었다 —
   단추마다 제 `<form>` 으로 감싸 놓아서(CSRF·act 를 각각 실어야 한다),
   `.med-slots` 의 flex 자식은 폼이다. 폼엔 flex 규칙이 없어 **글자 폭(42px)** 으로
   쪼그라들었고, 아래 `.med-slot { flex: 1 1 4.5rem }` 은 아무 일도 안 하고 있었다.
   (칸은 316px 인데 단추 셋이 42px 씩만 쓰고 있었다.)
   ⚠️ 하루 세 번 누르는 단추다 — 아이를 안은 채 한 손으로 누른다. 크기가 곧 쓸모다. */
.med-slots > form { flex: 1 1 4.5rem; display: flex; margin: 0; }
.med-slots > form > .med-slot { width: 100%; }
.med-slot {
  flex: 1 1 4.5rem; min-height: 3.5rem; padding: .5rem .5rem;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface-2); color: var(--ink-2); font-size: 1rem; line-height: 1.2;
}
.med-slot small { font-size: .72rem; color: var(--ink-3); margin-top: .15rem; }
.med-slot.on { background: color-mix(in srgb, var(--primary) 12%, var(--surface));
               border-color: var(--primary); color: var(--ink); }
.med-slot.on small { color: var(--ink-2); }
button.med-slot { cursor: pointer; }
.med-end { text-align: right; margin-top: .5rem; }

/* ══ 오늘의 주인공 ══ 2026-08-18.
   ⚠️ **질문과 답이 한 덩이로 읽혀야 한다** — 다른 놀이처럼 한 줄에 칸을 나누면
      "누가 무엇을 물었고 뭐라고 답했나"가 흩어진다. 질문 아래 답을 들여쓴다. */
.star-row { padding: .625rem 0; border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent); }
.star-row:last-child { border-bottom: 0; }
.star-q { margin: 0; }
.star-a { margin: .35rem 0 0 1.25rem; padding-left: .625rem;
          border-left: 2px solid var(--primary); color: var(--ink); }
.star-reply { display: flex; gap: .4rem; margin: .35rem 0 0 1.25rem; }
.star-reply input[name="text"] {
  flex: 1 1 auto; min-height: 2.75rem; padding: 0 .75rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
}
.star-reply .btn { flex: 0 0 auto; min-height: 2.75rem; padding: 0 .9rem; }

/* ══ 짝 맞추기 ══ 2026-08-18. 놀이 여덟 중 **유일한 "진짜 게임"**.
   ⚠️ 카드가 **손가락으로 눌리는 크기**여야 한다 — 짝 맞추기는 아이가 하는 게임이고,
      작으면 옆 카드를 누른다. 4쌍이면 8장, 8쌍이면 16장이 한 화면에 들어가야 해서
      grid 로 자동 배치하고 카드는 정사각(aspect-ratio)으로 둔다.
   ⚠️ **뒷면이 빈 칸이면 "안 눌리는 곳"으로 보인다** — 무늬를 준다.
   ⚠️ 뒤집기 애니메이션을 **짧게**(150ms) — 길면 아이가 기다리다 두 번 누른다. */
.match-hud {
  display: flex; gap: .75rem; align-items: baseline; margin: .75rem 0 .5rem;
}
.match-hud #mtime { font-size: 1.5rem; font-weight: 600; color: var(--primary); }
.match-board {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem;
}
.mcard {
  position: relative; aspect-ratio: 1 / 1; padding: 0; border: 0; background: none;
  border-radius: var(--radius); overflow: hidden; cursor: pointer;
}
.mcard .mback, .mcard .mface {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius); transition: opacity 150ms var(--ease);
}
.mcard .mback {
  opacity: 1; background: var(--surface-2);
  border: 1px solid var(--line);
  /* 무늬 — ⚠️ 빈 칸으로 두면 안 눌리는 곳처럼 보인다 */
  background-image: radial-gradient(circle at 50% 50%,
    color-mix(in srgb, var(--primary) 18%, transparent) 18%, transparent 19%);
  background-size: 1.5rem 1.5rem;
}
.mcard .mface { opacity: 0; background: var(--surface); border: 1px solid var(--primary); }
.mcard .mface img { width: 100%; height: 100%; object-fit: cover; }
.mcard .mtxt { font-size: 1.1rem; font-weight: 600; color: var(--ink); }
.mcard.on .mback, .mcard.done .mback { opacity: 0; }
.mcard.on .mface, .mcard.done .mface { opacity: 1; }
/* ⚠️ 맞힌 카드는 **없애지 않고 눕힌다** — 없애면 판이 흔들려 다음 카드를 놓친다 */
.mcard.done { cursor: default; }
.mcard.done .mface { opacity: .45; border-color: var(--line); }
@media (max-width: 380px) { .match-board { grid-template-columns: repeat(3, 1fr); } }

/* ══ 그림 맞히기 ══ 2026-08-19. 아홉째 놀이 — 이 앱에서 **유일하게 캔버스를 쓴다.**
   ⚠️ **그림판 바탕은 늘 흰 종이다**(토큰을 안 쓴다). 다크모드(설정에서 켠다)에서 바탕이
      어두워지면 검정 선이 안 보인다 — 종이는 어느 화면에서나 종이여야 한다.
   ⚠️ **붓이 켜진 칸만 touch-action:none** 이다. 보는 사람 화면까지 막으면 큰 칸 위에서
      손가락으로 스크롤이 안 돼 화면에 갇힌다.
   ⚠️ 칸은 **정사각**(aspect-ratio)이다 — 좌표를 0~1000 한 칸으로 주고받으므로 화면 비율이
      다르면 아빠가 그린 동그라미가 아이 화면에서 찌그러진다. */
.draw-wrap { position: relative; margin: .75rem 0 .5rem; }
.draw-pad {
  display: block; width: 100%; aspect-ratio: 1 / 1;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
}
.draw-pad.on { touch-action: none; cursor: crosshair; }
.draw-wait {
  position: absolute; inset: 0; margin: 0; display: flex; align-items: center;
  justify-content: center; color: var(--ink-3); font-size: .95rem; pointer-events: none;
}
.draw-tools { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; }
.draw-colors, .draw-widths, .draw-acts2 { display: flex; align-items: center; gap: .4rem; }
.draw-acts2 { margin-left: auto; }
/* ⚠️ 색·굵기 단추도 **손가락 크기**(44px)여야 한다 — 아이가 누르는 것들이다 */
.draw-color {
  width: 2.75rem; height: 2.75rem; padding: 0; border-radius: 50%;
  border: 2px solid var(--line); cursor: pointer;
}
.draw-color.on { border-color: var(--ink); box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--ink-3); }
/* ⚠️ 이 여섯 값은 draw.js 의 COLORS 와 **같아야 한다**(한쪽만 고치면 고른 색과 그려진
   색이 달라진다 — 화면에서는 이유를 알 수 없는 결함이 된다). */
.draw-color.c0 { background: #26262b; } .draw-color.c1 { background: #e5484d; }
.draw-color.c2 { background: #3e63dd; } .draw-color.c3 { background: #30a46c; }
.draw-color.c4 { background: #f5a524; } .draw-color.c5 { background: #8e4ec6; }
.draw-width {
  width: 2.75rem; height: 2.75rem; padding: 0; display: flex; align-items: center;
  justify-content: center; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); cursor: pointer;
}
.draw-width.on { border-color: var(--primary); background: var(--primary-l); }
.draw-width span { display: block; border-radius: 50%; background: var(--ink); }
.draw-width.w0 span { width: .25rem; height: .25rem; }
.draw-width.w1 span { width: .5rem;  height: .5rem; }
.draw-width.w2 span { width: .9rem;  height: .9rem; }
.draw-acts2 .btn {
  /* ⚠️ 도구는 **한 화면에 들어와야** 한다 — 색 여섯 줄 아래로 굵기와 단추가 각각 한 줄씩
     내려가면 그림판 아래가 세 줄이 되어 단추가 아래 탭에 가린다(2026-08-19 실측).
     기본 단추(3.5rem)를 여기서만 낮춰 굵기와 한 줄에 세운다. */
  min-height: 2.75rem; padding: 0 .75rem; font-size: .9rem;
}
.draw-state { margin: .25rem 0 .5rem; }
/* 지난 그림 — ⚠️ 작아도 **무엇을 그린 것인지 읽혀야** 해서 두 칸까지만 줄인다 */
.draw-past { display: grid; grid-template-columns: repeat(2, 1fr); gap: .75rem; margin-top: .5rem; }
.draw-thumb { margin: 0; }
.draw-mini {
  display: block; width: 100%; aspect-ratio: 1 / 1;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
}
.draw-thumb figcaption { margin-top: .25rem; font-size: .9rem; color: var(--ink); }

/* ══ 숫자 놀이 ══ 2026-08-19. 열·열한째 놀이(숫자 맞히기·숫자야구).
   ⚠️ **적은 수는 자릿수가 맞아 보여야 한다** — 추리 놀이라 위아래로 훑으며 비교한다.
      비례폭 글꼴에서는 1 과 8 의 폭이 달라 세로줄이 어긋나고, 그러면 눈으로 못 좁힌다.
   ⚠️ 화면 구조는 초성게임 것을 그대로 쓴다(.cho-board·.sched·.word-send) — 새 뼈대를
      만들지 않는다. 여기서 더하는 것은 **숫자를 읽기 좋게** 하는 것뿐이다. */
.num-page #nummask { letter-spacing: .15em; }
.num-try { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.num-try .pill { margin-left: .35rem; }

/* ── 눌러서 복사되는 줄 (2026-08-18) ─────────────────────────────────────
   ⚠️ 눌리는 것처럼 **보여야** 누른다 — 그냥 글자면 아무도 안 누른다.
      그래서 테두리·손가락 커서를 주고, 오른쪽에 "누르면 복사"를 늘 띄워 둔다. */
.copy-line {
  display: flex; align-items: center; gap: .6rem; cursor: pointer;
  margin: .35rem 0 0; padding: .7rem .85rem;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.copy-line:hover, .copy-line:focus-visible { border-color: var(--accent); background: var(--surface); }
.copy-line:focus-visible { outline: none; }
.copy-url  { flex: 1 1 auto; word-break: break-all; font-size: .85rem; }
/* 알림칸은 폭이 고정이라야 글자가 바뀔 때 주소가 안 밀린다 */
.copy-hint { flex: 0 0 auto; font-size: .75rem; color: var(--ink-3); white-space: nowrap; }

/* ── 사용법(manual.php)의 접히는 항목 ── 2026-08-19 ────────────────────────
   ⚠️ 한 화면에 스무 항목을 다 펼치면 "쉬운" 매뉴얼이 아니게 된다 — 제목만 훑다가
      궁금한 것만 연다. <details> 라 JS 가 필요 없다.
   ⚠️ 눌리는 줄이라는 걸 **화살표로** 말한다. 기본 삼각형은 브라우저마다 달라 직접 그린다. */
.manual-item { border: 1px solid var(--line); border-radius: var(--radius);
               background: var(--surface); margin-bottom: .5rem; overflow: hidden; }
.manual-item > summary {
  list-style: none; cursor: pointer; padding: 1rem 1.1rem;
  font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: .6rem;
}
.manual-item > summary::-webkit-details-marker { display: none; }
/* 화살표 — 열리면 아래를 가리킨다 */
.manual-item > summary::before {
  content: ''; flex: 0 0 auto; width: .5rem; height: .5rem;
  border-right: 2px solid var(--ink-3); border-bottom: 2px solid var(--ink-3);
  transform: rotate(-45deg); transition: transform var(--dur) var(--ease);
}
.manual-item[open] > summary::before { transform: rotate(45deg); }
.manual-item > summary:hover { background: var(--surface-2); }
.manual-body { padding: 0 1.1rem 1.1rem; color: var(--ink-2); line-height: 1.65; }
.manual-body p { margin: 0 0 .6rem; }
.manual-body p:last-child { margin-bottom: 0; }
.manual-body ul { margin: 0 0 .6rem; padding-left: 1.1rem; }
.manual-body li { margin-bottom: .35rem; }
.manual-body strong { color: var(--ink); }

/* 아이용은 글자를 키운다 — 같은 장치라도 읽는 사람이 다르다(2026-08-19) */
.manual-kid > summary { font-size: 1.1rem; padding: 1.15rem 1.2rem; }
.manual-kid .manual-body { font-size: 1.02rem; line-height: 1.7; }

/* ── 처음 오신 분 안내 ── 2026-08-19 ─────────────────────────────────────────
   ⚠️ 경고처럼 보이면 안 된다 — 붉은 테두리·느낌표를 안 쓴다. 반가운 인사에 가깝다.
   ⚠️ 두 단추의 무게를 다르게 준다: 보러 가기는 채운 단추, "다음에"는 테두리만.
      둘이 같아 보이면 사람은 아무것도 안 누르고 지나간다. */
.firstrun { border: 1px solid var(--primary); background: var(--surface); }
.firstrun-t { margin: 0 0 .3rem; font-weight: 700; color: var(--ink); }
.firstrun-b { margin: 0 0 .9rem; color: var(--ink-2); font-size: .92rem; line-height: 1.6; }
.firstrun-row { display: flex; gap: .5rem; }
.firstrun-row > * { flex: 1 1 0; }
.firstrun-row .btn { width: 100%; }

/* ── "지난번" 표시 ── 2026-08-19 ────────────────────────────────────────────
   ⚠️ 크게 만들지 않는다. 이건 **거드는 말**이지 경고가 아니다 —
      소셜 이름보다 커지면 무엇을 누르는 화면인지가 흐려진다. */
.circle-badge {
  display: inline-block; margin-left: .3rem; padding: .05rem .35rem;
  font-size: .68rem; font-weight: 600; line-height: 1.5;
  color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, transparent);
  border-radius: 999px; vertical-align: middle;
}
/* 지난번에 쓴 동그라미에 얇은 테를 둘러 눈에 먼저 들어오게 한다 */
.circle-btn.circle-last { box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 35%, transparent); }

/* 아이디 확인 결과 — 2026-08-19. ⚠️ 색만으로 말하지 않는다(글자가 이미 말한다).
   색맹·흑백 화면에서도 "이미 쓰는 아이디예요"라는 **문장**이 정보를 다 담는다. */
.hint.ok { color: var(--primary); font-weight: 600; }
.hint.no { color: var(--danger); font-weight: 600; }

/* ── 확인 모달 ── 2026-08-19 ────────────────────────────────────────────────
   ⚠️ `.sheet` 뼈대를 그대로 빌려 쓴다 — 개인 관리·사진 크게 보기와 **같은 모양**이어야
      "이 앱의 창"으로 읽힌다. 확인창만 다르게 생기면 낯선 것이 끼어든 것처럼 보인다.
   ⚠️ 지우는 단추는 **빨갛게**(btn-danger). 되돌릴 수 없는 것과 그냥 끝내는 것은
      눌리는 무게가 달라야 한다 — 색이 그 말을 대신한다. */
.confirm-msg { color: var(--ink-2); line-height: 1.65; margin: 0 0 1.25rem; }
.confirm-row { display: flex; gap: .5rem; }
.confirm-row .btn { flex: 1 1 0; width: auto; }
/* ⚠️ 위험한 단추는 **주 색이 아니라 경고 색**이다.
   ⚠️ 그런데 `var(--danger)` 를 그대로 쓰면 안 된다 — 어두운 테마에서 그 값은
      **연분홍(#FFB4AB)** 이라 흰 글씨가 묻힌다(이 파일 위쪽에서 이미 한 번 겪은 함정이다).
      그래서 **값을 박아** 두 테마에서 같게 만든다. 진한 붉은 바탕 + 흰 글씨는 양쪽 다 읽힌다. */
.btn.btn-danger { background: #BA1A1A; border-color: #BA1A1A; color: #fff; }
.btn.btn-danger:hover { background: #9F1414; border-color: #9F1414; }
