/* 교적관리 — 폰/패드/데스크톱 대응 스타일
   모바일 우선. 브레이크포인트는 640px(패드), 1024px(데스크톱). */

:root {
  --bg: #f6f7f9;
  --surface: #ffffff;
  --border: #e2e5ea;
  --text: #1a1d21;
  --text-dim: #656d78;
  --accent: #2f6b4f;
  --accent-dim: #e6f0ea;
  --danger: #c0392b;
  --danger-dim: #fdecea;
  --warn: #9a6700;
  --warn-dim: #fff6e0;
  --radius: 10px;
  --shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  --header-h: 56px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #15181c;
    --surface: #1e2227;
    --border: #313740;
    --text: #e8eaed;
    --text-dim: #9aa3ae;
    --accent: #6cc296;
    --accent-dim: #1f3229;
    --danger: #ef8074;
    --danger-dim: #3a2320;
    --warn: #e0b155;
    --warn-dim: #352d18;
    --shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Apple SD Gothic Neo', 'Pretendard',
    'Malgun Gothic', system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ══════════════════════════════════════════════════════════════
   상·하단 바 — iOS 26 Liquid Glass
   ──────────────────────────────────────────────────────────────
   바 자체는 **존재하지 않는다.** 배경도 테두리도 없고, 그 위에 떠 있는
   유리 버튼과 알약만 있다. 본문은 그 아래로 그대로 흐르고 유리가 흐린다.
   예전처럼 위아래를 불투명한 띠 두 개가 잡아먹지 않아 화면이 넓어 보인다.
   ══════════════════════════════════════════════════════════════ */

.topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  /*
    ⚠️ 토스트(35)보다 **위**여야 한다. 상단 바는 이 화면에서 빠져나가는
       유일한 길(뒤로가기)이다. 무엇에든 가리면 사람이 갇힌다.

    예전에는 30 이었다. 토스트가 뜨면 뒤로가기도 편집도 눌리지 않았다 —
    토스트 상자가 버튼보다 아래에 그려지는데도 그랬다. 겉보기로는 겹치지
    않으니 원인을 짐작할 수 없고, 화면만 굳은 것처럼 보인다. 실제로
    「연락처 키가 없습니다」 알림이 뜬 뒤 상세 화면에서 나갈 수 없었다.
       (탭바는 멀쩡해서 더 헷갈렸다.)
  */
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: calc(env(safe-area-inset-top) + 10px) 14px 10px;
  /* 바가 통째로 클릭을 먹으면 그 아래 목록의 첫 줄을 못 누른다.
     바는 통과시키고 안의 버튼만 받는다. */
  pointer-events: none;
}
.topbar > * { pointer-events: auto; }

/* ⚠️ 상단 전면폭 가림막은 **금지.**
   iOS 26 사파리는 화면 위쪽에 배경 있는 바 모양 고정 요소가 있으면 그 색을
   상태바 뒤까지 불투명하게 칠해 버린다 (블러든 그라데이션이든, 위 끝에 닿지
   않아도). 그래서 본문이 다이나믹 아일랜드 밑으로 지나가는데도 보이지 않았다.
   시뮬레이터로 변형 다섯 가지를 실측해 확인했다 — 전면폭 요소를 아예 없애야
   본문이 맨 위 픽셀까지 올라간다. 제목 글자는 아래의 작은 유리 알약이 지킨다. */

.tb-side {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  min-width: 44px;
}
.tb-side.right { justify-content: flex-end; }
.tb-title {
  flex: 1;
  min-width: 0;
  margin: 0;
  display: flex;
  justify-content: center;
  /* 아이폰 내비게이션 제목 규격 — 17pt SF Semibold, 살짝 죄인 자간 */
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.02em;
}
/* 제목은 평범한 글자다 (아이폰 통화 앱처럼). 본문이 밑으로 지나갈 때를
   위해 아주 옅은 그림자만 — 유리 알약은 사장님이 뺐다. */
.tb-title span {
  display: inline-block;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.35);
}

/* 떠 있는 유리 버튼 — 원형이 기본, 글자가 들어가면 알약 */
.gbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 42px;
  min-width: 42px;
  padding: 0;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 600;
  font-family: inherit;
  color: var(--text);
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
  cursor: pointer;
  white-space: nowrap;
}
.gbtn:hover { text-decoration: none; filter: brightness(1.06); }
.gbtn:active { transform: scale(0.94); }
.gbtn.wide { padding: 0 18px; }
.gbtn.accent { color: #fff; background: var(--accent); border-color: transparent; }
.gbtn.danger { color: #fff; background: var(--danger); border-color: transparent; }
.gbtn[disabled] { opacity: 0.45; pointer-events: none; }
.gbtn .g-ico { font-size: 19px; line-height: 1; }

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .gbtn {
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
  }
}

/* ── 아이콘 — 흰색 단색 선 그림 ────────────────────
   이모지는 기기마다 그림이 다르고 색이 제멋대로다. 유리 위에 알록달록한 것이
   떠 있으면 유리로 보이지 않는다. currentColor 를 따르게 해서 글자색과 맞춘다. */
.ic {
  width: 1.35em;
  height: 1.35em;
  display: block;
  flex: 0 0 auto;
  vertical-align: middle;
}

/* ══════════════════════════════════════════════════════════════
   토스트 — 상단에 내려오는 알림 한 장 (iOS 배너 결)
   ──────────────────────────────────────────────────────────────
   [문구] [동작 알약] [✕] 세 덩이. 잠금처럼 중요한 알림은 위에서 내려오는 편이
   눈에 먼저 든다. 본문 흐름을 밀지 않게 떠 있고, 하단 알약과도 겹치지 않는다.
   ══════════════════════════════════════════════════════════════ */
.toast {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 62px);
  left: 14px; right: 14px;
  z-index: 35;
  max-width: 560px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 10px 10px 16px;
  border-radius: 22px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
  animation: toast-in 0.28s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-14px) scale(0.96); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .toast { -webkit-backdrop-filter: blur(24px) saturate(180%); backdrop-filter: blur(24px) saturate(180%); }
}
.toast.warn { border-color: var(--warn); }
.toast.error { border-color: var(--danger); }
.toast-body { flex: 1; min-width: 0; }
.toast-body strong { display: block; font-size: 15px; letter-spacing: -0.01em; }
.toast-text { font-size: 12.5px; color: var(--text-dim); overflow-wrap: anywhere; }
.toast .gbtn { height: 40px; font-size: 14.5px; }
/* 닫기 — 이미지처럼 반투명 동그라미 */
.toast-x {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 50%;
  background: rgba(127, 127, 127, 0.22);
  color: var(--text);
  cursor: pointer;
}
.toast-x .ic { width: 16px; height: 16px; }
.toast-x:hover { background: rgba(127, 127, 127, 0.34); }

/* 뒤로가기 갈매기표 — 글꼴에 기대지 않고 직접 그린다 */
.chev-l, .chev-r {
  width: 10px; height: 10px;
  border-left: 2.4px solid currentColor;
  border-bottom: 2.4px solid currentColor;
  border-radius: 1px;
}
.chev-l { transform: rotate(45deg); margin-left: 3px; }
.chev-r { transform: rotate(-135deg); margin-right: 3px; }

/* ── 하단 탭 — 떠 있는 알약 ────────────────────────── */
nav.tabbar {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(env(safe-area-inset-bottom) + 12px);
  /* 상단 바와 같은 이유로 토스트(35)보다 위. 길을 막는 것이 없어야 한다. */
  z-index: 38;
  display: flex;
  align-items: center;
  /* 탭 알약은 왼쪽 끝, 동작 버튼은 오른쪽 끝. 가운데로 몰아 놓으면 한 손으로
     엄지를 뻗기 애매한 자리에 모인다. */
  justify-content: space-between;
  gap: 10px;
  padding: 0 14px;
  pointer-events: none;
}
/* 탭 알약 옆에 붙는 동그란 버튼 (검색·추가·저장).
   엄지가 가장 편하게 닿는 자리라 그 화면에서 제일 자주 누르는 것을 둔다. */
nav.tabbar .gbtn {
  pointer-events: auto;
  height: 52px;
  min-width: 52px;
  font-size: 16px;
}
nav.tabbar .gbtn .g-ico { font-size: 21px; }
nav.tabbar .tabpill {
  display: flex;
  gap: 2px;
  padding: 5px;
  border-radius: 999px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
  pointer-events: auto;
  max-width: 100%;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  nav.tabbar .tabpill {
    -webkit-backdrop-filter: blur(24px) saturate(180%);
    backdrop-filter: blur(24px) saturate(180%);
  }
}
nav.tabbar .tabpill a {
  display: block;
  min-width: 68px;
  padding: 5px 12px 6px;
  border-radius: 999px;
  text-align: center;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-dim);
  line-height: 1.25;
}
nav.tabbar .tabpill a:hover { text-decoration: none; }
nav.tabbar .tabpill a .ico { display: block; font-size: 19px; line-height: 1.25; }
nav.tabbar .tabpill a.active {
  background: var(--glass-hi);
  color: var(--accent);
  font-weight: 700;
}

/* 하단 버튼을 눌렀을 때 탭 위로 올라오는 판.
   검색·거르개가 화면에 상주하며 자리를 먹지 않게, 필요할 때만 떠오른다. */
.dock-panel {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(env(safe-area-inset-bottom) + 76px);
  z-index: 37;
  padding: 0 14px;
  display: flex;
  justify-content: center;
  pointer-events: none;
}
.dock-panel[hidden] { display: none; }
.dock-panel > .inner {
  pointer-events: auto;
  width: 100%;
  max-width: 560px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 10px;
  border-radius: 20px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .dock-panel > .inner {
    -webkit-backdrop-filter: blur(24px) saturate(180%);
    backdrop-filter: blur(24px) saturate(180%);
  }
}
.dock-panel input, .dock-panel select {
  padding: 9px 12px;
  font-size: 16px;
  border-radius: 12px;
  border-color: transparent;
  background: rgba(255, 255, 255, 0.4);
}
@media (prefers-color-scheme: dark) {
  .dock-panel input, .dock-panel select { background: rgba(255, 255, 255, 0.08); }
}
.dock-panel .wide { flex: 1 0 100%; }
.dock-panel select { flex: 1 1 0; min-width: 0; width: auto; }

main {
  /* 위 여백은 떠 있는 버튼(42px) + 안전영역, 아래는 탭 알약 높이만큼 */
  padding: calc(env(safe-area-inset-top) + 68px) 16px calc(env(safe-area-inset-bottom) + 104px);
  max-width: 900px;
  margin: 0 auto;
}
body.solo main { padding-bottom: 40px; }

@media (min-width: 640px) {
  main { padding-left: 24px; padding-right: 24px; }
}

/* ── 카드 / 섹션 ──────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 16px;
  box-shadow: var(--shadow);
}
.card > h2, .card > h3 { margin-top: 0; }

h1 { font-size: 22px; margin: 0 0 16px; }
h2 { font-size: 17px; margin: 0 0 12px; }
h3 { font-size: 15px; margin: 0 0 8px; }

.muted { color: var(--text-dim); }
/* 경고 문구용. .badge.danger 와 달리 글자색만 바꾼다. */
.danger { color: var(--danger); }
.small { font-size: 13px; }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* ── 통계 타일 ────────────────────────────────────── */
.tiles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-bottom: 16px;
}
@media (min-width: 640px) { .tiles { grid-template-columns: repeat(4, 1fr); } }
.tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  box-shadow: var(--shadow);
}
.tile .label { font-size: 12px; color: var(--text-dim); }
.tile .value { font-size: 22px; font-weight: 700; margin-top: 2px; }
.tile .value small { font-size: 13px; font-weight: 400; color: var(--text-dim); }

/* ── 표 ───────────────────────────────────────────── */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
th, td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
th {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-dim);
  background: var(--bg);
  position: sticky;
  top: 0;
}
tbody tr:hover { background: var(--bg); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── 폼 ───────────────────────────────────────────── */
.form-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}
@media (min-width: 640px) { .form-grid { grid-template-columns: repeat(2, 1fr); } }
.form-grid .full { grid-column: 1 / -1; }

label { display: block; font-size: 13px; color: var(--text-dim); margin-bottom: 4px; }

input[type='text'], input[type='date'], input[type='number'], input[type='email'],
input[type='password'], input[type='search'], input[type='tel'], select, textarea {
  width: 100%;
  padding: 10px 12px;
  font-size: 16px; /* iOS 자동 확대 방지 */
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}
textarea { min-height: 80px; resize: vertical; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 16px;
  font-size: 14px;
  font-family: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
}
.btn:hover { opacity: 0.9; text-decoration: none; }
.btn.secondary { background: var(--surface); color: var(--text); border-color: var(--border); }
.btn.danger { background: var(--danger); border-color: var(--danger); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* ── 뱃지 / 알림 ──────────────────────────────────── */
.badge {
  display: inline-block;
  padding: 2px 8px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 999px;
  background: var(--accent-dim);
  color: var(--accent);
}
.badge.gray { background: var(--border); color: var(--text-dim); }
.badge.danger { background: var(--danger-dim); color: var(--danger); }
.badge.warn { background: var(--warn-dim); color: var(--warn); }

.alert {
  padding: 12px 14px;
  border-radius: var(--radius);
  margin-bottom: 16px;
  font-size: 14px;
  border: 1px solid;
  /* 오류 원문에는 띄어쓰기 없는 긴 문자열(base64 챌린지 등)이 섞여 들어올 수 있다.
     그대로 두면 상자 밖으로 삐져나가므로 어디서든 접히게 한다. */
  overflow-wrap: anywhere;
  word-break: break-word;
  /* 그래도 지나치게 긴 메시지가 화면을 통째로 밀어내지는 않게 한다 */
  max-height: 40vh;
  overflow-y: auto;
}
.alert.info { background: var(--accent-dim); border-color: var(--accent); color: var(--text); }
.alert.error { background: var(--danger-dim); border-color: var(--danger); color: var(--text); }
.alert.warn { background: var(--warn-dim); border-color: var(--warn); color: var(--text); }
.alert strong { display: block; margin-bottom: 4px; }

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 16px;
}
.toolbar .grow { flex: 1; min-width: 160px; }

.empty { text-align: center; padding: 40px 16px; color: var(--text-dim); }

ul.plain { list-style: none; padding: 0; margin: 0; }
ul.plain li { padding: 10px 0; border-bottom: 1px solid var(--border); }
ul.plain li:last-child { border-bottom: none; }

.row-split { display: flex; justify-content: space-between; align-items: center; gap: 12px; }

pre.file-preview {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
  overflow-x: auto;
  font-size: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre;
  margin: 0;
}

/* 로그인 화면 */
.login-wrap {
  min-height: 100dvh;
  display: grid;
  /* safe — 내용이 화면보다 크면 가운데 정렬이 위쪽을 잘라 낸다(스크롤로도 못 감).
     넘칠 때는 위에서부터 흐르게 한다. */
  place-items: safe center;
  padding: 24px;
}

/*
  아이폰 사파리의 하단 주소창은 100dvh 안쪽에 겹쳐 그려진다. 그래서 폼 맨
  아래 버튼이 그 알약 뒤로 들어가 **눌리지 않는다.**

  하필 이 클래스를 쓰는 화면이 공개 폼(교인 등록 /join, 주민번호 제출
  /submit)이다. 외부인이 쓰는 화면이라 여기서 막히면 접수 자체가 안 되고,
  그 사람은 왜 안 되는지 물어볼 데도 없다. 시뮬레이터에서 「암호화하여
  제출」이 정확히 그렇게 가려져 있었다.

  넓은 화면에는 이 여백이 필요 없다 — 가운데 정렬만 어긋난다.
*/
@media (max-width: 639px) {
  .login-wrap { padding-bottom: calc(24px + env(safe-area-inset-bottom) + 76px); }
}
.login-box { width: 100%; max-width: 360px; }

/* 로그인 화면의 "마스터 관리자" 토글 — 기본 삼각형 마커를 숨긴다 */
details > summary { list-style: none; }
details > summary::-webkit-details-marker { display: none; }
details > summary::marker { content: ''; }
details > summary:hover { color: var(--accent); }

/* ══════════════════════════════════════════════════════════════
   Liquid Glass — 반투명 유리 레이어
   backdrop-filter 를 쓴다. Safari/Chrome/Edge(데스크톱·모바일) 모두 지원하고,
   미지원 브라우저에서는 @supports 밖의 불투명 배경으로 자연스럽게 내려앉는다.
   ══════════════════════════════════════════════════════════════ */

:root {
  --glass-bg: rgba(255, 255, 255, 0.55);
  --glass-brd: rgba(255, 255, 255, 0.7);
  --glass-hi: rgba(255, 255, 255, 0.9);
  --glass-sh: 0 8px 32px rgba(31, 38, 135, 0.1);
  --mesh-1: rgba(47, 107, 79, 0.18);
  --mesh-2: rgba(120, 180, 220, 0.16);
  --mesh-3: rgba(230, 190, 130, 0.14);
}

@media (prefers-color-scheme: dark) {
  :root {
    --glass-bg: rgba(38, 44, 52, 0.55);
    --glass-brd: rgba(255, 255, 255, 0.1);
    --glass-hi: rgba(255, 255, 255, 0.14);
    --glass-sh: 0 8px 32px rgba(0, 0, 0, 0.36);
    --mesh-1: rgba(60, 140, 100, 0.22);
    --mesh-2: rgba(70, 120, 170, 0.2);
    --mesh-3: rgba(150, 120, 70, 0.16);
  }
}

/* 배경 — 은은한 색 덩어리. 유리가 굴절시킬 대상이 있어야 유리처럼 보인다. */
body {
  background-attachment: fixed;
  background-image:
    radial-gradient(60rem 40rem at 8% -10%, var(--mesh-1), transparent 60%),
    radial-gradient(50rem 36rem at 100% 8%, var(--mesh-2), transparent 62%),
    radial-gradient(46rem 34rem at 40% 108%, var(--mesh-3), transparent 60%);
}

.glass-panel,
.card,
.tile,
.ios-group {
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .glass-panel,
  .card,
  .tile,
  .ios-group {
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
  }
}

.glass-panel,
.card,
.tile {
  border-radius: 18px;
  position: relative;
}

/* 위쪽 가장자리의 가는 하이라이트 — 유리 두께감 */
.glass-panel::before,
.card::before,
.tile::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  border-radius: 18px 18px 0 0;
  background: linear-gradient(90deg, transparent, var(--glass-hi), transparent);
  pointer-events: none;
}

/* ══════════════════════════════════════════════════════════════
   iOS 연락처식 목록
   ──────────────────────────────────────────────────────────────
   표를 쓰지 않는다. 폰에서 표는 열이 안 줄어들어 옆으로 스크롤되고,
   카드 안에 넣으면 이중 스크롤이 되어 손가락이 어디를 잡을지 모르게 된다.
   한 줄에 두 단(제목·부제)을 쌓고, 셀 높이를 고정해 눈이 흐르게 한다.
   ══════════════════════════════════════════════════════════════ */

.ios-list { margin: 0 0 24px; }

/* 초성 머리글 — 스크롤할 때 위에 붙는다 */
.ios-sec {
  position: sticky;
  top: calc(env(safe-area-inset-top) + 58px);
  z-index: 5;
  margin: 0;
  padding: 8px 14px 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-dim);
  background: linear-gradient(to bottom, var(--bg) 70%, transparent);
}

.ios-group {
  border-radius: 16px;
  overflow: hidden;
  margin-bottom: 8px;
}

.ios-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  /* 높이를 고정한다. 부제가 있든 없든 줄이 같은 리듬으로 흘러야 훑을 수 있다. */
  min-height: 62px;
  padding: 9px 12px 9px 16px;
  color: var(--text);
  border-bottom: 1px solid var(--sep, var(--glass-brd));
}
.ios-group > .ios-row:last-child { border-bottom: none; }
.ios-row:hover { text-decoration: none; background: var(--glass-hi); }
.ios-row:active { background: var(--glass-hi); }

/**
 * 줄 전체를 누르면 들어가고, 줄 안의 전화 버튼은 따로 눌린다.
 *
 * <a> 안에 <a> 를 넣으면 HTML 파서가 바깥 <a> 를 강제로 닫아 버려서 줄이
 * 두 동강 난다(실제로 그랬다). 그래서 줄은 <div> 로 두고, 눌리는 면적만
 * 깔개처럼 절대배치한 링크로 덮는다. 버튼은 그 위에 올린다.
 */
.rw-hit { position: absolute; inset: 0; z-index: 1; }
.rw-body { flex: 1; min-width: 0; pointer-events: none; } /* 글자를 통과해 깔개가 눌리도록 */
.rw-trail > * { position: relative; z-index: 2; }
.rw-title {
  display: block;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  /* 이름이 길어도 옆으로 밀지 않는다 — 가로 스크롤이 생기지 않게 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rw-sub {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 1px;
  font-size: 13px;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rw-sub .dot { opacity: 0.45; }
.rw-trail { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.rw-amt { font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; }

/* 셀 안의 동그란 버튼 (전화·연락처 저장) */
.rw-act {
  width: 38px; height: 38px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 17px;
  color: var(--accent);
  background: var(--accent-dim);
  border: 1px solid var(--glass-brd);
  cursor: pointer;
}
.rw-act:hover { text-decoration: none; filter: brightness(1.08); }
.rw-act:active { transform: scale(0.92); }
.rw-chev { color: var(--text-dim); opacity: 0.5; }

/* ── 상세 화면 (iOS 연락처 카드) ──────────────────── */
.det-head { text-align: center; padding: 6px 0 18px; }
.det-name {
  margin: 0;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}
.det-sub { margin: 6px 0 0; font-size: 14px; color: var(--text-dim); }

/* 이름 아래 동그란 동작 버튼 줄 */
.det-acts {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin: 20px 0 26px;
  flex-wrap: wrap;
}
.det-act {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--text-dim);
  background: none;
  border: none;
  font-family: inherit;
  cursor: pointer;
  padding: 0;
}
.det-act:hover { text-decoration: none; }
.det-act .cir {
  width: 56px; height: 56px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 22px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .det-act .cir { -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
}
.det-act:active .cir { transform: scale(0.93); }
.det-act[disabled] { opacity: 0.35; pointer-events: none; }

/* 라벨 + 값이 쌓인 줄 (휴대전화 / 010-… 처럼) */
.det-field {
  display: block;
  padding: 10px 16px;
  min-height: 58px;
  border-bottom: 1px solid var(--sep, var(--glass-brd));
  color: var(--text);
}
.ios-group > .det-field:last-child { border-bottom: none; }
.det-field .k { font-size: 12px; color: var(--text-dim); }
.det-field .v { font-size: 16px; overflow-wrap: anywhere; }
a.det-field .v { color: var(--accent); }
a.det-field:hover { text-decoration: none; background: var(--glass-hi); }

.sec-label {
  margin: 22px 6px 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
}

/* ══════════════════════════════════════════════════════════════
   헌금 입력 줄 — 리마인더에 항목 더하듯
   윗줄에 이름·금액(중요), 아랫줄에 날짜·종류·적요(덜 중요).
   적요는 맨 뒤에서 남는 폭을 가져간다.
   ══════════════════════════════════════════════════════════════ */
.ofr {
  border-radius: 16px;
  margin-bottom: 8px;
  padding: 10px 12px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .ofr { -webkit-backdrop-filter: blur(20px) saturate(180%); backdrop-filter: blur(20px) saturate(180%); }
}
.ofr.bad { border-color: var(--danger); }

.ofr-top { display: flex; gap: 8px; align-items: center; }
/* 아랫줄은 접힌다. 폰 폭에서는 [날짜][종류][✕] 가 한 줄, 적요가 그 아래 한 줄이 된다.
   날짜 입력칸은 브라우저가 만드는 것이라 일정 폭 아래로는 안 줄어든다. */
.ofr-bot { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }

/* 칸처럼 보이지 않게 — 리마인더처럼 글자만 있는 줄로 */
.ofr-in {
  width: 100%;
  padding: 7px 10px;
  font-size: 16px;
  font-family: inherit;
  color: var(--text);
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid transparent;
  border-radius: 10px;
}
@media (prefers-color-scheme: dark) {
  .ofr-in { background: rgba(255, 255, 255, 0.07); }
}
.ofr-in:focus { outline: none; border-color: var(--accent); }
.ofr-in::placeholder { color: var(--text-dim); opacity: 0.8; }

.ofr-name { position: relative; flex: 1 1 auto; min-width: 0; }
.ofr-amt {
  flex: 0 0 40%;
  max-width: 150px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.ofr-date { flex: 1 1 auto; width: auto; min-width: 0; font-size: 14px; padding: 5px 8px; }
.ofr-kind { flex: 0 1 auto; width: auto; min-width: 0; font-size: 14px; padding: 5px 8px; }
/* 적요는 셋 중 가장 덜 중요하다. 줄을 바꿔 아래에 통째로 놓는다 —
   위쪽 셋(날짜·종류·지우기)을 좁히면서까지 자리를 나눌 값이 아니다. */
.ofr-note { order: 3; flex: 1 1 100%; min-width: 0; font-size: 14px; padding: 5px 8px; }

.ofr-x {
  order: 2;
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--text-dim);
  font-size: 15px;
  cursor: pointer;
}
.ofr-x:hover { color: var(--danger); background: var(--danger-dim); }

/* 이름 자동완성 */
.ofr-menu {
  position: absolute;
  z-index: 40;
  top: calc(100% + 4px);
  left: 0; right: 0;
  max-height: 220px;
  overflow-y: auto;
  border-radius: 12px;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--glass-brd);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.18);
}
.ofr-mi { padding: 9px 12px; border-radius: 8px; font-size: 15px; cursor: pointer; }
.ofr-mi:hover, .ofr-mi.on { background: var(--accent-dim); color: var(--accent); }

/* 셀 안의 삭제 버튼도 동그란 동작 버튼과 같은 모양 */
.rw-act[type='submit'] {
  color: var(--text-dim);
  background: rgba(127, 127, 127, 0.12);
  font-size: 14px;
}
.rw-act[type='submit']:hover { color: var(--danger); background: var(--danger-dim); }

/* 필터 줄 — 위쪽 떠 있는 버튼과 겹치지 않게 위 여백을 조금 준다 */
.filter-bar { border-radius: 16px; }

/* ══════════════════════════════════════════════════════════════
   이번 주 생일 — 교인 목록 맨 위 한 줄
   요일 일곱 칸을 그리드로 나눈다. 가로 스크롤이 생기지 않게 폭을 1/7 로 고정하고
   이름이 길면 줄이 바뀌게 둔다.
   ══════════════════════════════════════════════════════════════ */
:root {
  --male: #2f6fd0;
  --male-bg: rgba(47, 111, 208, 0.14);
  --female: #d0468a;
  --female-bg: rgba(208, 70, 138, 0.14);
}
@media (prefers-color-scheme: dark) {
  :root {
    --male: #8ab8ff;
    --male-bg: rgba(120, 170, 255, 0.16);
    --female: #ff9ec8;
    --female-bg: rgba(255, 150, 195, 0.16);
  }
}

.bday-strip { margin: 0 0 18px; }
.bday-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
  margin: 0 6px 6px;
}
.bday-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  padding: 8px 6px 10px;
  border-radius: 16px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .bday-week { -webkit-backdrop-filter: blur(20px) saturate(180%); backdrop-filter: blur(20px) saturate(180%); }
}
.bday-col { min-width: 0; text-align: center; border-radius: 10px; padding: 2px; }
.bday-col.today { background: none; }
.bd-d {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: 3px;
}
.bday-col.today .bd-d { color: var(--accent); }
.bd-n {
  display: block;
  margin: 2px 0;
  padding: 3px 2px;
  border-radius: 7px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.bd-n:hover { text-decoration: none; filter: brightness(1.08); }
.bd-n.m { color: var(--male); background: var(--male-bg); }
.bd-n.f { color: var(--female); background: var(--female-bg); }
.bd-n.x { color: var(--text-dim); background: rgba(127, 127, 127, 0.14); }

/* ── 연락처 화면 ─────────────────────────────────────────────── */
.page-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}
.page-head h1 { margin: 0; }

.count-pill {
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-dim);
  border: 1px solid var(--glass-brd);
}
.count-pill.sm { font-size: 11px; padding: 2px 8px; }

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding: 10px;
  margin-bottom: 16px;
}
/* 검색은 한 줄을 다 쓰고, 고르는 것들은 그 아래 나란히. 폰에서 셋을 한 줄에
   욱여넣으면 각각이 너무 좁아져 무엇을 고르는 칸인지 알 수 없다. */
.filter-bar .grow { flex: 1 0 100%; }
.filter-bar select { flex: 1 1 0; width: auto; min-width: 0; }
.filter-bar input, .filter-bar select {
  padding: 8px 10px;
  font-size: 15px;
  background: rgba(255, 255, 255, 0.35);
  border-radius: 12px;
  border-color: transparent;
}
@media (prefers-color-scheme: dark) {
  .filter-bar input, .filter-bar select { background: rgba(255, 255, 255, 0.06); }
}

.check-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 8px 12px;
  border-radius: 999px;
  font-size: 13px;
  color: var(--text);
  background: rgba(255, 255, 255, 0.35);
  border: 1px solid var(--glass-brd);
  cursor: pointer;
  white-space: nowrap;
}
@media (prefers-color-scheme: dark) {
  .check-pill { background: rgba(255, 255, 255, 0.06); }
}
.check-pill input { width: auto; margin: 0; }
.check-pill:has(input:checked) {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.parish-block { margin-bottom: 24px; }
.parish-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  margin: 0 0 10px 4px;
  color: var(--text-dim);
}

.contact-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
}
@media (min-width: 560px) { .contact-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .contact-grid { grid-template-columns: repeat(3, 1fr); } }

.contact-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  color: var(--text);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.contact-card:hover {
  text-decoration: none;
  transform: translateY(-2px);
  box-shadow: 0 12px 36px rgba(31, 38, 135, 0.16);
}

.avatar {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 14px;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-dim);
  border: 1px solid var(--glass-brd);
}

.contact-body { flex: 1; min-width: 0; }
.contact-name {
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 6px;
}
.role-tag {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-dim);
  padding: 1px 6px;
  border-radius: 6px;
  background: rgba(127, 127, 127, 0.14);
}
.contact-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 2px;
}

.call-btn {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 15px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--glass-brd);
}
@media (prefers-color-scheme: dark) {
  .call-btn { background: rgba(255, 255, 255, 0.08); }
}
.call-btn:hover { background: var(--accent); }

/* ── 교구 칩 ─────────────────────────────────────────────────── */
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 8px 6px 12px;
  border-radius: 999px;
  font-size: 13px;
  background: rgba(255, 255, 255, 0.35);
  border: 1px solid var(--glass-brd);
}
@media (prefers-color-scheme: dark) {
  .chip { background: rgba(255, 255, 255, 0.06); }
}
.chip-x {
  border: none;
  background: none;
  color: var(--text-dim);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}
.chip-x:hover { color: var(--danger); }

.inline-form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* 버튼도 살짝 유리처럼 */
.btn.secondary {
  background: rgba(255, 255, 255, 0.45);
  border-color: var(--glass-brd);
}
@media (prefers-color-scheme: dark) {
  .btn.secondary { background: rgba(255, 255, 255, 0.07); }
}

/* 움직임을 줄이도록 설정한 사용자에게는 전환 효과를 끈다 */
@media (prefers-reduced-motion: reduce) {
  .contact-card { transition: none; }
  .contact-card:hover { transform: none; }
}

/* ── 주보 편집 ────────────────────────────────────────────── */

.bl-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 6px 0;
}

.bl-tools button {
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
  cursor: pointer;
}

.bl-tools button:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* 메모창은 내용만큼 늘어난다. 안에서 따로 스크롤되지 않고 페이지가 통째로 스크롤된다.
   높이는 bulletin-edit.js 가 입력할 때마다 다시 잡는다. */
#bl-body {
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 14px;
  line-height: 1.7;
  tab-size: 2;
  overflow: hidden;
  resize: none;
}

.bl-help {
  margin: 4px 0;
  font-size: 13px;
}

.bl-help summary {
  cursor: pointer;
  color: var(--text-dim);
}

.bl-help-t {
  margin: 8px 0;
  border-collapse: collapse;
}

.bl-help-t td {
  padding: 3px 14px 3px 0;
  vertical-align: top;
}

.bl-help-t code {
  padding: 1px 6px;
  border-radius: 5px;
  background: var(--bg);
  font-size: 12.5px;
  white-space: pre;
}

.bl-danger {
  margin-top: 28px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

/* ── 연도 선택 바 ─────────────────────────────────────────────
   연도를 가로로 늘어놓는다. 좁은 화면에서는 이 줄만 옆으로 스크롤되고
   페이지 본문은 밀리지 않는다. */
.year-bar {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  padding: 4px 2px 8px;
  margin-bottom: 12px;
}
.year-chip {
  flex: 0 0 auto;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid var(--line, #2a3441);
  background: var(--panel, #161c24);
  color: var(--text, #e6edf3);
  text-decoration: none;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.year-chip:hover { border-color: var(--accent, #5ac08f); }
.year-chip.active {
  background: var(--accent, #5ac08f);
  border-color: var(--accent, #5ac08f);
  color: #06210f;
  font-weight: 600;
}

/* ── 암구호 입력창 (askpass.js) ─────────────────────────────── */
.ap-back {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(0, 0, 0, 0.55);
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
}
.ap-box {
  background: var(--card, #1c1c1e); border: 1px solid var(--line, #333);
  border-radius: 12px; padding: 20px; width: 100%; max-width: 380px;
}
.ap-title { margin: 0 0 6px; font-size: 16px; }
.ap-desc { margin: 0 0 14px; white-space: pre-line; }
.ap-box input[type='password'] { width: 100%; }
.ap-btns { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }

/* ══════════════════════════════════════════════════════════════
   색 — 다크를 기본으로
   ──────────────────────────────────────────────────────────────
   앞의 팔레트는 어두운 회색 위에 어두운 회색을 얹어 답답했다. 유리는 뒤가
   비쳐야 유리로 보이는데, 유리도 배경도 같이 어두우면 그냥 검은 판이 된다.
   그래서 ① 유리를 훨씬 밝게 올리고 ② 배경의 색 덩어리를 진하게 깔았다.
   글자는 흰색에 가깝게, 강조는 시원한 민트로 —— 화면이 트여 보인다.

   이 블록이 파일 맨 끝에 있는 이유: 같은 우선순위면 뒤에 온 것이 이긴다.
   앞의 :root 와 @media(dark) 를 여기서 덮는다.
   ══════════════════════════════════════════════════════════════ */
:root {
  color-scheme: dark light;

  --bg: #0b1016;
  --surface: #19212b;
  --border: #2c3846;
  --text: #f3f6fa;
  --text-dim: #9fb0c2;

  --accent: #3ddc97;          /* 시원한 민트 — 씨앗의 초록을 밝게 */
  --accent-dim: rgba(61, 220, 151, 0.18);
  --danger: #ff6b6b;
  --danger-dim: rgba(255, 107, 107, 0.16);
  --warn: #ffc75f;
  --warn-dim: rgba(255, 199, 95, 0.16);

  /* 유리 — 앞의 0.55 는 어두운 배경에서 그냥 검은 판이었다. 흰빛을 올린다. */
  --glass-bg: rgba(255, 255, 255, 0.085);
  --glass-brd: rgba(255, 255, 255, 0.1);
  --glass-hi: rgba(255, 255, 255, 0.16);
  --glass-sh: 0 10px 40px rgba(0, 0, 0, 0.45);

  /* 배경 색 덩어리 — 유리가 굴절시킬 대상. 진해야 유리가 산다. */
  --mesh-1: rgba(61, 220, 151, 0.26);
  --mesh-2: rgba(80, 150, 255, 0.24);
  --mesh-3: rgba(190, 110, 255, 0.18);

  --male: #6cb3ff;
  --male-bg: rgba(108, 179, 255, 0.18);
  --female: #ff8fc0;
  --female-bg: rgba(255, 143, 192, 0.18);
}

/* 밝은 화면을 쓰는 사람에게는 밝게 */
@media (prefers-color-scheme: light) {
  :root {
    --bg: #eef2f7;
    --surface: #ffffff;
    --border: #dfe5ec;
    --text: #101720;
    --text-dim: #5d6b7a;

    --accent: #12996b;
    --accent-dim: rgba(18, 153, 107, 0.14);
    --danger: #d4453b;
    --danger-dim: rgba(212, 69, 59, 0.12);
    --warn: #9a6700;
    --warn-dim: rgba(255, 199, 95, 0.22);

    --glass-bg: rgba(255, 255, 255, 0.62);
    --glass-brd: rgba(255, 255, 255, 0.85);
    --glass-hi: rgba(255, 255, 255, 0.95);
    --glass-sh: 0 10px 34px rgba(31, 38, 135, 0.12);

    --mesh-1: rgba(18, 153, 107, 0.2);
    --mesh-2: rgba(80, 150, 255, 0.18);
    --mesh-3: rgba(190, 110, 255, 0.14);

    --male: #1f6fd0;
    --male-bg: rgba(31, 111, 208, 0.12);
    --female: #c93b83;
    --female-bg: rgba(201, 59, 131, 0.12);
  }
}

/* 배경 덩어리를 조금 더 크고 부드럽게 — 화면이 넓어 보인다 */
body {
  background-image:
    radial-gradient(70rem 46rem at 6% -12%, var(--mesh-1), transparent 62%),
    radial-gradient(58rem 42rem at 104% 4%, var(--mesh-2), transparent 64%),
    radial-gradient(52rem 40rem at 38% 112%, var(--mesh-3), transparent 62%);
}

/* 입력칸도 유리 위에 얹는다. 흰 상자가 튀면 유리가 깨져 보인다. */
input[type='text'], input[type='date'], input[type='number'], input[type='email'],
input[type='password'], input[type='search'], input[type='tel'], select, textarea {
  background: var(--glass-bg);
  border-color: var(--glass-brd);
  border-radius: 12px;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}

.btn { border-radius: 12px; }
.btn.secondary { background: var(--glass-bg); border-color: var(--glass-brd); color: var(--text); }

/* 강조 버튼의 글자는 배경과 확실히 갈라 놓는다 (민트 위 흰 글자는 흐릿하다) */
.gbtn.accent { color: #05271a; }
@media (prefers-color-scheme: light) { .gbtn.accent { color: #fff; } }

/* 셀·목록 안의 동그란 버튼 속 아이콘 크기 */
.rw-act .ic { width: 19px; height: 19px; }
.det-act .cir .ic { width: 24px; height: 24px; }
.gbtn .ic { width: 20px; height: 20px; }
nav.tabbar .gbtn .ic { width: 22px; height: 22px; }
nav.tabbar .tabpill a .ic { width: 22px; height: 22px; margin: 0 auto 1px; }

/* 토스트가 떠 있는 동안에는 본문을 그만큼 내린다. 안 그러면 목록 첫 줄이나
   교인 이름이 토스트 뒤에 가려 무엇이 가려졌는지도 모른다. */
body:has(.toast) main { padding-top: calc(env(safe-area-inset-top) + 150px); }

/* ── 알약·판의 좌우 끝을 본문과 맞춘다 ─────────────────
   본문은 max-width 900px 안에서 16px(넓은 화면 24px) 여백을 두는데, 하단 알약은
   창 끝까지 붙어 있어 넓은 화면에서 둘의 좌우 선이 어긋났다. 같은 상자에 넣는다. */
nav.tabbar,
.dock-panel {
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}
.dock-panel > .inner { max-width: none; }
@media (min-width: 640px) {
  nav.tabbar,
  .dock-panel { padding-left: 24px; padding-right: 24px; }
}

/* 하단 오른쪽 버튼 묶음 — 몇 개가 오든 한 덩이로 오른쪽 끝에 붙는다 */
.dock-side {
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: none;
}
.dock-side > * { pointer-events: auto; }

/* 연도 칩 — 예전 변수(--line/--panel)가 지금은 없어 색이 빠져 있었다 */
.year-chip {
  border-color: var(--glass-brd);
  background: var(--glass-bg);
  color: var(--text);
}
.year-chip:hover { border-color: var(--accent); text-decoration: none; }
.year-chip.active {
  background: var(--accent);
  border-color: transparent;
  color: #05271a;
  font-weight: 700;
}
@media (prefers-color-scheme: light) { .year-chip.active { color: #fff; } }

/* ── 연락처 한 줄 ──────────────────────────────────────
   이름과 연생만 둔다. 직분·교구는 훑을 때 눈에 걸리기만 하고, 정작 사람을
   가려내는 것은 이름과 나이다. 한 줄이면 화면에 두 배가 들어온다. */
.ios-row.one-line { min-height: 52px; padding-top: 6px; padding-bottom: 6px; }
.rw-year { color: var(--text-dim); font-weight: 500; font-variant-numeric: tabular-nums; }

/* 누를 수 없는 동작 버튼 — 없는 것처럼 감추면 줄 높이가 들쭉날쭉해진다 */
.rw-act.off {
  opacity: 0.28;
  pointer-events: none;
}

/* ══════════════════════════════════════════════════════════════
   화면 전환 — 진짜 이동(URL 변경)에 애니메이션만 얹는다
   ──────────────────────────────────────────────────────────────
   화면을 자바스크립트로 갈아 끼우는 방식(SPA)을 쓰지 않는다. 그러면 주소가
   실제로 바뀌지 않거나, 바뀌어도 새로고침하면 다른 화면이 나오는 문제가 따라온다.
   교차문서 View Transition 은 평범한 링크 이동 그대로라 주소·뒤로가기·새로고침이
   전부 원래대로 동작하고, 그 위에 전환만 얹힌다. 지원하지 않는 브라우저에서는
   애니메이션 없이 그냥 이동한다 — 기능은 그대로다.
   ══════════════════════════════════════════════════════════════ */
@view-transition { navigation: auto; }

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: vt-out 0.22s cubic-bezier(0.4, 0, 1, 1) both;
  }
  ::view-transition-new(root) {
    animation: vt-in 0.28s cubic-bezier(0, 0, 0.2, 1) both;
  }
  @keyframes vt-out {
    to { opacity: 0; transform: scale(0.985); }
  }
  @keyframes vt-in {
    from { opacity: 0; transform: translateY(10px) scale(0.99); }
  }

  /* ⚠️ 상·하단 바에 view-transition-name 을 주면 안 된다.
     그 속성이 스태킹 컨텍스트를 만들어 사파리에서 backdrop-filter 가 죽는다
     (주보 화면에서 알약이 유리가 아니라 그냥 반투명 판으로 보였다).
     전환 중 바가 함께 흐르는 것쯤은 유리를 잃는 것보다 낫다. */
}

/* 상단에서 내려오는 판 (국세청·수집함 같은 가끔 쓰는 메뉴) */
.dock-panel.top {
  top: calc(env(safe-area-inset-top) + 62px);
  bottom: auto;
}
.dock-panel.top .ios-row:hover { background: var(--glass-hi); }

/* ══════════════════════════════════════════════════════════════
   헌금 목록 — 셀 안에서 바로 고친다 (아이폰 달력 수정 화면의 결)
   이름·날짜·금액이 각각 눌리는 알약이다. 고치면 즉시 저장된다.
   ══════════════════════════════════════════════════════════════ */
.ofr-row {
  padding: 10px 14px;
  border-bottom: 1px solid var(--sep, var(--glass-brd));
}
.ios-group > .ofr-row:last-child { border-bottom: none; }
.ofr-row-top { display: flex; align-items: center; gap: 8px; }
.ofr-row-meta {
  display: flex;
  gap: 6px;
  margin-top: 3px;
  padding-left: 2px;
  font-size: 12.5px;
  color: var(--text-dim);
}

.pill-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: rgba(127, 127, 127, 0.16);
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.pill-btn:hover { background: rgba(127, 127, 127, 0.26); }
.pill-btn.name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; display: block; text-align: left; }
.pill-btn.date { flex: 0 0 auto; font-variant-numeric: tabular-nums; }
/* 날짜 입력칸은 알약 위에 투명하게 덮어 둔다. 눌리는 것은 기기 기본 달력이지만
   보이는 것은 알약이다 (브라우저마다 다른 못생긴 칸을 그대로 두지 않는다). */
.pill-btn.date input {
  position: absolute;
  inset: 0;
  width: 100%;
  opacity: 0;
  border: none;
  padding: 0;
  cursor: pointer;
}
.pill-btn.amount {
  flex: 0 0 auto;
  width: 116px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.pill-btn.amount:focus { outline: none; border-color: var(--accent); background: rgba(127, 127, 127, 0.26); }

@keyframes pill-saved { 0% { box-shadow: 0 0 0 0 var(--accent); } 100% { box-shadow: 0 0 0 6px transparent; } }
@keyframes pill-failed { 0%, 100% { transform: none; } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
.pill-btn.saved { animation: pill-saved 0.6s ease-out; }
.pill-btn.failed { animation: pill-failed 0.3s; border-color: var(--danger); }

/* 이름 고르는 창 — 아래에서 올라온다 */
.sheet-back {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 14px;
  background: rgba(0, 0, 0, 0.45);
}
.sheet {
  width: 100%;
  max-width: 520px;
  max-height: 74vh;
  display: flex;
  flex-direction: column;
  padding: 14px;
  border-radius: 22px;
  background: var(--surface);
  border: 1px solid var(--glass-brd);
  box-shadow: 0 -10px 44px rgba(0, 0, 0, 0.4);
  animation: sheet-in 0.24s cubic-bezier(0.2, 0.9, 0.3, 1);
}
@keyframes sheet-in { from { transform: translateY(24px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .sheet { animation: none; } }
.sheet-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.sheet-list { flex: 1; overflow-y: auto; margin-top: 8px; }

/* ── 생일 주간 — 화면 폭을 다 쓴다 ─────────────────────
   카드로 감싸면 좌우 여백이 두 겹이 되어 요일 일곱 칸이 그만큼 좁아진다.
   양옆의 < > 로 지난주·다음 주를 넘긴다. */
.bday-strip { margin: 0 -16px 18px; }
@media (min-width: 640px) { .bday-strip { margin-left: -24px; margin-right: -24px; } }
.bday-label { margin: 0 16px 6px; }

.bday-week {
  display: flex;
  align-items: stretch;
  gap: 2px;
  padding: 6px 4px 8px;
  border-radius: 0;
  border-left: none;
  border-right: none;
  border-top: 1px solid var(--glass-brd);
  border-bottom: 1px solid var(--sep, var(--glass-brd));
  box-shadow: none;
}
.bday-days {
  flex: 1;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.bday-arrow {
  flex: 0 0 auto;
  width: 30px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 10px;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
}
.bday-arrow:hover { background: var(--glass-hi); color: var(--text); }
.bday-arrow:active { transform: scale(0.9); }

/* ── 하단 알약을 안전영역에 바짝 붙인다 ────────────────
   폰에서 알약과 주소표시줄 사이가 뜨면 그 틈으로 목록이 비쳐 레이어가 하나 더
   있는 것처럼 보였다. */
nav.tabbar { bottom: calc(env(safe-area-inset-bottom) + 4px); }
.dock-panel:not(.top) { bottom: calc(env(safe-area-inset-bottom) + 68px); }
main { padding-bottom: calc(env(safe-area-inset-bottom) + 88px); }

/* ── 입력 중인 줄 — 저장된 줄과 같은 모양 ──────────────
   입력할 때와 저장한 뒤가 달라 보이면 방금 넣은 것이 반영됐는지 눈으로
   확인하기 어렵다. 그래서 한 줄 구성을 똑같이 맞춘다. */
.ofr-row.draft { border-bottom: none; }
.ofr-name { position: relative; flex: 1 1 auto; min-width: 0; }
.ofr-name .pill-btn.name { width: 100%; }

/* 아랫줄의 작은 칸들 — 종류·적요. 위 칸들과 크기를 확실히 갈라 놓아야
   「금액인가 적요인가」 하고 헷갈리지 않는다. */
.meta-in {
  padding: 3px 8px;
  font-size: 12.5px;
  font-family: inherit;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid var(--glass-brd);
  border-radius: 8px;
  width: auto;
}
.meta-in:focus { outline: none; border-color: var(--accent); color: var(--text); }
.meta-in.kind { flex: 0 0 auto; }
.meta-in.note { flex: 1 1 auto; min-width: 0; }
.ofr-row-meta { align-items: center; gap: 6px; }

.ofr-row .ofr-x {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
}
.ofr-row .ofr-x .ic { width: 14px; height: 14px; }
.ofr-row .ofr-x:hover { color: var(--danger); background: var(--danger-dim); }
.ofr-row.bad { outline: 1px solid var(--danger); outline-offset: 2px; border-radius: 12px; }

/* 금액은 「눌러서 고치는 칸」이라는 것이 보여야 한다.
   테두리와 밑줄을 함께 줘서 알약이 아니라 입력칸으로 읽히게 한다. */
.pill-btn.amount {
  border: 1px solid var(--glass-brd);
  border-bottom-color: var(--accent);
  background: rgba(127, 127, 127, 0.1);
}
.pill-btn.amount::placeholder { color: var(--text-dim); opacity: 0.7; }
.pill-btn.amount:hover { background: rgba(127, 127, 127, 0.2); }

/* ── 유리가 안 되는 곳을 위한 대비 ─────────────────────
   backdrop-filter 를 못 쓰면(구형 브라우저, 또는 스태킹 컨텍스트에 갇힌 경우)
   흐림 없이 거의 투명한 판만 남아 글자가 그대로 비쳐 읽을 수 없다.
   기본값은 **불투명에 가깝게** 두고, 흐림이 될 때만 투명하게 올린다. */
.glass-panel, .card, .tile, .ios-group, .gbtn, .toast,
nav.tabbar .tabpill, .dock-panel > .inner, .ofr, .bday-week {
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  border-color: var(--glass-brd-fb, rgba(255, 255, 255, 0.28));
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .glass-panel, .card, .tile, .ios-group, .gbtn, .toast,
  nav.tabbar .tabpill, .dock-panel > .inner, .ofr, .bday-week {
    background: var(--glass-bg);
    border-color: var(--glass-brd);
  }
}

/* ── 주보 도구줄 — 화면에 붙여 둔다 ────────────────────
   긴 주보를 쓰다 보면 도구줄이 위로 밀려 올라가, 제목 하나 넣으려고 맨 위까지
   스크롤해야 했다. */
.bl-tools {
  position: sticky;
  top: calc(env(safe-area-inset-top) + 58px);
  z-index: 10;
  padding: 8px;
  margin: 0 0 10px;
  border-radius: 14px;
  /* ⚠️ sticky 요소 자신에게 배경·블러를 칠하면 사파리가 그 색을 상태바
     뒤까지 불투명하게 늘려 본문이 잘린다 (상단 이마 규칙). 유리는 아래
     가상요소에만 얹는다. */
  border: none;
  background: none;
  isolation: isolate;
}
.bl-tools::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 14px;
  border: 1px solid var(--glass-brd);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .bl-tools::before {
    background: var(--glass-bg);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
  }
}
.bl-tools button {
  border-radius: 999px;
  border-color: transparent;
  background: none;
  color: var(--text);
  position: relative;
  isolation: isolate;
}
.bl-tools button::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 999px;
  border: 1px solid var(--glass-brd);
  background: rgba(127, 127, 127, 0.16);
}
.bl-tools button:hover { color: var(--text); border-color: transparent; background: none; }
.bl-tools button:hover::before { background: rgba(127, 127, 127, 0.3); }

/* ══════════════════════════════════════════════════════════════
   색 — 단아한 검정 · 흰 글자 · 파랑 버튼
   ──────────────────────────────────────────────────────────────
   앞서 깔았던 색 덩어리(메시 그라디언트)는 화면마다 배경색이 달라 보여
   산만했다. 아이폰 통화 기록처럼 배경은 검정 하나로 두고, 색은 **버튼에만**
   쓴다. 그래야 눌러야 할 곳이 한눈에 보인다.
   ══════════════════════════════════════════════════════════════ */
:root {
  --bg: #000000;
  --surface: #1c1c1e;          /* 아이폰의 두 번째 배경 */
  --border: #38383a;
  --text: #ffffff;
  --text-dim: #98989f;

  --accent: #0a84ff;           /* 아이폰 파랑 */
  --accent-dim: rgba(10, 132, 255, 0.18);
  --danger: #ff453a;
  --danger-dim: rgba(255, 69, 58, 0.18);
  --warn: #ffd60a;
  --warn-dim: rgba(255, 214, 10, 0.16);

  --glass-bg: rgba(255, 255, 255, 0.075);
  /* 림은 은은하게. 흐림이 안 되는 폴백에서만 진하게 올린다 — 아래 대비 블록 */
  --glass-brd: rgba(255, 255, 255, 0.1);
  --glass-brd-fb: rgba(255, 255, 255, 0.28); /* 흐림 폴백일 때만 쓰는 진한 테두리 */
  --glass-hi: rgba(255, 255, 255, 0.16);
  --sep: rgba(255, 255, 255, 0.1);
  --glass-sh: 0 8px 30px rgba(0, 0, 0, 0.6);

  --male: #0a84ff;
  --male-bg: rgba(10, 132, 255, 0.18);
  --female: #ff6fb5;
  --female-bg: rgba(255, 111, 181, 0.18);
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f2f2f7;
    --surface: #ffffff;
    --border: #d8d8dd;
    --text: #000000;
    --text-dim: #6c6c70;

    --accent: #007aff;
    --accent-dim: rgba(0, 122, 255, 0.12);
    --danger: #ff3b30;
    --danger-dim: rgba(255, 59, 48, 0.12);
    --warn: #b25000;
    --warn-dim: rgba(255, 204, 0, 0.22);

    --glass-bg: rgba(255, 255, 255, 0.72);
    --glass-brd: rgba(0, 0, 0, 0.08);
    --glass-brd-fb: rgba(0, 0, 0, 0.25);
    --glass-hi: rgba(0, 0, 0, 0.04);
    --sep: rgba(0, 0, 0, 0.08);
    --glass-sh: 0 8px 26px rgba(0, 0, 0, 0.1);

    --male: #007aff;
    --male-bg: rgba(0, 122, 255, 0.12);
    --female: #d6317f;
    --female-bg: rgba(214, 49, 127, 0.12);
  }
}

/* 배경은 검정 하나. 색 덩어리를 걷어낸다. */
body { background-image: none; }

/* 파랑 버튼 위의 글자는 흰색이다 (민트 시절에는 어두운 글자를 썼다) */
.gbtn.accent, .gbtn.danger { color: #fff; }
.year-chip.active { color: #fff; }

/* 셀 안의 동그란 동작 버튼 — 어두운 회색 원에 파란 그림 (통화 기록과 같은 결) */
.rw-act {
  color: var(--accent);
  background: rgba(255, 255, 255, 0.09);
  border-color: transparent;
}
.rw-act:hover { background: rgba(255, 255, 255, 0.16); }
.rw-act.off { color: var(--text-dim); }

/* ── 생일 달력 — 다시 카드로 ────────────────────────────
   화면 폭을 다 쓰게 했더니 목록과 좌우 선이 어긋나 두 덩이가 따로 놀았다.
   주 이동은 카드 머리글 오른쪽에 글자 버튼으로 둔다 — 색을 입히면 이 화면에서
   가장 눈에 띄는 것이 생일 이동이 되어 버린다. */
.bday-strip { margin: 0 0 18px; }
.bday-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin: 0 4px 6px;
}
.bday-nav { display: flex; gap: 10px; flex: 0 0 auto; }
.bday-step {
  border: none;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--text-dim);
  cursor: pointer;
}
.bday-step:hover { color: var(--text); text-decoration: underline; }

.bday-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  padding: 8px 6px 10px;
  border: 1px solid var(--sep, var(--glass-brd));
  border-radius: 16px;
  box-shadow: var(--glass-sh);
}

/* ── 전환은 빠르게 ──────────────────────────────────────
   0.22s + 0.28s 는 화면을 오갈 때마다 기다린다는 느낌을 줬다. 이동은 이미
   서버 왕복만큼 걸리므로, 애니메이션까지 길면 두 번 기다리는 셈이 된다.
   크기 변화도 뺀다 — 흐려졌다 나타나는 것만으로 충분하다. */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: vt-out 0.1s linear both; }
  ::view-transition-new(root) { animation: vt-in 0.14s ease-out both; }
  @keyframes vt-out { to { opacity: 0; } }
  @keyframes vt-in { from { opacity: 0; } }
}

/* ══════════════════════════════════════════════════════════════
   헌금 입력 줄 — 두 줄까지만 (아이폰 달력 편집 화면의 결)
   ──────────────────────────────────────────────────────────────
   윗줄  이름 · 금액      ← 반드시 채워야 하는 둘
   아랫줄 날짜 · 적요 · ✕  ← 기본값이 있어 그냥 둬도 되는 것들
   칸이 넷 다섯으로 늘어지면 어느 칸이 무엇인지 읽는 데만 시간이 걸린다.
   ══════════════════════════════════════════════════════════════ */
.ofr-row-top { display: flex; align-items: center; gap: 8px; }
.ofr-row-bot { display: flex; align-items: center; gap: 8px; margin-top: 8px; }

/* 모든 칸을 같은 높이·같은 모서리로 맞춘다. 크기가 제각각이면 파탄나 보인다. */
.ofr-row .pill-btn {
  height: 38px;
  border-radius: 12px;
  font-size: 15px;
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid transparent;
}
.ofr-row .pill-btn:focus,
.ofr-row .pill-btn:focus-within { outline: none; border-color: var(--accent); }
.ofr-row .pill-btn.name { flex: 1 1 auto; min-width: 0; }
.ofr-row .pill-btn.amount {
  flex: 0 0 auto;
  width: 118px;
  text-align: right;
  border-bottom-color: transparent;
}
.ofr-row .pill-btn.date { flex: 0 0 auto; }
/* 고르는 칸 — 오른쪽에 화살표 자리를 비워 둔다 */
.ofr-row .pill-btn.pick {
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
  padding-right: 30px;
  appearance: none;
  -webkit-appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 15px) 17px, calc(100% - 10px) 17px;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  color: var(--text);
}
.ofr-row .pill-btn.free { flex: 1 1 auto; min-width: 0; }

.ofr-row.draft { padding: 12px 14px; }
.ofr-row .ofr-x { width: 30px; height: 30px; }

/* ══════════════════════════════════════════════════════════════
   수평 스크롤 봉인
   ──────────────────────────────────────────────────────────────
   ⚠️ 아이폰 사파리는 글씨가 16px 미만인 칸에 커서가 들어가면 **페이지를 확대**한다.
      확대되면 화면보다 넓어져 옆으로 밀린다 — 「추가」를 눌러 이름 칸에 커서가
      가는 순간 수평 스크롤이 생긴 것이 이것이다. 눌리는 칸은 전부 16px 이상.
   ══════════════════════════════════════════════════════════════ */
input, select, textarea, .pill-btn, .ofr-row .pill-btn,
.filter-bar input, .filter-bar select,
.dock-panel input, .dock-panel select {
  font-size: 16px;
}

/* 그래도 무엇 하나가 삐져나가면 화면이 통째로 밀린다. 마지막 방벽.
   clip 은 hidden 과 달리 스크롤 컨테이너를 만들지 않아 position:fixed 를
   망가뜨리지 않는다. */
html, body { overflow-x: clip; max-width: 100%; }
main, .ios-group, .ios-row, .ofr-row, .ofr-row-top, .ofr-row-bot { min-width: 0; }

/* ── 누른 즉시 반응 ─────────────────────────────────────
   이동은 서버 왕복만큼 걸린다. 그동안 화면이 그대로면 「안 눌렸나」 싶어
   한 번 더 누르게 된다. 누르는 순간 본문을 흐리게 해서 받았다는 것을 알린다.
   떠 있는 바는 그대로 둔다 — 아이폰에서도 탭바는 화면이 바뀌어도 가만히 있다. */
/* (화면 전체 딤은 걷어냈다 — 아래 「누른 줄만 밝히기」 참고) */

/* 이름 고르는 창의 삭제 버튼 — 손가락이 닿을 만큼 */
.sheet .gbtn.danger { height: 50px; font-size: 16px; }

/* 주보 메모창 — 아이폰이 확대하지 않게 16px 이상 */
#bl-body { font-size: 16px; }

/* ══════════════════════════════════════════════════════════════
   눌러서 나오는 메뉴 — 아이폰의 길게 누르기 메뉴 결
   화면 폭을 다 쓰지 않고, 아이콘에 동그란 테두리를 두르지 않으며, 화살표도 없다.
   ══════════════════════════════════════════════════════════════ */
.dock-panel.menu { justify-content: flex-start; }
.dock-panel.menu > .inner {
  width: auto;
  max-width: 300px;
  min-width: 250px;
  flex-direction: column;
  gap: 0;
  padding: 4px;
  border-radius: 16px;
}
.menu-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  border-radius: 12px;
  color: var(--text);
}
.menu-row + .menu-row { border-top: 1px solid var(--glass-brd); }
.menu-row:hover { text-decoration: none; background: var(--glass-hi); }
.menu-row:active { background: var(--glass-hi); }
.menu-txt { flex: 1; min-width: 0; }
.menu-title { display: block; font-size: 15px; font-weight: 600; }
.menu-sub { display: block; font-size: 12.5px; color: var(--text-dim); }
/* 테두리 없는 맨 아이콘 */
.menu-ico { width: 22px; height: 22px; flex: 0 0 auto; color: var(--text); }

/* 달력 주 이동 — 화살표 둘뿐 */
.bday-nav { align-items: center; gap: 4px; }
.bday-step {
  width: 28px; height: 28px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 8px;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
}
.bday-step:hover { background: var(--glass-hi); color: var(--text); text-decoration: none; }

/* 생일자가 없는 주에도 높이가 유지되게. 주를 넘길 때마다 카드가 커졌다 작아졌다
   하면 아래 목록이 위아래로 출렁인다. 이름이 여럿이면 그만큼 길어지는 것은 괜찮다. */
.bday-col { min-height: 50px; }

/* ── 누르는 즉시 눌린 티 ────────────────────────────────
   아이폰은 touch 리스너가 없는 요소에는 :active 를 적용하지 않는다.
   -webkit-tap-highlight-color 로 회색 사각형이 번쩍이는 것도 막는다. */
a, button, .ios-row, .menu-row, .tabpill a, .gbtn {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation; /* 두 번 눌러 확대하는 동작을 끊어 탭 판정이 빨라진다 */
}

/* 화면을 통째로 흐리게 하지 않는다 — 누른 그 줄만 밝힌다 (네이티브 앱과 같은 결).
   화면 전체가 흐려지면 「뭔가 잘못됐나」로 읽히고, 넘어갈 때 한 번 더 깜빡인다. */
.ios-row.pressed, .menu-row.pressed, .det-field.pressed { background: var(--glass-hi); }
.tabpill a.pressed, .gbtn.pressed { filter: brightness(1.35); }
.ios-row, .menu-row, .det-field, .tabpill a, .gbtn { transition: background-color 0.06s, filter 0.06s; }

/* ══════════════════════════════════════════════════════════════
   잠금 덮개 — 열기 전에는 지나가지 못한다
   알림만 띄우던 시절에는 잠긴 채로도 화면이 눌려서, 이름이 「잠김」인 상태로
   헌금을 넣거나 교인을 고칠 수 있었다. 엉뚱한 사람에게 붙기 쉽다.
   ══════════════════════════════════════════════════════════════ */
/* 덮개가 떠 있는 동안에는 문서 배경까지 어둡게. 사파리가 띠를 칠할 때
   theme-color 대신 문서 배경을 볼 때도 있고, 고무줄 스크롤로 끝이 드러날
   때도 밝은 색이 비치면 안 된다. theme-color 는 decrypt-view.js 가 함께 바꾼다. */
body:has(#lock-veil) { background: #0e1116; }

.lock-veil {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.72);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .lock-veil { -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); }
}
.lock-box {
  width: 100%;
  max-width: 320px;
  text-align: center;
  padding: 26px 22px;
  border-radius: 22px;
  background: var(--surface);
  border: 1px solid var(--glass-brd);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.lock-box .lock-ic { width: 34px; height: 34px; margin: 0 auto 12px; color: var(--accent); }
.lock-box strong { display: block; font-size: 17px; margin-bottom: 6px; }
.lock-box p { margin: 0 0 18px; }
.lock-box .gbtn { width: 100%; }

/* 아이콘이 버튼 안에서 세로로 어긋나던 것 — svg 는 인라인 요소라 글꼴의
   기준선(baseline)에 맞춰 앉는다. 블록으로 두고 가운데 정렬한다. */
.gbtn .ic, .rw-act .ic, .det-act .cir .ic, .menu-ico, .toast-x .ic, .ofr-x .ic {
  display: block;
  margin: 0;
}
.gbtn, .rw-act, .ofr-x, .toast-x { line-height: 0; }
.gbtn.wide { line-height: 1; }

/* ── 아래 안전영역까지 같은 검정 ──────────────────────
   본문이 짧으면 body 가 화면보다 짧아지고, 그 아래(홈 인디케이터가 있는
   안전영역)는 html 의 배경이 드러나 색이 한 겹 달라 보였다. 둘을 맞춘다. */
html {
  background: var(--bg);
  /* ⚠️ overscroll-behavior-y: none 을 두면 iOS 의 고무줄(바운스백) 스크롤이
     통째로 죽는다. 당길 때 드러나는 영역은 html 배경색이 같아서 문제없다. */
}
body { min-height: 100dvh; }

/* ⚠️ nav.tabbar 안에는 탭 알약 말고 dock 버튼도 있다. 예전에는 `nav.tabbar a`
   로 잡아서, <a> 로 만든 dock 버튼(주보의 미리보기)만 탭 여백과 display:block 을
   뒤집어써 아이콘이 위로 쏠렸다. <button> 인 저장은 멀쩡해서 더 헷갈렸다.
   선택자를 알약 안으로 좁혔고, dock 버튼은 어떤 태그든 같게 못을 박는다. */
nav.tabbar .dock-side .gbtn,
nav.tabbar .dock-side a.gbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  min-width: 52px;
  height: 52px;
  line-height: 0;
}
nav.tabbar .dock-side .gbtn.wide { padding: 0 18px; line-height: 1; }
nav.tabbar .dock-side .gbtn .ic { margin: 0; width: 22px; height: 22px; }

/* ── 상·하단 바를 본문 폭에 맞춘다 ─────────────────────
   본문은 max-width 900px 안에서 좌우 여백을 두는데, 상단 바만 창 끝까지
   퍼져 있었다. 넓은 화면에서 「+」와 설정이 목록보다 바깥에 떠 있었다. */
.topbar {
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
  /* 알약이 본문(16px)보다 조금 안쪽에 서게 — 사파리 유리 알약의 좌우 한계와
     맞춘다. 콘텐츠는 넓게, 떠 있는 것들은 그보다 좁게. */
  padding-left: 20px;
  padding-right: 20px;
}
nav.tabbar { padding-left: 20px; padding-right: 20px; }

@media (min-width: 640px) {
  .topbar { padding-left: 24px; padding-right: 24px; }
  nav.tabbar { padding-left: 24px; padding-right: 24px; }
  /* 데스크톱은 화면이 넓다. 알약이 창 밑바닥에 붙어 있으면 답답하다. */
  nav.tabbar { bottom: 24px; }
  .dock-panel:not(.top) { bottom: 92px; }
  main { padding-bottom: 116px; }
}

/* ── 헌금 줄 — 넓은 화면에서 칸이 늘어지지 않게 ────────
   폰에서는 이름 칸이 남는 폭을 다 쓰는 게 맞지만, 데스크톱에서는 900px 를
   혼자 차지해 「이름 하나에 화면 절반」이 된다. 사람 이름은 길어야 대여섯 자다.
   칸에 상한을 두고 남는 자리는 비워 둔다. */
@media (min-width: 640px) {
  .ofr-row-top, .ofr-row-bot { max-width: 560px; }
  /* 상한은 입력칸이 아니라 **그것을 감싼 상자**에도 걸어야 한다.
     상자만 늘어나면 칸은 260px 인데 그 오른쪽에 빈 공간이 생겨 금액이 멀리 밀린다. */
  .ofr-row .ofr-name { flex: 0 1 260px; max-width: 260px; }
  .ofr-row .pill-btn.name { max-width: 260px; }
  .ofr-row .pill-btn.pick { max-width: 200px; flex: 0 1 200px; }
  /* 아랫줄 오른쪽에 빈 자리를 만들어 ✕ 가 칸 바로 옆에 붙게 한다 */
  .ofr-row-bot { justify-content: flex-start; }
  .ofr-row .ofr-x { margin-left: 0; }
}

/* 이름 칸을 감싼 상자에도 상한을 건다.
   상자만 늘어나면 칸은 260px 인데 그 오른쪽에 빈 공간이 생겨, 금액이 화면
   오른쪽 끝까지 밀려난다 (실측: 상자 434px, 칸 260px, 사이 174px 이 빈 채로). */
@media (min-width: 640px) {
  .ofr-row-top .ofr-name {
    flex: 0 1 260px !important;
    max-width: 260px;
  }
}

/* ══════════════════════════════════════════════════════════════
   넓은 화면에서는 헌금 한 건이 한 줄
   ──────────────────────────────────────────────────────────────
   폰에서는 칸이 다섯이라 두 줄로 접어야 하지만, 데스크톱에서는 가로가 남는데도
   두 줄을 쓰면서 폭의 절반만 채우고 있었다. display:contents 로 안쪽 묶음을
   풀어 한 줄에 늘어놓고, order 로 이름·날짜·종류·금액 순서를 잡는다.
   (자바스크립트는 그대로 두고 CSS 만으로 편다)
   ══════════════════════════════════════════════════════════════ */
@media (min-width: 640px) {
  .ofr-row {
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .ofr-row-top,
  .ofr-row-bot { display: contents; }

  /* 앞서 걸어 둔 상한을 푼다 — 한 줄이면 이름이 남는 폭을 써도 된다 */
  .ofr-row-top, .ofr-row-bot { max-width: none; }
  .ofr-row-top .ofr-name,
  .ofr-row .ofr-name { flex: 1 1 auto !important; max-width: none; }
  .ofr-row .pill-btn.name { max-width: none; }

  .ofr-row .pill-btn.name  { order: 1; }
  .ofr-row .ofr-name       { order: 1; }
  .ofr-row .pill-btn.date  { order: 2; }
  .ofr-row .pill-btn.pick  { order: 3; flex: 0 0 150px; max-width: 150px; }
  .ofr-row .ofr-row-meta   { order: 3; margin-top: 0; flex: 0 0 auto; white-space: nowrap; }
  .ofr-row .pill-btn.amount{ order: 4; margin-left: auto; }
  .ofr-row .ofr-x          { order: 5; }
}

/* ══════════════════════════════════════════════════════════════
   통화 앱처럼 — 교인 목록은 카드가 아니다
   ──────────────────────────────────────────────────────────────
   카드(둥근 모서리·좌우 테두리·유리판)는 설정류 화면의 문법이고,
   연락처·통화 기록 같은 **목록**은 검정 바탕에 구분선만 흐른다.
   가장자리까지 셀이 이어져야 아이폰 기본 앱과 같은 결이 난다.
   ══════════════════════════════════════════════════════════════ */
#m-list .ios-group {
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
#m-list .ios-group { margin-left: -16px; margin-right: -16px; }
#m-list .ios-row {
  padding-left: 20px;
  padding-right: 20px;
  border-bottom: none;
}
#m-list .ios-row::after {
  content: '';
  position: absolute;
  left: 20px;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--sep, var(--glass-brd));
}
@media (min-width: 640px) {
  #m-list .ios-group { margin-left: -24px; margin-right: -24px; }
  #m-list .ios-row { padding-left: 28px; padding-right: 28px; }
  #m-list .ios-row::after { left: 28px; }
}

/* ══════════════════════════════════════════════════════════════
   유리 테두리 — 애플 유리는 림(테두리 빛)이 있어 잘 보인다
   ──────────────────────────────────────────────────────────────
   단순 반투명은 어두운 배경에서 묻힌다. 위쪽에 빛이 닿은 듯한
   안쪽 하이라이트 한 줄 + 조금 밝은 테두리가 유리를 유리로 보이게 한다.
   ══════════════════════════════════════════════════════════════ */
/* 사파리에 진짜 리퀴드 글래스 CSS(-apple-visual-effect)가 있지만 아직
   웹에는 잠겨 있다. 열리는 날 자동으로 진짜 유리가 되도록 걸어만 둔다. */
@supports (-apple-visual-effect: -apple-system-glass-material) {
  .gbtn,
  nav.tabbar .tabpill,
  .dock-panel > .inner {
    -apple-visual-effect: -apple-system-glass-material;
  }
}

/* ══════════════════════════════════════════════════════════════
   iOS 26 사파리 이마 회피 — 위쪽 유리는 전부 가상요소에 칠한다
   ──────────────────────────────────────────────────────────────
   사파리 26은 화면 위·아래 가장자리의 고정 요소에서 **요소 자신의**
   background-color 와 backdrop-filter 를 표본해 상태바 뒤를 그 색으로
   칠한다. 절대배치 자식·가상요소는 표본하지 않는다 (WebKit #302272).
   그래서 상단 버튼·제목 알약 자신은 투명하게 두고, 유리(배경·흐림·테두리)는
   absolute ::before 에만 얹는다 — 화면은 같아 보이지만 이마는 안 칠해진다.
   ══════════════════════════════════════════════════════════════ */
.topbar .gbtn {
  position: relative;
  isolation: isolate;
  background: none;
  border-color: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
}
.topbar .gbtn::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 999px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .topbar .gbtn::before {
    -webkit-backdrop-filter: blur(24px) saturate(180%);
    backdrop-filter: blur(24px) saturate(180%);
  }
}
/* 파랑(저장)·빨강 버튼도 칠은 가상요소에 */
.topbar .gbtn.accent { color: #fff; }
.topbar .gbtn.danger { color: #fff; }
.topbar .gbtn.accent::before { background: var(--accent); border-color: transparent; }
.topbar .gbtn.danger::before { background: var(--danger); border-color: transparent; }

/* 하단도 같은 처방 — 알약·버튼 자신은 투명, 유리는 절대배치 가상요소에.
   (시뮬레이터 iOS 26.4 는 하단을 안 칠하지만, 그 전 버전 기기에서는
   주소표시줄 위가 검게 잘린다 — 표본 규칙은 위아래가 같다.) */
nav.tabbar .tabpill,
nav.tabbar .dock-side .gbtn,
.dock-panel > .inner {
  position: relative;
  isolation: isolate;
  background: none;
  border-color: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
}
nav.tabbar .tabpill::before,
nav.tabbar .dock-side .gbtn::before,
.dock-panel > .inner::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 999px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
}
.dock-panel > .inner::before { border-radius: 22px; }
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  nav.tabbar .tabpill::before,
  nav.tabbar .dock-side .gbtn::before,
  .dock-panel > .inner::before {
    -webkit-backdrop-filter: blur(24px) saturate(180%);
    backdrop-filter: blur(24px) saturate(180%);
  }
}
nav.tabbar .dock-side .gbtn.accent { color: #fff; }
nav.tabbar .dock-side .gbtn.accent::before { background: var(--accent); border-color: transparent; }

/* 제목이 빈 화면(교인 상세처럼 본문에 큰 이름이 있는 곳)에서는
   빈 유리 알약만 덩그러니 뜬다 — 비어 있으면 그리지 않는다 */
.tb-title span:empty { display: none; }

/* ── 검색 중에는 알약이 비켜 준다 ──────────────────────
   키보드가 올라온 좁은 화면에서 탭 알약까지 떠 있으면 어수선하다. */
body:has(.dock-panel input:focus) nav.tabbar {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s;
}

/* 하단 유리의 검은 그림자 제거 — 검정 배경에서는 유리 밑에 어두운 덩어리가
   한 겹 더 있는 것처럼 보인다 (주소표시줄 부근의 「그림자 배경」). */
nav.tabbar .tabpill::before,
nav.tabbar .dock-side .gbtn::before,
.dock-panel > .inner::before {
  box-shadow: none;
}

/* 검색 판: 입력 + 닫기(X) 한 줄 — 사파리 검색창과 같은 모양 */
.dock-panel .inner.oneline { flex-wrap: nowrap; align-items: center; }
.dock-panel .inner.oneline input { flex: 1; min-width: 0; }
.dock-panel .inner.oneline .gbtn { flex: 0 0 auto; }


/* 흐림(backdrop-filter)이 안 되는 브라우저 — 가상요소 유리의 폴백.
   반투명만 남으면 형태가 사라지므로 배경은 불투명에 가깝게, 테두리는 얇게 진하게. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar .gbtn::before,
  nav.tabbar .tabpill::before,
  nav.tabbar .dock-side .gbtn::before,
  .dock-panel > .inner::before {
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    border-color: var(--glass-brd-fb);
  }
}


/* ══════════════════════════════════════════════════════════════
   교인 검색 — 아이폰 메시지 앱 검색과 같은 모양
   ──────────────────────────────────────────────────────────────
   바깥 상자 없이 「돋보기 든 알약 입력」과 「X 원」 둘만 떠 있다.
   입력 자체가 유리 알약이므로 칸 테두리·포커스 링은 두지 않는다.
   ══════════════════════════════════════════════════════════════ */
#m-searchpanel .inner {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  gap: 10px;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
#m-searchpanel .inner::before { display: none; }
#m-searchpanel input {
  height: 50px;
  border: none;
  border-radius: 999px;
  padding: 0 18px 0 46px;
  font-size: 17px;
  background-color: var(--glass-bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='10.8' cy='10.8' r='6.2' fill='none' stroke='rgba(255,255,255,0.55)' stroke-width='1.8'/%3E%3Cpath d='M15.4 15.4 20 20' stroke='rgba(255,255,255,0.55)' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 15px center;
  background-size: 21px;
}
#m-searchpanel input:focus {
  outline: none;
  border: none;
  box-shadow: none;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  #m-searchpanel input {
    -webkit-backdrop-filter: blur(24px) saturate(180%);
    backdrop-filter: blur(24px) saturate(180%);
  }
}
@media (prefers-color-scheme: light) {
  #m-searchpanel input {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='10.8' cy='10.8' r='6.2' fill='none' stroke='rgba(0,0,0,0.45)' stroke-width='1.8'/%3E%3Cpath d='M15.4 15.4 20 20' stroke='rgba(0,0,0,0.45)' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  }
}
#m-searchpanel .gbtn { width: 50px; height: 50px; }

/* 키보드가 올라오면(=입력 포커스) 알약이 숨으므로 그 자리까지 내려가
   키보드에 바짝 붙는다. iOS 26 사파리는 고정 요소가 키보드 위를 따라온다. */
.dock-panel { transition: bottom 0.15s ease-out; }
body:has(.dock-panel input:focus) .dock-panel {
  bottom: calc(env(safe-area-inset-bottom) + 8px);
}


/* 검색 버튼과 검색창은 둘 중 하나만 — 판이 열려 있으면 버튼은 숨는다 */
body:has(#m-searchpanel:not([hidden])) #m-searchbtn { display: none; }

/* 현재 탭 표시가 유리 위에서 너무 연했다 — 채움을 또렷하게 */
nav.tabbar .tabpill a.active {
  background: color-mix(in srgb, var(--text) 16%, transparent);
}


/* ══════════════════════════════════════════════════════════════
   상단 — 「바」가 아니라 떠 있는 버튼 셋
   ──────────────────────────────────────────────────────────────
   ⚠️ iOS 26 사파리는 화면 위 끝의 **고정 요소가 바 모양이면** 배경이 없어도
   그 아래로 본문을 밀어낸다 (다이나믹 아일랜드 옆이 검게 잘리던 원인).
   시뮬레이터 실측으로 찾은 유일한 회피법: 컨테이너를 **높이 0** 으로 두고
   자식을 절대배치한다. 그러면 바로 판정되지 않아 본문이 맨 위 픽셀까지 흐른다.
   ══════════════════════════════════════════════════════════════ */
.topbar {
  height: 0;
  padding: 0;
  overflow: visible;
  display: block;
  max-width: none;
}
.tb-side,
.tb-title {
  position: absolute;
  top: calc(env(safe-area-inset-top) + 10px);
}
/* 본문(max-width 900px)의 좌우 가장자리에 맞춘다 */
.tb-side:not(.right) { left: max(20px, calc(50vw - 430px)); }
.tb-side.right { right: max(20px, calc(50vw - 430px)); }
/* 제목은 **화면 전체 폭 기준** 가운데. 양옆 버튼과 겹치지 않게 여백을 둔다. */
.tb-title {
  left: 0;
  right: 0;
  padding: 0 84px;
  justify-content: center;
  align-items: center;
  height: 52px;
}

/* 오른쪽에 버튼이 둘 이상이면 **하나의 연결된 알약**으로 (아이폰 기본 앱과 같은 결).
   낱개 유리 동그라미 둘이 나란히 있으면 사이의 틈이 어수선하다. */
.tb-side.right {
  gap: 0;
  position: absolute;
  isolation: isolate;
  border-radius: 999px;
}
.tb-side.right::before {
  display: none;
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 999px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  box-shadow: var(--glass-sh);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .tb-side.right::before {
    -webkit-backdrop-filter: blur(24px) saturate(180%);
    backdrop-filter: blur(24px) saturate(180%);
  }
}
/* 동작 버튼이 있을 때만 연결 알약. 설정(⚙) 하나뿐이면 낱개 동그라미다 */
.tb-side.right:has(.tb-actions .gbtn)::before { display: block; }
.tb-side.right:has(.tb-actions .gbtn) .gbtn { background: none; border-color: transparent; box-shadow: none; }
.tb-side.right:has(.tb-actions .gbtn) .gbtn::before { display: none; }
.tb-side.right .tb-actions:empty { display: none; }

/* ⚠️ 하단도 상단과 같은 문제 — 화면 아래 끝에 붙은 고정 요소가 있으면
   사파리가 주소표시줄 위를 검게 칠해 본문이 잘린다. 실측 해법: 고정 앵커를
   90px 위에 두고(판정 구역 밖), 알약은 절대배치 자식으로 아래로 늘어뜨린다.
   절대배치 자식은 표본하지 않으므로 본문이 맨 아래 픽셀까지 흐른다. */
nav.tabbar {
  height: 0;
  padding: 0;
  display: block;
  overflow: visible;
  bottom: calc(env(safe-area-inset-bottom) + 90px);
}
nav.tabbar .tabpill { position: absolute; left: 20px; top: 24px; }
nav.tabbar .dock-side { position: absolute; right: 20px; top: 24px; }
.dock-panel:not(.top) { bottom: calc(env(safe-area-inset-bottom) + 64px); }
@media (min-width: 640px) {
  nav.tabbar { bottom: 24px; }
  .dock-panel:not(.top) { bottom: 92px; }
}


/* ══════════════════════════════════════════════════════════════
   카드 없는 룩 — 화면 전체가 한 장
   ──────────────────────────────────────────────────────────────
   카드(유리판·테두리·둥근 모서리)로 감싸면 좁은 화면이 답답하다.
   목록·설정·상세 전부 검정 바탕에 구분선만 흐른다.
   ══════════════════════════════════════════════════════════════ */
.ios-group {
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* 주보 글 칸 — 테두리 없이, 보기에 전체 너비인 것처럼 */
#bl-body {
  background: none;
  border: none;
  border-radius: 0;
  padding-left: 0;
  padding-right: 0;
}
#bl-body:focus { outline: none; box-shadow: none; border: none; }

/* 키보드가 올라와 있는 동안(폰) 하단 알약은 어떤 스크롤에도 나오지 않는다 */
@media (pointer: coarse) {
  body:has(input:focus, textarea:focus, select:focus) nav.tabbar {
    opacity: 0;
    pointer-events: none;
  }
}

/* 주보 편집 중(글 칸 포커스) — 도구줄을 화면에 고정한다.
   sticky 는 키보드가 올라오면 레이아웃 뷰포트 위로 밀려 사라진다.
   iOS 26 사파리의 fixed 는 비주얼 뷰포트를 따라오므로 fixed 로 바꾼다. */
body:has(#bl-body:focus) .bl-tools {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 8px);
  left: 16px;
  right: 16px;
  z-index: 40;
}
/* 주보를 스크롤하면 제목은 비켜 준다 — (목차바)(설정)만 남는다 */
body.bl-scrolled .tb-title,
body:has(#bl-body:focus) .tb-title { opacity: 0; transition: opacity 0.15s; }

/* 값이 서버에 저장되면 그 자리 밑에 잠깐 확인 표시 */
.saved-note {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: #30d158;
  animation: saved-note 3s forwards;
}
@keyframes saved-note {
  0% { opacity: 0; transform: translateY(-2px); }
  8%, 80% { opacity: 1; transform: none; }
  100% { opacity: 0; }
}

/* ══════════════════════════════════════════════════════════════
   설정류 화면(하단 알약이 없는 화면)만 — 아이폰 설정 앱의 카드
   ──────────────────────────────────────────────────────────────
   목록·상세는 카드 없이 흐르지만, 설정 메뉴는 애플 설정처럼
   불투명한 둥근 카드에 담는다. 구분선은 글자 시작선부터.
   ══════════════════════════════════════════════════════════════ */
body:not(.solo):has(nav.tabbar.off) .ios-group, body:not(.solo):not(:has(nav.tabbar)) .ios-group {
  background: var(--surface);
  border-radius: 24px;
  overflow: hidden;
  margin-bottom: 20px;
}
body:not(.solo):has(nav.tabbar.off) .ios-row, body:not(.solo):not(:has(nav.tabbar)) .ios-row { border-bottom: none; }
body:not(.solo):has(nav.tabbar.off) .ios-row::after, body:not(.solo):not(:has(nav.tabbar)) .ios-row::after {
  content: '';
  position: absolute;
  left: 62px;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--sep);
}
body:not(.solo):has(nav.tabbar.off) .ios-row:last-child::after, body:not(.solo):not(:has(nav.tabbar)) .ios-row:last-child::after { display: none; }
/* 아이콘은 애플처럼 모서리 둥근 타일로 */
body:not(.solo):has(nav.tabbar.off) .ios-row .rw-act, body:not(.solo):not(:has(nav.tabbar)) .ios-row .rw-act {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  flex: 0 0 32px;
}
body:not(.solo):has(nav.tabbar.off) .rw-chev, body:not(.solo):not(:has(nav.tabbar)) .rw-chev { opacity: 0.5; }


/* 탭 밖 화면(설정·국세청 등)에서는 하단 알약을 숨긴다 — 요소는 항상 있다 */
nav.tabbar.off { display: none; }
/* 설정류 카드 판별도 같은 기준으로 */

/* 덮개 속 「마스터 비밀번호로 열기」 — 기기를 잃었을 때의 두 번째 길 */
.lock-secret { margin-top: 14px; text-align: left; }
.lock-secret summary { cursor: pointer; text-align: center; padding: 6px 0; }
.lock-secret input { margin-top: 10px; }
.lock-secret .gbtn { margin-top: 8px; }
