:root{
  --enamel:#E8EDEF; --panel:#FFF; --ink:#26333A; --ink-soft:#6B7C85;
  --line:#D3DDE1; --chrome:#B9C6CC; --cold:#3F7A8B;
  --pig:#F3A6BA; --pig-deep:#DE7093; --pig-line:#B84E6E;
  --danger:#C4442E;
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
body{
  font-family:Pretendard,-apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo","Malgun Gothic",sans-serif;
  background:var(--enamel);color:var(--ink);font-size:15px;line-height:1.5;
  display:flex;justify-content:center;
}
.phone{width:100%;max-width:430px;min-height:100vh;display:flex;flex-direction:column;position:relative}
.top{padding:18px 20px 10px;display:flex;align-items:baseline;justify-content:space-between}
.month{font-size:20px;font-weight:800;letter-spacing:-.02em}
.who{font-size:13px;color:var(--ink-soft);background:none;border:none;
  font-family:inherit;cursor:pointer;padding:0}
.bell{background:none;border:none;font-size:17px;cursor:pointer;position:relative;font-family:inherit}
.bell .dot{position:absolute;top:-1px;right:-4px;background:var(--danger);color:#fff;
  font-size:10px;font-weight:700;border-radius:999px;padding:0 5px}

.pigstage{padding:4px 20px 0;text-align:center;position:relative}
/* 아이폰에서 기울기를 켜 뒀는데 이번 실행에서 아직 허락을 못 받았을 때만 뜬다(아이폰은
   허락을 기억하지 않는다). 누를 때만 묻는다. 돼지를 가리지 않게 오른쪽 위 구석에 */
.tiltask{position:absolute;top:4px;right:16px;z-index:2;border:1px solid var(--line);
  background:var(--panel);color:var(--ink-soft);font:inherit;font-size:12px;font-weight:700;
  padding:6px 10px;border-radius:999px;cursor:pointer}
/* viewBox 가 232x260 (세로로 길다). 폭이 아니라 **높이**를 맞춰야 화면이 안 밀린다
   — 200px 로 두면 높이가 224 로, 그 전 돼지(210x220) 와 거의 같다 */
.pigstage svg{width:100%;max-width:200px;height:auto;margin:0 auto;display:block}
.left-amount{font-size:32px;font-weight:800;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.left-amount.over{color:var(--danger)}
.left-label{font-size:13px;color:var(--ink-soft);margin-top:1px}
.pace{font-size:13px;font-weight:600;color:var(--cold);margin-top:6px}
.pace.over{color:var(--danger)}
.pigname{font-size:15px;font-weight:800;margin-top:2px}
.pigtabs{font-size:12px;color:var(--ink-soft);margin-top:2px}
.pigdots{display:flex;gap:7px;justify-content:center;padding:12px 0 2px}
.pigdot{width:8px;height:8px;border-radius:50%;border:none;padding:0;cursor:pointer;
  background:var(--chrome);transition:background .15s,transform .15s}
.pigdot.on{background:var(--ink);transform:scale(1.25)}
.pigdot.add{background:none;border:1.5px dashed var(--chrome)}
.pigdot.add.on{border-color:var(--ink);background:none}
/* 맨 끝의 예산 추가 칸. **돼지 자리와 크기가 같아야 한다** — 다르면 끝까지 넘길 때 화살표와
   아래 점이 튄다. 돼지를 232x260(높이 224)으로 다시 그렸을 때 이 칸만 예전 돼지 높이(150)로
   남아 있어서 실제로 그랬다. 그래서 높이를 박지 않고 돼지 viewBox 와 같은 비율 · .pigstage svg
   와 같은 최대 폭으로 둔다(check-pwa 가 대조한다). 가운데 정렬은 auto 여백이 맡는다 — 화살표가
   돼지 화면처럼 양 끝에 붙는다 */
.addpig{flex:1;min-width:0;max-width:200px;aspect-ratio:232/260;margin:0 auto;
  border:2px dashed var(--line);border-radius:20px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:4px;background:none;font-family:inherit;cursor:pointer}
.addpig:hover{border-color:var(--pig-deep)}
.addpig-plus{display:block;font-size:34px;color:var(--chrome);line-height:1}
.addpig-label{display:block;font-size:14px;font-weight:700;color:var(--ink-soft)}
.pigrow{display:flex;align-items:center;gap:2px}
.pignav{flex:0 0 auto;width:38px;height:64px;border:none;background:none;cursor:pointer;
  font-size:30px;line-height:1;color:var(--chrome);font-family:inherit;padding:0;
  border-radius:10px;transition:color .15s,background .15s}
.pignav:hover:not(:disabled){color:var(--ink);background:rgba(38,51,58,.05)}
.pignav:disabled{opacity:.25;cursor:default}
.pigtap{flex:1;min-width:0;background:none;border:none;padding:0;cursor:pointer;display:block}
.pigactions{display:flex;flex-wrap:wrap;gap:0 18px;justify-content:center}
.statsum{text-align:center;padding:2px 0 16px;border-bottom:1px solid var(--line);margin-bottom:16px}
.bar{margin-bottom:11px}
.bar-head{display:flex;justify-content:space-between;font-size:13px;margin-bottom:5px}
.bar-head span:last-child{color:var(--ink-soft);font-variant-numeric:tabular-nums}
.bar-track{height:9px;background:var(--enamel);border-radius:999px;overflow:hidden}
.bar-fill{height:100%;background:var(--pig-deep);border-radius:999px}
.bar-fill.muted{background:var(--chrome)}
.rank{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid var(--line)}
.rank:last-child{border-bottom:none}
.rank-no{width:18px;font-size:12px;font-weight:800;color:var(--chrome)}
.rank-name{flex:1;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank-amt{font-size:13px;color:var(--ink-soft);font-variant-numeric:tabular-nums;white-space:nowrap}
.budget-set{margin-top:10px;font-size:14px;color:var(--cold);background:none;border:none;
  font-family:inherit;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
/* 고정지출(2026-10-23) — 한 줄(날 · 이름 · 금액 · 나갔나). 관리 시트에선 단추(누르면 고치기), 통계에선 그냥 줄. 예산 밖이라
   통계의 탭별 막대(.bar)와 다른 결로 */
.fixlist{display:flex;flex-direction:column}
.fixrow{display:flex;align-items:center;gap:10px;width:100%;padding:10px 0;border:none;border-bottom:1px solid var(--line);
  background:none;font-family:inherit;font-size:14px;color:var(--ink);text-align:left}
.fixrow:last-child{border-bottom:none}
button.fixrow{cursor:pointer;touch-action:manipulation}
.fixday{width:32px;flex:none;font-size:12px;font-weight:800;color:var(--chrome);font-variant-numeric:tabular-nums}
.fixname{flex:1;min-width:0;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fixamt{font-size:13px;color:var(--ink-soft);font-variant-numeric:tabular-nums;white-space:nowrap}
.fixtag{flex:none;font-size:11px;font-weight:700;padding:2px 7px;border-radius:999px;background:var(--enamel);
  color:var(--ink-soft);white-space:nowrap}
.fixtag.soon{background:none;border:1px solid var(--line);color:var(--cold)}
.fixtag.last{background:none;border:1px solid var(--line);color:var(--danger)}
.fixsum{font-size:13px;color:var(--ink-soft);margin-bottom:2px}
.fixsum b{color:var(--ink);font-size:15px}
.fixempty{font-size:13px;color:var(--ink-soft);padding:2px 0}
.fixopen{margin-top:8px}
.sheet-note.fixnote{text-align:left;margin:0 0 12px}
/* 매달 나가는 날 — 앱의 하나뿐인 고르기 칸. 입력 칸처럼 흰 바탕(기본 모양은 회색) */
select.text-input{background:var(--panel)}
.save.fixresume{background:none;color:var(--cold);border:1px solid var(--line);margin-top:8px}

.strip{position:relative;display:flex;align-items:center}
.strip > .tabs, .strip > .picker{flex:1;min-width:0}
.stripnav{display:none;flex:0 0 auto;width:26px;align-self:stretch;border:none;cursor:pointer;
  background:none;font-family:inherit;font-size:20px;line-height:1;color:var(--ink-soft);padding:0}
.strip.scrollable > .stripnav{display:block}
.stripnav:disabled{opacity:.2;cursor:default}
/* 화살표가 생기면 목록의 바깥 여백은 화살표가 대신한다 */
.strip > .tabs{padding-left:0;padding-right:0}
.strip{padding:16px 14px 12px}
.strip:has(> .picker){padding:14px 0}
.tabs{display:flex;gap:7px;overflow-x:auto;padding:16px 20px 12px;scrollbar-width:none}
.tabs::-webkit-scrollbar,.picker::-webkit-scrollbar,.friendbar::-webkit-scrollbar{display:none}
.tab{flex:0 0 auto;border:1px solid var(--line);background:var(--panel);color:var(--ink-soft);
  border-radius:999px;padding:7px 14px;font-family:inherit;font-size:14px;font-weight:600;
  cursor:pointer;display:flex;align-items:center;gap:5px;white-space:nowrap}
.tab[aria-selected="true"]{background:var(--ink);border-color:var(--ink);color:#fff}
.tab .lock{font-size:11px;opacity:.75}
.tab.add{border-style:dashed;color:var(--chrome)}

.list{flex:1;padding:0 20px calc(130px + env(safe-area-inset-bottom))}
.daygroup{margin-bottom:20px}
.dayhead{font-size:12px;font-weight:700;color:var(--ink-soft);padding:0 2px 7px;
  display:flex;justify-content:space-between}
.dayhead .over{color:var(--danger)}
.row{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:12px 14px;margin-bottom:7px}
.row[data-tx]{cursor:pointer}
button.row.notif{display:block;width:100%;text-align:left;font-family:inherit;
  font-size:15px;color:var(--ink);cursor:pointer}
.row[data-tx]:active{background:#F6F9FA}
.row-main{display:flex;align-items:center;gap:10px}
.row-name{font-weight:600;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row-amt{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.row-meta{font-size:12px;color:var(--ink-soft);margin-top:4px;display:flex;gap:7px;flex-wrap:wrap;align-items:center}
.chip{border:1px solid var(--line);border-radius:5px;padding:1px 6px;font-size:11px}
.chip.private{border-color:var(--chrome);color:var(--chrome)}
.chip.latechip{color:var(--ink-soft)}
.excuse{margin-top:8px;padding-left:9px;border-left:2px solid var(--pig);font-size:13px;color:var(--ink-soft)}
.excuse-add{margin-top:6px;background:none;border:none;font-family:inherit;font-size:12px;
  color:var(--cold);cursor:pointer;padding:0}
.excuse-input{margin-top:7px;width:100%;border:1px solid var(--line);border-radius:8px;
  padding:8px 10px;font-family:inherit;font-size:13px;color:var(--ink)}
.excuse-input:focus{outline:2px solid var(--cold);outline-offset:-1px}
.more{width:100%;padding:11px;border:1px dashed var(--line);border-radius:11px;
  background:none;font-family:inherit;font-size:13px;font-weight:600;color:var(--cold);
  cursor:pointer;margin-top:2px}
.more:hover{border-color:var(--cold)}
.backlink{background:none;border:none;font-family:inherit;font-size:14px;font-weight:600;
  color:var(--ink-soft);cursor:pointer;padding:2px 0 6px}
.detail-head{display:flex;justify-content:space-between;align-items:center}
.detail-head .backlink:last-child{font-size:20px;line-height:1;padding:0 4px 8px}
/* 로딩 자리표시 */
.sk{background:linear-gradient(90deg,#E3EAEC 25%,#EDF2F3 37%,#E3EAEC 63%);
  background-size:400% 100%;animation:sk 1.4s ease infinite;border-radius:10px}
@keyframes sk{0%{background-position:100% 0}100%{background-position:0 0}}
.sk-pig{width:100%;max-width:260px;height:150px;margin:6px auto 0;border-radius:18px}
.sk-line{height:14px}
.sk-tab{width:72px;height:34px;border-radius:999px;flex:0 0 auto}
.sk-row{height:64px;margin-bottom:7px}
@media (prefers-reduced-motion:reduce){.sk{animation:none}}
.calm .sk{animation:none}

.empty{text-align:center;color:var(--ink-soft);font-size:14px;padding:44px 20px;
  border:1px dashed var(--line);border-radius:14px}

/* 가로 스크롤이면 4번째부터 안 보인다. 줄바꿈으로 전부 노출한다 */
.feed-head{display:flex;justify-content:flex-end;padding:0 20px 4px}
.friendbar{display:grid;grid-template-columns:repeat(4,1fr);gap:10px 8px;padding:4px 20px 18px}
.friendpig{text-align:center;background:none;border:none;
  font-family:inherit;cursor:pointer;padding:0;min-width:0}
.friendpig svg{width:100%;height:auto}
.friendpig .nm{font-size:13px;font-weight:700;margin-top:-4px}
.friendpig .pc{font-size:12px;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.friendpig .pc.over{color:var(--danger)}
.nags{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}
.nag{border:1px solid var(--line);background:var(--panel);border-radius:999px;padding:5px 11px;
  font-family:inherit;font-size:13px;color:var(--ink-soft);cursor:pointer}
.nag.on{background:var(--pig);border-color:var(--pig-deep);color:#5C2439;font-weight:600}
.nag.write{border-style:dashed;color:var(--cold)}
.naggroup{margin-bottom:14px}
.naggroup-title{font-size:12px;font-weight:700;color:var(--ink-soft);margin-bottom:7px}
.naggroup .nags{margin-top:0}
button.stamp.own{border:none;font-family:inherit;cursor:pointer}
.nagged{margin-top:9px;display:flex;gap:6px;flex-wrap:wrap}
.stamp{line-height:1.6}
.stamp{background:var(--pig);color:#5C2439;border-radius:999px;padding:3px 10px;font-size:12px;font-weight:600}
/* 돼지 잔소리(자동 잔소리 — src/autonag.ts) — 친구 잔소리(분홍)와 갈라 보이게 노랑 */
.stamp.pignag{background:#FFEDB3;color:#5B4300}

/* ---------------- 잔소리 특수효과 ----------------
   보낸 사람이 고른 효과(src/effects.ts)가 그 사람의 잔소리 칸(.stamp)에 붙는다.
   빛줄기(::after)는 transform 으로만 옮긴다 — 배경 위치를 움직이면 칸마다 매 프레임 다시
   칠해서 피드에 효과 칸이 여럿이면 무거워진다. 반짝이(✦, ::before)는 오른쪽 여백에 둔다.
   움직임 줄이기면 둘 다 멈추고 색과 반짝이 모양만 남는다. */
.stamp.fx{display:inline-block;position:relative;overflow:hidden;isolation:isolate;padding-right:18px}
.stamp.fx::after{content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.85) 48%,transparent 66%);
  transform:translateX(-110%);animation:fxshine 2.8s ease-in-out infinite}
.stamp.fx::before{content:'✦';position:absolute;right:6px;top:50%;margin-top:-7px;font-size:10px;
  line-height:14px;pointer-events:none;animation:fxtwinkle 1.9s ease-in-out infinite}
.nagged .stamp.fx:nth-child(2n)::after{animation-delay:-1.4s}
.nagged .stamp.fx:nth-child(2n)::before{animation-delay:-.9s}
@keyframes fxshine{0%{transform:translateX(-110%)}55%,100%{transform:translateX(110%)}}
@keyframes fxtwinkle{0%,100%{opacity:.3;transform:scale(.6) rotate(0)}50%{opacity:1;transform:scale(1.15) rotate(25deg)}}
.stamp.fx-gold{color:#5b3a00;box-shadow:inset 0 0 0 1px #d4a017,0 1px 3px rgba(212,160,23,.45);
  background:linear-gradient(135deg,#f7dc83 0%,#e7b23e 38%,#fff0b8 52%,#dca42c 68%,#f3cf6b 100%)}
.stamp.fx-gold::before{color:#fffbe6;text-shadow:0 0 4px #ffc21a}
.stamp.fx-platinum{color:#223047;box-shadow:inset 0 0 0 1px #b9c6e0,0 1px 4px rgba(120,150,210,.45);
  background:linear-gradient(135deg,#fbfcff 0%,#dbe4f7 34%,#ffffff 50%,#ccd8f0 66%,#f2f5fd 100%)}
.stamp.fx-platinum::before{color:#fff;text-shadow:0 0 5px #7fb2ff,0 0 1px #4d75b8}
.stamp.fx-platinum::after{background:linear-gradient(105deg,transparent 28%,rgba(225,238,255,.95) 46%,
  #fff 50%,transparent 66%)}
/* 실버 — 플래티넘보다 어둡고 차가운 회색 금속. 첫 이정표(3일)와 DB 1단계 */
.stamp.fx-silver{color:#2a313b;box-shadow:inset 0 0 0 1px #9aa4b1,0 1px 3px rgba(90,100,115,.35);
  background:linear-gradient(135deg,#e6eaef 0%,#b3bcc7 38%,#f5f7f9 52%,#a3adb9 68%,#d7dde4 100%)}
.stamp.fx-silver::before{color:#fff;text-shadow:0 0 3px #b8c2cf}
/* 불꽃 — 아래가 붉고 위가 노랗고 주황 불빛이 번진다. 밝은 불꽃 덩이가 쉬지 않고 위로 치솟고(두 배 높은 띠를
   위에 붙여 반씩 올린다 — 덩이는 한 칸 안에만 둬야 이음매가 안 보인다) 빛이 빠르게 일렁인다 */
.stamp.fx-fire{color:#3a0d00;text-shadow:0 0 3px rgba(255,236,160,.9);
  box-shadow:inset 0 0 0 1px #ff6a00,0 0 6px rgba(255,98,0,.85),0 0 14px rgba(255,60,0,.45);
  background:linear-gradient(0deg,#e0300a 0%,#ff7a00 45%,#ffd23f 100%)}
.stamp.fx-fire::after{inset:0 0 auto 0;height:200%;transform:none;
  background-image:radial-gradient(38% 30% at 18% 72%,rgba(255,250,215,.95),transparent 70%),
    radial-gradient(34% 28% at 52% 32%,rgba(255,238,150,.9),transparent 70%),
    radial-gradient(30% 26% at 84% 66%,rgba(255,255,235,.9),transparent 70%);
  background-size:100% 50%;background-repeat:repeat-y;
  animation:fxrise .8s linear infinite,fxflicker .6s ease-in-out infinite}
.stamp.fx-fire::before{color:#fff6d5;text-shadow:0 0 4px #ff7a00,0 0 8px #ff3d00}
@keyframes fxrise{from{transform:translateY(0)}to{transform:translateY(-50%)}}
@keyframes fxflicker{0%{opacity:.6}20%{opacity:1}40%{opacity:.7}60%{opacity:.95}80%{opacity:.65}100%{opacity:.6}}
/* 네온 — 어두운 바탕에 분홍 빛 글자·테두리. 낡은 네온관처럼 칸째 불규칙하게 깜빡이고(투명도만),
   안쪽 빛이 크게 숨 쉰다. 칸째 움직이니 움직임 줄이기 규칙에 .stamp.fx 도 들어 있다 */
.stamp.fx-neon{color:#fff;background:#150a2c;
  text-shadow:0 0 2px #fff,0 0 5px #ff5ee0,0 0 10px #ff5ee0,0 0 18px #ff2bd6;
  box-shadow:inset 0 0 0 1px #ff7ae8,inset 0 0 6px rgba(255,94,224,.6),0 0 8px rgba(255,94,224,.85),
    0 0 18px rgba(255,43,214,.45);
  animation:fxbuzz 3.2s linear infinite}
.stamp.fx-neon::after{transform:none;
  background:radial-gradient(120% 140% at 50% 50%,rgba(255,94,224,.55),transparent 70%);
  animation:fxpulse 1.1s ease-in-out infinite}
.stamp.fx-neon::before{color:#7df9ff;text-shadow:0 0 4px #00e5ff,0 0 9px #00e5ff}
.nagged .stamp.fx-neon:nth-child(2n){animation-delay:-1.7s}
@keyframes fxpulse{0%,100%{opacity:.3}50%{opacity:1}}
@keyframes fxbuzz{0%,17%,19.5%,22%,61%,63.5%,100%{opacity:1}18%,21%,62%{opacity:.3}}
/* 무지개 — 선명한 일곱 빛이 옆으로 흐른다. 세 배 넓은 띠를 한 칸씩 옮겨 이음매 없이 돈다 */
.stamp.fx-rainbow{color:#fff;background:#ff6b6b;text-shadow:0 1px 1px rgba(0,0,0,.35);
  box-shadow:0 1px 4px rgba(120,80,200,.35)}
.stamp.fx-rainbow::after{inset:0 auto 0 0;width:300%;transform:none;
  background-image:linear-gradient(90deg,#ff6b6b,#ffb347,#ffe066,#6ee7a0,#5bc0ff,#8e7dff,#ff6b6b);
  background-size:33.3334% 100%;background-repeat:repeat-x;animation:fxflow 3s linear infinite}
.stamp.fx-rainbow::before{color:#fff;text-shadow:0 0 3px rgba(0,0,0,.35)}
@keyframes fxflow{from{transform:translateX(0)}to{transform:translateX(-33.3334%)}}
/* 홀로그램 — 진주빛 바탕에 오색 빛띠가 쉬지 않고 지나간다. 무지개와 달리 바탕은 옅다 */
.stamp.fx-holo{color:#342b4a;box-shadow:inset 0 0 0 1px #d6c8ff,0 1px 4px rgba(150,120,230,.35);
  background:linear-gradient(135deg,#f6f3ff 0%,#e8f6ff 35%,#fdf0fb 65%,#eefff6 100%)}
.stamp.fx-holo::after{background:linear-gradient(105deg,transparent 15%,rgba(255,120,210,.5) 30%,
  rgba(120,210,255,.55) 45%,rgba(140,255,190,.5) 60%,rgba(255,236,120,.5) 72%,transparent 85%);
  animation:fxshine 2.2s linear infinite}
.stamp.fx-holo::before{color:#fff;text-shadow:0 0 4px #b98cff}
/* 은하수 — 밤하늘에 분홍·파랑 성운이 번지고, 별 띠가 흘러가며 반짝인다. 두 배 넓은 별 띠를 반씩 옮긴다 */
.stamp.fx-galaxy{color:#f6f0ff;text-shadow:0 0 4px rgba(210,185,255,.95),0 0 9px rgba(140,110,255,.75);
  background:radial-gradient(60% 120% at 22% 35%,rgba(255,80,200,.5),transparent 70%),
    radial-gradient(55% 110% at 80% 65%,rgba(60,170,255,.5),transparent 70%),
    linear-gradient(135deg,#120c38 0%,#3a1466 50%,#0b2458 100%);
  box-shadow:inset 0 0 0 1px #8a6bff,0 0 8px rgba(123,92,255,.75),0 0 16px rgba(255,80,200,.35)}
.stamp.fx-galaxy::after{inset:0 auto 0 0;width:200%;transform:none;
  background-image:radial-gradient(1.5px 1.5px at 8% 28%,#fff 50%,transparent 51%),
    radial-gradient(1px 1px at 19% 70%,#e2d8ff 50%,transparent 51%),
    radial-gradient(2px 2px at 31% 45%,#fff 50%,transparent 51%),
    radial-gradient(1px 1px at 44% 18%,#bfe3ff 50%,transparent 51%),
    radial-gradient(1.5px 1.5px at 57% 80%,#fff 50%,transparent 51%),
    radial-gradient(1px 1px at 69% 36%,#ffd6f5 50%,transparent 51%),
    radial-gradient(2px 2px at 82% 62%,#fff 50%,transparent 51%),
    radial-gradient(1px 1px at 93% 24%,#d8ccff 50%,transparent 51%);
  background-size:50% 100%;background-repeat:repeat-x;
  animation:fxdrift 3.5s linear infinite,fxstars 1.2s ease-in-out infinite alternate}
.stamp.fx-galaxy::before{color:#fff;text-shadow:0 0 5px #c9b6ff,0 0 10px #8f6bff}
@keyframes fxdrift{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@keyframes fxstars{from{opacity:.5}to{opacity:1}}
/* 다이아 — 얼음빛 결정. 무지갯빛 가장자리의 빛줄기가 플래티넘보다 빠르게(1.6초) 지나가고, 반짝임 하나가
   세 자리를 차례로 돌며 튄다 — 자리는 투명할 때만 옮긴다(움직임은 transform·투명도로만) */
.stamp.fx-diamond{color:#17324f;text-shadow:0 0 2px #fff;
  box-shadow:inset 0 0 0 1px #9fd3ff,0 0 6px rgba(140,205,255,.85),0 0 14px rgba(200,235,255,.55);
  background:linear-gradient(135deg,#f5fbff 0%,#cdeaff 20%,#ffffff 34%,#b7ddff 50%,#f0f9ff 64%,#c9e7ff 80%,#ffffff 100%)}
.stamp.fx-diamond::after{background:linear-gradient(105deg,transparent 30%,rgba(255,170,230,.55) 42%,
  #fff 47%,rgba(160,230,255,.9) 52%,rgba(255,255,255,.95) 55%,transparent 68%);
  animation:fxshine 1.6s ease-in-out infinite}
.stamp.fx-diamond::before{color:#fff;text-shadow:0 0 4px #7cc8ff,0 0 9px #cfeeff;
  animation:fxglint 2.4s ease-in-out infinite}
@keyframes fxglint{
  0%{opacity:0;transform:translate(0,0) scale(.3) rotate(0deg)}
  9%{opacity:1;transform:translate(0,0) scale(1.35) rotate(25deg)}
  18%{opacity:0;transform:translate(0,0) scale(.3) rotate(0deg)}
  33%{opacity:0;transform:translate(-26px,-4px) scale(.3) rotate(0deg)}
  42%{opacity:1;transform:translate(-26px,-4px) scale(1.15) rotate(25deg)}
  51%{opacity:0;transform:translate(-26px,-4px) scale(.3) rotate(0deg)}
  66%{opacity:0;transform:translate(-48px,3px) scale(.3) rotate(0deg)}
  75%{opacity:1;transform:translate(-48px,3px) scale(1.25) rotate(25deg)}
  84%{opacity:0;transform:translate(-48px,3px) scale(.3) rotate(0deg)}
  100%{opacity:0;transform:translate(0,0) scale(.3) rotate(0deg)}}
/* 태양 — 금빛 바탕 뒤로 햇살이 한 바퀴 돌고(돌면 제자리라 이음매가 없다) 빛이 숨 쉰다. 햇살 판은 잔소리
   칸보다 크게(320px) 가운데에 두고 돌린다 — 칸 밖은 잘린다 */
.stamp.fx-sun{color:#5a2600;text-shadow:0 0 3px rgba(255,249,214,.95);
  background:radial-gradient(90% 170% at 50% 50%,#fff6c2 0%,#ffd84d 45%,#ffab1a 100%);
  box-shadow:inset 0 0 0 1px #ffb300,0 0 8px rgba(255,190,40,.9),0 0 18px rgba(255,140,0,.5)}
.stamp.fx-sun::after{inset:auto;left:50%;top:50%;width:320px;height:320px;margin:-160px 0 0 -160px;
  background:repeating-conic-gradient(from 0deg,rgba(255,255,255,.6) 0deg 7deg,rgba(255,255,255,0) 7deg 20deg);
  transform:none;animation:fxspin 12s linear infinite,fxbreathe 2.4s ease-in-out infinite}
.stamp.fx-sun::before{color:#fff8d6;text-shadow:0 0 5px #ff9d00,0 0 10px #ffd000}
@keyframes fxspin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
@keyframes fxbreathe{0%,100%{opacity:.45}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.stamp.fx,.stamp.fx::before,.stamp.fx::after{animation:none}}
.calm .stamp.fx,.calm .stamp.fx::before,.calm .stamp.fx::after{animation:none}

/* 설정의 고르기 칸 — 칸마다 실제 잔소리와 같은 모양의 보기와, 며칠이면 열리는지가 들어간다 */
.fxgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
.fxopt{display:flex;flex-direction:column;align-items:center;gap:6px;padding:12px 8px 9px;
  border:1px solid var(--line);border-radius:13px;background:var(--panel);font:inherit;cursor:pointer}
.fxopt.on{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.fxname{font-size:12px;font-weight:700;color:var(--ink-soft)}
.fxopt.on .fxname{color:var(--ink)}
.fxwhen{font-size:11px;color:var(--ink-soft);margin-top:-3px}
/* 안 열린 칸 — 보기는 그대로 보여 주되 흐리게. 지금 붙은 것(DB 에서 넣어 준 것)은 또렷하게 */
.fxopt:disabled{cursor:not-allowed}
.fxopt:disabled:not(.on){opacity:.5}
/* 꾸미기 — 보기 돼지 + 자리 고르기 + 칸 (효과 칸과 같은 결). 잠긴 칸도 누를 수 있다(이유를 알려 준다) */
/* 보기 돼지 칸은 시트 폭 전부 — 두 손가락을 돼지 옆에 놓아도 된다(app.js 의 fitGesture). 맞출 장식이 있으면(.grab)
   손가락을 직접 받는다 — 시트가 밀리거나 화면이 커지지 않게. 길게 눌러도 글자 고르기 · 메뉴가 안 뜨게 */
.decoprev{margin:0 auto 6px;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
.decoprev.grab{touch-action:none;cursor:grab}
.decoprev>svg{width:170px;max-width:100%;height:auto;display:block;margin:0 auto}
/* 고른 장식의 위치·크기 막대 — 보기 돼지 바로 밑(밀면서 돼지를 본다) */
.decofit:not(:empty){margin:0 0 12px;padding:8px 12px;border:1px solid var(--line);border-radius:14px;background:var(--panel)}
.fithead{display:flex;align-items:center;justify-content:space-between;font-size:13px;font-weight:700;color:var(--ink)}
.fithead .linkbtn:disabled{opacity:.4;cursor:default}
.fitrow{display:flex;align-items:center;gap:10px;font-size:12px;color:var(--ink-soft)}
.fitrow span{flex:none;width:30px}
.fitrange{flex:1;min-width:0;height:28px;accent-color:var(--pig-deep)}
.fithint{margin-top:2px;font-size:11px;color:var(--ink-soft)}
.decotabs{display:flex;justify-content:center;margin:4px 0 12px}
.decogrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
.decoopt{display:flex;flex-direction:column;align-items:center;gap:5px;padding:10px 4px 8px;
  border:1px solid var(--line);border-radius:13px;background:var(--panel);font:inherit;cursor:pointer;
  touch-action:manipulation}
.decoopt.on{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.decoopt.locked .decotile{opacity:.45}
.decotile{display:block;width:44px;height:36px}
.decotile-none{box-sizing:border-box;border:1.5px dashed var(--line);border-radius:8px}
.deconame{font-size:11px;color:var(--ink-soft);white-space:nowrap}
.decoopt.on .deconame{color:var(--ink);font-weight:700}
/* 특별한 꾸미기(보상 장식)의 움직임 — 고리가 둥실, 날개가 퍼덕, 반짝이가 깜빡, 빛살이 돈다. 움직이는 요소엔 transform
   속성을 두지 않는다(CSS 애니메이션이 덮는다 — 자리는 감싸는 g 에). 움직임 줄이기·지난 달(마을, .still)은 멈춘다 */
.pgfx{transform-box:fill-box;transform-origin:center}
.pgfx-bob{animation:pgfxbob 2.6s ease-in-out infinite}
.pgfx-flap{transform-origin:100% 60%;animation:pgfxflap 1.8s ease-in-out infinite}
.pgfx-twinkle{animation:pgfxtwinkle 1.6s ease-in-out infinite}
.pgfx-spin{animation:pgfxspin 30s linear infinite}
@keyframes pgfxbob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
@keyframes pgfxflap{0%,100%{transform:rotate(0)}50%{transform:rotate(-9deg)}}
@keyframes pgfxtwinkle{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.3;transform:scale(.55)}}
@keyframes pgfxspin{to{transform:rotate(360deg)}}

.pgfx-glow{animation:pgfxglow 3.2s ease-in-out infinite}
.pgfx-sway{animation:pgfxsway 7s ease-in-out infinite}
.pgfx-sway2{animation:pgfxsway 9.5s ease-in-out infinite reverse}
.pgfx-burst{animation:pgfxburst 3s ease-out infinite}

@keyframes pgfxglow{0%,100%{opacity:.45}50%{opacity:1}}
@keyframes pgfxsway{0%,100%{transform:translateX(-7px)}50%{transform:translateX(7px)}}
@keyframes pgfxburst{0%{opacity:0;transform:scale(.15)}12%{opacity:1}65%{opacity:.9;transform:scale(1)}
  100%{opacity:0;transform:scale(1.08)}}
.pgfx-rainbow{animation:pgfxrainbow 2.4s linear infinite}
.pgfx-zap{animation:pgfxzap 1.1s linear infinite}
.pgfx-gaze{transform-origin:0 50%;animation:pgfxgaze 5s linear infinite}
.pgfx-girth{transform-origin:0 50%;animation:pgfxgirth 1.7s ease-in-out infinite}
@keyframes pgfxgaze{to{transform:rotate(360deg)}}
@keyframes pgfxgirth{0%,100%{transform:scaleY(.45)}50%{transform:scaleY(1.7)}}
/* 취한 눈 — 두 소용돌이가 서로 반대로 돈다. 움직임 줄이기 규칙(아래)보다 앞에 둔다 — 뒤에 두면 이게 이긴다 */
.pgfx-dizzy{animation:pgfxspin 1.6s linear infinite}
.pgfx-rev{animation-direction:reverse}
/* 광선이 단추·목록 위를 지나도 누르는 걸 가로채지 않게 */
.pgd-laser{pointer-events:none}
@keyframes pgfxrainbow{0%,100%{fill:#ff1f1f}17%{fill:#ff922b}33%{fill:#ffd43b}50%{fill:#40c057}67%{fill:#228be6}
  83%{fill:#7950f2}}
@keyframes pgfxzap{0%{opacity:0;transform:translateX(0)}12%{opacity:1}100%{opacity:0;transform:translateX(380px)}}
/* 레이저 눈은 홈·친구 화면의 큰 돼지에서만 그림 상자 밖으로 — 시선이 360° 돌며 그 칸을 훑는다. 넘친 것은 레이저를 낀
   그 .pigstage 가 잘라(clip — hidden 과 달리 스크롤 칸이 안 생긴다) 머리글·목록 위로 안 번지고 가로 스크롤도 없다.
   clip·:has 를 모르는 옛 브라우저는 그림 상자 안에서 돈다 */
@supports (overflow:clip){.pigstage:has(.pgd-laser){overflow:clip}.pigstage svg:has(.pgd-laser){overflow:visible}}
/* 새 꾸미기(2026-10-02) — 눈물 방울 · 저금통 동전 · 떨어지는 단풍과 돈. 움직임 줄이기 규칙(아래)보다 앞에 둔다 */
.pgfx-drip{animation:pgfxdrip 1.7s ease-in infinite}
.pgfx-coin{animation:pgfxcoin 2.4s ease-in infinite}
.pgfx-fall{animation:pgfxfall 6.5s linear infinite}
@keyframes pgfxdrip{0%{opacity:0;transform:translateY(-3px)}25%{opacity:1}100%{opacity:0;transform:translateY(12px)}}
@keyframes pgfxcoin{0%{opacity:0;transform:translateY(-8px)}25%{opacity:1}70%{opacity:1;transform:translateY(7px)}
  100%{opacity:0;transform:translateY(9px)}}
@keyframes pgfxfall{0%{transform:translateY(-140px) rotate(0)}100%{transform:translateY(140px) rotate(250deg)}}
/* 펫(2026-10-06) — 다 움직인다. 축이 있는 것(꼬리 · 고개 · 부리)은 그 g 의 상자 가운데가 축이다(pig.js 의 pivot),
   펭귄만 발밑. 움직임 줄이기 규칙(아래)보다 앞에 둔다 — 뒤에 두면 무게가 같아 이겨서 계속 돈다(check-pwa) */
.pgfx-peck{animation:pgfxpeck 3.4s ease-in-out infinite}
.pgfx-wag{animation:pgfxwag .45s ease-in-out infinite alternate}
.pgfx-tilt{animation:pgfxtilt 4.6s ease-in-out infinite}
.pgfx-swish{animation:pgfxswish 3s ease-in-out infinite}
.pgfx-blink{animation:pgfxblink 4.2s linear infinite}
.pgfx-nibble{animation:pgfxnibble .4s ease-in-out infinite alternate}
.pgfx-hop{animation:pgfxhop 2.8s ease-in-out infinite}
.pgfx-hopshade{animation:pgfxhopshade 2.8s ease-in-out infinite}
.pgfx-waddle{transform-origin:50% 100%;animation:pgfxwaddle 1.3s ease-in-out infinite}
.pgfx-swim{animation:pgfxswim 6s ease-in-out infinite}
.pgfx-bubble{animation:pgfxbubble 2.4s ease-out infinite}
@keyframes pgfxpeck{0%,48%,100%{transform:rotate(0)}56%{transform:rotate(-36deg)}62%{transform:rotate(-10deg)}
  68%{transform:rotate(-36deg)}78%{transform:rotate(0)}}
@keyframes pgfxwag{from{transform:rotate(-16deg)}to{transform:rotate(16deg)}}
@keyframes pgfxtilt{0%,55%,100%{transform:rotate(0)}64%,84%{transform:rotate(10deg)}}
@keyframes pgfxswish{0%,100%{transform:rotate(-4deg)}50%{transform:rotate(14deg)}}
@keyframes pgfxblink{0%,90%,100%{transform:scaleY(1)}94%{transform:scaleY(.1)}}
@keyframes pgfxnibble{from{transform:translateY(0)}to{transform:translateY(-1.4px)}}
@keyframes pgfxhop{0%,50%,100%{transform:translateY(0)}62%{transform:translateY(-10px)}74%{transform:translateY(0)}
  80%{transform:translateY(-3px)}86%{transform:translateY(0)}}
@keyframes pgfxhopshade{0%,50%,100%{transform:scaleX(1)}62%{transform:scaleX(.6)}74%{transform:scaleX(1)}
  80%{transform:scaleX(.86)}86%{transform:scaleX(1)}}
@keyframes pgfxwaddle{0%,100%{transform:rotate(-7deg)}50%{transform:rotate(7deg)}}
@keyframes pgfxswim{0%{transform:translateX(-5px) scaleX(1)}44%{transform:translateX(5px) scaleX(1)}
  50%{transform:translateX(5px) scaleX(-1)}94%{transform:translateX(-5px) scaleX(-1)}100%{transform:translateX(-5px) scaleX(1)}}
@keyframes pgfxbubble{0%{opacity:0;transform:translateY(0)}25%{opacity:.9}100%{opacity:0;transform:translateY(-12px)}}
/* 펫 둘째(2026-10-06) — 병아리 · 나비(소품에서 옮겨 왔다)와 새 펫 일곱. 축은 위와 같다(pivot · 상자 가장자리) */
.pgfx-cheep{animation:pgfxcheep 2.4s ease-in-out infinite}
.pgfx-wingflap{transform-origin:50% 12%;animation:pgfxwingflap 2.4s ease-in-out infinite}
.pgfx-flutter{animation:pgfxflutter .32s ease-in-out infinite alternate}
.pgfx-drift{animation:pgfxdrift 4.4s ease-in-out infinite}
.pgfx-beewing{transform-origin:50% 100%;animation:pgfxbeewing .12s linear infinite alternate}
.pgfx-buzz{animation:pgfxbuzz 2.6s ease-in-out infinite}
.pgfx-munch{animation:pgfxmunch .42s ease-in-out infinite alternate}
.pgfx-poke{animation:pgfxpoke 5s ease-in-out infinite}
.pgfx-sniff{animation:pgfxsniff 1.8s ease-in-out infinite}
.pgfx-flick{animation:pgfxflick 3.2s ease-in-out infinite}
.pgfx-puff{animation:pgfxpuff 2.2s ease-in-out infinite}
@keyframes pgfxcheep{0%,52%,100%{transform:translateY(0)}60%{transform:translateY(-4px)}68%{transform:translateY(0)}
  76%{transform:translateY(-4px)}84%{transform:translateY(0)}}
@keyframes pgfxwingflap{0%,52%,100%{transform:rotate(0)}58%,74%{transform:rotate(30deg)}66%,82%{transform:rotate(0)}}
@keyframes pgfxflutter{from{transform:scaleX(1)}to{transform:scaleX(.3)}}
@keyframes pgfxdrift{0%,100%{transform:translate(0,0)}25%{transform:translate(3px,-3px)}50%{transform:translate(0,-5px)}
  75%{transform:translate(-3px,-2px)}}
@keyframes pgfxbeewing{from{transform:scaleY(1)}to{transform:scaleY(.35)}}
@keyframes pgfxbuzz{0%,100%{transform:translate(0,0)}25%{transform:translate(5px,-3px)}50%{transform:translate(1px,2px)}
  75%{transform:translate(-4px,-2px)}}
@keyframes pgfxmunch{from{transform:translateY(0)}to{transform:translateY(-1.4px)}}
@keyframes pgfxpoke{0%,35%,100%{transform:translateX(0)}50%,75%{transform:translateX(-6px)}}
@keyframes pgfxsniff{0%,40%,100%{transform:translate(0,0)}48%,64%{transform:translate(.9px,-.9px)}56%,72%{transform:translate(0,0)}}
@keyframes pgfxflick{0%,64%,100%{transform:rotate(0)}70%{transform:rotate(10deg)}76%{transform:rotate(-4deg)}
  82%{transform:rotate(8deg)}88%{transform:rotate(0)}}
@keyframes pgfxpuff{0%,55%,100%{transform:scale(1)}65%,80%{transform:scale(1.5)}}
/* 펫 셋째(2026-10-06) — 웰시코기 엉덩이 씰룩(앞발이 축 — 상자 오른쪽 아래), 해파리 갓 오므리기(갓 아래가 축) */
.pgfx-wiggle{transform-origin:80% 100%;animation:pgfxwiggle .36s ease-in-out infinite alternate}
.pgfx-pulse{transform-origin:50% 100%;animation:pgfxpulse 1.8s ease-in-out infinite}
@keyframes pgfxwiggle{from{transform:rotate(-2.5deg)}to{transform:rotate(2.5deg)}}
@keyframes pgfxpulse{0%,100%{transform:scale(1,1)}50%{transform:scale(1.08,.86)}}
/* 가을 꾸미기(2026-10-08) — 군고구마 김 · 은행잎 떨림(낙엽 철썩 — 꼭지 밑동이 축, pivot) · 더미에 내려앉는 잎 · 고추잠자리
   (멈췄다 휙 · 날개 떨기 — 몸이 축, pivot) · 벼(밑동이 축) */
.pgfx-steam{animation:pgfxsteam 2.6s ease-out infinite}
.pgfx-rustle{animation:pgfxrustle 3s ease-in-out infinite}
.pgfx-leafdrop{animation:pgfxleafdrop 3.8s ease-in-out infinite}
.pgfx-dart{animation:pgfxdart 5s ease-in-out infinite}
.pgfx-dfwing{animation:pgfxdfwing .08s linear infinite alternate}
.pgfx-reed{transform-origin:50% 100%;animation:pgfxreed 4s ease-in-out infinite}
@keyframes pgfxsteam{0%{opacity:0;transform:translateY(3px) scale(.7)}30%{opacity:.85}
  100%{opacity:0;transform:translateY(-12px) scale(1.25)}}
@keyframes pgfxrustle{0%,50%,100%{transform:rotate(0)}58%{transform:rotate(-10deg)}66%{transform:rotate(6deg)}
  74%{transform:rotate(-7deg)}82%{transform:rotate(3deg)}90%{transform:rotate(0)}}
@keyframes pgfxleafdrop{0%{opacity:0;transform:translate(-6px,-34px) rotate(-60deg)}12%{opacity:1}
  40%{transform:translate(6px,-20px) rotate(20deg)}70%{transform:translate(-3px,-6px) rotate(-30deg)}
  82%{opacity:1;transform:translate(0,0) rotate(-12deg)}100%{opacity:0;transform:translate(0,0) rotate(-12deg)}}
@keyframes pgfxdart{0%,28%,100%{transform:translate(0,0)}34%,58%{transform:translate(8px,-6px)}
  64%,86%{transform:translate(-4px,3px)}}
@keyframes pgfxdfwing{from{transform:scaleY(1)}to{transform:scaleY(.5)}}
@keyframes pgfxreed{0%,100%{transform:rotate(-4deg)}50%{transform:rotate(5deg)}}
/* 하얀 드워프 햄스터(2026-10-08) — 볼주머니 오물오물(두 번씩 · 볼 가운데가 축) · 새근새근 숨쉬기(발밑이 축) */
.pgfx-cheek{animation:pgfxcheek 2.6s ease-in-out infinite}
.pgfx-breathe{transform-origin:50% 100%;animation:pgfxbreathe 3.2s ease-in-out infinite}
@keyframes pgfxcheek{0%,40%,100%{transform:scale(1)}48%{transform:scale(1.14)}56%{transform:scale(1)}
  64%{transform:scale(1.14)}72%{transform:scale(1)}}
@keyframes pgfxbreathe{0%,100%{transform:scale(1,1)}50%{transform:scale(1.035,.95)}}
/* 고양이 일곱(2026-10-08) — 귀 쫑긋(귀 밑동 pivot) · 꾹꾹이(어깨 pivot — 두 앞발이 반 박자씩, animation-delay) · 털실 공 툭
   (어깨 pivot) · 공 데굴 · 천천히 깜빡(고양이 인사) · 그루밍(어깨 pivot, 세 번 쓱쓱) · 혀 · 상자에서 빼꼼 · 하품 · 하품할 때
   질끈 감는 눈. 혀 · 벌린 입은 그림에서 opacity 0 — 멈추면(움직임 줄이기 · 마을) 안 보이고 움직임이 덮어 보여 준다 */
.pgfx-earflick{animation:pgfxearflick 3.6s ease-in-out infinite}
.pgfx-knead{animation:pgfxknead 1.1s ease-in-out infinite}
.pgfx-roll{animation:pgfxroll 3s ease-in-out infinite}
.pgfx-bat{animation:pgfxbat 3s ease-in-out infinite}
.pgfx-slowblink{animation:pgfxslowblink 5.6s ease-in-out infinite}
.pgfx-groom{animation:pgfxgroom 3s ease-in-out infinite}
.pgfx-tongue{animation:pgfxtongue 3s ease-in-out infinite}
.pgfx-peek{animation:pgfxpeek 4.4s ease-in-out infinite}
.pgfx-yawn{animation:pgfxyawn 5.2s ease-in-out infinite}
.pgfx-yawneye{animation:pgfxyawneye 5.2s ease-in-out infinite}
@keyframes pgfxearflick{0%,64%,100%{transform:rotate(0)}70%{transform:rotate(16deg)}75%{transform:rotate(-4deg)}
  80%{transform:rotate(13deg)}86%{transform:rotate(0)}}
@keyframes pgfxknead{0%,50%,100%{transform:rotate(0)}25%{transform:rotate(-17deg)}}
@keyframes pgfxroll{0%,40%,100%{transform:translateX(0) rotate(0)}50%{transform:translateX(5px) rotate(140deg)}
  74%{transform:translateX(1.6px) rotate(60deg)}}
@keyframes pgfxbat{0%,26%,48%,100%{transform:rotate(0)}34%{transform:rotate(-24deg)}40%{transform:rotate(6deg)}}
@keyframes pgfxslowblink{0%,52%,100%{transform:scaleY(1)}62%,76%{transform:scaleY(.1)}}
@keyframes pgfxgroom{0%,60%,100%{transform:rotate(0)}10%,30%,50%{transform:rotate(10deg)}20%,40%{transform:rotate(0)}}
@keyframes pgfxtongue{0%,58%,100%{opacity:0}4%,54%{opacity:1}}
@keyframes pgfxpeek{0%,14%,90%,100%{transform:translateY(12px)}30%,74%{transform:translateY(0)}}
@keyframes pgfxyawn{0%,58%,100%{opacity:0;transform:scale(0)}68%,82%{opacity:1;transform:scale(1)}}
@keyframes pgfxyawneye{0%,58%,100%{transform:scaleY(1)}66%,84%{transform:scaleY(.14)}}
.pgdeco.still .pgfx{animation:none}
@media (prefers-reduced-motion:reduce){.pgfx{animation:none}}
.calm .pgfx{animation:none}

/* 연속 기록 배지 (src/streaks.ts 의 MILESTONES). 얻은 것은 또렷하게, 못 얻은 것은 흐리게 */
.msgrid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px}
.msbadge{display:flex;flex-direction:column;align-items:center;gap:1px;padding:9px 4px 7px;
  border:1px solid var(--line);border-radius:12px;background:var(--panel)}
.msbadge:not(.got){opacity:.4;filter:grayscale(1)}
.msicon{font-size:22px;line-height:1.2}
.msname{font-size:12px;font-weight:700}
.msdays{font-size:11px;color:var(--ink-soft)}
.msmark{font-size:12px}
.msbig{font-size:44px;text-align:center;margin:2px 0 8px;letter-spacing:4px}
/* 방패 칸 (계정 화면, 배지 아래) */
.shieldrow{display:flex;gap:8px;align-items:flex-start;margin:12px 0 0;padding:10px 12px;
  border:1px solid var(--line);border-radius:12px;background:var(--panel);
  font-size:12px;line-height:1.5;color:var(--ink-soft);text-align:left}
.shieldrow b{color:var(--ink)}
.shieldrow .todaybtn{margin-top:10px}
.shieldicon{font-size:20px;line-height:1.2}

/* 돼지 마을 — 울타리 친 풀밭에 한 해가 집 한 채. 울타리는 위·아래 말뚝(무늬를 옆으로 되풀이)과 양옆 가로대.
   SVG 무늬라 색은 hex(#은 %23) */
.village-wrap{padding:0 20px calc(130px + env(safe-area-inset-bottom))}
.village{position:relative;border-radius:22px;padding:44px 22px 46px;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='30'%3E%3Crect y='10' width='20' height='4' fill='%23c98b4a'/%3E%3Crect y='21' width='20' height='4' fill='%23c98b4a'/%3E%3Cpath d='M6 30V7l4-5 4 5v23z' fill='%23f6dcb4' stroke='%23b9773a'/%3E%3C/svg%3E") repeat-x left 0 top 8px,
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='30'%3E%3Crect y='10' width='20' height='4' fill='%23c98b4a'/%3E%3Crect y='21' width='20' height='4' fill='%23c98b4a'/%3E%3Cpath d='M6 30V7l4-5 4 5v23z' fill='%23f6dcb4' stroke='%23b9773a'/%3E%3C/svg%3E") repeat-x left 0 bottom 6px,
    linear-gradient(#c98b4a,#c98b4a) no-repeat left 10px top 24px / 4px calc(100% - 52px),
    linear-gradient(#c98b4a,#c98b4a) no-repeat right 10px top 24px / 4px calc(100% - 52px),
    linear-gradient(180deg,#d8efc4,#bfe3a3)}
.vlots{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 14px}
.vhouse,.vlot{display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 2px 6px;border:none;
  background:none;font:inherit;color:inherit}
.vhouse{cursor:pointer;touch-action:manipulation;border-radius:14px}
.vhouse:active{background:rgba(255,255,255,.35)}
.vlot{opacity:.8}
.vhouse-art{width:100%;max-width:132px;height:auto;display:block}
.vyear{font-size:14px;font-weight:800;color:#3b2a16}
.vcount{font-size:11px;color:#5f4b32}
/* 집안 — 한 장짜리 그림(roomSVG) + 달마다 한 줄 */
.room-wrap{padding:0 16px}
.room{width:100%;height:auto;display:block;border-radius:18px;border:1px solid var(--line)}
.roomlist{margin:12px 20px calc(130px + env(safe-area-inset-bottom))}
.roomrow{display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid var(--line)}
.roomrow svg{width:40px;height:auto;flex:none}
.roomrow-ph{width:40px;height:34px;flex:none;border:1px dashed var(--line);border-radius:9px}
.roomrow-mo{font-size:14px;font-weight:800;min-width:34px}
.roomrow-v{flex:1;font-size:12px;color:var(--ink-soft)}
.roomrow-pc{font-size:12px;font-weight:700;font-variant-numeric:tabular-nums}
.roomrow-pc.over{color:var(--danger)}
.roomrow.blank{opacity:.55}
/* 돼지는 SVG 안이라 그 자리에 투명한 단추를 겹친다(roomLayout). 목록의 달도 단추 */
.roombox{position:relative}
.roomhit{position:absolute;padding:0;border:none;background:none;border-radius:12px;cursor:pointer;
  touch-action:manipulation}
.roomhit:active{background:rgba(255,255,255,.3)}
button.roomrow{width:100%;border:none;border-bottom:1px solid var(--line);background:none;font:inherit;
  color:inherit;text-align:left;cursor:pointer;touch-action:manipulation}
.roomrow-go{color:var(--chrome);font-size:18px;line-height:1}
/* 그 달 내역 시트 — 숫자 줄 + 하루 묶음(목록과 같은 결, 읽기만) */
.monthsum{display:flex;align-items:center;gap:12px;margin:-4px 0 12px;font-size:13px;line-height:1.5;
  color:var(--ink-soft)}
.monthsum svg{width:56px;height:auto;flex:none}
.monthsum b{color:var(--ink)}
.monthsum b.over{color:var(--danger)}
/* 그 달 내역을 탭별로 — 칩(전체·탭마다)과 누를 수 있는 탭별 막대 */
.monthtabs{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 14px}
.monthtab{border:1px solid var(--line);border-radius:999px;padding:5px 11px;background:var(--panel);font:inherit;
  font-size:12px;font-weight:700;color:var(--ink-soft);cursor:pointer;touch-action:manipulation}
.monthtab[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:#fff}
button.monthbar{display:block;width:100%;padding:0;border:none;background:none;font:inherit;color:inherit;
  text-align:left;cursor:pointer;touch-action:manipulation}
/* 그 달 내역 제목 줄 — 왼쪽 건수·합, 오른쪽 "잔소리 빼고 보기"(체크박스 모양 단추. 누르는 건 <button>) */
.monthlisthead{display:flex;align-items:center;justify-content:space-between;gap:8px}
.nagcheck{display:inline-flex;align-items:center;gap:6px;flex:none;min-height:30px;margin:-6px 0;padding:0 2px;
  border:none;background:none;font:inherit;font-size:12px;font-weight:700;color:var(--ink-soft);cursor:pointer;
  touch-action:manipulation}
.nagcheck-box{display:grid;place-items:center;width:17px;height:17px;border:1.5px solid var(--chrome);border-radius:5px;
  background:var(--panel)}
.nagcheck[aria-checked="true"]{color:var(--ink)}
.nagcheck[aria-checked="true"] .nagcheck-box{background:var(--ink);border-color:var(--ink)}
.nagcheck[aria-checked="true"] .nagcheck-box::after{content:'';width:8px;height:4px;margin-top:-2px;
  border:solid #fff;border-width:0 0 2px 2px;transform:rotate(-45deg)}

/* 하단 메뉴에 가리던 자리.
   두 가지가 겹쳤다 — (1) z-index 가 .nav(25)보다 낮아 메뉴가 위에 덮었고,
   (2) .nav 는 padding-bottom 에 env(safe-area-inset-bottom) 을 먹어 아이폰에서
   ~34px 더 커지는데 fab 의 bottom 은 고정이라 그만큼 메뉴 안으로 들어갔다.
   브라우저 탭에서는 안 보이고 홈 화면 앱에서만 드러난다. */
.fab{position:fixed;bottom:calc(88px + env(safe-area-inset-bottom));left:50%;
  transform:translateX(calc(-50% + 145px));
  width:58px;height:58px;border-radius:50%;border:none;background:var(--ink);color:#fff;
  font-size:27px;font-family:inherit;cursor:pointer;box-shadow:0 5px 18px rgba(38,51,58,.3);
  z-index:26}
.nav{position:fixed;bottom:0;width:100%;max-width:430px;background:rgba(255,255,255,.94);
  backdrop-filter:blur(12px);border-top:1px solid var(--line);display:flex;z-index:25;
  padding-bottom:env(safe-area-inset-bottom)}
.nav button{flex:1;background:none;border:none;padding:13px 0 15px;font-family:inherit;
  font-size:12px;font-weight:600;color:var(--chrome);cursor:pointer}
.nav button[aria-current="page"]{color:var(--ink)}
.nav .ic{display:block;font-size:19px;margin-bottom:2px}
.nav .ic .pigmark{display:block;width:23px;height:23px;margin:0 auto}

.scrim{position:fixed;inset:0;background:rgba(38,51,58,.42);z-index:40;opacity:0;
  pointer-events:none;transition:opacity .22s}
.scrim.on{opacity:1;pointer-events:auto}
.sheet{position:fixed;bottom:0;left:50%;transform:translate(-50%,100%);width:100%;max-width:430px;
  background:var(--panel);z-index:41;border-radius:20px 20px 0 0;
  padding:18px 20px calc(20px + env(safe-area-inset-bottom));
  transition:transform .28s cubic-bezier(.3,.8,.4,1);
  /* 내용이 길어지면 시트 안에서 스크롤되게. 없으면 위쪽이 화면 밖으로 잘린다 */
  max-height:85vh;overflow-y:auto;overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch}
/* 시트 안 제목은 스크롤해도 남아 있게 */
.sheet h2,.sheet-head{position:sticky;top:-18px;background:var(--panel);
  padding-top:2px;z-index:1}
.sheet.on{transform:translate(-50%,0)}
.sheet h2{font-size:16px;font-weight:800;margin-bottom:14px;padding-bottom:6px}
.sheet-head{display:flex;align-items:baseline;justify-content:space-between}
.linkbtn{background:none;border:none;font-family:inherit;font-size:13px;color:var(--cold);
  cursor:pointer;padding:0}
.amount-display{font-size:38px;font-weight:800;text-align:right;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;padding:6px 2px 12px;border-bottom:2px solid var(--ink)}
.amount-display.zero{color:var(--chrome)}
.picker{display:flex;gap:7px;overflow-x:auto;padding:14px 0;scrollbar-width:none}
.keypad{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;margin-top:4px}
.key{padding:15px 0;border:1px solid var(--line);background:var(--panel);border-radius:11px;
  font-family:inherit;font-size:20px;font-weight:600;color:var(--ink);cursor:pointer}
.key:active{background:var(--enamel)}
.save{width:100%;margin-top:11px;padding:16px;border:none;border-radius:13px;background:var(--ink);
  color:#fff;font-family:inherit;font-size:16px;font-weight:700;cursor:pointer}
.save:disabled{background:var(--chrome);cursor:default}
.save.danger{background:none;color:var(--danger);border:1px solid var(--line);margin-top:8px}
.sheet-note{font-size:12px;color:var(--ink-soft);margin-top:9px;text-align:center}
.help{border-bottom:1px solid var(--line)}
.help summary{padding:13px 2px;font-size:15px;font-weight:600;cursor:pointer;list-style:none;
  display:flex;justify-content:space-between;align-items:center;gap:10px}
.help summary::-webkit-details-marker{display:none}
.help summary::after{content:"+";color:var(--chrome);font-weight:400;font-size:19px}
.help[open] summary::after{content:"\2212"}
.help[open] summary{color:var(--cold)}
.help div{padding:0 2px 14px;font-size:14px;line-height:1.65;color:var(--ink-soft)}
.help b{color:var(--ink)}
.text-input{width:100%;border:1px solid var(--line);border-radius:10px;padding:12px;
  font-family:inherit;font-size:15px;color:var(--ink);margin-bottom:9px}
.suggest{display:flex;flex-direction:column;gap:4px;margin:-4px 0 9px}
.suggest-item{display:flex;justify-content:space-between;align-items:center;gap:8px;
  width:100%;padding:9px 12px;border:1px solid var(--line);border-radius:9px;
  background:var(--enamel);font-family:inherit;font-size:14px;color:var(--ink);cursor:pointer}
.suggest-item:hover{border-color:var(--cold)}
/* 돌아보기의 잔소리 집계 — 많이 들은 말 · 잔소리 많이 한 친구의 작은 제목 */
.tallyhead{font-size:12px;font-weight:700;color:var(--ink-soft);margin:10px 0 2px}
.nagtally .nagged{margin-top:4px}
/* 자주 쓰는 곳 — 이름 칸이 비었을 때 그 밑에 칩으로(app.js 의 freqHTML) */
.freqrow{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.freqlabel{font-size:12px;font-weight:700;color:var(--ink-soft);margin-right:2px}
.freqchip{border:1px solid var(--line);border-radius:999px;background:var(--panel);padding:6px 12px;
  font-family:inherit;font-size:13px;font-weight:600;color:var(--ink);cursor:pointer;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.freqchip:hover{border-color:var(--cold)}
/* 지출 감정(2026-10-26 — app.js 의 FEELINGS) — 묶음 색: 필요했던 청록 · 적절했던 초록 · 안 써도 됐던 분홍, 안 남김은 회색.
   고르는 칸(.feelpick — 묶음이 한 열, 머리에 묶음 이름) · 줄 꼬리표(.feeltag — .chip 과 따로: 그 달 시트 검사가 .chip 을
   탭 이름으로 센다) · 통계(.feelstats — 묶음 몫을 이은 막대와 묶음 줄) */
.feelpick{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:auto auto auto;
  grid-auto-flow:column;gap:5px 6px;margin:0 0 10px}
.feelhead{font-size:11px;font-weight:800;text-align:center;letter-spacing:.02em}
.feelbtn{min-height:36px;padding:4px 2px;border:1px solid var(--line);border-radius:10px;background:var(--panel);
  font:inherit;font-size:clamp(11.5px,3.4vw,13px);font-weight:700;letter-spacing:-.02em;line-height:1.2;color:var(--ink);
  word-break:keep-all;cursor:pointer;touch-action:manipulation}
.feelbtn[aria-pressed="true"]{color:#ffffff}
.feelhead.fg-need,.feeltag.fg-need{color:#2F6676}
.feelhead.fg-fine,.feeltag.fg-fine{color:#2F7550}
.feelhead.fg-waste,.feeltag.fg-waste{color:#B84E6E}
.feelbtn.fg-need[aria-pressed="true"]{background:#3F7A8B;border-color:#3F7A8B}
.feelbtn.fg-fine[aria-pressed="true"]{background:#3E8E5F;border-color:#3E8E5F}
.feelbtn.fg-waste[aria-pressed="true"]{background:#D0587C;border-color:#D0587C}
.feeltag{border-radius:5px;padding:1px 6px;font-size:11px;font-weight:700;white-space:nowrap}
.feeltag.fg-need{background:#E1EEF1}
.feeltag.fg-fine{background:#E3F2E8}
.feeltag.fg-waste{background:#FBE3EA}
.feelsum{font-size:13px;color:var(--ink-soft);margin-bottom:8px}
.feelsum b{color:#B84E6E}
.feelstack{display:flex;height:12px;border-radius:999px;overflow:hidden;background:var(--enamel);margin-bottom:8px}
.feelstack span{height:100%}
.feelstack span + span{border-left:2px solid var(--panel)}
.feelstack .fg-need,.feeldot.fg-need{background:#3F7A8B}
.feelstack .fg-fine,.feeldot.fg-fine{background:#3E8E5F}
.feelstack .fg-waste,.feeldot.fg-waste{background:#D0587C}
.feelstack .fg-none,.feeldot.fg-none{background:var(--chrome)}
.feelrow{display:flex;align-items:center;gap:8px;font-size:13px;padding:3px 0}
.feeldot{width:9px;height:9px;border-radius:50%;flex:none}
.feelname{flex:1;min-width:0;font-weight:700}
.feelrow.fg-none .feelname{font-weight:600;color:var(--ink-soft)}
.feelamt{color:var(--ink-soft);font-variant-numeric:tabular-nums;white-space:nowrap}
.feelparts{font-size:12px;color:var(--ink-soft);padding:0 0 4px 17px}
.feelempty{font-size:12px;color:var(--ink-soft)}
.budget-input{width:100%;border:none;border-bottom:2px solid var(--ink);font-family:inherit;
  font-size:34px;font-weight:800;text-align:right;padding:6px 2px 12px;color:var(--ink);
  font-variant-numeric:tabular-nums}
.budget-input:focus{outline:none}
/* 예산 금액 칸 밑의 단위 단추 — 위 줄 더하기 · 아래 줄 빼기, 다섯 칸씩 */
.amtsteps{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;margin:10px 0 6px}
.amtstep{min-height:34px;padding:0 2px;border:1px solid var(--line);border-radius:10px;background:var(--panel);
  font:inherit;font-size:13px;font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap;
  cursor:pointer;touch-action:manipulation}
.amtstep.minus{background:var(--enamel);color:var(--ink-soft)}
.amtstep:active{transform:scale(.96)}
/* 돼지 코인 — 오른쪽 위 단추(받을 퀘스트가 있으면 점), 코인 시트(퀘스트 · 상점 · 룰렛 · 내역) */
.pigcoin{flex:none;vertical-align:-.2em}
/* 아래 탭의 코인 — 아이콘 칸에 동전과 점(받을 퀘스트) */
.nav .coinic{position:relative;width:23px;height:23px;margin:0 auto 2px}
.nav .coinic .pigcoin{display:block}
.coindot{position:absolute;top:-2px;right:-4px;width:9px;height:9px;border-radius:50%;background:var(--danger);
  box-shadow:0 0 0 2px var(--enamel)}
.coinbal{font-size:17px;font-weight:800;color:var(--ink)}
.coinbal-in{display:inline-flex;align-items:center;gap:6px}
.questrow{display:flex;align-items:center;gap:10px;padding:12px;margin-bottom:8px;border:1px solid var(--line);
  border-radius:14px;background:var(--panel)}
.questrow.claimed{opacity:.6}
.questrow.bonus{border-style:dashed}
.questicon{font-size:22px;flex:none}
.questmain{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.questmain b{font-size:14px;color:var(--ink)}
.questmain span{font-size:12px;color:var(--ink-soft)}
.questbtn{display:inline-flex;align-items:center;gap:4px;flex:none;min-height:34px;padding:0 12px;border:none;
  border-radius:999px;background:var(--ink);color:#fff;font:inherit;font-size:13px;font-weight:800;cursor:pointer;
  touch-action:manipulation}
.questbtn:disabled{background:var(--enamel);color:var(--ink-soft);cursor:default}
.questdone{display:inline-flex;align-items:center;gap:4px;flex:none;font-size:13px;font-weight:800;color:var(--ink-soft)}
.questhead{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.questhead~.questhead{margin-top:22px}
.questcount{font-weight:800;color:var(--pig-line)}
.questleft{font-size:13px;font-weight:800;color:var(--ink-soft)}
/* 친구 도전 — 받은 도전장의 받기 · 거절, 연한 단추(거절 · 거두기), 도전장 창의 목표 고르기(app.js 의 challengeRow · paintChallenge) */
.chalbtns{display:flex;flex-direction:column;gap:6px;flex:none}
.questmain .chalwho{flex:none;width:3.6em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.questbtn.soft{background:var(--enamel);color:var(--ink)}
.chalgoals{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:6px}
.chalgoal{display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:12px;border:1px solid var(--line);
  border-radius:14px;background:var(--panel);font:inherit;text-align:left;color:var(--ink);cursor:pointer;touch-action:manipulation}
.chalgoal b{font-size:15px}
.chalgoal span:last-child{font-size:12px;color:var(--ink-soft)}
.chalgoal-icon{font-size:22px}
/* 주간 · 월간 퀘스트의 막대 — 센 값 / 목표(app.js 의 periodHTML) */
.questmain .questprog{display:flex;align-items:center;gap:6px;margin-top:3px;font-weight:700;font-variant-numeric:tabular-nums}
.questmain .questbar{flex:1;max-width:140px;height:6px;border-radius:999px;background:var(--enamel);overflow:hidden}
.questbar i{display:block;height:100%;border-radius:999px;background:var(--pig-deep)}
.orderlist{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}
.orderrow{display:flex;align-items:center;gap:8px;padding:8px 10px 8px 14px;border:1px solid var(--line);
  border-radius:12px;background:var(--panel)}
.ordername{flex:1;min-width:0;font-size:14px;font-weight:700;color:var(--ink);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.ordername .lock{font-size:11px;opacity:.75;margin-left:3px}
.orderbtn{flex:none;width:42px;height:36px;border:none;border-radius:10px;background:var(--enamel);color:var(--ink);
  font-size:13px;cursor:pointer}
.orderbtn:disabled{opacity:.35;cursor:default}
.shopgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.shopslot{margin:12px 2px 6px;font-size:12px;font-weight:800;color:var(--ink-soft)}
.shopslot:first-of-type{margin-top:4px}
.shopitem,.shoppack{display:flex;flex-direction:column;align-items:center;gap:4px;padding:10px 6px;
  border:1px solid var(--line);border-radius:14px;background:var(--panel);font:inherit;color:var(--ink);cursor:pointer;
  touch-action:manipulation}
.shopitem .decotile{width:56px;height:42px;border-radius:10px;background:var(--enamel)}
.shopitem.have{opacity:.65;cursor:default}
.shopname{font-size:12px;font-weight:700;color:var(--ink);text-align:center}
.shopprice{display:inline-flex;align-items:center;gap:3px;font-size:12px;font-weight:800;color:#b45309}
.shopitem.have .shopprice{color:var(--ink-soft)}
.shoppacks{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.shoppack{padding:12px 6px;font-size:14px;font-weight:800}
.decoprice{display:inline-flex;align-items:center;gap:2px;margin-top:1px;font-size:11px;font-weight:800;color:#b45309}
/* 한정 꾸미기(코인으로 못 산다) — 값 대신 🎁 한정. 알림함의 🎁 줄에는 받은 장식을 작게 */
.shopprice.limited,.decoprice.limited{color:var(--pig-line)}
.shopitem.have .shopprice.limited{color:var(--ink-soft)}
.dlglimited{margin-top:6px;font-weight:700;color:var(--pig-line)}
.notiftiles{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 2px}
.notiftiles .decotile{width:40px;height:32px;border-radius:8px;background:var(--enamel)}
.wheelbox{width:min(290px,82%);margin:2px auto 4px}
.wheel{display:block;width:100%;height:auto}
/* 바퀴는 app.js 가 Web Animations 로 돌린다(spinTo — 빨리 돌다 마지막 경계를 기어가며 넘는다). 바늘은 위 가운데를 축으로 튄다 */
.wheelspin{transform-box:view-box;transform-origin:0 0}
.wheelneedle{transform-box:fill-box;transform-origin:50% 0}
/* 글자 크기는 칸 너비에 맞춰 app.js 가 준다(wheelSVG — font-size 속성. 여기서 정하면 속성을 덮는다) */
.wheeltxt{font-weight:800;fill:#7c2d12;font-family:inherit}
.spinresult{min-height:26px;margin:2px 0 8px;text-align:center;font-size:16px;font-weight:800;color:var(--ink)}
.betbox{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:4px 0 0;padding:10px 14px;
  border:1px solid var(--line);border-radius:14px;background:var(--panel)}
.betlabel{font-size:14px;font-weight:700;color:var(--ink-soft)}
.betamt{display:inline-flex;align-items:center;gap:6px;font-size:22px;font-weight:800;color:var(--ink);
  font-variant-numeric:tabular-nums}
.betquick{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin:0 0 12px}
.betpick{min-height:34px;border:1px solid var(--line);border-radius:10px;background:var(--enamel);font:inherit;
  font-size:13px;font-weight:800;color:var(--ink);cursor:pointer;touch-action:manipulation}
.betpick:active{transform:scale(.96)}
.wheeltxt.hot{fill:#ffffff}
.spinnote{margin:8px 2px 0;font-size:12px;color:var(--ink-soft);text-align:center}
/* 룰렛 결과·잔액은 바퀴가 멈춘 뒤에 보인다 — 값은 이미 서버가 정했고, 보이는 때만 늦춘다(시간 재는 코드 없이) */
.late{display:inline-flex;align-items:center;gap:6px;animation:coinlate .35s ease-out 3.9s both}
@keyframes coinlate{from{opacity:0;transform:scale(.85)}to{opacity:1;transform:none}}
.rank-amt.plus{color:var(--cold);font-weight:800}
.rank-amt.minus{color:var(--ink-soft)}
/* 꽃가루 — 룰렛 ×5 · ×10 이 멈출 때(app.js 의 confetti). 화면을 덮지만 누르는 건 다 지나간다 — 시트(41) 위 · 확인 창(50)
   밑(check-pwa). 조각마다 날아가는 길이 달라서 움직임은 JS(Web Animations)가 그리고 여기는 모양만. 움직임 줄이기면 안 뜬다 */
.confetti{position:fixed;inset:0;z-index:45;pointer-events:none;overflow:hidden}
.cf{position:absolute;display:block;margin:-5px 0 0 -4px;border-radius:2px}
.cf-dot{border-radius:50%}
.cf-petal{border-radius:0 100% 0 100%}
@media (prefers-reduced-motion:reduce){.late{animation:none}.confetti{display:none}}
.calm .late{animation:none}.calm .confetti{display:none}
/* 친구 상세의 돼지 아래 — 그 친구의 돼지 마을로. 글자 링크였더니 눈에 안 띄었다 */
.villagego{display:inline-flex;align-items:center;gap:8px;margin-top:14px;padding:10px 14px 10px 16px;
  border:1px solid var(--line);border-radius:999px;background:var(--panel);font:inherit;font-size:14px;font-weight:700;
  color:var(--ink);cursor:pointer;touch-action:manipulation}
.villagego-go{color:var(--chrome);font-size:18px;line-height:1}
/* 예산 금액 칸 밑 — 목표 없음으로 되돌리기(칸만 비운다) */
.amtclear{margin:0 0 4px;padding:6px 0}
.code{background:var(--enamel);border-radius:11px;padding:16px;text-align:center;
  font-size:26px;font-weight:800;letter-spacing:.12em;font-variant-numeric:tabular-nums;
  margin-bottom:10px;user-select:all}
.invite-url{background:var(--enamel);border-radius:10px;padding:12px;font-size:13px;
  word-break:break-all;color:var(--ink-soft);margin-bottom:10px}
/* 결제 알림 — 단축어 만드는 법(설정의 결제 알림 칸) */
.paysteps{margin:10px 0 4px;padding-left:20px;font-size:13px;line-height:1.6;color:var(--ink-soft)}
.paysteps li{margin:0 0 4px}
.toggle{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--ink-soft);margin:2px 0 6px}

/* 확인 다이얼로그 — 시트보다 위에 뜬다 */
.scrim2{position:fixed;inset:0;background:rgba(38,51,58,.5);z-index:50;opacity:0;
  pointer-events:none;transition:opacity .18s}
.scrim2.on{opacity:1;pointer-events:auto}
.dialog{position:fixed;left:50%;top:50%;transform:translate(-50%,-46%) scale(.97);
  width:min(340px,calc(100% - 44px));background:var(--panel);border-radius:16px;
  padding:20px 20px 14px;z-index:51;opacity:0;pointer-events:none;
  box-shadow:0 14px 40px rgba(38,51,58,.28);
  transition:opacity .18s,transform .18s cubic-bezier(.3,.8,.4,1)}
.dialog.on{opacity:1;pointer-events:auto;transform:translate(-50%,-50%) scale(1)}
.dialog-title{font-size:16px;font-weight:800;margin-bottom:8px;line-height:1.4}
.dialog-body{font-size:14px;color:var(--ink-soft);line-height:1.6;margin-bottom:18px}
.dialog-body b{color:var(--ink)}
.dialog-actions{display:flex;gap:8px}
.dlg-btn{flex:1;padding:13px;border-radius:11px;border:1px solid var(--line);
  background:var(--panel);font-family:inherit;font-size:15px;font-weight:700;
  color:var(--ink-soft);cursor:pointer}
.dlg-btn.danger{background:var(--danger);border-color:var(--danger);color:#fff}
.dlg-btn.danger:disabled{background:var(--chrome);border-color:var(--chrome);cursor:default}
.dlg-btn.buy{background:var(--ink);border-color:var(--ink);color:#fff}
.dlg-btn.buy:disabled{background:var(--chrome);border-color:var(--chrome);cursor:default}
.dlgcoin{display:inline-flex;align-items:center;gap:3px;font-weight:800;color:#b45309;vertical-align:-2px}
/* 상점 미리보기 — 내 돼지에 입혀 본 모습 */
.dlgprev{margin:0 0 6px}
/* 개발자에게 커피값 — 금액 둘(결제는 준비 중 — 누르면 고른 칸만 칠하고 잠근다) */
.coffeepicks{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:14px 0 10px}
.coffeepick{display:flex;flex-direction:column;align-items:center;gap:4px;padding:16px 8px;border:1px solid var(--line);
  border-radius:14px;background:var(--panel);font:inherit;color:var(--ink);cursor:pointer;touch-action:manipulation}
.coffeepick .coffeeicon{font-size:26px;line-height:1.2}
.coffeepick b{font-size:18px}
.coffeepick span:last-child{font-size:12px;color:var(--ink-soft)}
.coffeepick.on{border-color:var(--pig-line);box-shadow:inset 0 0 0 2px var(--pig-line)}
.coffeepick:disabled:not(.on){opacity:.55;cursor:default}
.coffeenote{margin:0 0 6px;text-align:center;font-size:14px;font-weight:700;color:var(--ink);line-height:1.5}
.dlgprev svg{display:block;width:140px;height:auto;margin:0 auto}
.dlgshort{margin-top:6px;font-weight:700;color:var(--danger)}

.toast{position:fixed;bottom:150px;left:50%;transform:translateX(-50%) translateY(8px);
  background:var(--ink);color:#fff;padding:11px 19px;border-radius:999px;font-size:14px;
  font-weight:600;z-index:70;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s}
.toast.on{opacity:1;transform:translateX(-50%) translateY(0)}

.login{min-height:100vh;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:18px;padding:30px;text-align:center}
.login h1{font-size:26px;font-weight:800;letter-spacing:-.03em}
.login p{color:var(--ink-soft);font-size:15px;max-width:22em}
.login svg{width:230px;height:auto}
.gbtn{background:var(--ink);color:#fff;border:none;border-radius:13px;padding:15px 26px;
  font-family:inherit;font-size:15px;font-weight:700;cursor:pointer;text-decoration:none}
.login .warn{border:1px solid var(--pig-deep);background:#FDF2F5;border-radius:11px;
  padding:12px 14px;font-size:13px;color:var(--pig-line);max-width:24em}
.login .warn b{color:var(--pig-line)}
.login .fine{font-size:12px;color:var(--chrome);max-width:24em;margin-top:-4px}
@media (prefers-reduced-motion:reduce){*{transition-duration:.01ms !important}}
/* 앱 안 움직임 줄이기 스위치(html.calm) — 위 미디어 규칙들마다 짝을 둔다(check-pwa 가 대조). 클래스가 하나 더 붙어
   무거워서 파일 순서와 상관없이 이긴다 */
.calm *{transition-duration:.01ms !important}

/* 아래로 끌어당겨 새로고침.
   홈 화면에 추가하면 주소창이 없어 브라우저 새로고침을 쓸 수 없어서 직접 만든다.
   position:fixed 라 iOS 고무줄 스크롤에 본문이 밀려도 표시는 제자리에 있는다. */
.ptr{position:fixed;top:0;left:50%;z-index:30;width:36px;height:36px;
  display:flex;align-items:center;justify-content:center;font-size:19px;line-height:1;
  background:var(--panel);border:1px solid var(--line);border-radius:50%;
  box-shadow:0 2px 10px rgba(38,51,58,.14);
  transform:translate(-50%,-52px);opacity:0;pointer-events:none}
/* 손을 떼고 제자리로 돌아갈 때만 애니메이션. 끄는 동안은 손가락을 그대로 따라야 한다 */
.ptr.snap{transition:transform .26s cubic-bezier(.3,.8,.4,1),opacity .26s ease}
.ptr.ready{border-color:var(--pig-deep)}
.ptr.spin span{display:block;animation:ptrspin .9s linear infinite}
@keyframes ptrspin{to{transform:rotate(360deg)}}

/* 지출 사진. 파일은 R2 에 있고 주소에 photoKey 가 붙어 캐시가 자연히 갈린다 */
.txshot{display:block;width:88px;height:66px;margin-top:8px;padding:0;line-height:0;
  border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--enamel)}
.txshot img{width:100%;height:100%;object-fit:cover}

.pickshot{display:flex;align-items:center;gap:8px;width:100%;margin-top:10px;
  padding:12px 14px;border:1px dashed var(--line);border-radius:12px;
  background:var(--panel);color:var(--ink-soft);font-size:14px;cursor:pointer}
.pickshot.has{border-style:solid;color:var(--ink)}
.shotprev{margin-top:10px;border:1px solid var(--line);border-radius:12px;
  overflow:hidden;line-height:0}
.shotprev img{width:100%;max-height:220px;object-fit:cover}

/* 크게 보기. 시트(41)·확인창(51) 보다 위여야 수정 시트에서도 열린다 */
/* 사진 안의 두 손가락·이동은 app.js 가 직접 처리한다(touch-action:none).
   transform-origin 을 왼쪽 위로 둬야 "손가락 밑의 점이 제자리" 계산이 맞는다 */
.shotview{position:fixed;inset:0;z-index:60;background:rgba(24,32,36,.92);
  display:none;align-items:center;justify-content:center;padding:20px;
  touch-action:none;overflow:hidden}
.shotview.on{display:flex}
.shotview img{max-width:100%;max-height:100%;border-radius:10px;transform-origin:0 0;
  user-select:none;-webkit-user-select:none;-webkit-user-drag:none}
.shotview.zoomed img{border-radius:0}
.shotclose{position:absolute;top:calc(12px + env(safe-area-inset-top));right:12px;
  width:40px;height:40px;border-radius:50%;border:none;background:rgba(255,255,255,.16);
  color:#fff;font-size:24px;line-height:40px;cursor:pointer;font-family:inherit}
/* 사진을 못 불러왔을 때. 깨진 이미지 아이콘보다 빈 칸이 낫다.
   데모에서는 <img> 가 목 서버를 안 타서(목은 window.fetch 만 가로챈다) 늘 이 상태다 */
.txshot.noshot img,.shotprev.noshot img,.shotview.noshot img{display:none}
.txshot.noshot,.shotprev.noshot{display:flex;align-items:center;justify-content:center;
  color:var(--chrome);font-size:20px}
.txshot.noshot::after,.shotprev.noshot::after{content:'📷';opacity:.55}
.shotprev.noshot{height:120px}

/* 화면 확대·축소를 막는다 — 손가락으로는 스크롤만 된다.
   이 앱에서 키워 볼 건 영수증뿐이라 그건 사진 보기(.shotview) 안에서 따로 키운다.
   iOS 는 이 값만으로는 두 손가락 확대가 안 막혀서 app.js 가 gesture 이벤트도 막는다.
   덤으로 탭 지연도 사라진다 — 확대 가능한 페이지면 iOS 는 더블탭 확대인지 보려고
   탭마다 ~300ms 기다린 뒤 click 을 쏜다(키패드가 통째로 굼떠 보였다). */
html{touch-action:pan-x pan-y}
/* 위와 겹치지만 남겨 둔다. 확대를 다시 허락하게 되면 이 줄이 탭 지연을 막는다 */
button,a,label,.row{touch-action:manipulation}

/* 업데이트 공지 목록 */
ul.notice{margin:0;padding-left:18px;font-size:14px;line-height:1.6}
ul.notice li{margin-bottom:5px}
ul.notice li:last-child{margin-bottom:0}

/* ---------- 지출이 없는 날의 기록 ---------- */
/* 홈 맨 위의 이번 달 요약 (연속 기록 · 방패 알림 · 무지출 N일 · N원 참음) — 줄마다 쌓는다. 남기는 건 + 에서 한다 —
   예전에 여기 있던 "오늘 무지출 · 참았어요" 버튼은 뺐다. 이름이 마을 시트의 .monthsum(돼지 옆 숫자 — 가로 flex)과
   같았을 땐 그 규칙을 물려받아 연속 기록 줄과 요약이 옆으로 붙고 끝 글자만 다음 줄로 떨어졌다(2026-10-26) */
.todaysum{padding:12px 20px 0;text-align:center;font-size:12px;color:var(--ink-soft)}
.todaysum > div{text-wrap:balance}
/* " · " 사이의 덩어리 — 안에선 줄을 안 바꾼다(넘치면 덩어리 사이에서 넘어간다) */
.tseg{white-space:nowrap}
/* 연속 기록 (src/streaks.ts). 이번 달 요약 위에 한 줄 — 0 이면 안 뜬다. 어제가 비었으면 호박색 */
.streakline{font-size:13px;font-weight:800;color:var(--pig-line);margin-bottom:2px}
.streakline.gap{color:#B45309}
/* 청록 알약 버튼. 달력의 "어제 무지출로 남기기" 가 쓴다 */
.todaybtn{border:1px solid var(--line);background:var(--panel);border-radius:999px;
  padding:7px 14px;font-family:inherit;font-size:13px;font-weight:600;color:var(--cold);
  cursor:pointer;touch-action:manipulation}
.todaybtn:disabled{color:var(--chrome);border-color:var(--line);cursor:default}

/* 지출 줄과 구분되게 왼쪽에 색 띠를 둔다. 금액이 없는 줄이 섞여 있어서다 */
.row.log{border-left:3px solid var(--cold)}
.row.log.resist{border-left-color:var(--pig-deep)}
/* 사고싶다(2026-10-09) — 아직 안 산 것이라 노랑. 바꾸기는 줄이 아니라 상세 안에(2026-10-10) */
.row.log.want{border-left-color:#E8A33D}
.row.log .row-amt{color:var(--ink-soft);font-size:13px}
/* 기록 줄의 배경 효과(2026-10-21 요청 — 시안에서 고른 셋). 무지출은 해(오른쪽 끝에 걸린 해, 햇살이 30초에 한 바퀴),
   참았다는 방패(옅은 방패 위로 몇 초마다 빛이 지나간다), 사고싶다는 쇼윈도 전구(윗변 전구 두 줄이 번갈아 켜지고 오른쪽 위에서
   조명). 줄의 배경 · ::before · ::after 로만 그려 화면 코드는 그대로다 — 내 목록 · 친구 상세 · 피드 카드 · 마을의 지난 달이
   다 같은 줄이다. 글씨 · 도장 뒤에서만(z-index:-1 — 줄이 isolation 으로 판을 만든다, 잔소리 특수효과 칸과 같은 방법) 움직이고
   transform · opacity 만 움직인다. 움직임 줄이기와 마을(.monthlist — 지난 기록은 조용히)에서는 멈춘 한 장 — 방패의 빛은 기본
   자리가 줄 밖이라 움직일 때만 보인다 */
.row.log{position:relative;isolation:isolate;overflow:hidden}
.row.log.nospend{background:linear-gradient(90deg,rgba(219,240,244,0) 30%,rgba(219,240,244,.9)),var(--panel)}
.row.log.nospend::before{content:'';position:absolute;right:-74px;top:50%;width:200px;height:200px;margin-top:-100px;
  z-index:-1;pointer-events:none;background:repeating-conic-gradient(rgba(255,206,92,.32) 0 9deg,rgba(255,206,92,0) 9deg 24deg);
  -webkit-mask-image:radial-gradient(circle,#000 16%,transparent 68%);mask-image:radial-gradient(circle,#000 16%,transparent 68%);
  animation:lograys 30s linear infinite}
.row.log.nospend::after{content:'';position:absolute;right:-16px;top:50%;width:58px;height:58px;margin-top:-29px;
  z-index:-1;pointer-events:none;border-radius:50%;background:radial-gradient(circle,#FFE49A 0 40%,rgba(255,228,154,0) 72%)}
@keyframes lograys{to{transform:rotate(360deg)}}
.row.log.resist{background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 50'%3E%3Cg opacity='.2'%3E%3Cpath d='M22 2 L41 9 V24 C41 37 32 45 22 48 C12 45 3 37 3 24 V9 Z' fill='%23DE7093'/%3E%3Cpath d='M13 25 L20 32 L32 18' stroke='%23FFFFFF' stroke-width='4' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/g%3E%3C/svg%3E") no-repeat right 14px center/46px 52px,
  linear-gradient(90deg,rgba(222,112,147,.03),rgba(222,112,147,.11)),var(--panel)}
.row.log.resist::after{content:'';position:absolute;top:-12%;bottom:-12%;left:0;width:34%;z-index:-1;pointer-events:none;
  background:linear-gradient(90deg,rgba(255,255,255,0),rgba(255,255,255,.95) 50%,rgba(255,255,255,0));
  transform:translateX(-160%) skewX(-20deg);animation:logglint 3.6s ease-in-out infinite}
@keyframes logglint{0%,30%{transform:translateX(-160%) skewX(-20deg)}78%,100%{transform:translateX(400%) skewX(-20deg)}}
.row.log.want{background:radial-gradient(110% 90% at 88% -20%,rgba(255,210,130,.42),rgba(255,210,130,0) 62%),var(--panel)}
.row.log.want::before,.row.log.want::after{content:'';position:absolute;left:10px;right:10px;top:3px;height:8px;
  z-index:-1;pointer-events:none;
  background:radial-gradient(circle,#FFB938 0 2.2px,rgba(255,185,56,.35) 2.6px 3.6px,rgba(255,185,56,0) 4px) 0 0/18px 8px repeat-x;
  animation:logbulbs 1.4s steps(1,end) infinite}
.row.log.want::after{background-position:9px 0;animation-delay:-.7s}
@keyframes logbulbs{0%{opacity:1}50%{opacity:.18}}
@media (prefers-reduced-motion:reduce){.row.log.nospend::before,.row.log.resist::after,.row.log.want::before,.row.log.want::after{animation:none}}
.calm .row.log.nospend::before,.calm .row.log.resist::after,.calm .row.log.want::before,.calm .row.log.want::after{animation:none}
.monthlist .row.log.nospend::before,.monthlist .row.log.resist::after,.monthlist .row.log.want::before,.monthlist .row.log.want::after{animation:none}

/* + 시트 맨 위의 종류 고르기 (지출 / 무지출 / 참았다).
   .picker 와 달리 개수가 고정이라 가로 스크롤이 필요 없다 — .modes 는
   enhanceStrips 가 안 잡으니 화살표도 안 붙는다 */
.modes{display:flex;gap:6px;margin:0 0 14px}
.modebtn{flex:1;border:1px solid var(--line);background:var(--panel);color:var(--ink-soft);
  border-radius:10px;padding:9px 0;font-family:inherit;font-size:14px;font-weight:600;
  cursor:pointer;touch-action:manipulation}
.modebtn[aria-selected="true"]{background:var(--ink);border-color:var(--ink);color:#fff}

/* 엄마 화면에서 목표를 넘긴 새끼 요약.
   엄마 예산은 새끼들의 합이라 한 마리가 터져도 엄마는 멀쩡해 보인다 */
.overpigs{margin:12px 0 0;text-align:left}
.overpigs-head{font-size:12px;font-weight:700;color:var(--danger);padding:0 2px 6px}
.overpig{display:block;width:100%;text-align:left;background:var(--panel);
  border:1px solid var(--line);border-left:3px solid var(--danger);border-radius:10px;
  padding:9px 12px;margin-bottom:6px;font-family:inherit;cursor:pointer;
  touch-action:manipulation}
.overpig:active{background:#F6F9FA}
.overpig-main{display:flex;align-items:center;gap:10px}
.overpig-name{font-size:14px;font-weight:700;color:var(--ink);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.overpig-amt{font-size:14px;font-weight:800;color:var(--danger);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.overpig-meta{display:block;font-size:12px;color:var(--ink-soft);margin-top:2px}

/* 계정 화면의 목록.
   세 번 바뀌었다 — 알약 버튼 둘을 나란히 뒀더니 비좁아 안 읽혔고, 흰 카드(.row)로 두니
   지출 줄과 똑같이 생겨 누를 것으로 안 읽혔고, 진하게 칠했더니 진한 덩어리가 여섯 개가
   돼 무엇이 중요한 버튼인지 안 읽혔다("정신없다"). 지금은 **설정 화면의 모양**이다:
   한 장의 카드(.menugroup) 안에 줄을 모으고, 줄 사이는 가는 선, 오른쪽에 ›, 앞에 아이콘.
   지출 줄(떨어진 카드들)과 생김새가 달라 누를 것으로 읽힌다.
   **진한 채움은 화면의 주 버튼 하나(코드 복사)에만 쓴다.** */
.menugroup{background:var(--panel);border:1px solid var(--line);border-radius:13px;
  overflow:hidden}
.menugroup > .row{margin:0;border:none;border-radius:0;background:none}
.menugroup > .row + .row{border-top:1px solid var(--line)}
button.row.menurow,button.row.togglerow{display:block;width:100%;text-align:left;
  font-family:inherit;color:var(--ink);padding:13px 42px 13px 15px;cursor:pointer;
  position:relative;touch-action:manipulation}
button.row.menurow:active,button.row.togglerow:active{background:var(--enamel)}
button.row.menurow::after{content:'›';position:absolute;right:15px;top:50%;
  transform:translateY(-50%);color:var(--ink-soft);font-size:22px;line-height:1}
.menurow-main{display:block;font-size:15px;font-weight:700;color:var(--ink)}
.menurow-sub{display:block;font-size:12px;color:var(--ink-soft);margin-top:3px}
/* 설정의 돼지 그림 — 네 칸에 그 그림의 작은 돼지(위)와 이름(아래). 고른 칸은 진한 테두리 */
.pigstylepicks{display:grid;grid-template-columns:repeat(2, minmax(0, 1fr));gap:8px;margin-top:10px}
.pigstylepick{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:8px 6px;
  border:1px solid var(--line);
  border-radius:12px;background:var(--panel);font-family:inherit;font-size:14px;font-weight:700;color:var(--ink);
  cursor:pointer;touch-action:manipulation}
.pigstylepick .pigmark{width:30px;height:30px;flex:none}
.pigstylepick[aria-pressed="true"]{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
/* 로그아웃. 드물게 누르고 되돌리기 번거로운 것이라 빨간 글씨로만, 채우지 않는다 */
button.row.menurow.danger .menurow-main{color:var(--danger)}
button.row.menurow.danger::after{content:none}

/* 켜고 끄기는 버튼이 아니라 스위치다. 버튼은 "누르면 뭐가 되는지" 를 적어야 해서
   (알림 켜기 / 알림 끄기) 지금 켜져 있는지를 한 번 더 생각하게 한다 */
button.row.togglerow{padding-right:74px}
.switch{position:absolute;right:15px;top:50%;transform:translateY(-50%);width:46px;height:28px;
  border-radius:14px;background:var(--chrome);transition:background .15s}
.switch::after{content:'';position:absolute;top:3px;left:3px;width:22px;height:22px;
  border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.22);transition:transform .15s}
.togglerow[aria-checked="true"] .switch{background:var(--ink)}
.togglerow[aria-checked="true"] .switch::after{transform:translateX(18px)}
.togglerow:disabled{cursor:default;opacity:.6}

/* 닉네임은 입력칸 옆 작은 저장. **바꿨을 때만 켜진다** — 늘 켜져 있으면 진한 버튼이 하나
   더 생기고, 안 바꾼 걸 저장할 이유도 없다 */
.nickrow{display:flex;gap:8px;align-items:stretch}
.nickrow .text-input{margin:0;flex:1;min-width:0}
.inlinesave{flex:0 0 auto;border:none;border-radius:10px;background:var(--ink);color:#fff;
  font-family:inherit;font-size:14px;font-weight:700;padding:0 18px;cursor:pointer;
  touch-action:manipulation}
.inlinesave:disabled{background:var(--enamel);color:var(--chrome);cursor:default}

/* 돌아보기의 한 줄 평. 아래 숫자들보다 먼저 읽혀야 한다 */
.comment{margin:0 0 16px;padding:11px 13px;background:var(--enamel);border-radius:10px;
  font-size:14px;font-weight:700;text-align:center;color:var(--ink)}

/* 돌아보기에서 이전 기간으로 넘기는 줄 */
.revnav{display:flex;align-items:center;gap:8px;margin:-4px 0 12px}
.revlabel{flex:1;text-align:center;font-size:13px;color:var(--ink-soft)}
.revarrow{width:34px;height:34px;flex:0 0 auto;border-radius:50%;
  border:1px solid var(--line);background:var(--panel);color:var(--ink-soft);
  font-size:18px;line-height:1;font-family:inherit;cursor:pointer;
  touch-action:manipulation}
.revarrow:disabled{color:var(--line);cursor:default}

/* 많이 쓴 곳. 전체를 보여주되 시트가 끝없이 길어지지 않게 안쪽에서 스크롤한다.
   .sheet 가 이미 overscroll-behavior:contain 이라 바깥으로 안 새어나간다.
   높이는 6줄 남짓 — 마지막 줄이 살짝 잘려 보여야 더 있다는 게 읽힌다 */
.ranklist{max-height:238px;overflow-y:auto;overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch}

/* 돼지 물결. 한 바퀴에 pig.js 의 WAVE(90) 만큼 옮겨야 이음매가 안 보인다 —
   check-pwa 가 대조한다. 속도·방향·위상은 pig.js 가 돼지마다 인라인으로 준다 */
.pgflow{animation-name:pgflow;animation-timing-function:linear;
  animation-iteration-count:infinite}
@keyframes pgflow{from{transform:translateX(0)}to{transform:translateX(-90px)}}
/* 움직임 줄이기를 켠 사람에게는 물결을 멈춘다. 게이지는 수면 높이라 멈춰도 읽힌다 */
@media (prefers-reduced-motion:reduce){.pgflow{animation:none}}
.calm .pgflow{animation:none}

/* 개발자에게 잔소리하기. 도장은 잔소리 도장(.nag)과 같은 모양이고 하나만 고른다 */
.fbstamps{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.fbstamp{border:1px solid var(--line);background:var(--panel);border-radius:999px;
  padding:7px 12px;font-family:inherit;font-size:13px;color:var(--ink-soft);cursor:pointer;
  touch-action:manipulation}
.fbstamp.on{background:var(--pig);border-color:var(--pig-deep);color:#5C2439;font-weight:700}
.fbtext{resize:vertical;min-height:110px;line-height:1.5}

/* 업데이트마다 붙는 반응 줄. 공지 시트와 설정의 업데이트 내역에 같이 뜬다 */
.rxrow{margin-top:10px}
.rxbtns{display:flex;gap:6px}
.rxbtn{border:1px solid var(--line);background:var(--panel);border-radius:999px;
  padding:5px 11px;font-family:inherit;font-size:13px;color:var(--ink-soft);cursor:pointer;
  touch-action:manipulation}
.rxbtn.on{background:var(--ink);border-color:var(--ink);color:#fff;font-weight:700}
.rxnote{display:flex;gap:6px;margin-top:8px}
.rxnote .text-input{margin:0;padding:9px 11px;font-size:14px}
.rxsend{flex:0 0 auto;border:none;border-radius:10px;background:var(--ink);color:#fff;
  padding:0 14px;font-family:inherit;font-size:13px;font-weight:700;cursor:pointer}
.rxsend:disabled{opacity:.5}
.rxsent{margin-top:6px;font-size:12px;color:var(--ink-soft)}

/* 설정 맨 아래의 버전 칸. 예전에는 흐린 글자 한 줄이라 누를 수 있는 줄 몰랐다.
   업데이트 확인은 청록으로 채운다 — 진한 먹색 채움은 화면의 주 버튼 몫이다 */
.verrow{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 12px 10px 15px}
.verrow .menurow-main{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vernum{font-weight:600;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.verbtn{flex:0 0 auto;border:none;border-radius:999px;background:var(--cold);color:#fff;
  padding:8px 14px;font-family:inherit;font-size:13px;font-weight:700;cursor:pointer;
  touch-action:manipulation}
.verbtn:active{filter:brightness(.92)}

/* ---------- 달력 ----------
   홈 목록을 날짜 칸으로도 본다. 목록과 같은 것을 다른 모양으로 그린 것이다(app.js 의 homeScope).
   색은 이미 있는 뜻을 따른다 — 쓴 돈은 돼지처럼 **회색이 진할수록 많이 빠진 날**,
   무지출 선언은 기록 줄(.row.log)의 청록, 참은 날은 참았다 줄의 분홍 */
/* 목록 ↔ 달력. 탭 스트립 바로 아래 오른쪽 */
.viewbar{display:flex;justify-content:flex-end;margin:-4px 0 10px}
.viewseg{display:inline-flex;gap:2px;padding:2px;border:1px solid var(--line);
  border-radius:999px;background:var(--panel)}
.viewseg button{border:none;background:none;border-radius:999px;padding:4px 12px;
  font-family:inherit;font-size:12px;font-weight:700;color:var(--ink-soft);cursor:pointer;
  touch-action:manipulation}
.viewseg button[aria-pressed="true"]{background:var(--ink);color:#fff}

.calcard{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:8px 6px 10px}
/* minmax(0,1fr) — 1fr 만 쓰면 긴 금액이 칸을 밀어 일곱 칸 폭이 달라진다 */
.calhead,.calgrid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}
.calhead span{font-size:11px;font-weight:700;color:var(--ink-soft);text-align:center;padding:2px 0 5px}
.calday{position:relative;display:flex;flex-direction:column;align-items:center;gap:2px;
  min-width:0;min-height:50px;padding:5px 1px 4px;border:none;border-radius:9px;background:none;
  font-family:inherit;color:var(--ink);cursor:pointer;touch-action:manipulation}
.calnum{display:block;width:22px;height:22px;line-height:22px;border-radius:50%;
  font-size:12px;font-weight:700;font-variant-numeric:tabular-nums}
.calamt{display:block;max-width:100%;overflow:hidden;white-space:nowrap;
  font-size:10px;font-weight:600;line-height:1.3;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.calday.h1{background:rgba(38,51,58,.06)}
.calday.h2{background:rgba(38,51,58,.13)}
.calday.h3{background:rgba(38,51,58,.22)}
.calday.ns{background:#E1EEF1}
.calday.ns .calamt{color:var(--cold);font-weight:700}
/* 토요일 청록, 일요일 빨강. 아래 두 줄(아직 안 온 날, 오늘)이 이것을 덮는다 — 순서를 지킬 것 */
.calhead .sat,.calday.sat .calnum{color:var(--cold)}
.calhead .sun,.calday.sun .calnum{color:var(--danger)}
.calday.future .calnum{color:var(--chrome)}
.calday.today .calnum{background:var(--ink);color:#fff}
.calday[aria-pressed="true"]{box-shadow:inset 0 0 0 2px var(--ink)}
.caldot{position:absolute;top:5px;right:5px;width:6px;height:6px;border-radius:50%;
  background:var(--pig-deep)}
.callegend{display:flex;flex-wrap:wrap;justify-content:center;gap:4px 12px;margin-top:9px;
  font-size:11px;color:var(--ink-soft)}
.callegend span{display:inline-flex;align-items:center;gap:5px}
.calkey{display:inline-block;width:10px;height:10px;border-radius:3px}
.calkey.h2{background:rgba(38,51,58,.13)}
.calkey.ns{background:#E1EEF1;box-shadow:inset 0 0 0 1px var(--cold)}
.calkey.rs{width:6px;height:6px;border-radius:50%;background:var(--pig-deep)}
/* 고른 날. 목록의 하루 묶음(.daygroup)을 그대로 쓴다 */
.calpanel{margin-top:16px}
.calpanel .empty{padding:22px 16px}
.calnospend{margin:-10px 0 20px}
/* 방패 — 막은 날은 옅은 금빛에 🛡️, 막을 수 있는 빈 날은 점선 테두리만(칠하지 않는다 — 빈 날은 빈 칸) */
.calday.shd{background:#FFF4D6}
/* 막을 수 있는 날 — 금색 점선. 연회색이었더니 기록 있는 날의 회색 바탕에서 안 보였다. 고른 날의 안쪽 테두리(2px)와
   안 겹치게 4px 안에 */
.calday.gapday{outline:2px dashed #D9A400;outline-offset:-4px}
.calkey.gap{box-sizing:border-box;border:1.5px dashed #D9A400}
/* 나중에 적은 지출만 있는 날 — 왼쪽 위 (오른쪽 위는 참음 점) */
.callate{position:absolute;top:3px;left:4px;font-size:9px;line-height:1}
.calkey.shd{background:#FFF4D6;box-shadow:inset 0 0 0 1px #d9a400}
.calshield{margin:-10px 0 20px;padding:12px 14px;border:1px solid var(--line);border-radius:12px;
  background:var(--panel);font-size:13px;line-height:1.5;color:var(--ink-soft)}
.calshield .todaybtn{margin-top:10px}
.calshield.on{color:var(--ink)}
.calshield.early{margin:12px 0 0}
.calshield.shield-guide{margin:12px 0 20px}
.shield-guide b{display:block;color:var(--ink);margin-bottom:4px}
.calshield-left{margin-top:6px;font-size:11px;text-align:center}
.shieldhint{font-size:12px;color:var(--ink-soft);margin-top:3px}

/* ---------- 새 달 예산 ----------
   새 달이 시작되면 지난달 그대로 쓸지 묻고, 새로 정하면 새끼마다 지난달 결과·한 줄 평·목표 칸.
   두 번째 버튼(새로 정하기)은 채우지 않는다 — 진한 채움은 주 버튼 하나(그대로 쓰기)의 몫이다 */
.save.alt{background:none;color:var(--ink);border:1px solid var(--line);margin-top:8px}
.mbcard{border:1px solid var(--line);border-radius:13px;padding:12px 14px;margin-bottom:9px}
.mbhead{display:flex;align-items:center;gap:10px}
/* 돼지 viewBox 가 232x260 이라 폭 46 이면 높이가 52 쯤 된다. 목표 없던 새끼의 빈 자리도 같은 높이 */
.mbpig{flex:0 0 auto;width:46px}
.mbpig svg{display:block;width:100%;height:auto}
.mbblank{height:52px;border:1px dashed var(--line);border-radius:9px}
.mbwho{min-width:0}
.mbname{font-size:15px;font-weight:800}
.mbtabs{font-size:12px;color:var(--ink-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mbres{font-size:13px;margin-top:8px;font-variant-numeric:tabular-nums}
.mbres .over{color:var(--danger)}
.mbres .ok{color:var(--cold)}
.mbsay{font-size:13px;color:var(--ink-soft);margin-top:3px}
.mbamt{display:flex;align-items:center;gap:8px;margin-top:10px;
  font-size:13px;font-weight:700;color:var(--ink-soft)}
.mbamt .text-input{flex:1;min-width:0;margin:0;text-align:right;font-weight:800;color:var(--ink);
  font-variant-numeric:tabular-nums}
.mbtotal{display:flex;justify-content:space-between;align-items:baseline;margin:6px 2px 0;
  font-size:14px;color:var(--ink-soft)}
.mbtotal b{color:var(--ink);font-variant-numeric:tabular-nums}

/* 고정지출 진입 — + 시트에서 설명과 함께, 홈에서는 손가락으로 누르기 쉬운 버튼 */
.fixed-entry{display:flex;align-items:center;gap:10px;width:100%;padding:11px 13px;margin:0 0 12px;
  border:1px solid var(--cold);border-radius:12px;background:#EDF5F7;color:var(--ink);font:inherit;
  text-align:left;cursor:pointer;touch-action:manipulation}
.fixed-entry-icon{font-size:23px;flex:none}
.fixed-entry-copy{flex:1;min-width:0}
.fixed-entry-copy strong{display:block;font-size:14px}
.fixed-entry-copy span{display:block;font-size:12px;color:#42616C;line-height:1.5}
.fixed-entry > :last-child{font-size:24px;color:var(--cold)}
.fixed-entry:focus-visible,.budget-set.fixed-home:focus-visible{outline:3px solid var(--cold);outline-offset:3px}
.budget-set.fixed-home{min-height:44px;padding:9px 14px;border:1px solid var(--cold);border-radius:12px;
  background:#EDF5F7;font-weight:700;text-decoration:none}
.save.fixed-add{margin:0 0 16px}

/* 한정 뽑기 — 일반/한정/코인 결과를 같은 카드에, 차감과 실제 지급을 함께 표시한다. */
.gacha-box{padding:16px;border:1px solid var(--line);border-radius:18px;background:var(--panel);text-align:center}
.gacha-icon{margin:0 0 8px}.gacha-price{display:flex;gap:5px;justify-content:center;align-items:center;margin:10px 0}
.gacha-collection{background:var(--enamel);border-radius:12px;padding:12px;font-size:13px;line-height:1.8;margin:12px 0}
.gacha-result{border:2px solid var(--line);border-radius:16px;padding:16px;margin:14px 0;background:var(--panel)}
.gacha-limited{border-color:#b99b58;background:#fffaf0;color:#503f25}.gacha-grade{font-size:13px;font-weight:800}
.gacha-result p{font-size:13px;margin:8px 0;line-height:1.6}.gacha-art{height:100px;display:flex;align-items:center;justify-content:center;margin:8px 0}
.gacha-art>svg{max-width:130px;max-height:100px}.gacha-actions{display:flex;justify-content:center;gap:10px;flex-wrap:wrap;margin-top:12px}
.gacha-opening{padding:18px;font-size:16px}.gacha-odds,.gacha-pool{text-align:left;font-size:13px;line-height:1.7;margin-top:14px}
.gacha-odds summary,.gacha-pool summary{cursor:pointer;font-weight:700}.gacha-odds table{width:100%;border-collapse:collapse;margin:10px 0}
.gacha-odds td,.gacha-odds th{border-bottom:1px solid var(--line);padding:7px}.gacha-odds td:last-child{text-align:right}
.gacha-pool-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:8px}
.gacha-pool-list button{padding:9px;border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--ink);font:inherit}
.gacha-history{margin-top:20px}.gacha-history .row{text-align:left;justify-content:space-between;width:100%;font:inherit}
.gacha-history small{display:block;color:var(--ink-soft);font-size:11px;margin-top:4px}
.gacha-reveal{animation:gachaReveal .45s ease-out both}@keyframes gachaReveal{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
@media (prefers-reduced-motion:reduce){.gacha-reveal{animation:none}}.calm .gacha-reveal{animation:none}

.gacha-meta{display:block;color:var(--ink-soft);font-size:12px;margin-top:6px}

/* 상자 열기 — 유한 애니메이션 끝과 서버 응답을 함께 기다린다. */
.gacha-icon svg{display:block;margin:auto;overflow:visible}
.gacha-glow{opacity:0;transform-origin:80px 70px}
.gacha-unsealing .gacha-gift{transform-origin:80px 125px;animation:gachaShake .45s ease-in-out both}
.gacha-unsealing .gacha-lid{transform-origin:80px 70px;animation:gachaLid 1.1s ease-in-out both}
.gacha-unsealing .gacha-glow{animation:gachaGlow 1.1s ease-out both}
@keyframes gachaShake{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-6deg)}40%,80%{transform:rotate(6deg)}}
@keyframes gachaLid{0%,40%{transform:translateY(0) rotate(0)}75%{transform:translate(-8px,-35px) rotate(-16deg)}100%{transform:translate(-5px,-30px) rotate(-12deg)}}
@keyframes gachaGlow{0%,40%{opacity:0;transform:scale(.5)}75%{opacity:1;transform:scale(1.1)}100%{opacity:.8;transform:scale(1)}}
/* 폭죽은 시트 위에서, 입력을 가로막지 않고 짧게 사라진다. */
.gacha-fireworks{position:fixed;inset:0;z-index:55;overflow:hidden;pointer-events:none}
.gacha-spark{position:absolute;display:block;width:4px;height:12px;border-radius:4px;will-change:transform,opacity}
@media (prefers-reduced-motion:reduce){
  .gacha-unsealing .gacha-gift,.gacha-unsealing .gacha-lid,.gacha-unsealing .gacha-glow{animation:none}
  .gacha-fireworks{display:none}
}
.calm .gacha-unsealing .gacha-gift,.calm .gacha-unsealing .gacha-lid,.calm .gacha-unsealing .gacha-glow{animation:none}
.calm .gacha-fireworks{display:none}

/* 당첨 결과 — 뽑기 시트 위에, 작은 화면에서는 팝업 안에서 스크롤한다. */
.dialog.gacha-result-popup{width:min(360px,calc(100% - 32px));max-height:calc(100vh - 32px);max-height:calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 32px);overflow-y:auto;overscroll-behavior:contain}
.gacha-result-popup .dialog-title{text-align:center}
.gacha-result-popup .dialog-body{margin-bottom:12px;color:var(--ink)}
.gacha-result-popup .gacha-result{text-align:center;margin:0;padding:14px}
.gacha-result-popup .gacha-result h3{font-size:20px;overflow-wrap:anywhere}
.gacha-result-popup .dialog-actions .dlg-btn{background:var(--ink);color:#fff;border-color:var(--ink);min-height:44px}
@media (prefers-reduced-motion:reduce){.gacha-result-popup{transition:none}}
.calm .gacha-result-popup{transition:none}

/* 새 한정 당첨 전용: 열린 상자의 광채 → 금빛 팝업 → 별가루. 모두 한 번만 재생한다. */
.gacha-icon{position:relative;isolation:isolate}
.gacha-rare-opening{position:absolute;inset:0;pointer-events:none;z-index:-1}
.gacha-opening-rays,.gacha-opening-ring{position:absolute;left:50%;top:50%;width:210px;height:210px;margin:-105px;border-radius:50%}
.gacha-opening-rays{background:repeating-conic-gradient(from 0deg,#ffdf8580 0deg 10deg,transparent 10deg 30deg);mask-image:radial-gradient(circle,#000 10%,transparent 70%);animation:gachaGoldRays .95s ease-out both}
.gacha-opening-ring{border:3px solid #f9cf68;box-shadow:0 0 28px #ffce6a;animation:gachaGoldRing .95s ease-out both}
.gacha-opening-star{position:absolute;left:50%;top:50%;color:#c48a26;font-size:21px;font-style:normal;animation:gachaGoldStar .95s ease-out both}
.gacha-jackpot-opening .gacha-gift>rect{fill:#f6c64c;stroke:#a77420}
.gacha-jackpot-opening .gacha-glow{filter:drop-shadow(0 0 8px #ffc34d)}
@keyframes gachaGoldRays{from{opacity:0;transform:scale(.45) rotate(-25deg)}40%{opacity:1}to{opacity:0;transform:scale(1.5) rotate(25deg)}}
@keyframes gachaGoldRing{from{opacity:1;transform:scale(.2)}to{opacity:0;transform:scale(1.3)}}
@keyframes gachaGoldStar{from{opacity:0;transform:rotate(var(--angle)) translateY(-25px) scale(.2)}35%{opacity:1}to{opacity:0;transform:rotate(var(--angle)) translateY(-100px) scale(1.2)}}
.gacha-result-popup .gacha-limited{position:relative;overflow:hidden;background:linear-gradient(145deg,#fffdf4,#fff3ce);border-color:#d7a442}
.gacha-limited .gacha-art{position:relative;isolation:isolate}
.gacha-limited .gacha-art>svg{position:relative;z-index:1}
.gacha-rare-aura{position:absolute;width:148px;height:148px;left:50%;top:50%;transform:translate(-50%,-50%);border-radius:50%;background:radial-gradient(circle,#fff7d8 15%,#ffe09070 45%,transparent 70%);pointer-events:none}
.gacha-rare-fresh{border:2px solid #e4bc61;box-shadow:0 0 30px #f5cd6a60,0 18px 70px #49361380;animation:gachaRarePopup .65s cubic-bezier(.16,.9,.32,1.18) both}
.gacha-rare-fresh .dialog-title{color:#875c16}
.gacha-rare-fresh .gacha-rare-aura::before{content:"";position:absolute;inset:-12px;border-radius:50%;background:repeating-conic-gradient(#f9cf6870 0deg 8deg,transparent 8deg 30deg);mask-image:radial-gradient(circle,transparent 12%,#000 30%,transparent 70%);animation:gachaRareAura 2.4s ease-out both}
.gacha-rare-fresh .gacha-result::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(110deg,transparent 30%,#fff9 48%,transparent 65%);animation:gachaRareSheen 1.6s ease-out both}
@keyframes gachaRarePopup{from{opacity:0;transform:translate(-50%,-50%) scale(.78)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
@keyframes gachaRareAura{from{opacity:0;transform:rotate(-35deg) scale(.6)}25%{opacity:1}to{opacity:1;transform:rotate(40deg) scale(1)}}
@keyframes gachaRareSheen{from{transform:translateX(-120%)}to{transform:translateX(120%)}}
.gacha-spark{width:5px;height:16px;box-shadow:0 0 5px #ffe6a2a0}
.gacha-star{position:absolute;display:block;width:13px;height:13px;clip-path:polygon(50% 0,62% 35%,100% 50%,62% 65%,50% 100%,38% 65%,0 50%,38% 35%);will-change:transform,opacity}
@media (prefers-reduced-motion:reduce){
  .gacha-rare-opening{display:none}
  .gacha-rare-fresh,.gacha-rare-fresh .gacha-rare-aura::before,.gacha-rare-fresh .gacha-result::after{animation:none}
  .gacha-rare-fresh .gacha-result::after{display:none}
}
.calm .gacha-rare-opening{display:none}
.calm .gacha-rare-fresh,.calm .gacha-rare-fresh .gacha-rare-aura::before,.calm .gacha-rare-fresh .gacha-result::after{animation:none}
.calm .gacha-rare-fresh .gacha-result::after{display:none}

/* 받기를 누를 때 지급하는 관리자 전체 선물 */
.coin-gifts{margin-bottom:20px;padding:14px;border:1px solid #e3c58a;border-radius:16px;background:#fffbf1}
.coin-gifts h3{font-size:15px}.coin-gifts>.sheet-note{margin:5px 0 10px}
.coin-gift{display:flex;gap:12px;align-items:center;padding:12px 0;border-top:1px solid #e9dbbb}
.coin-gift>div{flex:1;min-width:0}.coin-gift b{overflow-wrap:anywhere;font-size:14px}
.coin-gift p{white-space:pre-wrap;overflow-wrap:anywhere;font-size:12px;color:var(--ink-soft);margin:5px 0}
.coin-gift strong{display:flex;align-items:center;gap:4px;font-size:14px;color:#875c16}
.coin-gift small{display:block;font-size:11px;color:var(--ink-soft);margin-top:5px}
.coin-gift button{flex:none;min-height:44px;min-width:56px}

/* 친구 지출 묶음과 명시적 확인 */
.expense-batch { border:1px solid var(--line,#e5e1dc); border-radius:16px; margin:14px 0; overflow:hidden; background:var(--paper,#fffdf9); }
.batch-heading { padding:16px; }
.batch-kicker { color:var(--muted,#817870); font-size:12px; margin-bottom:6px; }
.batch-title { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px; font-size:17px; }
.batch-dates { display:flex; flex-wrap:wrap; gap:6px; font-size:12px; color:var(--muted,#817870); margin-top:7px; }
.unread-chip { background:#fbe8d0; color:#91551a; font-size:11px; }
.late-chip { background:#eaf1ff; color:#416595; font-size:10px; }
.seen-label { color:var(--muted,#817870); font-size:11px; }
.entry-date { color:var(--muted,#817870); margin-left:5px; }
.seen-tx { font-size:12px; margin-top:7px; }
.catchup-go,.batch-seen { display:flex; justify-content:space-between; align-items:center; width:100%; padding:12px 16px; border:0; background:#f9eddd; color:#85531f; font-weight:700; font-size:13px; cursor:pointer; }
.catchup-go { border-radius:10px; margin:8px 0; }
.friend-reading { display:flex; gap:6px; padding-top:12px; scroll-margin-top:80px; }
.friend-reading button { flex:1; padding:10px 6px; border:1px solid var(--line,#e5e1dc); border-radius:10px; background:transparent; color:inherit; font-size:13px; cursor:pointer; }
.friend-reading button.on { background:#694c3c; color:white; border-color:#694c3c; }
.reading-hint { font-size:12px; line-height:1.6; color:var(--muted,#817870); margin:9px 0 16px; }
.expense-batch .row { padding-left:16px; padding-right:16px; }
.batch-expand { font-size:13px; }

/* 개인 잔소리 도장 */
.my-nag-picker { margin-top:12px; padding-top:10px; border-top:1px dashed var(--line); }
.my-nag-top,.my-nag-card-head,.my-nag-manage-row { display:flex; align-items:center; justify-content:space-between; gap:10px; }
.my-nag-top { color:var(--ink-soft); font-size:11px; margin-bottom:6px; }
.my-nag-top .linkbtn { font-size:11px; }
.my-nag-categories,.my-nag-options { display:flex; gap:6px; overflow-x:auto; padding:3px 0 7px; scrollbar-width:thin; }
.my-nag-categories button { flex:none; border:0; border-radius:7px; background:var(--enamel); color:var(--ink-soft); padding:5px 9px; font:inherit; font-size:11px; cursor:pointer; }
.my-nag-categories button.on { background:var(--cold); color:#fff; }
.my-nag-options .nag { flex:none; max-width:100%; white-space:normal; overflow-wrap:anywhere; text-align:left; }
.my-nag-note { text-align:left; margin:10px 0 16px; }
.my-nag-card { border:1px solid var(--line); border-radius:14px; padding:13px; margin-bottom:12px; }
.my-nag-card-head { margin-bottom:10px; }
.my-nag-card-head b { min-width:0; overflow-wrap:anywhere; }
.my-nag-card-head>div,.my-nag-manage-row>div { display:flex; flex:none; gap:9px; }
.my-nag-card .linkbtn { font-size:11px; }
.my-nag-manage-row { padding:8px 0; border-top:1px solid var(--enamel); }
.my-nag-manage-row>.nag { min-width:0; overflow-wrap:anywhere; white-space:normal; }
.my-nag-label { display:block; margin:14px 0 6px; color:var(--ink-soft); font-size:12px; }
.my-nag-entry { margin:12px 0 0; }
.feed-head { display:flex; justify-content:space-between; gap:12px; }
