/*
 * 화면 곳곳이 함께 쓰는 조각들 — 토스트, 창 부품, 뼈대(스켈레톤).
 *
 * base.css 와 나눈 기준: base 는 '페이지의 뼈대'(헤더·탭바·버튼·카드),
 * 여기는 '상황에 따라 나타났다 사라지는 것'이다. 두 파일이 같은 것을
 * 다루기 시작하면 무엇을 어디서 고쳐야 하는지 아무도 모르게 된다.
 */

/* ── 토스트 ─────────────────────────────────────────────
 *
 * 한 번에 하나만. 여러 개가 쌓이면 마지막 것만 읽히고 나머지는 소음이다.
 * 되돌릴 수 있는 일에는 되돌릴 버튼을 함께 준다.
 */
.toast {
    position: fixed;
    left: 50%;
    bottom: calc(var(--sp-5) + var(--safe-b));
    transform: translate(-50%, 12px);
    z-index: 400;

    display: none;
    align-items: center;
    gap: 10px;
    max-width: min(520px, calc(100vw - 32px));
    padding: 11px 14px 11px 15px;
    border-radius: var(--r-pill);

    /*
     * 빨강 바탕에 흰 글자.
     *
     * 예전에는 rgba(30, 24, 21, 0.96) 이었다 — 어두운 테마의 갈색이 그대로
     * 남았는데 글자는 밝은 테마의 검정(--ink)으로 바뀌어서, 검정 위 검정이
     * 되어 대비가 1.16:1 이었다. 아무것도 안 보이는 알림이었다.
     *
     * 이제 이 서비스의 두 색(빨강·흰색)으로 못 박아 둔다.
     * 토큰이 바뀌어도 짝이 갈라지지 않게 둘 다 여기서 정한다.
     */
    background: var(--brand);
    border: 1px solid var(--brand-dark);
    color: #FFFFFF;
    font-size: var(--t-caption);
    line-height: 1.45;
    box-shadow: var(--edge), var(--sh-3);

    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-2) var(--ease-out),
                transform var(--dur-2) var(--ease-out);
}
.toast.is-on {
    display: flex;
    opacity: 1;
    transform: translate(-50%, 0);
    pointer-events: auto;
}
.toast .i { flex: none; color: #FFFFFF; opacity: 0.85; }
.toast__msg { flex: 1 1 auto; min-width: 0; }
.toast__act {
    flex: none;
    margin: -4px -6px -4px 2px;
    padding: 6px 12px;
    border: 0;
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, 0.18);
    color: #FFFFFF;
    font: inherit;
    font-size: var(--t-caption);
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
}
.toast__act:hover { background: rgba(255, 255, 255, 0.30); }

/* 색조는 테두리로만 말한다. 글자·아이콘은 흰색을 지킨다 — 빨강 바탕에
   초록 아이콘을 얹으면 그 아이콘이 다시 안 보인다. */
.toast--ok { background: var(--safe); border-color: var(--safe); }
.toast--warn { background: var(--hazard-ink); border-color: var(--hazard-ink); }
.toast--bad { background: var(--danger-ink); border-color: var(--danger-ink); }


/*
 * 지도 화면은 맨 아래에 맵기 다이얼이 있다.
 *
 * 넓은 화면에서는 탭바가 없어 아래 미디어 쿼리가 안 걸리는데, 다이얼은
 * 그대로 있다. 그래서 '필터로 N곳이 숨겨졌습니다' 가 **그 알림을 부른 바로
 * 그 손잡이**를 덮고 있었다 — 다이얼을 움직일수록 못 만지게 되는 셈이었다.
 */
.map-page .toast { bottom: calc(var(--sp-3) + 66px + var(--safe-b)); }

/* 모바일에는 아래에 탭바가 있다. 그 위로 띄우지 않으면 토스트가 가려진다. */
@media (max-width: 800px) {
    .toast { bottom: calc(var(--sp-3) + var(--tabbar-h) + var(--safe-b)); }
    /* 지도 화면은 탭바 위에 다이얼이 하나 더 있다 */
    .map-page .toast {
        bottom: calc(var(--sp-3) + var(--tabbar-h) + var(--safe-b) + 74px);
    }
    /* 가게 화면은 탭바 위에 길찾기 줄이 하나 더 있다 */
    .store-page .toast {
        bottom: calc(var(--sp-3) + var(--tabbar-h) + var(--safe-b) + 62px);
    }
}

/* ── 창 부품 ─────────────────────────────────────────── */

.modal.is-closing {
    animation: modalOut 140ms var(--ease) forwards;
    pointer-events: none;
}
.modal.is-closing .modal__box { animation: modalBoxOut 140ms var(--ease) forwards; }
@keyframes modalOut { to { opacity: 0 } }
@keyframes modalBoxOut { to { opacity: 0; transform: translateY(8px) scale(0.99) } }

.modal__box--wide { max-width: 560px; }

.modal__note--top { margin-top: 0; }

/* 진행 막대. 3문항 중 어디쯤인지 숫자 말고 몸으로도 보이게 한다. */
.modal__bar {
    height: 3px;
    margin: 0 0 var(--sp-4);
    border-radius: var(--r-pill);
    background: rgba(26, 18, 16, 0.1);
    overflow: hidden;
}
.modal__bar span {
    display: block;
    height: 100%;
    border-radius: var(--r-pill);
    background: var(--heat-ramp-soft);
    transition: width var(--dur-3) var(--ease-out);
}

/* 되돌릴 수 없는 창의 경고 표시 */
.modal__warn {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    margin: 0 0 var(--sp-3);
    border-radius: 50%;
    background: rgba(212, 42, 22, 0.14);
    border: 1px solid rgba(212, 42, 22, 0.4);
    color: var(--danger-ink);
}

.modal__hint {
    margin: 10px 0 0;
    font-size: var(--t-caption);
    color: var(--smoke);
    min-height: 1.5em;   /* 글자가 바뀔 때 아래 것이 들썩이지 않게 */
}

/* ── 글자 수 세기 ──────────────────────────────────────
   .me-count 로 두지 않는 이유: 그 이름은 이미 나의 화면에서
   '카드 제목 옆 개수 배지'를 가리킨다. 한 이름이 두 가지를 뜻하면
   창을 열었을 때 세기가 배지 모양으로 바뀌며 자리를 잃는다. */

.me-field { position: relative; }
.char-count {
    position: absolute;
    right: 10px;
    bottom: 9px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--smoke);
    background: linear-gradient(90deg, transparent, var(--paper) 30%);
    padding-left: 10px;
    pointer-events: none;
}
.me-field input { padding-right: 68px; }
.me-field textarea { padding-bottom: 26px; }

/* ── 위험 버튼 ───────────────────────────────────────── */

.btn--danger {
    background: rgba(212, 42, 22, 0.16);
    border-color: rgba(212, 42, 22, 0.55);
    color: var(--danger-ink);
}
.btn--danger:hover { background: rgba(212, 42, 22, 0.28); }
.btn--danger[disabled] { opacity: 0.45; }

/* 방금 눌러서 결과가 나온 버튼. 잠깐만 이 상태였다가 돌아간다. */
.btn.is-done {
    color: var(--safe);
    border-color: rgba(111, 163, 131, 0.5);
    background: rgba(111, 163, 131, 0.12);
}

/* ── 뼈대(스켈레톤) ─────────────────────────────────────
 *
 * "불러오는 중…" 글자 대신 앞으로 들어올 것의 모양을 미리 놓는다.
 * 글자는 다 읽어야 뜻을 알지만 모양은 안 읽어도 알고,
 * 무엇보다 내용이 도착할 때 화면이 덜컥 뛰지 않는다.
 */
.skel {
    position: relative;
    overflow: hidden;
    background: var(--surface-2);
    border-radius: var(--r-sm);
}
.skel::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg,
        transparent, rgba(26, 18, 16, 0.07), transparent);
    animation: skelSweep 1.35s infinite;
}
@keyframes skelSweep { to { transform: translateX(100%) } }

.skel-line { height: 12px; margin-bottom: 8px; }
.skel-line:last-child { margin-bottom: 0; }
.skel-line--sm { height: 10px; width: 45%; }
.skel-line--lg { height: 18px; width: 62%; }

.skel-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    padding: var(--sp-4);
    margin-bottom: var(--sp-3);
}
.skel-card__head {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin-bottom: var(--sp-3);
}
.skel-dot { width: 40px; height: 40px; border-radius: 50%; flex: none; }
.skel-pill { width: 74px; height: 26px; border-radius: var(--r-pill); flex: none; }

/* 움직임을 줄여 달라고 한 사람에게는 흐르는 빛을 지운다. 모양은 남는다. */
@media (prefers-reduced-motion: reduce) {
    .skel::after { display: none; }
}

/* ── 앵커 ────────────────────────────────────────────── */

/*
 * 헤더가 sticky 라 #id 로 뛰면 제목이 헤더 밑에 깔린다.
 * 뛰어간 곳이 안 보이면 사용자는 링크가 고장 났다고 생각한다.
 */
:target,
.doc h2[id], .doc h3[id], [id^="rv"] {
    scroll-margin-top: calc(var(--header-h) + var(--sp-4));
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

.skel-wrap { display: grid; }
.empty-state__act { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }


/* ── 기다리는 중 표시 (busy.js) ─────────────────────────
 *
 * 뼈대(.skel)를 못 까는 자리에 쓴다 — 지도처럼 자리는 이미 있고
 * 내용만 늦게 오는 곳이다.
 */
.busy {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 30;

    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 10px 16px 10px 13px;
    border-radius: var(--r-pill);

    /* 빨강 바탕에 흰 글자. 이 서비스의 두 색이고, 지도 위 어디에 놓여도
       읽힌다 — 흰 알약은 밝은 지도 위에서 경계가 사라진다. */
    background: var(--brand);
    color: #FFFFFF;
    border: 1px solid var(--brand-dark);
    font-size: var(--t-caption);
    font-weight: 600;
    box-shadow: var(--sh-3);
    pointer-events: none;
}

/* 목록 안에 끼워 넣는 경우. 지도가 아니라 흐름 속에 놓인다. */
.busy--inline {
    position: static;
    transform: none;
    display: flex;
    width: fit-content;
    margin: var(--sp-4) auto;
}

.busy__ring {
    flex: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #FFFFFF;
    animation: busySpin 0.75s linear infinite;
}
.busy__ring--sm {
    width: 13px;
    height: 13px;
    border-width: 2px;
    border-color: rgba(255, 255, 255, 0.4);
    border-top-color: #FFFFFF;
}
/* 옅은 단추 안에서는 흰 고리가 안 보인다. 글자색을 그대로 따라간다. */
.btn--ghost .busy__ring, .btn--quiet .busy__ring {
    border-color: rgba(26, 18, 16, 0.22);
    border-top-color: currentColor;
}
@keyframes busySpin { to { transform: rotate(360deg); } }

/* 도는 것을 싫어하는 사람에게는 깜빡임으로 바꾼다. 멈춘 것처럼 보이면 안 된다. */
@media (prefers-reduced-motion: reduce) {
    .busy__ring { animation: busyPulse 1.2s ease-in-out infinite; }
    @keyframes busyPulse { 50% { opacity: 0.25; } }
}

.is-busy { opacity: 0.85; cursor: progress; }


/* == 사진 크게 보기 (lightbox.js) ======================
 *
 * 전체 화면으로 덮고 좌우로 넘긴다.
 * 예전에는 원본을 새 탭으로 열었는데, 그러면 다음 사진을 보려고
 * 탭을 닫고 돌아와 다시 눌러야 했다 — 사진이 열한 장이면 열한 번이다.
 */
.lbox {
    position: fixed;
    inset: 0;
    z-index: 900;
    display: none;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 16px;
    /* 사진 볼 때는 뒤를 확실히 죽인다. 반투명이면 뒤 글자가 사진에 섞인다. */
    background: rgba(12, 8, 7, 0.94);
}
.lbox.is-on { display: flex; }
body.lbox-open { overflow: hidden; }

.lbox__fig {
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    max-width: 100%;
    min-width: 0;
}
.lbox__img {
    max-width: 100%;
    /* 설명과 단추 자리를 남긴다. 100% 로 두면 캡션이 화면 밖으로 밀린다. */
    max-height: calc(100vh - 150px);
    object-fit: contain;
    border-radius: var(--r-sm);
    background: rgba(255, 255, 255, 0.06);
}
.lbox__cap {
    display: flex;
    align-items: center;
    gap: 10px;
    max-width: 92vw;
    color: rgba(255, 255, 255, 0.82);
    font-size: var(--t-caption);
    text-align: center;
}
.lbox__cap span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.lbox__cap a { color: #FFFFFF; text-decoration: underline; flex: none; }

.lbox__nav {
    flex: none;
    width: 46px;
    height: 46px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.14);
    color: #FFFFFF;
    cursor: pointer;
}
.lbox__nav .i { width: 26px; height: 26px; }
.lbox__nav:hover { background: rgba(255, 255, 255, 0.3); }

.lbox__x {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 40px;
    height: 40px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.14);
    color: #FFFFFF;
    cursor: pointer;
}
.lbox__x .i { width: 18px; height: 18px; }
.lbox__x:hover { background: rgba(255, 255, 255, 0.3); }

.lbox__n {
    position: absolute;
    top: 18px;
    left: 50%;
    transform: translateX(-50%);
    color: rgba(255, 255, 255, 0.82);
    font-family: var(--font-mono);
    font-size: var(--t-caption);
}

/* 좁은 화면에서는 단추를 사진 위에 겹친다. 옆에 두면 사진이 그만큼 작아진다. */
@media (max-width: 640px) {
    .lbox { padding: 8px; }
    .lbox__nav {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
    }
    .lbox__nav--prev { left: 8px; }
    .lbox__nav--next { right: 8px; }
    .lbox__img { max-height: calc(100vh - 130px); }
}


/* == 주소 누르기 (addr.js) ============================== */

/*
 * 누를 수 있다는 것을 보여 준다.
 *
 * 밑줄 하나로 충분하다. 단추처럼 만들면 주소가 주소로 안 읽히고,
 * 아무 표시도 없으면 아무도 안 누른다.
 */
.addr-hit {
    cursor: pointer;
    text-decoration: underline;
    text-decoration-style: dotted;
    text-underline-offset: 3px;
    text-decoration-color: var(--line-3);
}
.addr-hit:hover { color: var(--brand-dark); text-decoration-color: var(--brand); }

.addr__text {
    margin: 12px 0 4px;
    padding: 12px 14px;
    border-radius: var(--r-md);
    background: var(--surface-2);
    color: var(--ink);
    font-size: 1rem;
    line-height: 1.6;
    word-break: keep-all;
}

.addr__acts { list-style: none; margin: 12px 0 0; padding: 0; }
.addr__acts li + li { margin-top: 6px; }
.addr__act {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 13px 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
}
.addr__act:hover { border-color: var(--brand); color: var(--brand-dark); }
.addr__act > span { flex: 1 1 auto; }
/* 밖으로 나가는 것은 그렇다고 표시한다. 앱이 바뀌는 것은 미리 알아야 한다. */
.addr__act .i:last-child { flex: none; color: var(--smoke); }
