/* ============================================================
   공통 베이스 — 폰트 + 라이트박스 기본 스타일의 "단일 소스".
   모든 레이아웃(layout/main · admin/shell)이 이 파일 하나만 import.
   화면마다 @font-face·리셋을 따로 박지 말 것.
   ============================================================ */

/* 폰트(omyu pretty) — 한 곳에서만 정의, 필요한 레이아웃이 이 파일을 import해 사용 */
@font-face {
    font-family: 'omyu pretty';
    src: url('/fonts/omyu_pretty.woff2') format('woff2');
    font-display: swap;
    size-adjust: 118%;
}

/* 모바일 화면 확대 막기(2026-10-26) — 더블탭·핀치로 화면 전체가 커지지 않게. 스크롤(pan)만 허용.
   🚨 라이트박스(#lightbox)는 뺀다 — 터치기기의 사진 확대가 브라우저 핀치줌이다(ui.js zoomed()). 거기 더블탭은 build() 의 manipulation 이 막는다.
   🚨 body·html 에는 걸지 말 것 — touch-action 은 조상과 교집합이라 라이트박스 핀치까지 죽는다.
   :where() = 특이도 0 → 기존 touch-action(pan-y·none·manipulation)이 그대로 이긴다. iOS 보조는 ui.js gesturestart. */
/* 앱(웹뷰)은 뺀다(0098, 사용자 지시) — 앱은 viewport 확대 끄기(ui.js lpZoomable)가 막는다. 이 터치 설정은 브라우저용. */
:where(html:not(.in-app) body *:not(#lightbox, #lightbox *)) { touch-action: pan-x pan-y; }
/* 🚨 아이폰은 manipulation 이어야 더블탭 판정이 꺼진다(0098) — pan-x pan-y 는 핀치만 막고 더블탭 판정은 남겨서, 한 손가락으로 빠르게
   다음 칸을 누르면 그 탭이 '더블탭의 두 번째'로 먹혀 취소됐다(인물 같이 찾기 연속 선택 빠짐). touch-action 은 조상과 교집합이라
   카드에만 걸어선 안 되고 전체를 바꾼다. 아이폰 핀치는 ui.js gesturestart 가 막는다. 안드로이드는 위 pan-x pan-y 그대로(핀치 차단).
   :where() 안에 다 넣어 특이도 0 유지 — 화면별 touch-action(pan-y·none)이 그대로 이긴다. html.ios = layout/main.jte */
:where(html.ios:not(.in-app) body *:not(#lightbox, #lightbox *)) { touch-action: manipulation; }

/* 라이트박스(ui.js #lightbox) 공통 기본스타일 —
   사용자 페이지는 Tailwind preflight가 깔리지만, 관리자 셸은 preflight가 없어서
   버튼 기본 회색/패딩·동영상 미축소 등 차이가 났음. 그 차이를 여기 한 곳에서 흡수.
   :where() = 특이도 0 → Tailwind 유틸(bg-white/15, max-w-full …)이 항상 정상 우선. */
:where(#lightbox), :where(#lightbox) * { box-sizing: border-box; }
:where(#lightbox) { font-family: 'omyu pretty', system-ui, -apple-system, sans-serif; }
:where(#lightbox) button {
    -webkit-appearance: none; appearance: none;
    background-color: transparent; background-image: none;
    border: 0; padding: 0; margin: 0; cursor: pointer;
    color: inherit; font-family: inherit; line-height: inherit;
}
:where(#lightbox) img, :where(#lightbox) svg, :where(#lightbox) video { display: block; }
:where(#lightbox) img, :where(#lightbox) video { max-width: 100%; height: auto; }
/* 동영상은 화면(뷰포트) 안에 contain — 잘리지 않게. 상단 X·정보 아이콘과 안 겹치게 위 공간(5.5rem) 확보 */
:where(#lightbox) .lb-stage video { max-height: calc(100vh - 5.5rem); object-fit: contain; }

/* ===== 공통 로딩 스피너 — leapfrog: 맨앞 점이 위로 튀어 맨뒤로 점프, 나머지는 앞으로 슬라이드(반복) ===== */
@keyframes lp-leap {
    0%   { transform: translate(0, 0); }                 /* slot0 — 제자리 2번 튀기 */
    6%   { transform: translate(0, -7px); }
    12%  { transform: translate(0, 0); }
    18%  { transform: translate(0, -7px); }
    22%  { transform: translate(0, 0); }
    25%  { transform: translate(7px, -12px); }           /* slot0→slot2 곡선 점프(맨앞→맨뒤) */
    28%  { transform: translate(14px, -16px); }
    31%  { transform: translate(21px, -12px); }
    33%  { transform: translate(28px, 0); }              /* slot2 착지 — 2번 튀기 */
    39%  { transform: translate(28px, -7px); }
    45%  { transform: translate(28px, 0); }
    51%  { transform: translate(28px, -7px); }
    55%  { transform: translate(28px, 0); }
    60%  { transform: translate(21px, -6px); }           /* 앞으로 슬라이드 → slot1 */
    66%  { transform: translate(14px, 0); }              /* slot1 — 2번 튀기 */
    72%  { transform: translate(14px, -7px); }
    78%  { transform: translate(14px, 0); }
    84%  { transform: translate(14px, -7px); }
    88%  { transform: translate(14px, 0); }
    94%  { transform: translate(7px, -6px); }            /* 앞으로 슬라이드 → slot0 */
    100% { transform: translate(0, 0); }
}
.lp-dots { position: relative; display: inline-block; width: 36px; height: 26px; }
.lp-dots > i { position: absolute; left: 0; bottom: 0; width: 8px; height: 8px; border-radius: 9999px; background: linear-gradient(135deg, #fb7185, #fb923c, #fbbf24); animation: lp-leap 4.5s infinite ease-in-out; }
.lp-dots > i:nth-child(2) { animation-delay: -1.5s; }
.lp-dots > i:nth-child(3) { animation-delay: -3s; }

/* ===== 공통 토스트 — 위에서 아래로 슬라이드. 다크(노을 테두리+노을 체크)로 상단 선택바(노을 알약)와 색으로 구분 ===== */
.lp-toast { position: fixed; top: 0; left: 50%; z-index: 400; max-width: 90vw;
    display: flex; align-items: center; gap: .5rem; padding: .6rem 1.05rem .6rem .58rem;
    border-radius: 9999px; color: #fff; font-weight: 700; font-size: .9rem; white-space: nowrap; pointer-events: none;
    border: 1.5px solid transparent;
    background: linear-gradient(#211b25, #211b25) padding-box, linear-gradient(135deg, #fb7185, #fb923c, #fbbf24) border-box;
    box-shadow: 0 12px 32px rgba(0,0,0,.34);
    transform: translate(-50%, -320%); transition: transform .5s cubic-bezier(.16,1,.3,1); }
.lp-toast.show { transform: translate(-50%, calc(4.8rem + env(safe-area-inset-top, 0px))); }
.lp-toast .lp-toast-ico { flex: none; width: 20px; height: 20px; border-radius: 9999px; display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, #fb7185, #fb923c, #fbbf24); box-shadow: 0 1px 3px rgba(0,0,0,.3); }
/* 토스트 내 '되돌리기'(휴지통 복원) 버튼 — 토스트는 pointer-events:none이라 버튼만 auto. */
.lp-toast .lp-toast-undo { pointer-events: auto; flex: none; display: inline-flex; align-items: center; gap: .22rem; margin-left: .35rem; padding: .28rem .78rem .28rem .62rem; border-radius: 9999px;
    background: linear-gradient(135deg, #fb7185, #fb923c, #fbbf24); color: #fff; font-weight: 800; font-size: .82rem; box-shadow: 0 1px 3px rgba(0,0,0,.35); }
.lp-toast .lp-toast-undo:active { opacity: .82; }

/* ===== 공통 선택 표시 — 노을 점(원 안 원). 메인·태그·가린항목·패밀리·인물·지역 그리드 모두 동일(.sel-check + [data-pid].is-sel) =====
   🚨 html.selecting 규칙은 **사진 그리드([data-photo-grid]) 안으로만** 건다(2026-09-16) — 인물 상세의 병합 패널 인물카드도 data-pid 를 달고 있어
   사진 선택 중에 같이 흐려지고 빈 동그라미가 떴다. 인물카드 선택은 html.people-selecting 이 따로 담당한다. */
html.selecting [data-photo-grid] .sel-check { display: flex; }
.sel-check { display: none; color: transparent; }
[data-pid].is-sel .sel-check::after { content: ''; display: block; width: 15px; height: 15px; border-radius: 9999px; background: linear-gradient(135deg, #fb7185, #fb923c, #fbbf24); }
/* 🚨 선택 표시 = **안 고른 것을 흐리게**(2026-09-01). 예전엔 고른 것에 주황 테두리를 둘렀는데,
   정사각 셀이 빽빽한 그리드에서 테두리가 사진을 잘라먹는 것처럼 보였다. 고른 것은 또렷하게 남기고 나머지를 죽인다. */
[data-pid].is-sel { border-radius: .5rem; }
html.selecting [data-photo-grid] [data-pid] { transition: opacity .15s ease; }
/* 선택모드: 옆으로 끌기 = 바로 범위선택(ui.js LPSelect·index.jte) — 브라우저가 옆 이동을 가로 스크롤/뒤로가기로 먹지 않게 세로만 허용 */
html.selecting [data-photo-grid] { touch-action: pan-y; }
html.selecting [data-photo-grid] [data-pid]:not(.is-sel) { opacity: .38; }

/* ===== 인물 카드(같이 찾기) 선택 표시 — 앱 공통 sel-check(원 안 원, 노을 점) 재사용. 원형 썸네일이라 코너 대신 원 가장자리에 배치(overflow 없는 .person-thumb 자식 → 안 잘림) + 사각 outline 대신 원 바깥 링 + 이름 하이라이트. ===== */
a.person-card.is-sel { outline: none; }   /* 위 [data-pid].is-sel 사각 outline 무효화(인물 카드는 원형 표시) */
.person-card { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
/* 🚨 길게 누를 때 iOS 가 <img> 를 집어 올려(링크 미리보기·드래그) 둥근 클립 없이 **네모**로 뜨던 것(2026-10-16) — 이미지는 터치 대상에서 뺀다 */
.person-card img, .lp-facecell img { pointer-events: none; -webkit-user-drag: none; -webkit-touch-callout: none; }   /* 롱프레스 선택모드 진입 시 iOS 링크 프리뷰/텍스트선택 방지 */
.person-card .sel-check { position: absolute; top: 5%; right: 5%; width: 24px; height: 24px; border-radius: 9999px; border: 2px solid rgba(255,255,255,.9); background: rgba(0,0,0,.28); align-items: center; justify-content: center; }
html.people-selecting .person-card .sel-check { display: flex; }   /* 선택모드: 미선택도 빈 원(선택 가능 표시) */
.person-card.is-sel .sel-check { display: flex; }                  /* 선택됨: 안쪽 노을 점은 공통 [data-pid].is-sel .sel-check::after 사용 */
.person-card.is-sel .ph-clip { box-shadow: 0 0 0 3px #fb923c; }
.person-card.is-sel .person-name { color: #f97316; font-weight: 700; }

/* ===== 가로 스크롤바 숨김 — 패밀리 상단 알약탭·구성원 필터 스트립 ===== */
.no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.no-scrollbar::-webkit-scrollbar { display: none; }

/* ===== 패밀리 구성원 필터 칩 — 기본 회색 테두리, 선택(is-on)=노을 채움 ===== */
.mem-chip { border-color: #e2e8f0; color: #64748b; background: #fff; }
.mem-chip.is-on { background: linear-gradient(135deg, #fb7185, #fb923c, #fbbf24); color: #fff; border-color: transparent; }
/* 특정 구성원 필터 선택 시 업로더 아바타 숨김(전체일 때만 표시) */
.hide-owner .owner-badge { display: none; }

/* ===== iOS 입력 포커스 자동 줌 방지 — 텍스트 입력류 최소 16px(핀치줌·라이트박스 줌은 유지). Tailwind text-sm(14px) 오버라이드 위해 :not 다중 지정으로 특이도 확보. ===== */
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]):not([type=color]),
textarea,
select { font-size: 16px; }

/* 인물 상세 '얼굴 보기' 다중선택(person-detail.jte) — 선택모드에선 ★/✕ 줄 숨기고 체크 원 */
.lp-facecell .face-check { display: none; position: absolute; top: 6%; right: 6%; width: 22px; height: 22px; border-radius: 9999px; border: 2px solid rgba(255,255,255,.9); background: rgba(0,0,0,.28); pointer-events: none; }
#face-grid.face-selecting .face-acts { display: none; }
#face-grid.face-selecting .face-check { display: block; }
#face-grid.face-selecting .lp-facecell:not(.is-fsel) { opacity: .55; }
#face-grid .lp-facecell.is-fsel { box-shadow: 0 0 0 3px #fb923c; }
#face-grid .lp-facecell.is-fsel .face-check { background: linear-gradient(135deg,#fb7185,#fb923c,#fbbf24); }

/* 인물 '같이 찾기' 하단 바 — 화면 폭 전체를 덮는 띠(투명)로 깔아, 버튼을 살짝 빗나간 탭이
   뒤 인물 카드로 새지 않게 막는다. 버튼 자체도 크게(높이 48px, 알약 전체가 눌림). 비었을 땐 숨김. */
#together-bar { position: fixed; left: 0; right: 0; z-index: 40; display: flex; justify-content: center; align-items: center;
  bottom: calc(var(--dock-c) - 32px); height: 64px; padding: 0 16px; background: transparent; }   /* 알약 가운데 = 하단 기준선(--dock-c, 아래 '하단 알약 기준선') */   /* 흰 그라데이션은 뒤 카드 이름을 흐리게 덮어 지저분했다(0026) — 띠는 투명하게, 탭만 막는다 */
#together-bar:empty { display: none; }
#together-bar .tg-pill { display: flex; align-items: stretch; min-height: 48px; border-radius: 9999px; overflow: hidden;
  box-shadow: 0 6px 16px rgba(251,146,60,.35); white-space: nowrap; }
#together-bar .tg-pill > * { display: flex; align-items: center; justify-content: center; font-size: 15px; color: #fff; }
#together-bar .tg-cancel { padding: 0 18px; color: rgba(255,255,255,.8); }
#together-bar .tg-sep { width: 1px; align-self: center; height: 20px; background: rgba(255,255,255,.3); flex: none; }
#together-bar .tg-go { padding: 0 24px; font-weight: 700; text-decoration: none; }
#together-bar .tg-hint { padding: 0 22px; color: rgba(255,255,255,.7); }
#together-bar .tg-go:active, #together-bar .tg-cancel:active { background: rgba(0,0,0,.08); }

/* ===== 추억(For You) — foryou.jte ===== */
.fy-wrap { padding: 4px 0 24px; }
.fy-family { display: flex; align-items: center; gap: 10px; margin: 0 0 14px; padding: 12px 14px; border-radius: 14px;
  background: #fff7ed; color: #9a3412; font-size: 14px; text-decoration: none; }
.fy-empty { text-align: center; color: #cbd5e1; padding: 64px 0; font-size: 14px; }
.fy-item { position: relative; flex: none; }
.fy-card { display: block; position: relative; overflow: hidden; border-radius: 16px; background: #e2e8f0; color: #fff; text-decoration: none; }
/* 추억 스켈레톤(2026-10-20) — 사진이 뜨기 전 카드는 빛이 지나가는 회색. 글자도 사진 뜬 뒤에(회색 위 흰 글씨가 안 읽혀서). */
.fy-card:not(.fy-ok) { background: linear-gradient(100deg, #e2e8f0 30%, #f1f5f9 50%, #e2e8f0 70%) 0 0 / 300% 100%; animation: fy-sk 1.4s linear infinite; }
.fy-card:not(.fy-ok) .fy-txt, .fy-card:not(.fy-ok) .fy-shade { opacity: 0; }
.fy-card .fy-txt, .fy-card .fy-shade { transition: opacity .4s ease; }
@keyframes fy-sk { from { background-position: 100% 0; } to { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .fy-card:not(.fy-ok) { animation: none; } }
.fy-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  pointer-events: none; -webkit-user-drag: none; -webkit-touch-callout: none; }
.fy-shade { position: absolute; inset: 0; background: linear-gradient(to top, rgba(0,0,0,.62), rgba(0,0,0,0) 55%); }
.fy-txt { position: absolute; left: 12px; right: 12px; bottom: 10px; display: flex; flex-direction: column; gap: 2px; text-shadow: 0 1px 3px rgba(0,0,0,.35); }
.fy-txt b { font-size: 16px; font-weight: 700; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.fy-txt small { font-size: 11.5px; opacity: .88; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fy-hero .fy-card { aspect-ratio: 4 / 5; max-height: 70vh; width: 100%; }
.fy-hero .fy-txt { left: 16px; right: 16px; bottom: 16px; }
.fy-hero .fy-txt b { font-size: 24px; }
.fy-hero .fy-txt small { font-size: 13px; }
.fy-more { position: absolute; top: 6px; right: 6px; width: 32px; height: 32px; border-radius: 9999px; display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.28); color: #fff; font-size: 18px; line-height: 1; letter-spacing: 1px; }
.fy-sec { margin: 18px 0 8px; font-size: 18px; font-weight: 700; color: #1e293b; }
.fy-row { display: flex; gap: 10px; overflow-x: auto; margin: 0 -16px; padding: 0 16px 4px; scroll-snap-type: x mandatory; scrollbar-width: none; }
.fy-row::-webkit-scrollbar { display: none; }
.fy-row .fy-item { width: 150px; scroll-snap-align: start; }
.fy-row .fy-card { aspect-ratio: 3 / 4; }
/* 추억 입체 카드 고리(0138 · 0139 큰 카드) — 섹션마다 한 줄. 카드 크기(--fw/--fh)·각도는 foryou.jte 가 화면 폭으로 정한다.
   카드 = 큰 네모 하나에 사진 한 장 또는 세 장(.fy-col), 양옆 카드가 가장자리에 살짝 보이는 캐로셀. 점 표시(인디케이터)는 없앰(0139).
   🚨 고리 안 카드(.fy-item)의 transform 은 스크립트 몫 — CSS 로 transform 을 걸지 말 것(.fy-card:active 의 scale 은 카드 안쪽이라 괜찮다). */
.fy-ring { position: relative; height: calc(var(--fh, 300px) + 26px); margin: 0 -16px; perspective: 1000px; perspective-origin: 50% 40%;
  overflow: hidden; touch-action: pan-y; -webkit-user-select: none; user-select: none; }
.fy-world { position: absolute; left: 50%; top: 6px; transform-style: preserve-3d; transform: rotateX(-5deg); }
/* 넓은 화면(0150) — 가운데 3장이 진짜 평면이게 줄 기울기(rotateX)를 뺀다. 바닥 그림자(.fy-ring::after)는 0150 에 없앰. */
.fy-flat .fy-world { transform: none; }
.fy-rg { position: absolute; transform-style: preserve-3d; }
.fy-rg .fy-item { position: absolute; top: 0; width: var(--fw, 280px); height: var(--fh, 300px); left: calc(var(--fw, 280px) / -2);
  backface-visibility: hidden; -webkit-backface-visibility: hidden; will-change: transform; }
/* 옆 카드 어둡게 = 진짜 덮개 요소(.fy-dim, 스크립트가 붙임)의 opacity. filter(0140 전)·CSS 변수 + ::after(0141 전)는 매 프레임 카드를 다시 그려 끊겼다. */
.fy-rg .fy-dim { position: absolute; inset: 0; z-index: 4; border-radius: 18px; background: #000; opacity: 0; pointer-events: none; will-change: opacity; }
/* 고리 줄은 통째로 흐려지며 올라오지 않는다 — 3D 위 투명도는 납작하게 다시 그려 첫 화면이 끊겼다(0140). 제목만 올라오고 카드는 살짝 돌며 등장. */
.fy-js .fy-block.fy-rv { opacity: 1; transform: none; transition: none; }
.fy-js .fy-block.fy-rv .fy-sec { opacity: 0; transform: translateY(14px); transition: opacity .5s ease-out, transform .6s cubic-bezier(.16, 1, .3, 1); }
.fy-js .fy-block.fy-rv.is-in .fy-sec { opacity: 1; transform: none; }
/* 카드 경계(0153) — 겹친 카드 사이가 구분되게 흰 테 + 옆 그늘. 그림자는 카드에 고정(움직일 때 바뀌지 않음)이라 다시 그리지 않는다. */
.fy-rg .fy-card { height: 100%; border-radius: 18px; box-shadow: 0 0 0 2px #fff, 0 8px 22px -6px rgba(30, 20, 10, .38); }
.fy-rg .fy-item:not(.front) .fy-more { display: none; }
/* 고리 카드 제목·장수 = 왼쪽 위(0149) — 오른쪽 위 '⋯' 자리만큼 비운다. 그늘도 위에서 아래로. */
.fy-rg .fy-txt { left: 16px; right: 52px; top: 14px; bottom: auto; }
.fy-rg .fy-shade { background: linear-gradient(to bottom, rgba(0,0,0,.58), rgba(0,0,0,0) 45%); }
.fy-rg .fy-txt b { font-size: 21px; }
.fy-rg .fy-txt small { font-size: 12.5px; }
.fy-foot { margin: 26px 0 0; text-align: center; font-size: 12px; color: #94a3b8; }
/* 추억 — 넘겨 보기(켄 번스): 사진을 겹쳐 두고 .on 만 보인다. .kb = 천천히 확대(기준점 --kx/--ky 무작위). 보이는 카드만 돈다(foryou.jte). */
.fy-card img { opacity: 0; transition: opacity 1.1s ease; transform-origin: var(--kx, 50%) var(--ky, 50%); }
/* 동영상 미리보기(0032) — 사진과 같은 자리에 겹쳐 두고 .on 이면 소리 없이 재생. 재생 중엔 작은 ▶ 표시 */
.fy-card video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .8s ease; pointer-events: none; }
.fy-card video.on { opacity: 1; }
.fy-card.fy-playing::before { content: ''; position: absolute; z-index: 3; top: 12px; left: 12px; width: 0; height: 0;
  border-left: 9px solid rgba(255,255,255,.92); border-top: 6px solid transparent; border-bottom: 6px solid transparent; filter: drop-shadow(0 1px 2px rgba(0,0,0,.4)); }
/* 🚨 iOS: 둥근 모서리 + overflow:hidden 은 확대(transform) 중인 자식을 제대로 못 자른다 → 카드가 레이어로 따로 그려지게(isolation·마스크) */
.fy-card { isolation: isolate; -webkit-mask-image: -webkit-radial-gradient(white, black); -webkit-user-drag: none; -webkit-touch-callout: none; user-select: none; }
.fy-row { overscroll-behavior-x: contain; scroll-padding-inline: 16px; }   /* 붙기(snap) 기준을 안쪽 여백에 — 넘치는 줄은 첫 카드가 왼쪽 끝에 딱 붙었다(2026-10-18) */
.fy-card img.on { opacity: 1; }
.fy-card img.kb { animation: fy-kb 7.5s ease-out forwards; }
.fy-card.fy-paused img.kb { animation-play-state: paused; }
@keyframes fy-kb { from { transform: scale(1); } to { transform: scale(1.16); } }
/* 스크롤 등장 — 아래에서 올라온다(yein 홈페이지 방식). JS 가 .fy-js 를 달았을 때만 숨김 → JS 없으면 그대로 보임 */
.fy-js .fy-rv { opacity: 0; transform: translateY(40px); transition: opacity .6s ease-out, transform .75s cubic-bezier(.16, 1, .3, 1); }
.fy-js .fy-rv.is-in { opacity: 1; transform: none; }
/* 숨긴 추억(맨 아래 접힘) · 카드 상세 '전체 보기' */
.fy-hidden { margin: 26px 0 0; }
.fy-hidden summary { cursor: pointer; font-size: 13px; color: #94a3b8; text-align: center; list-style: none; }
.fy-hidden summary::-webkit-details-marker { display: none; }
.fy-hid { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid #f1f5f9; }
.fy-hid img { width: 44px; height: 44px; border-radius: 10px; object-fit: cover; flex: none; }
.fy-hid span { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.fy-hid b { font-size: 14px; color: #334155; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fy-hid small { font-size: 11.5px; color: #94a3b8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fy-unhide { flex: none; padding: 6px 12px; border-radius: 9999px; font-size: 12.5px; font-weight: 600; color: #ea580c; background: #fff7ed; border: 1px solid #fed7aa; }
.fy-all { display: block; margin: 18px auto 0; padding: 12px; text-align: center; font-size: 14px; font-weight: 600; color: #ea580c; }
@media (prefers-reduced-motion: reduce) {
  .fy-card img.kb { animation: none; }
  .fy-js .fy-rv { opacity: 1; transform: none; transition: none; }
}

/* 저장 진행 패널 — 지금 받는 항목 점(깜빡임). ui.js saveActive */
.lp-sv-busy { background: #fb923c; animation: lp-sv-blink 1s ease-in-out infinite; }
@keyframes lp-sv-blink { 50% { opacity: .25; } }

/* ===== 움직임(0030) — 감사선포 챌린지처럼 '잘했어요' 순간에 반짝, 자주 보는 곳은 가볍게 ===== */
/* 톡 튀기(⭐ 켜기 등) */
.lp-pop { animation: lp-pop .5s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes lp-pop { 0% { transform: scale(1); } 35% { transform: scale(1.35); } 65% { transform: scale(.92); } 100% { transform: scale(1); } }
/* 별가루 — lpBurst 가 화면 고정 위치에 뿌린다 */
.lp-spark { position: fixed; z-index: 2147483000; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; border-radius: 9999px; pointer-events: none;
  animation: lp-spark .7s cubic-bezier(.15, .8, .3, 1) forwards; }
@keyframes lp-spark { 0% { transform: translate(0, 0) scale(1.2); opacity: 1; } 100% { transform: translate(var(--dx), var(--dy)) scale(0); opacity: 0; } }
/* 사진 목록 첫 화면 물결 — fill 은 backwards 만(끝난 뒤 셀의 선택 표시 transform 을 덮지 않게) */
.lp-wave { animation: lp-wave .45s cubic-bezier(.2, .8, .3, 1) backwards; }
@keyframes lp-wave { from { opacity: 0; transform: translateY(12px) scale(.95); } }
/* 바텀시트 — 살짝 튕기며 올라온다 · 뒤 어둠은 서서히 */
.lp-sheet-in { animation: lp-sheet-in .42s cubic-bezier(.2, 1.25, .4, 1) backwards; }
@keyframes lp-sheet-in { from { transform: translateY(100%); } }
.lp-ov-in { animation: lp-ov-in .25s ease-out backwards; }
@keyframes lp-ov-in { from { background-color: rgba(0, 0, 0, 0); } }
/* 추억 맨 위 큰 카드 — 나타날 때 빛이 한 번 쓸고 지나간다 */
.fy-hero .fy-card::after { content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgba(255,255,255,.38) 50%, transparent 65%); transform: translateX(-120%); }
.fy-hero.is-in .fy-card::after, .fy-wrap:not(.fy-js) .fy-hero .fy-card::after { animation: fy-sweep 1.3s .35s ease-in-out forwards; }
@keyframes fy-sweep { to { transform: translateX(120%); } }
@media (prefers-reduced-motion: reduce) {
  .lp-pop, .lp-wave, .lp-sheet-in, .lp-ov-in { animation: none; }
  .fy-hero .fy-card::after { display: none; }
}

/* ===== 움직임 2차(0031) ===== */
/* 선택 점이 톡 하고 찬다 */
[data-pid].is-sel .sel-check::after { animation: lp-dot-pop .32s cubic-bezier(.3, 1.7, .5, 1); }
@keyframes lp-dot-pop { from { transform: scale(0); } }
/* 추억 카드 열기 — 누른 카드가 화면 가득 커지며 넘어간다(fy-open 은 ui 가 아니라 foryou.jte 가 만든다) */
.fy-open { position: fixed; z-index: 90; background-size: cover; background-position: center; border-radius: 16px; pointer-events: none;
  transition: left .38s cubic-bezier(.2, .8, .2, 1), top .38s cubic-bezier(.2, .8, .2, 1), width .38s cubic-bezier(.2, .8, .2, 1), height .38s cubic-bezier(.2, .8, .2, 1), border-radius .38s ease, opacity .25s ease; }
.fy-card:active { transform: scale(.97); transition: transform .12s ease; }
@media (prefers-reduced-motion: reduce) {
  [data-pid].is-sel .sel-check::after { animation: none; }
  .fy-open { display: none; }
}

/* 패밀리 새 사진 띠 — 눈에 띄게(0031) */
.fy-wrap .fy-family { position: relative; overflow: hidden; color: #fff; font-weight: 600; text-decoration: none;
  background: linear-gradient(110deg, #fb7185, #fb923c, #fbbf24, #fb923c, #fb7185); background-size: 260% 100%;
  box-shadow: 0 8px 22px rgba(251,146,60,.38);
  animation: fy-fam-in .6s cubic-bezier(.2, 1.3, .4, 1) backwards, fy-fam-flow 5s linear infinite; }
.fy-wrap .fy-family b { font-weight: 800; font-variant-numeric: tabular-nums; }
.fy-wrap .fy-family::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgba(255,255,255,.45) 50%, transparent 65%); transform: translateX(-120%);
  animation: fy-sweep 1.2s .7s ease-in-out forwards, fy-fam-sweep 4.5s 3s ease-in-out infinite; }
.fy-fam-ico { position: relative; flex: none; width: 34px; height: 34px; border-radius: 9999px; background: rgba(255,255,255,.25);
  display: flex; align-items: center; justify-content: center; animation: fy-fam-wiggle 2.6s .8s ease-in-out infinite; }
.fy-fam-dot { position: absolute; top: 3px; right: 3px; width: 9px; height: 9px; border-radius: 9999px; background: #fff;
  box-shadow: 0 0 0 0 rgba(255,255,255,.8); animation: fy-fam-ping 1.6s ease-out infinite; }
.fy-fam-go { animation: fy-fam-nudge 1.4s ease-in-out infinite; }
.fy-wrap .fy-family:active { transform: scale(.98); }
@keyframes fy-fam-in { from { opacity: 0; transform: translateY(-14px) scale(.96); } }
@keyframes fy-fam-flow { to { background-position: 260% 0; } }
@keyframes fy-fam-sweep { 0%, 70% { transform: translateX(-120%); } 100% { transform: translateX(120%); } }
@keyframes fy-fam-wiggle { 0%, 70%, 100% { transform: rotate(0); } 76% { transform: rotate(-14deg); } 82% { transform: rotate(12deg); } 88% { transform: rotate(-8deg); } 94% { transform: rotate(4deg); } }
@keyframes fy-fam-ping { 0% { box-shadow: 0 0 0 0 rgba(255,255,255,.85); } 100% { box-shadow: 0 0 0 9px rgba(255,255,255,0); } }
@keyframes fy-fam-nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } }
@media (prefers-reduced-motion: reduce) {
  .fy-wrap .fy-family, .fy-wrap .fy-family::after, .fy-fam-ico, .fy-fam-dot, .fy-fam-go { animation: none; }
}

/* 추억 — 가로 카드에 세로 사진(0042): 사진은 통째로(contain), 뒤에 같은 사진을 흐리게 깔아 빈 곳을 채운다. foryou.jte fit() */
.fy-card img.fy-fit, .fy-card video.fy-fit { object-fit: contain; }
.fy-bd { position: absolute; inset: -30px; z-index: -1; background: center / cover no-repeat; filter: blur(28px) brightness(.82); opacity: 0; transition: opacity 1.1s ease; pointer-events: none; }
.fy-card img.on + .fy-bd, .fy-card video.on + .fy-bd { opacity: 1; }

/* PC 헤더 둘러보기 탭(0044) — 넓은 화면에서만. 모바일 하단 바처럼 고른 탭만 흰 알약 + 글자 */
.lp-hnav { display: none; }
@media (min-width: 1100px) {
  .lp-hnav { display: flex; align-items: center; gap: 2px; padding: 3px; margin-right: 6px; border-radius: 9999px; background: rgba(255,255,255,.18); box-shadow: inset 0 0 0 1px rgba(255,255,255,.35); }
  .lp-hnav a { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: 9999px; color: #fff; font-size: 14px; font-weight: 700; text-decoration: none; white-space: nowrap; transition: background .25s ease, color .25s ease, transform .15s ease; }
  .lp-hnav a svg { width: 18px; height: 18px; flex: none; transition: transform .35s cubic-bezier(.3,1.6,.5,1); }
  .lp-hnav a:hover { background: rgba(255,255,255,.18); }
  .lp-hnav a:hover svg { transform: rotate(-12deg) scale(1.12); }
  .lp-hnav a:active { transform: scale(.95); }
  .lp-hnav a.on { background: #fff; color: #f97316; box-shadow: 0 2px 8px rgba(0,0,0,.12); }
  .lp-hnav-dup { display: none !important; }
  header #hdr-title { position: static; transform: none; flex: 1; min-width: 0; margin-left: 14px; text-align: left; overflow: hidden; text-overflow: ellipsis; }   /* 가운데 제목은 탭과 겹친다 → 로고 옆으로 */   /* 추억·지역 동그라미는 탭에 이미 있다 */
}

/* 필수값 검사 표시(valid.js, 2026-10-19) — 걸린 첫 칸: 붉은 테두리 + 흔들림, 바로 아래 메시지. 전 화면 공통. */
.lp-invalid { border-color: #f43f5e !important; box-shadow: 0 0 0 3px rgba(244, 63, 94, .18) !important; outline: none !important; animation: lp-shake .38s ease; }
input[type=checkbox].lp-invalid { outline: 2px solid #f43f5e !important; outline-offset: 2px; }
.lp-invalid-msg { display: flex; align-items: center; gap: 6px; margin-top: 7px; color: #e11d48; font-size: 14px; font-weight: 600; line-height: 1.35; animation: lp-msg-in .2s ease backwards; }
.lp-invalid-msg svg { width: 16px; height: 16px; flex: none; }
@keyframes lp-shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-6px); } 40% { transform: translateX(5px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(2px); } }
@keyframes lp-msg-in { from { opacity: 0; transform: translateY(-4px); } }
/* 가운데 팝업(appSheet center) */
.lp-pop-in { animation: lp-pop-in .28s cubic-bezier(.2, 1.2, .4, 1) backwards; }
@keyframes lp-pop-in { from { opacity: 0; transform: translateY(14px) scale(.96); } }
@media (prefers-reduced-motion: reduce) { .lp-invalid, .lp-invalid-msg, .lp-pop-in { animation: none; } }

/* 추억 모자이크(2026-10-20) — 아이폰 보관함처럼 섹션마다 크기를 섞어 빈칸 없이 채운다. 배치는 foryou.jte layout() 이 칸 수(--c: 3·4·6·8)에 맞춰
   grid-column/row 를 직접 넣는다. 한 칸 높이 = 한 칸 너비(cqw — .fy-bento 가 컨테이너). data-sz: s 작은 · w 가로 · t 세로 · b 큰. */
.fy-wrap { --g: 8px; }
.fy-secs { display: flex; flex-wrap: wrap; align-items: flex-start; column-gap: var(--g); }
.fy-secs > .fy-block { width: 100%; min-width: 0; }
.fy-bento { container-type: inline-size; }
.fy-bg { --c: 3; display: grid; gap: var(--g); grid-template-columns: repeat(var(--c), minmax(0, 1fr));
  grid-auto-rows: calc((100cqw - (var(--c) - 1) * var(--g)) / var(--c)); }
.fy-bg .fy-item { min-width: 0; min-height: 0; }
.fy-bg .fy-card { height: 100%; border-radius: 14px; }
.fy-bg [data-sz="s"] .fy-txt { left: 9px; right: 9px; bottom: 8px; }
.fy-bg [data-sz="s"] .fy-txt b { font-size: 13px; -webkit-line-clamp: 1; }
.fy-bg [data-sz="s"] .fy-txt small { font-size: 10.5px; }
.fy-bg [data-sz="s"] .fy-more { width: 26px; height: 26px; top: 4px; right: 4px; font-size: 15px; }
.fy-bg [data-sz="w"] .fy-txt b, .fy-bg [data-sz="t"] .fy-txt b { font-size: 15px; }
.fy-bg [data-sz="b"] .fy-txt { left: 14px; right: 14px; bottom: 13px; }
.fy-bg [data-sz="b"] .fy-txt b { font-size: 20px; }
.fy-bg [data-sz="b"] .fy-txt small { font-size: 12.5px; }
@media (min-width: 960px) {
  .fy-wrap { --g: 10px; }
  .fy-bg .fy-card { border-radius: 16px; }
  .fy-bg [data-sz="b"] .fy-txt b { font-size: 24px; }
  .fy-sec { font-size: 21px; margin-top: 30px; }
}
/* 등장 — 섹션이 보이면 카드가 순서대로 톡톡 튀어나온다(--i). 가로 스크롤 줄이 아니라 transform 괜찮다. */
.fy-js .fy-bg .fy-item { opacity: 0; transform: translateY(18px) scale(.94); transition: opacity .5s ease-out, transform .65s cubic-bezier(.2, 1.3, .35, 1); }
.fy-js .fy-block.is-in .fy-bg .fy-item { opacity: 1; transform: none; transition-delay: calc(min(var(--i, 0), 10) * 55ms); }
/* 콜라주 — 카드 한 장 안에 사진 3장(큰 1 + 작은 2). 한 칸씩 바뀐다(colTick). */
.fy-col { position: absolute; inset: 0; display: grid; gap: 3px; grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; background: #fff; }
.fy-col .fy-cc { position: relative; overflow: hidden; background: #e2e8f0; }
.fy-col .fy-cc:first-child { grid-row: 1 / 3; }
.fy-col-r { grid-template-columns: 1fr 2fr; }
.fy-col-r .fy-cc:first-child { grid-column: 2; }
.fy-col-r .fy-cc:nth-child(2) { grid-column: 1; grid-row: 1; }
.fy-col-r .fy-cc:nth-child(3) { grid-column: 1; grid-row: 2; }
@media (prefers-reduced-motion: reduce) {
  .fy-js .fy-bg .fy-item { opacity: 1; transform: none; transition: none; }
}
/* 추억 카드 상세 — 언제·어디·몇 장 (2026-10-20: 작은 회색이라 안 보였다) */
.fy-sub { margin: 0; padding: 12px 16px 14px; font-size: 15px; font-weight: 600; line-height: 1.45; color: #334155; letter-spacing: -.01em; }
@media (min-width: 960px) { .fy-sub { font-size: 17px; padding: 16px 20px 18px; } }
/* 인물 목록 — 이름 글씨를 누르면 바로 이름 바꾸기(2026-10-20). 연필로 누를 수 있음을 알린다(같이 찾기 중엔 숨김). */
#people-grid .person-name, #pinned-grid .person-name { cursor: text; }
#people-grid .person-name::after, #pinned-grid .person-name::after { content: ' ✎'; font-size: 11px; font-weight: 400; color: #94a3b8; }
.people-selecting #people-grid .person-name::after, .people-selecting #pinned-grid .person-name::after { content: none; }

/* 인물 상세 탭 + 성장·함께 앨범(2026-10-20) */
.pd-tabs { display: flex; gap: 4px; padding: 4px; margin: 2px 0 16px; border-radius: 9999px; background: #f1f5f9; }
.pd-tabs button { flex: 1; padding: 9px 0; border-radius: 9999px; font-size: 14.5px; font-weight: 700; color: #64748b; transition: background .2s, color .2s, box-shadow .2s; }
.pd-tabs button.on { background: #fff; color: #ea580c; box-shadow: 0 1px 4px rgba(15,23,42,.12); }
.pd-off-photos #lp-sel-bar, .pd-off-photos #face-sel-bar { display: none !important; }
.al-wrap { padding-bottom: 96px; }
.al-nothing { text-align: center; color: #94a3b8; font-size: 14px; padding: 48px 0; line-height: 1.6; }
.al-birth { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-radius: 16px; background: linear-gradient(135deg, #fff1f2, #fff7ed); border: 1px solid #fed7aa; }
.al-cake { font-size: 24px; line-height: 1; flex: none; }
.al-bt { flex: 1; min-width: 0; font-size: 14.5px; color: #334155; line-height: 1.4; }
.al-bt b { color: #0f172a; }
.al-bt small { display: block; font-size: 12px; color: #94a3b8; margin-top: 2px; }
.al-btn { flex: none; padding: 7px 13px; border-radius: 9999px; font-size: 13px; font-weight: 700; color: #ea580c; background: #fff; border: 1px solid #fdba74; }
.al-btn-on { color: #fff; background: linear-gradient(135deg, #fb7185, #fb923c); border: 0; box-shadow: 0 2px 8px rgba(251,113,133,.35); }
.al-hint { margin: 10px 2px 2px; font-size: 12.5px; color: #64748b; line-height: 1.5; }
.al-hint b { color: #e11d48; }
.al-gt { margin: 20px 2px 10px; font-size: 16px; font-weight: 800; color: #1e293b; }
.al-grid { display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
@media (min-width: 960px) { .al-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; } }
.al-tile { position: relative; display: block; aspect-ratio: 1 / 1; border-radius: 14px; overflow: hidden; background: #e2e8f0; color: #fff; text-decoration: none; }
.al-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.al-tile:active { transform: scale(.97); transition: transform .12s ease; }
.al-shade { position: absolute; inset: 0; background: linear-gradient(to top, rgba(0,0,0,.6), rgba(0,0,0,0) 58%); }
.al-lab { position: absolute; left: 9px; right: 9px; bottom: 8px; display: flex; flex-direction: column; gap: 1px; text-shadow: 0 1px 3px rgba(0,0,0,.35); }
.al-lab b { font-size: 14px; font-weight: 800; line-height: 1.2; }
.al-lab small { font-size: 10.5px; opacity: .9; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.al-empty { background: #f8fafc; border: 2px dashed #e2e8f0; color: #94a3b8; }
.al-empty .al-lab { text-shadow: none; top: 9px; bottom: auto; }
.al-empty .al-lab b { color: #64748b; }
.al-none { position: absolute; left: 0; right: 0; bottom: 10px; text-align: center; font-size: 11.5px; color: #cbd5e1; }
.al-pk { position: absolute; top: 6px; right: 6px; min-width: 24px; height: 24px; padding: 0 7px 0 22px; border-radius: 9999px; font-size: 12px; font-weight: 800; line-height: 24px; color: #fff;
  background: #e11d48 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M6 3h12v18l-6-4-6 4z'/%3E%3C/svg%3E") no-repeat 6px 50% / 12px; box-shadow: 0 1px 4px rgba(0,0,0,.25); }
.al-comps { display: flex; gap: 10px; overflow-x: auto; margin: 0 -16px; padding: 6px 16px 8px; scrollbar-width: none; }
.al-comps::-webkit-scrollbar { display: none; }
.al-comp { flex: none; width: 72px; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.al-face { width: 60px; height: 60px; border-radius: 9999px; overflow: hidden; background: #e2e8f0; box-shadow: 0 0 0 2px #fff, 0 0 0 4px transparent; transition: box-shadow .2s; }
.al-face img { width: 100%; height: 100%; object-fit: cover; }
.al-comp.on .al-face { box-shadow: 0 0 0 2px #fff, 0 0 0 4px #fb923c; }
.al-comp b { font-size: 12.5px; color: #334155; max-width: 72px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 4px; }
.al-comp.on b { color: #ea580c; }
.al-comp small { font-size: 10.5px; color: #94a3b8; }
.al-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 8px; }
.al-who { font-size: 14px; color: #475569; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.al-who b { color: #0f172a; }
.al-seg { flex: none; display: flex; padding: 3px; border-radius: 9999px; background: #f1f5f9; }
.al-seg button { padding: 5px 12px; border-radius: 9999px; font-size: 12.5px; font-weight: 700; color: #64748b; }
.al-seg button.on { background: #fff; color: #ea580c; box-shadow: 0 1px 3px rgba(15,23,42,.12); }
/* 칸 화면 — 포토북에 담은 사진 책갈피 */
[data-photo-grid] [data-book="1"]::after { content: ''; position: absolute; left: 5px; bottom: 5px; width: 22px; height: 22px; border-radius: 9999px; pointer-events: none;
  background: #e11d48 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M6 3h12v18l-6-4-6 4z'/%3E%3C/svg%3E") no-repeat 50% 50% / 12px; box-shadow: 0 1px 4px rgba(0,0,0,.3); }
html.pd-merging:has(#merge-panel:not(.hidden)) #lp-sel-bar { display: none !important; }   /* 인물 합치기 버튼이 떠 있는 동안 사진 선택 알약 숨김(다른 화면으로 가면 :has 가 풀려 자동 복귀) */
/* 좁은 화면(폴드 접은 화면 ~360px, 2026-10-20) — 헤더 제목이 로고와 겹치면 사이 공간만(layout/main.jte fit) · 보기 바 버튼 여백 줄이기 */
header.hdr-tight #hdr-title { display: block; position: static; transform: none; flex: 1; min-width: 0; text-align: center; overflow: hidden; text-overflow: ellipsis; font-size: 15px; }
@media (max-width: 460px) {   /* 460: 마이크 버튼(0087)이 들어가며 아이폰 프로맥스(430)~455px 에서 넘쳤다(하네스 실측) */
  #lp-tools > div > button, #lp-tools > div > a { padding-left: 8px; padding-right: 8px; }
  #lp-tools [data-view-toggle] span { display: none; }   /* '정사각/비율' 글자 빼고 아이콘만 */
}
@media (max-width: 360px) {
  header a.shrink-0 img { height: 30px; }
  #lp-tools > div { font-size: 13px; }
  #lp-tools > div > button, #lp-tools > div > a { padding-left: 6px; padding-right: 6px; }
}
header.hdr-tight a.shrink-0 img { height: 30px; }   /* 제목이 빠듯하면 로고를 조금 줄여 제목 자리를 넓힌다 */

/* ── 라이트박스 동영상 재생바 + 미리보기 (ui.js vctl, 0069) ──
   브라우저 기본 컨트롤 대신 우리 재생바. 영상 아래쪽 안에 겹쳐 그린다(예전 기본 컨트롤 자리). */
#lightbox .lb-vbar { position: absolute; left: 0; right: 0; bottom: 0; z-index: 5; display: flex; align-items: center; gap: 6px;
  padding: 26px 8px 6px; color: #fff; background: linear-gradient(to top, rgba(0,0,0,.62), rgba(0,0,0,0));
  transition: opacity .25s ease; -webkit-user-select: none; user-select: none; }
#lightbox .lb-vbar.lb-vidle, #lightbox.lb-immersive .lb-vbar { opacity: 0; pointer-events: none; }
#lightbox .lb-vbtn { width: 34px; height: 34px; flex: none; display: flex; align-items: center; justify-content: center; border-radius: 9999px; color: #fff; }
#lightbox .lb-vbtn svg { width: 20px; height: 20px; filter: drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
#lightbox .lb-vbtn:active { transform: scale(.9); }
#lightbox .lb-vtime, #lightbox .lb-vdur { flex: none; font-size: 12px; font-variant-numeric: tabular-nums; text-shadow: 0 1px 2px rgba(0,0,0,.6); }
/* 손가락으로 잡기 쉽게 터치 영역은 크게(28px), 선은 가늘게. touch-action:none = 끄는 동안 화면 스크롤·제스처 안 생김 */
#lightbox .lb-vtrack { position: relative; flex: 1 1 auto; min-width: 40px; height: 28px; cursor: pointer; touch-action: none; }
#lightbox .lb-vline { position: absolute; left: 0; right: 0; top: 50%; height: 4px; margin-top: -2px; border-radius: 9999px; background: rgba(255,255,255,.28); overflow: hidden; transition: height .15s ease, margin-top .15s ease; }
#lightbox .lb-vtrack:hover .lb-vline, #lightbox .lb-vscrub .lb-vline { height: 6px; margin-top: -3px; }
#lightbox .lb-vbuf { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: rgba(255,255,255,.35); }
#lightbox .lb-vfill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: linear-gradient(90deg, #FB7185, #FB923C, #FBBF24); }
#lightbox .lb-vknob { position: absolute; top: 50%; left: 0; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 9999px; background: #fff;
  box-shadow: 0 1px 4px rgba(0,0,0,.45); transition: transform .12s ease; pointer-events: none; }
#lightbox .lb-vscrub .lb-vknob { transform: scale(1.35); }
/* 미리보기 말풍선 — 재생바 위. 장면은 모음 이미지의 칸을 background-position 으로 잘라 보여 준다 */
#lightbox .lb-vprev { position: absolute; bottom: 30px; left: 0; transform: translateX(-50%); display: none; flex-direction: column; align-items: center; gap: 4px; pointer-events: none; }
#lightbox .lb-vprev.on { display: flex; }
#lightbox .lb-vpimg { display: none; border-radius: 8px; border: 2px solid #fff; background-color: #111; background-repeat: no-repeat; box-shadow: 0 4px 14px rgba(0,0,0,.5); }
#lightbox .lb-vptime { padding: 1px 7px; border-radius: 9999px; background: rgba(0,0,0,.7); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* 좁으면(세로 영상을 PC 에서 볼 때 등) 남은 시간 칸은 뺀다 */
@media (max-width: 380px) { #lightbox .lb-vdur { display: none; } }
/* 전체화면(재생바째) — 검은 바탕에 영상 가운데 */
#lightbox .lb-vwrap:fullscreen { width: 100vw; height: 100vh; max-width: none; max-height: none; background: #000; }
#lightbox .lb-vwrap:fullscreen video { max-width: 100%; max-height: 100%; }
#lightbox .lb-vwrap:-webkit-full-screen { width: 100vw; height: 100vh; max-width: none; max-height: none; background: #000; }

/* ===== 레이아웃 공용(layout/main.jte 에 인라인으로 있던 것, 2026-10-26 0077 이동) =====
   관리자 셸·소개 페이지도 base.css 를 쓰지만 아래 규칙은 그 화면에 없는 클래스(또는 html.in-app·html.selecting)에만 걸린다. */
/* 스켈레톤 로딩 (모든 화면 공용) */
.skeleton { position:relative; overflow:hidden; background:#e2e8f0; }
.skeleton::after { content:''; position:absolute; inset:0; transform:translateX(-100%);
    background:linear-gradient(90deg, transparent, rgba(255,255,255,.65), transparent); animation:sk 1.2s infinite; }
@keyframes sk { 100% { transform:translateX(100%); } }
/* 어두운 배경(라이트박스)용 스켈레톤 — 흰 막대 대신 은은한 반투명 */
.sk-dark { position:relative; overflow:hidden; background:rgba(255,255,255,.12); }
.sk-dark::after { content:''; position:absolute; inset:0; transform:translateX(-100%);
    background:linear-gradient(90deg, transparent, rgba(255,255,255,.22), transparent); animation:sk 1.2s infinite; }
.ph-img { opacity:0; transition:opacity .25s; }
.ph-img.loaded { opacity:1; }
/* 원본 비율 보기 — JS(layoutRatio)가 저스티파이드 행(가로 순서, 꽉 찬 행)으로 셀 width/height 지정 */
/* 비율 보기 — 정사각 그리드(장수 유지) 안에 이미지를 잘림 없이 비율대로 담음(contain). 고정 그리드라 더보기 시 재배치·렉 없음 */
.pv-ratio > [data-pid] { background:#eef1f5; }
.pv-ratio img.ph-img, .pv-ratio video { object-fit:contain !important; }
/* 10열 등 조밀 모드: 영상 길이 텍스트 숨김(자리 부족, 재생아이콘만) */
.g-dense .dur-text { display:none !important; }
/* 더보기(무한 스크롤): 아직 노출 안 한 셀 숨김 */
.ph-hidden { display:none !important; }
/* 앱(웹뷰): 롱프레스 텍스트선택 전면 차단 — 선택 핸들·드래그 확장·돋보기·Live Text(Copy/Look Up/Translate)가
   사이드바·라이트박스 어디서나 튀어나와 네이티브 앱처럼 안 보였다(2026-08-21 제보).
   ⚠️ 브라우저(.in-app 아님)는 그대로 둔다 — 웹에서 텍스트 복사는 정상 기능이다.
   ⚠️ 확대(핀치줌)는 막지 않는다 — 라이트박스 사진 확대가 visualViewport.scale 에 의존한다. */
html.in-app, html.in-app body {
    -webkit-user-select: none; user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
}
/* 입력은 예외 — 안 그러면 타이핑·붙여넣기·커서 이동이 막힌다 */
html.in-app input, html.in-app textarea, html.in-app select,
html.in-app [contenteditable="true"], html.in-app .lp-selectable {
    -webkit-user-select: text; user-select: text; -webkit-touch-callout: default;
}
/* 그리드: 드래그 선택 중 텍스트선택·iOS 이미지 롱프레스 메뉴 방지 */
[data-photo-grid] { -webkit-user-select:none; user-select:none; -webkit-touch-callout:none; }
[data-photo-grid] img, [data-photo-grid] a { -webkit-user-drag:none; user-drag:none; }   /* PC: 사진 누르면 끌리는 기본 드래그 방지(드래그 선택 가능) */
/* 그리드 셀 연타(빠른 연속 선택) — iOS 더블탭 확대·300ms 클릭지연 제거로 즉시 반응 */
[data-photo-grid] > [data-pid] { touch-action: manipulation; }
/* 날짜 그룹 라벨 (연/월/일) — 한 줄 전체, 로고 노을색 그라데이션 하이라이트 */
/* 날짜 라벨 — 평소엔 노을 밴드(체크박스). 상단에 닿아 고정(.stuck)되면 가운데 알약으로 변신 */
.lp-glabel { grid-column:1 / -1; column-span:all; -webkit-column-span:all; display:flex; align-items:center; justify-content:space-between; font-weight:700; font-size:.8rem; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,.35); background:linear-gradient(90deg, rgba(251,113,133,.82), rgba(251,146,60,.82), rgba(251,191,36,.82)); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px); border-radius:.5rem; padding:.14rem .6rem; margin:.55rem 0 .2rem; transition:top .28s ease; }
.lp-glabel > span:first-child { padding:.18rem .2rem; }
.lp-glabel.stuck { background:none; backdrop-filter:none; -webkit-backdrop-filter:none; text-shadow:none; justify-content:center; }
.lp-glabel.stuck > span:first-child { padding:.18rem .85rem; border-radius:9999px; background:linear-gradient(135deg,#fb7185,#fb923c,#fbbf24); box-shadow:0 3px 10px rgba(251,146,60,.4); text-shadow:0 1px 2px rgba(0,0,0,.22); }
.lp-glabel.stuck .lp-gsel { display:none !important; }
/* 형제 sticky 라벨들이 같은 고정선에 겹칠 때 — 현재(알약) 아래로 가려진 라벨은 숨김(밴드↔알약 겹쳐보임 방지) */
.lp-glabel.lp-ghide { visibility:hidden; }
/* 기간(그룹) 전체 선택 체크박스 — 선택모드에서만 표시 */
.lp-gsel { display:none; width:22px; height:22px; border-radius:9999px; border:2px solid rgba(255,255,255,.92); flex-shrink:0; cursor:pointer; align-items:center; justify-content:center; }
html.selecting .lp-gsel { display:flex; }
.lp-gsel.lp-gsel-on::after { content:''; width:15px; height:15px; border-radius:9999px; background:linear-gradient(135deg,#fb7185,#fb923c,#fbbf24); }
.lp-glabel:first-child { margin-top:.1rem; }
/* 그룹(연/월/일) 라벨 — 보기옵션 바 아래로 고정(겹침 방지) */
[data-photo-grid]:not(.pv-ratio) .lp-glabel { position:sticky; top:calc(var(--hdr-h, 53px) + 3.25rem); z-index:10; }
/* 헤더·보기옵션이 idle로 숨으면(헤더 자리도 접힘) 날짜 라벨이 맨 위로 */
html.bars-hidden [data-photo-grid]:not(.pv-ratio) .lp-glabel { top:6px; }
/* 연/월 점프 — 그룹모드일 때 라벨/알약은 탭하면 기간 선택 시트가 뜨는 버튼(집계 있는 그리드만 initDateJump가 활성). */
[data-photo-grid] .lp-glabel { cursor:pointer; }
/* 연/월 점프 시트(바텀시트) */
#lp-jump { position:fixed; inset:0; z-index:80; display:none; }
#lp-jump.on { display:block; }
#lp-jump .lp-jump-bg { position:absolute; inset:0; background:rgba(0,0,0,.42); opacity:0; transition:opacity .2s ease; }
#lp-jump.on .lp-jump-bg { opacity:1; }
#lp-jump .lp-jump-panel { position:absolute; left:0; right:0; bottom:0; max-height:72vh; display:flex; flex-direction:column;
    background:#fff; border-radius:1.1rem 1.1rem 0 0; box-shadow:0 -8px 30px rgba(0,0,0,.25);
    transform:translateY(100%); transition:transform .26s cubic-bezier(.22,.61,.36,1); padding-bottom:env(safe-area-inset-bottom,0); }
#lp-jump.on .lp-jump-panel { transform:translateY(0); }
#lp-jump .lp-jump-hd { flex:0 0 auto; display:flex; align-items:center; justify-content:space-between; padding:.85rem 1.1rem .6rem; }
#lp-jump .lp-jump-hd h3 { font-weight:800; font-size:1rem; color:#0f172a; }
#lp-jump .lp-jump-x { width:2rem; height:2rem; border-radius:9999px; display:flex; align-items:center; justify-content:center; color:#64748b; font-size:1.2rem; }
#lp-jump .lp-jump-list { position:relative; flex:1 1 auto; overflow-y:auto; padding:.25rem .7rem 1rem; -webkit-overflow-scrolling:touch; }
#lp-jump .lp-jrow { width:100%; display:flex; align-items:center; justify-content:space-between; gap:.5rem;
    padding:.62rem .8rem; border-radius:.7rem; text-align:left; color:#0f172a; }
#lp-jump .lp-jrow:active { background:#f1f5f9; }
#lp-jump .lp-jrow.lp-jyear { font-weight:800; font-size:.98rem; margin-top:.15rem; }
#lp-jump .lp-jrow.lp-jmonth { font-weight:600; font-size:.9rem; color:#334155; padding-left:1.6rem; }
#lp-jump .lp-jrow.lp-jnow { font-weight:700; color:#fb7185; }
#lp-jump .lp-jrow .lp-jcnt { font-weight:600; font-size:.78rem; color:#94a3b8; }
#lp-jump .lp-jrow.lp-jcur { background:linear-gradient(135deg,rgba(251,113,133,.14),rgba(251,191,36,.14)); }
/* 상단 보기옵션 자리 확보용 스페이서 — 바가 숨으면 같이 접혀 빈 공간 제거 */
/* 스페이서 높이 = 알약 높이(JS 측정 --lp-tools-h) → 헤더↔알약(8px)과 알약↔첫사진 여백 대칭.
   transition 없음: 알약이 슬라이드로 나타날 때 스페이서가 뒤늦게 커지며 사진과 겹치는 것 방지(즉시 확보). */
#lp-tools-home { height:var(--lp-tools-h, 3.25rem); }
/* idle(자동숨김)에만 스페이서 접음. 선택모드(롱프레스)에선 스페이서 유지 → 상단 공백 안 사라져 사진목록이 위로 밀리지 않음. */
html.bars-hidden #lp-tools-home { height:0; }
/* '새로 올라온'(최근 업로드) 띠 — 그리드 맨 위 전폭. 날짜 라벨(applyGroup)과 별개 클래스라 유지됨 */
.lp-newband { grid-column:1 / -1; column-span:all; -webkit-column-span:all; display:flex; align-items:center; justify-content:space-between; gap:.5rem; font-weight:800; font-size:.82rem; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,.28); background:linear-gradient(90deg,#fb7185,#fb923c,#fbbf24); border-radius:.6rem; padding:.42rem .3rem .42rem .7rem; margin:.1rem .5px .3rem; }
.lp-newband-ok { flex:none; background:rgba(255,255,255,.95); color:#f97316; font-weight:800; font-size:.72rem; border-radius:9999px; padding:.24rem .8rem; }
.lp-newband-ok:active { transform:scale(.95); }
.pv-ratio > .lp-newband { flex:0 0 100%; width:100%; }
/* '새로 올라온' ↔ 타임라인 구분선 — 날짜묶음 없을(전체) 때만 표시(묶음 켜면 날짜라벨이 구분) */
.lp-newsep { grid-column:1 / -1; column-span:all; -webkit-column-span:all; height:0; border-top:1px solid #e5e7eb; margin:.7rem .5px .5rem; }
.pv-ratio > .lp-newsep { flex:0 0 100%; width:100%; }
/* 네비 FAB 현재 페이지 = 테마(노을) 그라데이션 */
.nav-ic-active { background:linear-gradient(135deg,#fb7185,#fb923c,#fbbf24) !important; border-color:transparent !important; }
/* 하단 선택/액션 바 — 검정 대신 테마(노을) 그라데이션. 버튼 글씨는 흰색+그림자로 가독 확보 */
.lp-selbar { background:linear-gradient(135deg,#fb7185,#fb923c,#fbbf24); }
.lp-selbar button { color:#fff !important; text-shadow:0 1px 2px rgba(0,0,0,.38); font-weight:600; }
/* 플로팅 보기옵션 알약 — 명시적 top(헤더 아래 8px). top:auto(static 위치 의존) 시 스크롤된 상태로 초기화되면 화면 밖으로 사라지던 버그 방지. 앱은 웹헤더 숨김→--hdr-h=0→8px. */
#lp-tools { top: calc(var(--hdr-h, 53px) + 8px); }
/* 구성원 알약 off(제외) 상태 — 다중 토글(전체=모두 on, 개별 탭으로 제외). off면 흐리게. */
#member-filter .mem-chip:not(.is-on) { opacity:.42; }
/* 선택모드에선 상단 보기옵션 바를 위로 숨김(선택 풀면 자동복귀). auto-bars 인라인 transform 위에 강제. */
html.selecting #lp-tools { transform:translateY(-220%) !important; }
/* 선택모드에선 좌하단 플로팅 뒤로가기도 숨김 — 하단 선택바(⭐·태그·가리기·공유·삭제)가 375px 에서 이미 꽉 차 겹친다. 나가기는 ✕ 취소. */
html.selecting #floating-back { display:none !important; }
/* 셀 안의 개별 액션(패밀리 태그 상세의 '태그에서 빼기' X) — 선택모드에선 숨겨 sel-check 자리와 겹치지 않게 */
html.selecting .lp-cell-x { display:none !important; }
/* 인물카드 선택모드(인물 합치기 패널 열림·같이 찾기) 중엔 사진 다중선택 '선택' 알약을 숨긴다 — 합치기 버튼과 겹쳐 보였다(2026-09-16 제보) */
html.people-selecting #lp-sel-bar { display:none !important; }
/* 네이티브 앱(웹뷰)에선 웹 헤더·섹션네비·플로팅백 숨김 — 네이티브 헤더/바텀이 대체.
   단, 콘텐츠 FAB(태그+/패밀리+/설정 등 콘텐츠 FAB)는 네이티브 바텀이 대체 못 하므로 유지. */
html.in-app header { display:none !important; }
/* 플로팅 네비(햄버거 FAB+메뉴) 제거 — 네비(사진첩/인물/태그/패밀리)는 프로필 메뉴로 통합(웹·앱 공통). 콘텐츠 FAB(콘텐츠 FAB)는 유지. */
#nav-menu, #nav-fab { display:none !important; }
html.in-app #floating-back { display:none !important; }
/* 하단 알약 기준선(2026-10-30) — 화면 아래 가운데 알약('선택'·'같이 찾기'·얼굴 선택 바)의 세로 가운데를 한 줄에 맞춘다.
   앱 = 네이티브 동그란 버튼의 가운데(바닥 16 + 높이 58/2 + 안전영역), 브라우저 = 오른쪽 아래 FAB(w-14, pb-5)의 가운데.
   바는 기준선을 가운데로 한 높이 64px 띠로 깔고 알약을 세로 가운데 정렬 — 알약 높이가 달라도 가운데가 같다. 새 하단 알약도 이 방식으로. */
:root { --dock-c: 48px; }
html.fab-nav { --dock-c: calc(env(safe-area-inset-bottom, 0px) + 45px); }
#lp-sel-bar { bottom: calc(var(--dock-c) - 32px); height: 64px; align-items: center; }
#face-sel-bar:not(.hidden) { bottom: calc(var(--dock-c) - 32px); height: 64px; display: flex; align-items: center; }
#floating-back { margin-bottom: 4px; }   /* w-12 → 가운데를 FAB(w-14)와 같은 줄로 */
/* 앱 하단 내비 = 오른쪽 아래 동그란 버튼(0091, 바닥 16px+높이 58px) — 콘텐츠 FAB 가 그 자리와 겹치지 않게 위로 올린다 */
/* 아래로 스크롤하면 떠 있는 버튼도 숨는다(ui.js lp-scroll-hide, 2026-10-29) — 앱 하단 내비와 같이. translate 는 transform(가운데 정렬)과 따로 먹는다.
   선택 중엔 '선택' 알약이 액션 바라 숨기지 않는다. 새 플로팅 버튼을 만들면 여기 목록에 넣을 것. */
#nav-fab-wrap, #lp-sel-bar, #floating-back, #together-bar { transition: translate .28s cubic-bezier(.22,1,.36,1), opacity .2s; }
html.lp-scroll-hide #nav-fab-wrap:not(:has(#nav-menu:not(.hidden))),
html.lp-scroll-hide:not(.selecting) #lp-sel-bar,
html.lp-scroll-hide:not(.people-selecting) #together-bar,
html.lp-scroll-hide #floating-back { translate: 0 calc(100% + 140px); opacity: 0; pointer-events: none; }
/* 앱 동그란 버튼 자리 막기(0098) — 앱이 웹뷰 터치 지연을 끄면서(preventGestureDelay) 웹뷰 위 버튼을 누르면 아래 웹도 같이 눌린다.
   버튼 자리(오른쪽 아래 58px)를 투명하게 덮어 탭을 먹는다. 버튼이 숨으면(선택 중·창·스크롤) 같이 빠지고,
   펼친 동안(앱이 lp-nav-open 을 달아 줌)은 화면 전체를 덮는다(딤 탭 = 닫기만, 아래 카드 안 눌림). */
html.fab-nav body::after { content: ''; position: fixed; right: 14px; bottom: calc(env(safe-area-inset-bottom, 0px) + 16px); width: 58px; height: 58px; z-index: 2147483000; }
html.fab-nav.lp-nav-hidden body::after, html.fab-nav.lp-scroll-hide body::after { display: none; }
html.fab-nav.lp-nav-open body::after { display: block; inset: 0; width: auto; height: auto; }
html.fab-nav #nav-fab-wrap { margin-bottom: calc(env(safe-area-inset-bottom, 0px) + 64px); }
/* 보기옵션 툴바는 initToolbar가 상단 플로팅 알약(fixed)으로 생성 — 별도 sticky 자리 불필요 */
/* content-visibility:auto 제거 — 화면 밖 셀을 버렸다가 복귀 시 이미지 재디코드로 스켈레톤/회색 번쩍임 발생.
   페이지네이션(.ph-hidden)이 이미 DOM을 제한하고 webp 썸네일이 작아 전환 성능은 충분. */

/* 삼성 인터넷 '맨 위로' 버튼(브라우저 것, 아래 정중앙 ≈ 바닥에서 16~64px)과 겹치지 않게 하단 선택 알약을 그 위로(0081). 앱·다른 브라우저는 그대로. */
html.sbrowser { --dock-c: calc(env(safe-area-inset-bottom, 0px) + 4.75rem + 22px); }

/* 우리 선택기(0092, ui.js lpPicker) — 폰 기본 날짜·목록 선택기 대신 */
.lp-pk { display:flex; align-items:center; justify-content:space-between; gap:.4rem; text-align:left; cursor:pointer; }
.lp-pk .lp-pk-t { flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lp-pk.is-empty .lp-pk-t { color:#94a3b8; }
.lp-pk .lp-pk-ic { width:16px; height:16px; color:#94a3b8; flex-shrink:0; display:flex; }
.lp-pk .lp-pk-ic svg { width:100%; height:100%; }
.lp-pk:active { background:#fff7ed; }
.lp-pk-dim { position:fixed; inset:0; z-index:200; background:rgba(15,23,42,0); display:flex; align-items:flex-end; justify-content:center; transition:background .2s; }
.lp-pk-dim.is-on { background:rgba(15,23,42,.4); }
.lp-pk-sheet { width:100%; max-width:28rem; background:#fff; border-radius:1.25rem 1.25rem 0 0; padding:0 1rem calc(env(safe-area-inset-bottom) + 14px);
               transform:translateY(100%); transition:transform .22s cubic-bezier(.2,.8,.2,1); max-height:80dvh; display:flex; flex-direction:column; }
.lp-pk-dim.is-on .lp-pk-sheet { transform:none; }
.lp-pk-hd { display:flex; align-items:center; justify-content:space-between; padding:1rem .25rem .6rem; font-size:1rem; color:#0f172a; }
.lp-pk-close { width:30px; height:30px; border-radius:9999px; background:#f1f5f9; color:#64748b; display:flex; align-items:center; justify-content:center; }
.lp-pk-close svg { width:16px; height:16px; }
.lp-pk-bd { overflow-y:auto; }
.lp-pk-opt { width:100%; display:flex; align-items:center; justify-content:space-between; padding:.8rem .6rem; border-radius:.75rem; font-size:.95rem; color:#334155; text-align:left; }
.lp-pk-opt.is-on { background:#fff7ed; color:#c2410c; font-weight:700; }
.lp-pk-opt svg { width:18px; height:18px; color:#fb923c; flex-shrink:0; }
.lp-pk-opt:active { background:#f8fafc; }
.lp-cal-nav { display:flex; align-items:center; justify-content:space-between; margin-bottom:.5rem; }
.lp-cal-arw { width:38px; height:38px; border-radius:9999px; display:flex; align-items:center; justify-content:center; color:#475569; }
.lp-cal-arw:active { background:#f1f5f9; }
.lp-cal-arw svg { width:20px; height:20px; }
.lp-cal-ttl { display:flex; align-items:center; gap:.25rem; font-weight:800; font-size:1.05rem; color:#0f172a; padding:.35rem .7rem; border-radius:9999px; background:#fff7ed; }
.lp-cal-ttl svg { width:16px; height:16px; color:#fb923c; }
.lp-cal-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; text-align:center; }
.lp-cal-wk span { font-size:.72rem; font-weight:700; color:#94a3b8; padding:.3rem 0; }
.lp-cal-wk .is-sun, .lp-cal-d.is-sun { color:#f43f5e; }
.lp-cal-wk .is-sat, .lp-cal-d.is-sat { color:#3b82f6; }
.lp-cal-d { aspect-ratio:1; max-height:44px; border-radius:9999px; font-size:.92rem; color:#334155; display:flex; align-items:center; justify-content:center; }
.lp-cal-d.is-today { box-shadow:inset 0 0 0 1.5px #fdba74; }
.lp-cal-d.is-on { background:linear-gradient(135deg,#fb7185,#fb923c,#fbbf24); color:#fff; font-weight:800; }
.lp-cal-d:disabled { opacity:.25; }
.lp-cal-d:active { background:#ffedd5; }
.lp-cal-mgrid { display:grid; grid-template-columns:repeat(3,1fr); gap:.5rem; padding:.25rem 0; }
.lp-cal-ys { max-height:16rem; overflow-y:auto; }
.lp-cal-m { padding:.75rem 0; border-radius:.8rem; background:#f8fafc; font-size:.92rem; color:#334155; }
.lp-cal-m.is-on { background:linear-gradient(135deg,#fb7185,#fb923c,#fbbf24); color:#fff; font-weight:800; }
.lp-cal-ft { display:flex; gap:.5rem; margin-top:.75rem; }
.lp-cal-b { flex:1; padding:.7rem 0; border-radius:.8rem; background:#f1f5f9; color:#475569; font-size:.88rem; font-weight:700; }
.lp-cal-b.is-main { background:#fff7ed; color:#c2410c; }
.lp-pk-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:.4rem; padding-bottom:.25rem; }
.lp-pk-grid .lp-pk-opt { justify-content:center; background:#f8fafc; padding:.7rem 0; }
.lp-pk-grid .lp-pk-opt:first-child { grid-column:1 / -1; }
.lp-pk-grid .lp-pk-opt.is-on { background:linear-gradient(135deg,#fb7185,#fb923c,#fbbf24); color:#fff; }
.lp-pk-grid .lp-pk-opt svg { display:none; }

/* ============================================================
   공통 확인창(ui.js showModal = appAlert/appConfirm/appPrompt) — 0112
   키트(colon-grid v4.19.2) 확인창과 같은 모양 규칙을 옮김: 본문 15px 진한 글 · keep-all · 질문 굵게 + 설명 ·
   [확인] 채운 주 단추(위험 = 빨강) · [취소] 흰 바탕 보조(hover 반전 없음) · 초점은 :focus-visible 링만.
   Tailwind 프리컴파일과 무관하게 여기서 직접 정의(새 유틸 클래스 쓰면 tailwind.css 재생성 필요해서).
   ============================================================ */
.am-ov { position: fixed; inset: 0; z-index: 200; background: rgba(0,0,0,.5); display: flex; align-items: center; justify-content: center; padding: 20px; }
.am-box { background: #fff; border-radius: 16px; width: 100%; max-width: 360px; padding: 20px; box-shadow: 0 20px 25px -5px rgba(0,0,0,.1), 0 8px 10px -6px rgba(0,0,0,.1);
  max-height: calc(100dvh - 40px); display: flex; flex-direction: column; }
.am-title { font-weight: 600; font-size: 13px; color: #64748b; margin-bottom: 6px; word-break: keep-all; overflow-wrap: anywhere; }
.am-body { font-size: 15px; line-height: 1.6; color: #1e293b; white-space: pre-line; word-break: keep-all; overflow-wrap: anywhere;
  overflow-y: auto; max-height: 60vh; margin-bottom: 4px; }
.am-q { font-size: 16px; font-weight: 700; color: #0f172a; }
.am-q + .am-detail { margin-top: 6px; }
.am-box .am-input { margin-top: 8px; font-size: 16px; }
.am-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.am-actions .am-secondary { margin-right: auto; font-size: 13px; color: #94a3b8; text-decoration: underline; background: none; border: 0; padding: 8px 2px; }
.am-actions .am-ok, .am-actions .am-cancel { min-height: 40px; padding: 8px 16px; border-radius: 10px; font-size: 15px; font-weight: 600; line-height: 1.3; cursor: pointer; }
.am-actions .am-ok { background: #0f172a; color: #fff; border: 1px solid #0f172a; }
.am-actions .am-ok.is-danger { background: #dc2626; border-color: #dc2626; }
.am-actions .am-cancel { background: #fff; color: #334155; border: 1px solid #cbd5e1; font-weight: 500; }
@media (hover: hover) {
  .am-actions .am-ok:hover { background: #1e293b; }
  .am-actions .am-ok.is-danger:hover { background: #b91c1c; }
  .am-actions .am-cancel:hover { background: #f1f5f9; }
}
.am-actions button:focus { outline: none; }
.am-actions button:focus-visible { outline: 2px solid #3b82f6; outline-offset: 2px; }
/* 좁은 화면 — 두 단추 반씩(44px) */
@media (max-width: 480px) {
  .am-actions:not(.has-sec) .am-ok, .am-actions:not(.has-sec) .am-cancel { flex: 1 1 0; min-height: 44px; }
}

/* ============================================================
   태그 책장(0130) — 태그 하나 = 책 한 권. 책등(세로 제목·장수·표지 한 장)이 선반에 꽂힌다.
   선반 판자는 컨테이너 배경(줄 높이 = 책 196 + 판자 18)으로 그린다 — 줄 수가 바뀌어도 따로 그릴 것 없음.
   누르면 책이 살짝 빠졌다가 표지가 가운데로 나와 펼쳐진다(.lp-book-open, tags.jte). 이동은 hx-boost 그대로.
   ============================================================ */
/* 책장 틀(0132) — 선반 = 칸(.lp-row: 책 자리 + 판자). 판자는 진짜 요소라 줄마다 정확히 책 밑에 온다(예전 배경 줄무늬는 줄이 어긋났다).
   빈 선반도 늘 그린다(최소 4칸 + 맨 아래 빈 칸 하나) — 앨범이 적어도 화면이 책장처럼 보이고, 끌어서 아무 칸에나 꽂을 수 있다. */
/* 5차(0132) — 책장 그림: 틀(위 머리판·아래 받침) + 뒷판 + 선반, 색은 밝은 나무(4차 색). 알록달록한 기본 책·소품 사이 사진 책이 우리 앨범. */
.lp-case { position: relative; margin: 26px 9px 22px; border-radius: 3px; padding: 0 10px;
  background: linear-gradient(180deg, #f7f2ec 0%, #f2ebe3 100%);
  box-shadow: 0 0 0 9px #e9dccb, 0 0 0 10px rgba(120, 90, 60, .14), 0 16px 26px -12px rgba(90, 60, 30, .28),
              inset 0 0 0 1px rgba(120, 90, 60, .07), inset 0 18px 30px -24px rgba(90, 60, 30, .18); }
.lp-case::before { content: ''; position: absolute; left: -17px; right: -17px; top: -25px; height: 15px; border-radius: 9px 9px 3px 3px;
  background: linear-gradient(to bottom, #f1e7da, #ddcdb9); box-shadow: 0 3px 4px -2px rgba(90, 60, 30, .22); pointer-events: none; }
.lp-case::after { content: ''; position: absolute; left: -14px; right: -14px; bottom: -21px; height: 11px; border-radius: 2px 2px 4px 4px;
  background: #d6c4ad; pointer-events: none; }
.lp-row { position: relative; padding-top: 16px; }
/* 위 판자가 드리운 그늘 — 칸 안쪽 깊이 */
.lp-row::before { content: ''; position: absolute; left: -10px; right: -10px; top: 0; height: 30px; pointer-events: none;
  background: linear-gradient(to bottom, rgba(90, 60, 30, .08), rgba(90, 60, 30, 0)); }
/* 🚨 선반은 평소 스크롤 칸이 아니다(overflow hidden) — overflow-x:auto 면 iOS 웹뷰가 선반마다 안쪽 스크롤을 만들어,
   책장 위에서 아래로 당겨도 앱 '당겨서 새로고침'이 안 걸렸다(0136). 앨범만으로 넘치는 선반만 .lp-wide 로 가로 스크롤. */
.lp-books { display: flex; align-items: flex-end; gap: 5px; height: 200px; padding: 0 4px; overflow: hidden;
  scrollbar-width: none; }
.lp-books.lp-wide { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.lp-books::-webkit-scrollbar { display: none; }
/* 판자 — 윗면(밝게) + 앞면 + 아래로 떨어지는 그림자 */
.lp-board { position: relative; z-index: 1; height: 14px; margin: 0 -10px; border-radius: 1px;
  background: linear-gradient(to bottom, #fffaf3 0, #fffaf3 3px, #eadfd1 3px, #ddcdb9 100%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 9px 12px -7px rgba(80, 52, 24, .32); }
.lp-row:last-child .lp-board { box-shadow: none; }
/* 책등 — 위는 표지 사진(넘겨 보기·동영상 재생), 아래로 앨범 색이 덮는다. 두께 = 장수(로그), 높이 = 앨범마다 조금씩(tags.jte --w/--h) */
.lp-spine { position: relative; flex: none; display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  height: var(--h, 184px); width: var(--w, 44px); border-radius: 6px 6px 3px 3px; color: #fff; text-decoration: none; overflow: hidden;
  background: var(--c, #fb923c); isolation: isolate; -webkit-touch-callout: none; user-select: none; -webkit-user-select: none;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .14), 2px 0 6px -2px rgba(15, 23, 42, .25);
  -webkit-tap-highlight-color: transparent; }
.lp-spine-cover { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; opacity: 0; transition: opacity .9s ease; }
.lp-spine-cover.on { opacity: 1; }
span.lp-spine-cover { opacity: 0; }
.lp-spine::before { content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 22%, var(--c, #fb923c) 66%); opacity: .95; }
.lp-spine::after { content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 3px; background: rgba(255, 255, 255, .3); }
.lp-spine-name { min-height: 0; max-height: 58%; margin-bottom: 6px; writing-mode: vertical-rl; text-orientation: upright; letter-spacing: -.5px;
  font-size: 13px; font-weight: 700; line-height: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-shadow: 0 1px 3px rgba(0, 0, 0, .25); }
.lp-spine-n { flex: none; margin-bottom: 7px; padding: 1px 5px; border-radius: 999px; background: rgba(255, 255, 255, .24);
  font-size: 9.5px; font-weight: 700; font-variant-numeric: tabular-nums; max-width: calc(100% - 4px); overflow: hidden; }
.lp-spine.is-video .lp-spine-n::before { content: '▶ '; font-size: 7px; vertical-align: 1px; }
/* 🚨 들림 효과는 transform 말고 translate 속성으로 — 끌기(Sortable)가 떠 있는 책을 transform 으로 손가락 위치에 옮기는데,
   transform 을 덮으면 책이 안 따라왔다(0132 '드래그할 때 책이 따라오게'). */
.lp-spine { transition: translate .25s cubic-bezier(.2, .8, .2, 1), box-shadow .25s ease; }
.lp-spine:active, .lp-spine.is-pull, .lp-spine.sortable-chosen { translate: 0 -12px; box-shadow: 0 14px 24px -8px rgba(15, 23, 42, .35); }
@media (hover: hover) { .lp-spine:hover { translate: 0 -8px; } }
/* 끌어 옮기기(Sortable) — 손가락을 따라오는 책(.shelf-float, body 에 붙는 복제)은 움직임·들림을 다 끈다. 빈 자리는 흐린 책 모양 */
.lp-spine.shelf-ghost { opacity: .3; translate: none; }
.lp-spine.shelf-float { transition: none !important; translate: none !important; opacity: .96; box-shadow: 0 22px 34px -10px rgba(15, 23, 42, .5); }

/* 기본 책(0132) — 사진 없는 장식 책. 색·두께·높이·장식이 제각각이라 진짜 책장처럼 보이고, 그 사이 '사진이 보이는 책'이 우리 앨범.
   tags.jte 가 선반 폭만큼 채운다(선반 번호로 고정 — 볼 때마다 같은 모양). 누르면 새 앨범 만들기. */
.lp-filler { position: relative; flex: none; height: var(--h, 170px); width: var(--w, 24px); border-radius: 3px 3px 2px 2px;
  /* 광택(0132) — 왼쪽 그늘 · 빛 받는 줄 · 오른쪽 그늘(예전은 매트해 보였다) */
  background: linear-gradient(90deg, rgba(0, 0, 0, .2) 0, rgba(255, 255, 255, .05) 10%, rgba(255, 255, 255, .38) 22%, rgba(255, 255, 255, .06) 34%, rgba(255, 255, 255, 0) 60%, rgba(0, 0, 0, .16) 100%), var(--c, #d9cbb8);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .12), 1px 0 4px -1px rgba(15, 23, 42, .2); -webkit-tap-highlight-color: transparent; cursor: pointer;
  transition: translate .25s cubic-bezier(.2, .8, .2, 1); }
.lp-filler:active { translate: 0 -6px; }
.lp-filler.lp-deco { background: none; box-shadow: none; border-radius: 0; }
.lp-filler.lp-deco::before, .lp-filler.lp-deco::after { display: none; }
.lp-filler.lp-deco svg { display: block; width: 100%; height: 100%; filter: drop-shadow(1px 2px 2px rgba(80, 52, 24, .18)); }
.lp-filler::before, .lp-filler::after { content: ''; position: absolute; left: 3px; right: 3px; }
/* 모양 1 — 위아래 가는 금줄 두 쌍 */
.lp-filler.f1::before { top: 12%; height: 5px; border-top: 1px solid rgba(255, 230, 170, .7); border-bottom: 1px solid rgba(255, 230, 170, .7); }
.lp-filler.f1::after { bottom: 10%; height: 5px; border-top: 1px solid rgba(255, 230, 170, .7); border-bottom: 1px solid rgba(255, 230, 170, .7); }
/* 모양 2 — 가운데 밝은 라벨 */
.lp-filler.f2::before { top: 30%; height: 18%; background: rgba(255, 255, 255, .55); border-radius: 2px; }
/* 모양 3 — 아래쪽 넓은 색 띠 */
.lp-filler.f3::after { bottom: 0; left: 0; right: 0; height: 26%; background: rgba(0, 0, 0, .14); }
.lp-filler.f3::before { top: 10%; height: 2px; background: rgba(255, 255, 255, .45); }
/* 모양 4 — 문고판: 위아래 진한 띠 + 가운데 점 */
.lp-filler.f4::before { top: 0; left: 0; right: 0; height: 9%; background: rgba(0, 0, 0, .18); }
.lp-filler.f4::after { top: 46%; left: 50%; right: auto; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: rgba(255, 255, 255, .6); }
/* 모양 5 — 무늬 없음(천 표지 느낌) */
.lp-filler.f5 { background: repeating-linear-gradient(0deg, rgba(255, 255, 255, .05) 0 2px, rgba(0, 0, 0, .03) 2px 4px),
  linear-gradient(90deg, rgba(0, 0, 0, .2) 0, rgba(255, 255, 255, .05) 10%, rgba(255, 255, 255, .38) 22%, rgba(255, 255, 255, .06) 34%, rgba(255, 255, 255, 0) 60%, rgba(0, 0, 0, .16) 100%), var(--c, #d9cbb8); }

/* 꺼내서 펼치기(0132) — 책이 가운데로 나오고(표지) → 표지가 왼쪽으로 완전히 넘어가며 펼쳐진다:
   왼쪽 = 표지 안쪽(앨범 색 종이), 오른쪽 = 첫 장(종이 위 사진 + 앨범 이름). 펼치면서 두 쪽이 가운데 오도록 오른쪽으로 반 칸 민다.
   <html> 에 붙어 있어 이동(body 교체) 뒤에도 남는다(tags.jte). */
.lp-book-open { position: fixed; z-index: 90; pointer-events: none; perspective: 1800px;
  transition: left .62s cubic-bezier(.2, .8, .2, 1), top .62s cubic-bezier(.2, .8, .2, 1), width .62s cubic-bezier(.2, .8, .2, 1), height .62s cubic-bezier(.2, .8, .2, 1),
              transform 1.1s cubic-bezier(.45, .05, .25, 1), opacity .5s ease; }
.lp-book-open.is-open { transform: translateX(50%); }
.lp-book-open .bk { position: absolute; inset: 0; transform-style: preserve-3d; }
.lp-book-open .pg { position: absolute; inset: 0; border-radius: 2px 10px 10px 2px; background: #fbf7f2; overflow: hidden;
  box-shadow: 0 22px 44px rgba(0, 0, 0, .3), inset 10px 0 16px -10px rgba(0, 0, 0, .3); }
.lp-book-open .pg::after { content: ''; position: absolute; top: 3px; bottom: 3px; right: 0; width: 5px;
  background: repeating-linear-gradient(90deg, #efe7dc 0 1px, #fffaf3 1px 2px); }
.lp-book-open .pg .ph { position: absolute; left: 11%; right: 13%; top: 9%; bottom: 20%; border-radius: 4px; background: #eee center / cover no-repeat;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .18); }
.lp-book-open .pg .tt { position: absolute; left: 11%; right: 13%; bottom: 7%; font-size: 15px; font-weight: 800; color: #3d2320;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lp-book-open .cv { position: absolute; inset: 0; transform-origin: left center; transform-style: preserve-3d;
  transition: transform 1.1s cubic-bezier(.45, .05, .25, 1); }
.lp-book-open .cv-f, .lp-book-open .cv-b { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.lp-book-open .cv-f { border-radius: 3px 10px 10px 3px; background: center / cover no-repeat; box-shadow: inset 7px 0 12px rgba(0, 0, 0, .28);
  display: flex; align-items: flex-end; padding: 16px; color: #fff; font-weight: 800; font-size: 20px; text-shadow: 0 1px 4px rgba(0, 0, 0, .5); }
.lp-book-open .cv-b { transform: rotateY(180deg); border-radius: 10px 3px 3px 10px;
  background: linear-gradient(rgba(251, 247, 242, .82), rgba(251, 247, 242, .82)), var(--c, #fb923c);
  box-shadow: inset -10px 0 16px -10px rgba(0, 0, 0, .3), 0 22px 44px rgba(0, 0, 0, .25); }
.lp-book-open.is-open .cv { transform: rotateY(-180deg); }
@media (prefers-reduced-motion: reduce) {
  .lp-spine, .lp-filler { transition: none; }
  .lp-book-open { display: none; }
}
