/* ==========================================================================
   그로스잇 멤버스 — 폰 프레임 + 앱 화면
   app-render.js 가 만든 마크업의 옷이다. 2·3·4단계가 같이 쓴다.

   ⚠ transform: scale() 로 폰을 줄이지 않는다.
     줄이면 getBoundingClientRect 가 화면상 크기를 돌려주어 실측값이 전부
     어긋나고(무엇이 몇 px 인지 알 수 없다), 글자도 흐려진다.
     대신 앱 폭을 실제 폰과 같은 390px 로 못 박고, 화면이 낮으면 폰 '높이'만
     계단식으로 줄인다(아래 media 참조).

   ⚠ 브랜드 색은 인라인 style 로 들어온다(--b, --b-on, --b-08 …).
     여기서 색을 하드코딩하면 브랜드 색을 바꿔도 반영되지 않는다.
     --b-on 은 밝기로 계산한 글자색이다(노란 브랜드에 흰 글자를 막는다).
   ========================================================================== */

/* ==========================================================================
   프레임
   ========================================================================== */
.ph {
  position: relative;   /* 알림(.bd-fx)의 기준 칸 */
  /* ⚠ **비율을 못 박는다**(사용자 결정 2026-09-17). 390 x 844 는 아이폰 13~15 의
     논리 크기이고 844/390 = 2.164 — 곧 **19.5:9** 다.
     ⚠ 폭을 360 이나 375 로 줄이지 말 것. 그러면 실제 폰보다 **좁은** 화면이
       되어 안의 글자와 여백이 실기기보다 크게 보인다 — 나중에 고객사가
       " 미리 본 것보다 글자가 크다" 를 겪는다. 19.5:9 를 지키는 폭이 390 이다.
     ⚠ 높이를 따로 정하지 말 것. 예전에는 화면이 낮으면 **높이만** 깎았는데,
       폭이 390 고정이라 그때마다 태블릿처럼 넙데데해졌다(사용자 지적).
       모자라면 높이가 아니라 **배율**을 줄인다(아래 `--ph-fit`). */
  --ph-w: 390px;
  --ph-ratio: 2.1641;                       /* 844 / 390 = 19.5 : 9 */
  --ph-h: calc(var(--ph-w) * var(--ph-ratio));
  /* ⚠ 테두리(베젤) 두께를 **변수로** 둔다. 상태바 가운데에 앉는 닫기 X 가
     이 값만큼 아래에서 시작해야 해서, 숫자로 박으면 좁은 화면(베젤 0)에서
     X 가 화면 밖 어두운 바닥에 뜬다. */
  --ph-bez: 10px;
  width: calc(var(--ph-w) + var(--ph-bez) * 2);
  flex: none;
  padding: var(--ph-bez);
  border-radius: 44px;
  background: #1b1b20;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, .06) inset,
    0 2px 6px rgba(16, 16, 24, .1),
    0 26px 60px rgba(16, 16, 24, .22);
}

.ph__screen {
  position: relative;
  width: var(--ph-w);
  height: var(--ph-h);
  border-radius: 35px;
  overflow: hidden;
  background: #fff;
}

/* 화면이 낮으면 폰을 낮춘다.
   붙어 있으려면 **화면 높이 ≥ sticky 위 여백 + 붙는 덩어리** 여야 한다.
   덩어리 = 테두리 20 + 폰 높이 + 설명줄.
   ⚠ 이 조건이 깨지면 페이지 맨 아래에서 폰이 위로 밀려 올라간다(실측 1~35px).
     '움직일 공간이 있다' 만 봐서는 못 잡는다. 끝까지 굴려서 제자리인지 봐야 한다.

   예전에는 5단 사다리(700/640/580/520/460)였는데 **460 아래가 없어서**
   화면 높이 620px 이하에서 하단 탭이 22~82px 잘렸다(실측).
   단을 더 놓는 대신 계산식으로 바꿨다. 화면 높이별 최대값을 20px 씩 훑어
   재보니 선형이었다(scratchpad solve.mjs):

     화면 1080→820 · 1040→780 · 1000→740 · 960→700 · 930→680
     (여기서 단계 칩이 static 이 되어 붙는 자리가 올라간다)
     900→720 · 870→680 · 840→660 · 800→620 · 750→560 · 700→520
     650→460 · 600→420 · 560→380 · 520→340

   ⚠ 상한 844px 은 아이폰 13~15 의 논리 높이다. 그보다 크게 그리면 세상에
     없는 폰이 되고, 폭이 390 고정이라 비율도 어긋난다.
   ⚠ aspect-ratio 와 width:auto 로 바꾸지 말 것. 폭이 390 이어야 그 안의
     글자 크기와 여백이 실제 앱과 같게 보인다. 폭이 줄면 고객사가 나중에
     '미리 본 것보다 글자가 크다' 를 겪는다. */
/* ⚠ 예전에는 여기서 `--ph-h` 를 깎았다. **비율이 깨지므로 되돌리지 말 것.**
   대신 폰 전체를 줄인다 — `--ph-fit` 은 `.ph` 에 거는 배율이다.
   ⚠ `transform` 은 **자리를 안 차지한다.** 줄인 만큼 아래를 당겨 주지 않으면
     폰 밑에 빈 칸이 남는다(늘릴 때 `--ph-lift` 를 넣는 것과 같은 까닭이다).
   ⚠ 빌더와 /v2 는 이 값을 쓰지 않는다. 거기는 `fitPhone`(build.js)이 칸을
     실측해 `.bd-scale` 에 배율을 건다 — 둘이 겹치면 배율이 곱해진다. */
.ph {
  transform: scale(var(--ph-fit, 1));
  transform-origin: top center;
  margin-bottom: calc(var(--ph-h) * (var(--ph-fit, 1) - 1));
}
/* 화면이 낮을수록 조금씩 줄인다. 값은 844 + 테두리 20 + 설명 줄이 들어갈
   높이에서 거꾸로 잡았다. */
@media (max-height: 940px) { .ph { --ph-fit: .92; } }
@media (max-height: 880px) { .ph { --ph-fit: .86; } }
@media (max-height: 820px) { .ph { --ph-fit: .80; } }
@media (max-height: 760px) { .ph { --ph-fit: .74; } }
@media (max-height: 700px) { .ph { --ph-fit: .68; } }
@media (max-height: 640px) { .ph { --ph-fit: .62; } }

/* 좁은 화면 — 테두리를 없애 프레임을 화면 폭에 맞춘다.
   ⚠ 전에는 `width: var(--ph-w)`(390px 고정)였다. 390px 보다 좁은 폰에서
     넘치거나 잘렸다. 실측: 빌더 375px 에서 문서 383/375 (갤럭시 S 360 ·
     아이폰 SE 375 는 흔한 폭이다), 안내 화면 320px 에서 폰이 70px 잘렸다.
   ⚠ `100vw` 를 쓰지 않는다. 세로 스크롤바가 있는 창에서 그만큼 넘친다.
     `width: 100%` + 좌우 여백만큼 음수 마진이면 정확히 화면 폭이 된다. */
@media (max-width: 460px) {
  .ph {
    width: 100%;
    padding: 0;
    border-radius: 22px;
    margin-inline: calc(var(--side-pad) * -1);
    /* ⚠ 여기서는 **배율을 쓰지 않는다.** 폰이 곧 화면이라 줄이면 좌우에
       빈 칸이 생겨 떠 보인다. 폭에 맞춰 놓고 세로로 굴린다(원래 그랬다). */
    --ph-fit: 1;
    margin-bottom: 0;
    /* 여기는 폰이 곧 화면이라 테두리가 없다. 상태바 가운데 X 도 그만큼 위로 온다. */
    --ph-bez: 0px;
  }
  /* ⚠ 화면(.ph__screen)도 함께 줄여야 한다. 여기가 390px 로 남아 있으면
     폰이 든 칸의 min-content 가 390px 이라 칸이 버텨 문서가 넘친다
     (실측: 320px 창에서 폰 칸이 358px, 문서 355/320). */
  /* ⚠ 높이도 **폭을 따라가야** 한다. `--ph-h` 는 `--ph-w`(390px 고정)에서
     계산되므로, 폭만 100% 로 줄이면 390 x 844 의 높이가 그대로 남아
     비율이 깨진다(실측 2026-09-17 · 390px 창: 219 x 844 = **3.85 : 1**).
     ⚠ 여기서는 `aspect-ratio` 가 맞는 도구다. " 쓰지 말 것" 이라는 경고는
       **폭을 떠다니게 두지 말라**는 뜻이었다 — 폭은 칸에 못 박혀 있고
       높이만 따라가는 이 자리는 그 경고와 다르다.
     ⚠ 그리고 여기는 폰이 곧 화면이라, 앱이 그 폭으로 다시 레이아웃되는 것이
       **오히려 맞다**(실기기도 그 폭이다). */
  .ph__screen {
    border-radius: 22px;
    width: 100%;
    height: auto;
    aspect-ratio: 9 / 19.5;
  }
  /* 폰 아래 설명도 같은 폭으로 묶는다(--ph-w 는 390px 고정이라 넘친다) */
  .ph-cap { max-width: 100%; }
  /* ⚠ 격자 칸은 min-width:auto 라 내용이 안 줄면 칸이 버틴다. 0 으로 푼다. */
  .bd__p, .bd-sticky, .ad__r { min-width: 0; }

  /* ⚠ **폰이 폭 0 으로 사라졌다**(실측 2026-09-13: 390 · 360 · 320px 전부
       `.ph` 가 0×536). `.bd-scale`(#phScale)은 transform 만 갖고 폭이 없는
       블록이라, 플렉스 안에서 **내용 폭으로 줄어든다.** 그 안의 `.ph` 는
       `width: 100%` 인데 부모 폭이 내용에서 나오니 서로 물려 0 으로 풀렸다.
     ⚠ 부모에 확정 폭을 준다. 넓은 화면은 `--ph-w` 가 폭을 정하므로 이 문제가
       없었다 — 좁은 화면에서만 `width: 100%` 로 바뀌면서 드러났다.
     ⚠ `fitPhone()` 이 `if (!w || !h) return` 으로 **조용히 빠져나가고** 있었다.
       그래서 오류도 안 나고 폰만 사라졌다. */
  .bd-scale { width: 100%; }

  /* ⚠ 폰이 **왼쪽으로 쏠려 오른쪽이 잘렸다**(실측 2026-09-13: 창 390 · 스테이지
       16~374 인데 폰은 0~358). `width: 100%` 와 좌우 음수 마진이 **겹쳐 셈**돼서
       그렇다 — 100% 는 이미 부모 폭(358)이고, 거기서 -16 을 더 밀면 왼쪽으로만
       움직인다. 오른쪽은 그대로라 32px 이 빈다.
     ⚠ `width: auto` 면 블록이 남는 폭을 다 먹으므로 음수 마진만큼 **양쪽으로**
       벌어져 정확히 화면 폭이 된다. 빌더 안에서만 바꾼다 — 안내 화면의 폰은
       플렉스 항목이라 auto 가 내용 폭으로 줄어든다. */
  .bd .ph { width: auto; }
  /* ⚠ 어드민도 **같은 자리**다. 2026-09-22 에 폰이 " 왼쪽으로 16px 쏠려
     보인다" 로 드러났다(실측 390px 창: 본문 가운데 195 · 폰 가운데 179).
     `width: 100%` 는 이미 부모 폭이라, 거기서 음수 마진을 더하면 왼쪽으로만
     움직이고 오른쪽에는 그만큼 빈 칸이 남는다.
   ⚠ 빌더 것을 고칠 때 **어드민을 같이 안 고쳤다.** 폰을 붙이는 곳이
     둘이라는 것을 놓쳤다 — 같은 규칙은 같이 건다. */
  .ad__r .ph { width: auto; }
}

/* 폰 아래 설명 — 알약 배지 둘 + 작은 안내 한 줄.
   ⚠ 줄글로 늘어놓으면 카드가 지저분해 보인다(고객사 지적). */
.ph-cap {
  /* ⚠ 이 줄은 붙는 덩어리 안에 있다. 여기서 1px 을 벌면 폰을 1px 키울 수 있다.
     안내 문구가 두 줄(42px)이던 것을 한 줄로 줄여 21px 을 벌었다. */
  margin: 8px auto 0;
  max-width: calc(var(--ph-w) + 20px);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
}
.ph-cap__b {
  padding: 5px 11px;
  border-radius: 99px;
  background: var(--bg);
  border: 1px solid var(--line);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--text-2);
  white-space: nowrap;
}
.ph-cap__d {
  flex: 1 0 100%;
  margin-top: 2px;
  font-size: var(--fs-xs);
  line-height: 1.6;
  color: var(--text-3);
  text-align: center;
}

/* ==========================================================================
   앱 — 껍데기
   ========================================================================== */
.ap {
  /* 앱 안쪽 색은 브랜드와 무관하게 고정이다 — 사이트 토큰을 쓰지 않는다
     (사이트 색이 바뀌면 앱 미리보기가 같이 변해 버린다) */
  --ap-text:  #16161a;
  --ap-text2: #6b7280;
  --ap-text3: #9aa0aa;
  --ap-line:  #eceef2;
  --ap-bg2:   #f6f7f9;
  --ap-ease:  cubic-bezier(.22, 1, .36, 1);

  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  font-family: var(--font);
  font-size: 14px;
  color: var(--ap-text);
  background: #fff;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
.ap * { box-sizing: border-box; }
.ap img { display: block; max-width: 100%; }

/* 누를 수 있는 것은 전부 button 이다 — 기본 모양을 지운다.
   ⚠ 안 지우면 <button> 기본 가운데 정렬·테두리·회색 배경이 그대로 나온다.
   ⚠ :where() 로 감싸야 한다. `.ap button` 은 명시도가 (0,1,1) 이라
     `.ap-tier--card`(0,1,0) 같은 컴포넌트 규칙보다 세다 — 그대로 두면
     등급 카드·칩·담기 버튼의 브랜드색 배경이 전부 지워진다(실제로 그랬다).
     :where() 는 명시도에 0 을 보태므로 이 규칙은 (0,1,0) 이 되어 뒤 규칙이 이긴다. */
.ap :where(button) {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ap :where(button):active { opacity: .72; }

/* ---------- 흰 테두리 폰 (2026-09-18 · 사용자 지시) ----------
   ⚠ 흰 바탕 위에 놓는 폰이다. 랜딩 히어로(어두운 바탕)와 고객사 현황
     (흰 바탕)이 **같은 옷**을 입는다 — 사용자가 " 통일감이 없다" 고 한 자리다.
   ⚠ 흰 테두리는 안쪽 흰 화면과 **경계가 사라진다.** 화면 쪽에 머리카락
     선을 한 줄 둘러 가른다. 테두리에 어두운 선을 그으면 도로 회색이 된다.
   ⚠ 그 선을 `inset` 으로 두지 말 것 — 화면 안쪽에 그려져 앱 상단바를 덮는다.
   ⚠ **두 곳에 적지 않는다.** 예전에는 `.ph--hero` 안에 흰색이 직접 적혀
     있었다. 쓰는 자리가 둘이 되는 순간 한쪽만 고쳐진다. */
.ph--light {
  background: #fff;
  box-shadow:
    0 18px 44px rgba(15, 23, 42, .16),
    0 0 0 1px rgba(15, 23, 42, .08);
}
.ph--light .ph__screen { box-shadow: 0 0 0 1px rgba(15, 23, 42, .12); }

/* ---------- 덮개로 띄웠을 때의 닫기 X ----------
   ⚠ **평소에는 안 보인다.** 넓은 화면에서는 폰이 늘 옆에 있어 닫을 일이
     없다 — 켜는 것은 `/v2` 의 덮개(`.v2-body.is-phone`)뿐이다.
   ⚠ 자리는 **상태바 가운데**다(사용자 지시 2026-09-17). 시계는 왼쪽,
     수신 · 배터리는 오른쪽이라 가운데가 비어 있다. 위쪽은 `--ph-bez` 만큼
     내려와야 화면 안에 앉는다.
   ⚠ 상태바는 **흰 바탕일 때도 브랜드 색일 때도** 있다(`.ap-status.is-fill`).
     한쪽에만 맞추면 다른 쪽에서 안 보인다 — 어두운 알에 **흰 테두리**를 둘러
     두 경우 모두에서 드러나게 한다. */
.ph-x {
  display: none;
  position: absolute; z-index: 6;
  top: calc(var(--ph-bez, 10px) + 4px);
  left: 50%; transform: translateX(-50%);
  align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: rgba(17, 17, 22, .74);
  color: #fff;
  font-size: 15px; line-height: 1;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .85), 0 2px 8px rgba(0, 0, 0, .3);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.ph-x:active { opacity: .7; }
.ph-x:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ---------- 상태바 ---------- */
.ap-status {
  flex: none;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 22px 0 26px;
  color: var(--ap-text);
}
.ap-status.is-fill { background: var(--b); color: var(--b-on); }
.ap-status__t { font-size: 14px; font-weight: 700; letter-spacing: -.01em; }
.ap-status__r { display: flex; align-items: center; gap: 5px; }
.ap-status__r svg { height: 11px; width: auto; fill: currentColor; }

/* ---------- 상단바 ---------- */
.ap-top {
  flex: none;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  background: #fff;
  color: var(--ap-text);
}
.ap-top.is-fill { background: var(--b); color: var(--b-on); }
.ap-top__logo {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -.03em;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  max-width: 210px;
}
.ap-top__acts { display: flex; align-items: center; gap: 4px; flex: none; }
.ap-ib {
  position: relative;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  color: inherit;
}
.ap-ib svg { width: 22px; height: 22px; }
.ap-ib--dot::after {
  content: "";
  position: absolute; top: 6px; right: 6px;
  width: 6px; height: 6px; border-radius: 50%;
  background: #ef4444;
  box-shadow: 0 0 0 1.6px #fff;
}
.ap-top.is-fill .ap-ib--dot::after { box-shadow: 0 0 0 1.6px var(--b); }
.ap-ib__n {
  position: absolute; top: 2px; right: 1px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 99px;
  background: #ef4444; color: #fff;
  font-size: 10px; font-weight: 800; font-style: normal;
  display: grid; place-items: center;
  box-shadow: 0 0 0 1.6px #fff;
}
.ap-top.is-fill .ap-ib__n { box-shadow: 0 0 0 1.6px var(--b); }

/* ---------- 구르는 가운데 ---------- */
.ap-scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  /* ⚠ 하단 탭이 화면 위에 떠 있어서 마지막 요소가 그 뒤로 숨는다.
     탭 높이(62px) 보다 넉넉해야 한다. */
  padding-bottom: 80px;
  /* 스크롤바가 앱 안에 뜨면 폰처럼 보이지 않는다 */
  scrollbar-width: none;
  overscroll-behavior: contain;
}
.ap-scroll::-webkit-scrollbar { width: 0; height: 0; }

/* ---------- 인사말 ---------- */
.ap-hello {
  margin: 0;
  padding: 14px 16px 10px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -.02em;
}

/* ==========================================================================
   등급 — 카드 · 한 줄 · 반칸
   ========================================================================== */
.ap-tier {
  position: relative;
  display: grid;
  align-items: center;
  gap: 0 10px;
  width: calc(100% - 32px);
  margin: 0 16px 4px;
}
.ap-tier__b {
  grid-area: b;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 14px; font-weight: 800;
  background: #f0b429; color: #4a3200;
}
.ap-tier__n { grid-area: n; font-size: 15px; font-weight: 800; letter-spacing: -.01em; }
.ap-tier__note { grid-area: note; font-size: 11px; opacity: .78; letter-spacing: -.02em; }
.ap-tier__bar {
  grid-area: bar;
  height: 7px; border-radius: 99px;
  background: rgba(255, 255, 255, .3);
  overflow: hidden;
}
.ap-tier__bar > i { display: block; height: 100%; border-radius: 99px; background: #f0b429; }
.ap-tier__nx { grid-area: nx; font-size: 11px; font-weight: 700; opacity: .85; }

/* A안 — 큰 브랜드색 카드 */
.ap-tier--card {
  padding: 14px 16px 15px;
  border-radius: 14px;
  background: var(--b);
  color: var(--b-on);
  grid-template-columns: 30px 1fr auto;
  grid-template-areas:
    "b n    note"
    "bar bar nx";
  row-gap: 12px;
}
.ap-tier--card .ap-tier__note { justify-self: end; text-align: right; }

/* B안 — 흰 카드 한 줄 */
.ap-tier--line {
  padding: 11px 14px 12px;
  border-radius: 99px;
  background: #fff;
  border: 1px solid var(--ap-line);
  box-shadow: 0 1px 2px rgba(16, 16, 24, .04);
  grid-template-columns: 30px auto 1fr auto;
  grid-template-areas: "b n bar nx";
  gap: 0 10px;
}
.ap-tier--line .ap-tier__note { display: none; }   /* 한 줄에 다 넣으면 안 읽힌다 */
.ap-tier--line .ap-tier__bar { background: var(--ap-bg2); }

/* C안 — 왼쪽 반칸 + 오른쪽 혜택모음 */
.ap-half {
  margin: 0 16px 4px;
  display: grid;
  grid-template-columns: 1fr 108px;
  gap: 10px;
  align-items: stretch;
}
.ap-half > * { min-width: 0; }
/* ⚠ 칸을 30px 1fr 로 만들면 진행바가 첫 칸(30px)에 갇혀 땅이만하게 나온다.
     진행바는 다음 등급이름 앞까지 뻗어야 하므로 칸을 셋으로 나눠 span 시킨다. */
.ap-tier--half {
  width: 100%;
  margin: 0;
  grid-template-columns: 30px 1fr auto;
  grid-template-areas:
    "cap cap  cap"
    "b   n    n"
    "bar bar  nx"
    "note note note";
  row-gap: 9px;
  padding: 13px 14px 14px;
}
.ap-tier__cap { grid-area: cap; font-size: 11px; font-weight: 700; opacity: .8; }
.ap-tier--half .ap-tier__nx { justify-self: end; padding-left: 8px; }
.ap-tier--half .ap-tier__note { font-size: 10px; justify-self: end; text-align: right; }

.ap-perkbox { display: flex; flex-direction: column; gap: 6px; }
.ap-perkbox__cap { font-size: 12px; font-weight: 800; letter-spacing: -.02em; padding: 2px 0 2px 2px; }
.ap-perkbox__row {
  flex: 1 1 auto;
  display: flex; align-items: center; gap: 6px;
  padding: 0 8px;
  border-radius: 10px;
  background: var(--ap-bg2);
  font-size: 11px; font-weight: 700; color: var(--ap-text2);
  letter-spacing: -.03em;
}
.ap-perkbox__row svg { width: 16px; height: 16px; flex: none; }

/* ==========================================================================
   혜택 아이콘 줄
   ========================================================================== */
.ap-perks { display: grid; padding: 16px 8px 14px; margin: 6px 0 2px; }
.ap-perks[data-n="3"] { grid-template-columns: repeat(3, 1fr); }
.ap-perks[data-n="4"] { grid-template-columns: repeat(4, 1fr); }
.ap-perks > * { min-width: 0; }

.ap-perk { display: flex; flex-direction: column; align-items: center; gap: 7px; }
/* 칸 사이 구분선은 숫자가 붙는 A안에만 있다(시안 그대로).
   B안 시안에는 선이 없다 — 전부에 넣으면 B안이 시안과 달라진다. */
.ap-perks[data-c="1"] .ap-perk { border-right: 1px solid var(--ap-line); }
.ap-perks[data-c="1"] .ap-perk:last-child { border-right: 0; }
.ap-perk svg { width: 26px; height: 26px; }
.ap-perk em {
  font-style: normal;
  font-size: 11.5px; font-weight: 700; letter-spacing: -.03em;
  color: var(--ap-text2);
  white-space: nowrap;
}
.ap-perk b { font-size: 16px; font-weight: 800; letter-spacing: -.02em; }

/* 아이콘 색 — 시안이 아이콘마다 다른 색을 쓴다 */
.ap-i--blue   { color: #3b82f6; }
.ap-i--red    { color: #ef4444; }
.ap-i--violet { color: #8b5cf6; }
.ap-i--green  { color: #10b981; }
.ap-i--amber  { color: #f59e0b; }

/* ==========================================================================
   배너 캐러셀
   ⚠ 슬라이드 사이에 grid gap 을 두지 말 것. 트랙 폭이 칸 폭의 정확히 n 배여야
     translateX(-100% / n * i) 가 한 칸씩 정확히 움직인다.
     여백은 슬라이드 안쪽 padding 으로 준다.
   ⚠ B안의 '좌우 엿보기' 는 바깥 칸 padding 으로 만든다.
     overflow:hidden 은 padding 안쪽까지 보여 주므로 그대로 이웃이 비친다.
     예전처럼 이웃 슬라이드에 aspect-ratio 를 주면 내용 높이에서 폭이 역산되어
     트랙을 20~28px 넘어간다(실측: scrollWidth 410 / clientWidth 390).
   ========================================================================== */
.ap-car {
  --peek: 8px;
  position: relative;
  overflow: hidden;
  padding: 0 var(--peek);
  margin: 8px 0 4px;
  touch-action: pan-y;
}
.ap-car--peek { --peek: 22px; }

/* ⚠ 트랙 폭을 칸 폭의 정확히 n 배로 못 박아야 한다.
     grid-auto-columns:100% 만 두면 칸은 넘치지만 **트랙 자신의 폭은 칸 폭 그대로**여서,
     translateX(-100%/n*i) 가 한 칸이 아니라 한 칸의 1/n 만 움직인다
     (실측: i=1 에서 -69.2px, 있어야 할 값은 -374px).
     width 를 n 배로 주고 칸을 1fr 로 나누면 -100%/n 이 정확히 한 칸이 된다. */
.ap-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  width: calc(100% * var(--n));
  transition: transform .38s var(--ap-ease);
  transform: translateX(calc(-100% / var(--n) * var(--i) + var(--drag, 0px)));
  will-change: transform;
}
.ap-slide { padding: 0 5px; min-width: 0; }
.ap-slide__in {
  position: relative;
  display: block;
  /* ⚠ 350/320(=1.09) 이던 것을 350/250(=1.40) 으로 눕혔다.
     보이는 칸이 488px 뿐인데 배너 혼자 333px(68%)을 먹어 B안·C안에서
     등급·혜택이 하단 탭 뒤로 밀렸다(실측). 70px 을 번다.
     ⚠ 더 눕히지 말 것. 사진이 900x600(=1.50) 이라 1.40 까지는 오히려 덜
       잘리지만 16:9(1.78) 부터는 위아래를 잘라 무엇인지 알기 어려워진다
       (후보 5종을 실제 칸에 넣어 보고 골랐다). */
  aspect-ratio: 350 / 250;
  border-radius: 14px;
  overflow: hidden;
  background: var(--ap-bg2);
}
.ap-slide__in img {
  width: 100%; height: 100%;
  object-fit: cover;
  user-select: none; -webkit-user-drag: none;
}
/* 사진 위 글자 — 아래쪽에 어두운 그라데이션을 깔아야 어떤 사진에서도 읽힌다 */
.ap-slide__tx {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 30px 16px 14px;
  display: flex; flex-direction: column; gap: 3px;
  color: #fff;
  background: linear-gradient(to top, rgba(10, 10, 14, .72) 0%, rgba(10, 10, 14, .35) 55%, transparent 100%);
}
.ap-slide__tx b { font-size: 18px; font-weight: 800; letter-spacing: -.03em; }
.ap-slide__tx em { font-style: normal; font-size: 12px; opacity: .88; letter-spacing: -.02em; }

/* 사진을 더 오려 오지 않고 색으로 그리는 마지막 두 장 */
.ap-slide__in--fill,
.ap-slide__in--tint {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px;
  padding: 0 24px; text-align: center;
}
.ap-slide__in--fill { background: var(--b); color: var(--b-on); }
.ap-slide__in--tint { background: var(--b-08); color: var(--ap-text); }
.ap-slide__in--fill b, .ap-slide__in--tint b { font-size: 20px; font-weight: 800; letter-spacing: -.03em; }
.ap-slide__in--fill em, .ap-slide__in--tint em { font-style: normal; font-size: 12px; opacity: .82; letter-spacing: -.02em; }

.ap-arrow {
  position: absolute; top: 50%;
  width: 30px; height: 30px;
  margin-top: -15px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, .82);
  color: #16161a;
  box-shadow: 0 1px 4px rgba(16, 16, 24, .2);
  opacity: 0;
  transition: opacity .2s ease;
}
.ap-arrow svg { width: 17px; height: 17px; }
.ap-arrow--l { left: calc(var(--peek) + 10px); }
.ap-arrow--r { right: calc(var(--peek) + 10px); }
/* 마우스가 있는 기기에서만 숨겼다 보인다. 터치에서는 늘 보인다(가리키기가 없다) */
.ap-car:hover .ap-arrow { opacity: 1; }
@media (hover: none) { .ap-arrow { opacity: .9; } }

.ap-car__pg {
  position: absolute;
  right: calc(var(--peek) + 12px); bottom: 34px;
  padding: 3px 9px;
  border-radius: 99px;
  background: rgba(16, 16, 24, .5);
  color: #fff;
  font-size: 11px; font-weight: 700;
}
.ap-dots {
  position: absolute; left: 0; right: 0; bottom: 12px;
  display: flex; justify-content: center; gap: 5px;
}
.ap-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: rgba(255, 255, 255, .55);
  box-shadow: 0 0 2px rgba(16, 16, 24, .35);
  transition: width .22s var(--ap-ease), background-color .22s ease;
}
.ap-dot.is-on { width: 16px; border-radius: 99px; background: #fff; }

/* ==========================================================================
   사용 모듈
   ========================================================================== */
/* 모듈 사이를 8px 회색 띠로 가른다.
   ⚠ 여백만 벌리면 '빈 데가 늘었다' 로 보인다. 실제 앱은 띠로 가른다. */
.ap-mod { margin: 0; padding: 16px 16px 18px; display: block; width: 100%; }
.ap-mod + .ap-mod,
.ap-mod + .ap-card,
.ap-card + .ap-mod { border-top: 8px solid var(--ap-bg2); }
.ap-card {
  margin: 16px 16px 18px;
  padding: 15px 14px 14px;
  border: 1px solid var(--ap-line);
  border-radius: 14px;
  background: #fff;
  width: calc(100% - 32px);
}
.ap-mod__h {
  margin: 0 0 12px;
  display: flex; align-items: center; gap: 6px;
  font-size: 15.5px; font-weight: 800; letter-spacing: -.03em;
}
.ap-mod__i { width: 15px; height: 15px; color: var(--ap-text3); flex: none; }

.ap-price {
  display: flex; align-items: baseline; gap: 4px;
  font-size: 12px; color: var(--ap-text2);
  letter-spacing: -.02em;
}
.ap-price b { font-size: 15px; font-weight: 800; color: var(--ap-text); }
.ap-price s { color: var(--ap-text3); font-size: 11px; }
.ap-off { font-style: normal; font-weight: 800; color: #ef4444; font-size: 14px; }
.ap-desc {
  font-size: 11.5px; line-height: 1.45; color: var(--ap-text2);
  letter-spacing: -.02em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* A. 시간별 추천상품 — 옆으로 넘기는 큰 카드.
   ⚠ overflow:hidden 으로만 자르면 둘째·셋째 칸에 닿을 수 없다. 진짜 스크롤로 둔다. */
.ap-chips {
  display: flex; gap: 6px; margin: 0 0 12px;
  overflow-x: auto; scrollbar-width: none;
}
.ap-chips::-webkit-scrollbar { height: 0; }
.ap-chip {
  flex: none;
  padding: 6px 11px;
  border-radius: 99px;
  background: var(--ap-bg2);
  font-size: 11.5px; font-weight: 700; color: var(--ap-text2);
  letter-spacing: -.03em; white-space: nowrap;
}
.ap-chip.is-on { background: #1b1b20; color: #fff; }

.ap-wide {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 178px;
  gap: 10px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-right: 16px;
  margin-right: -16px;
}
.ap-wide::-webkit-scrollbar { height: 0; }
.ap-big {
  border: 1px solid var(--ap-line);
  border-radius: 12px;
  overflow: hidden;
  display: flex; flex-direction: column; gap: 4px;
  padding-bottom: 11px;
  background: #fff;
}
.ap-big img { width: 100%; aspect-ratio: 1; object-fit: cover; background: var(--ap-bg2); }
.ap-big > b { padding: 10px 11px 0; font-size: 13.5px; font-weight: 700; letter-spacing: -.03em; }
.ap-big .ap-desc { padding: 0 11px; }
.ap-big .ap-price { padding: 2px 11px 0; }

/* B. 순위 모듈 */
.ap-rank { list-style: none; margin: 0; padding: 0; }
.ap-rank li {
  display: grid;
  grid-template-columns: 26px 46px 1fr 20px;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--ap-line);
  cursor: pointer;
}
.ap-rank li:last-child { border-bottom: 0; }
.ap-rank > li > * { min-width: 0; }
.ap-rank__n {
  width: 26px; height: 26px;
  display: grid; place-items: center;
  font-size: 12.5px; font-weight: 800; color: var(--ap-text3);
}
.ap-rank__n.is-medal { border-radius: 50%; color: #fff; }
.ap-rank__n.m1 { background: #f0b429; color: #4a3200; }
.ap-rank__n.m2 { background: #b0b7c3; }
.ap-rank__n.m3 { background: #cd8b62; }
.ap-rank img { width: 46px; height: 46px; border-radius: 10px; object-fit: cover; background: var(--ap-bg2); }
.ap-rank__t { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ap-rank__t > b {
  font-size: 13px; font-weight: 700; letter-spacing: -.03em;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.ap-rank__p { font-size: 15px; font-weight: 700; color: var(--ap-text3); text-align: right; }

/* C. 프로모션 전시 */
.ap-promo { padding: 0; margin-top: 14px; }
.ap-promo__art { position: relative; aspect-ratio: 390 / 300; overflow: hidden; }
.ap-promo__art img { width: 100%; height: 100%; object-fit: cover; }
.ap-promo__tx {
  position: absolute; inset: auto 0 0 0;
  padding: 40px 18px 34px;
  display: flex; flex-direction: column; gap: 4px;
  color: #fff;
  background: linear-gradient(to top, rgba(10, 10, 14, .7) 0%, transparent 100%);
}
.ap-promo__tx em { font-style: normal; font-size: 11.5px; opacity: .85; letter-spacing: -.02em; }
.ap-promo__tx b { font-size: 26px; font-weight: 800; letter-spacing: -.04em; line-height: 1.1; }
.ap-promo__card {
  margin: -26px 16px 0;
  position: relative;
  display: grid;
  grid-template-columns: 46px 1fr;
  align-items: center;
  gap: 11px;
  padding: 11px 13px;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 2px 6px rgba(16, 16, 24, .06), 0 10px 24px rgba(16, 16, 24, .1);
}
.ap-promo__card > * { min-width: 0; }
.ap-promo__card img { width: 46px; height: 46px; border-radius: 10px; object-fit: cover; }
.ap-promo__card > b { font-size: 13px; font-weight: 700; letter-spacing: -.03em; }

/* D. 추천상품 모듈 */
.ap-grid2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px 12px; }
.ap-grid2 > * { min-width: 0; }
.ap-cell { display: flex; flex-direction: column; gap: 5px; }
.ap-cell img { width: 100%; aspect-ratio: 1; border-radius: 12px; object-fit: cover; background: var(--ap-bg2); }
.ap-cell > b { font-size: 12.5px; font-weight: 700; color: var(--ap-text2); letter-spacing: -.03em; }
.ap-more {
  display: flex; align-items: center; justify-content: center; gap: 4px;
  width: 100%;
  margin-top: 13px; padding: 11px 0;
  border: 1px solid var(--ap-line); border-radius: 10px;
  font-size: 12.5px; font-weight: 700; color: var(--ap-text2);
}
.ap-more__i { width: 15px; height: 15px; }

/* 타임할인 (항상 들어간다) */
.ap-deal { display: block; }
.ap-deal .ap-mod__h { justify-content: space-between; }
.ap-deal__t {
  display: flex; align-items: center; gap: 4px;
  font-size: 11.5px; font-weight: 700; color: #ef4444;
  letter-spacing: -.02em;
}
.ap-deal__i { width: 14px; height: 14px; }
.ap-deal__row { display: grid; grid-template-columns: 56px 1fr; gap: 12px; align-items: center; }
.ap-deal__row > * { min-width: 0; }
.ap-deal__row img { width: 56px; height: 56px; border-radius: 10px; object-fit: cover; background: var(--ap-bg2); }

/* ==========================================================================
   안쪽 화면 (주문 · 전체메뉴 · 준비 중)
   ========================================================================== */
.ap-sub {
  display: flex; align-items: center; gap: 6px;
  padding: 12px 16px 10px;
  border-bottom: 1px solid var(--ap-line);
}
.ap-sub__back { width: 28px; height: 28px; display: grid; place-items: center; margin-left: -6px; }
.ap-sub__back svg { width: 20px; height: 20px; }
.ap-sub > b { font-size: 16px; font-weight: 800; letter-spacing: -.03em; }

.ap-store {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 8px;
  padding: 12px 16px;
  border-bottom: 8px solid var(--ap-bg2);
}
.ap-store__n { font-size: 14px; font-weight: 800; letter-spacing: -.03em; }
.ap-store__d { grid-column: 1; font-size: 11.5px; color: var(--ap-text2); letter-spacing: -.02em; }
.ap-store__c {
  grid-row: 1 / 3; grid-column: 2; align-self: center;
  padding: 6px 12px; border-radius: 99px;
  border: 1px solid var(--ap-line);
  font-size: 11.5px; font-weight: 700; color: var(--ap-text2);
}

.ap-cats {
  display: flex; gap: 6px;
  padding: 12px 16px 10px;
  overflow-x: auto; scrollbar-width: none;
  border-bottom: 1px solid var(--ap-line);
}
.ap-cats::-webkit-scrollbar { height: 0; }
.ap-cat {
  flex: none;
  padding: 7px 14px;
  border-radius: 99px;
  background: var(--ap-bg2);
  font-size: 12.5px; font-weight: 700; color: var(--ap-text2);
  letter-spacing: -.03em; white-space: nowrap;
}
.ap-cat.is-on { background: var(--b); color: var(--b-on); }

.ap-list { list-style: none; margin: 0; padding: 0 16px; }
.ap-list li {
  display: grid;
  grid-template-columns: 62px 1fr 30px;
  gap: 12px;
  align-items: center;
  padding: 13px 0;
  border-bottom: 1px solid var(--ap-line);
}
.ap-list > li > * { min-width: 0; }
.ap-list li:last-child { border-bottom: 0; }
.ap-list img { width: 62px; height: 62px; border-radius: 10px; object-fit: cover; background: var(--ap-bg2); }
.ap-list__t { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ap-list__t > b {
  font-size: 13.5px; font-weight: 700; letter-spacing: -.03em;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.ap-add {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--b); color: var(--b-on);
}
.ap-add svg { width: 17px; height: 17px; }
.ap-empty { margin: 30px 16px; text-align: center; font-size: 13px; color: var(--ap-text3); }

.ap-menu { list-style: none; margin: 0; padding: 0 16px; }
.ap-menu li {
  display: grid;
  grid-template-columns: 24px 1fr 18px;
  gap: 12px; align-items: center;
  padding: 15px 0;
  border-bottom: 1px solid var(--ap-line);
  cursor: pointer;
}
.ap-menu > li > * { min-width: 0; }
.ap-menu li span { display: flex; flex-direction: column; gap: 2px; }
.ap-menu li b { font-size: 14px; font-weight: 700; letter-spacing: -.03em; }
.ap-menu li em { font-style: normal; font-size: 11px; color: var(--ap-text3); }
.ap-menu__i { width: 22px; height: 22px; color: var(--b); }
.ap-menu__c { width: 18px; height: 18px; color: var(--ap-text3); }

.ap-soon {
  display: flex; flex-direction: column; align-items: center;
  gap: 12px; text-align: center;
  padding: 64px 34px;
}
.ap-soon__i { width: 40px; height: 40px; color: var(--b); }
.ap-soon > b { font-size: 15px; font-weight: 800; letter-spacing: -.03em; }
.ap-soon > span { font-size: 12.5px; line-height: 1.65; color: var(--ap-text2); }
.ap-soon__b {
  margin-top: 6px; padding: 11px 22px;
  border-radius: 99px;
  background: var(--b); color: var(--b-on);
  font-size: 13px; font-weight: 700;
}

/* 담았을 때 뜨는 알림 */
.ap-toast {
  position: absolute; left: 16px; right: 16px; bottom: 78px;
  z-index: 5;
  padding: 12px 15px;
  border-radius: 11px;
  background: rgba(16, 16, 24, .88);
  color: #fff;
  font-size: 12.5px; font-weight: 600; line-height: 1.5;
  text-align: center;
  animation: ap-toast .22s var(--ap-ease);
}
@keyframes ap-toast { from { opacity: 0; transform: translateY(8px); } }

/* ==========================================================================
   하단 탭
   ========================================================================== */
.ap-tabs {
  flex: none;
  height: 62px;
  display: flex;
  align-items: center;
  padding: 0 4px 6px;
  border-top: 1px solid var(--ap-line);
  background: #fff;
}
.ap-tab {
  flex: 1 1 0;
  min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  color: var(--ap-text2);
}
.ap-tab__i { width: 21px; height: 21px; }
.ap-tab em {
  font-style: normal;
  font-size: 9.5px; font-weight: 700; letter-spacing: -.04em;
  white-space: nowrap;
}
.ap-tab.is-on { color: var(--b); }

/* 가운데 한 칸은 원으로 띄운다 — 시안 세 장 모두 그렇다.
   ⚠ 고정이 아니다. 여섯 곳 중 두 곳이 결제·로고로 바꿨다(가이드북 10장). */
.ap-tab.is-mid { position: relative; }
.ap-tab.is-mid .ap-tab__i {
  width: 46px; height: 46px;
  padding: 12px;
  margin-top: -18px;
  border-radius: 50%;
  background: var(--b);
  color: var(--b-on);
  box-shadow: 0 3px 10px var(--b-30);
}
/* 브랜드 로고를 고르면 심벌 대신 브랜드 첫 글자를 원 안에 넣는다.
   ⚠ 남의 로고 파일을 우리가 들고 있을 수 없다. 5단계에서 고객사가 올린다. */
.ap-tab.is-mid .ap-tab__logo {
  width: 46px; height: 46px;
  margin-top: -18px;
  border-radius: 50%;
  background: var(--b);
  color: var(--b-on);
  box-shadow: 0 3px 10px var(--b-30);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 800; letter-spacing: -.04em;
}
/* 로고는 글자가 없다 — 그 칸만 라벨 높이를 대신 비워 준다(줄이 어긋나지 않게) */
.ap-tab.is-mid em:empty { display: block; height: 12px; }
.ap-tab.is-mid em { color: var(--ap-text2); }
.ap-tab.is-mid.is-on em { color: var(--b); }

/* ==========================================================================
   앱 아이콘 + 스토어 이름
   ⚠ 앱명은 앱 화면 안에 나오지 않는다(상단바는 브랜드명이다).
     그래서 앱명을 골라도 폰이 그대로여서 '눌러도 아무 일이 없다' 로 보였다.
     이 상자가 앱명이 보이는 유일한 자리다.
   ========================================================================== */
.apic {
  display: grid;
  grid-template-columns: 58px 1fr;
  grid-template-areas: "i n" "i d";
  gap: 2px 14px;
  align-items: center;
  align-content: center;
}
.apic__i {
  grid-area: i;
  width: 58px; height: 58px;
  border-radius: 15px;
  display: grid; place-items: center;
  background: var(--b); color: var(--b-on);
  font-family: var(--font);
  font-size: 27px; font-weight: 800; letter-spacing: -.04em;
  box-shadow: 0 1px 2px rgba(16, 16, 24, .08), 0 6px 16px rgba(16, 16, 24, .12);
}
.apic__n {
  grid-area: n;
  font-size: var(--fs-body); font-weight: 800; letter-spacing: -.02em;
  color: var(--text);
  align-self: end;
}
.apic__d {
  grid-area: d;
  font-style: normal;
  font-size: var(--fs-xs); color: var(--label);
  align-self: start;
}

/* ==========================================================================
   홈 화면 위젯 — 앱 안이 아니라 폰 바탕화면에 놓인다(가이드북 4장)
   ========================================================================== */
.wg { font-family: var(--font); letter-spacing: -.02em; }
.wg__logo { font-weight: 800; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

.wg--wide {
  width: 100%; max-width: 340px;
  border-radius: 20px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 1px 2px rgba(16, 16, 24, .06), 0 6px 20px rgba(16, 16, 24, .1);
}
.wg__bar { display: flex; align-items: center; gap: 10px; padding: 11px 14px; background: var(--b); color: var(--b-on); }
.wg__bar .wg__logo { font-size: 14px; max-width: 130px; }
.wg__cnt {
  margin-left: auto;
  display: flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 700; white-space: nowrap;
}
.wg__cnt i { width: 1px; height: 10px; background: currentColor; opacity: .45; }
.wg__row { display: grid; grid-template-columns: repeat(4, 1fr); padding: 14px 6px 15px; }
.wg__row > * { min-width: 0; }
.wg__it { display: flex; flex-direction: column; align-items: center; gap: 7px; }
.wg__ic {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: #f3f3f6; color: #1b1b20;
}
.wg__ic svg { width: 21px; height: 21px; }
.wg__it em { font-style: normal; font-size: 10.5px; font-weight: 700; color: #1b1b20; white-space: nowrap; }

.wg--sq {
  width: 170px; height: 170px;
  border-radius: 22px;
  padding: 13px 12px 14px;
  background: var(--b); color: var(--b-on);
  display: flex; flex-direction: column; align-items: center;
  box-shadow: 0 1px 2px rgba(16, 16, 24, .06), 0 6px 20px rgba(16, 16, 24, .12);
}
.wg--sq .wg__logo { font-size: 12px; max-width: 140px; }
.wg__ph { width: 72px; height: 72px; margin: 9px 0 8px; border-radius: 14px; overflow: hidden; background: #fff; flex: none; }
.wg__ph img { width: 100%; height: 100%; object-fit: cover; }
.wg__sub { font-size: 10.5px; font-weight: 600; opacity: .74; }
.wg__ttl { font-size: 13px; font-weight: 800; margin-top: 2px; text-align: center; }

/* ---------- 주문 화면 상단 세그먼트 (픽업 | 매장 | 배달) ----------
   가이드북 6장의 받는 방식 셋. 하단 탭을 차지하지 않는다.
   ⚠ 켠 것이 하나뿐이면 렌더러가 이 줄 자체를 그리지 않는다 —
     고를 것이 없는데 탭 줄을 두면 '왜 못 누르지' 가 된다. */
.ap-seg {
  display: flex;
  gap: 4px;
  padding: 10px 16px 2px;
  background: #fff;
}
.ap-seg__b {
  flex: 1 1 0;
  min-width: 0;
  padding: 9px 0;
  border-radius: 10px;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -.03em;
  text-align: center;
}
.ap-seg__b.is-on {
  background: var(--b);
  color: var(--b-on);
}

/* ---------- 주문 화면: 영수증 · 예약 고르기 · 안내줄 ----------
   주문내역은 하단 탭이 아니라 여기다 — 가이드북 10장 여섯 곳 중 탭에 둔 곳이 0곳이다. */
.ap-sub__act {
  margin-left: auto;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  color: var(--ap-text2);
}
.ap-sub__act svg { width: 20px; height: 20px; }

.ap-note {
  margin: 0;
  padding: 10px 16px 2px;
  font-size: 12px;
  line-height: 1.55;
  color: var(--ap-text2);
  letter-spacing: -.02em;
}

/* 예약 — 수령일시 (시안 ordertype-c) */
.ap-pick { padding: 12px 16px 4px; }
.ap-pick__h { display: block; font-size: 13px; font-weight: 800; margin: 8px 0 7px; }
.ap-pick__r { display: flex; gap: 6px; flex-wrap: wrap; }
.ap-pick__b {
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 12.5px;
  font-weight: 700;
}
.ap-pick__b.is-on { background: var(--b); color: var(--b-on); }

/* 주문 뒤 진행 — 10장: 세 곳 모두 네 단계 진행바 + 픽업번호 */
.ap-steps { padding: 10px 16px 14px; }
.ap-steps__h { display: block; font-size: 13px; font-weight: 800; margin-bottom: 8px; }
.ap-steps__r { display: flex; gap: 4px; }
.ap-steps__i {
  flex: 1 1 0;
  min-width: 0;
  padding: 7px 0;
  border-radius: 8px;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 10.5px;
  font-weight: 700;
  text-align: center;
  letter-spacing: -.04em;
}
.ap-steps__i.is-on { background: var(--b); color: var(--b-on); }
.ap-steps__d { display: block; margin-top: 7px; font-size: 11.5px; color: var(--ap-text2); }

/* ==========================================================================
   혜택 화면 (가이드북 7·8·9장)
   ⚠ 도장과 게이지는 **브랜드 색**(--b)을 쓴다. 1단계에서 색을 바꾸면 여기까지
     따라와야 "내 앱" 으로 보인다.
   ⚠ 시행 기준 세 안이 눈에 띄게 달라야 한다 — B안은 매장 줄, C안은 적립매장 목록.
   ========================================================================== */

/* ---------- 등급 ---------- */
.ap-pk { padding: 16px; border-bottom: 8px solid var(--ap-bg2); }
.ap-pk__h { display: flex; align-items: baseline; gap: 8px; }
.ap-pk__h b { font-size: 19px; font-weight: 800; letter-spacing: -.03em; color: var(--b); }
.ap-pk__h span { margin-left: auto; font-size: 11.5px; color: var(--ap-text2); }
.ap-pk__bar {
  margin: 10px 0 9px;
  height: 8px;
  border-radius: 99px;
  background: var(--ap-bg2);
  overflow: hidden;
}
.ap-pk__bar i { display: block; height: 100%; border-radius: 99px; background: var(--b); }
.ap-pk__steps { display: flex; gap: 4px; }
.ap-pk__s {
  flex: 1 1 0;
  min-width: 0;
  padding: 6px 0;
  border-radius: 7px;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 10px;
  font-weight: 700;
  text-align: center;
  letter-spacing: -.04em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ap-pk__s.is-on { background: var(--b-14); color: var(--b); }
.ap-pk__d { display: block; margin-top: 9px; font-size: 11.5px; line-height: 1.55; color: var(--ap-text2); }

/* ---------- 스탬프 ---------- */
.ap-st { padding: 16px; border-bottom: 8px solid var(--ap-bg2); }

/* B안 매장별 — 7장: "화면 위에 매장 이름과 변경 버튼이 붙습니다" */
.ap-st__store {
  display: flex; align-items: center; gap: 8px;
  margin: -4px 0 12px;
  padding: 9px 12px;
  border-radius: 10px;
  background: var(--b-08);
}
.ap-st__store b { font-size: 13.5px; font-weight: 800; color: var(--b); }
.ap-st__chg {
  margin-left: auto;
  padding: 4px 9px;
  border-radius: 99px;
  background: #fff;
  font-size: 11px;
  font-weight: 700;
  color: var(--ap-text2);
}

.ap-st__h { display: flex; align-items: baseline; }
.ap-st__h b { font-size: 15px; font-weight: 800; letter-spacing: -.03em; }
.ap-st__h span { margin-left: auto; font-size: 12.5px; font-weight: 700; color: var(--b); }

/* 판 개수가 10 이면 5칸씩 두 줄, 12 면 6칸씩 두 줄 */
.ap-st__grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 7px;
  margin: 11px 0 9px;
}
.ap-st__grid.is-12 { grid-template-columns: repeat(6, 1fr); gap: 6px; }
.ap-st__c {
  aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--ap-bg2);
  color: var(--ap-text3, #a6a6ae);
  font-size: 12px;
  font-weight: 700;
}
.ap-st__c.is-on { background: var(--b); color: var(--b-on); }
.ap-st__c svg { width: 17px; height: 17px; }
.ap-st__grid.is-12 .ap-st__c svg { width: 15px; height: 15px; }

.ap-st__d { display: block; font-size: 11.5px; line-height: 1.55; color: var(--ap-text2); }
.ap-st__note { margin: 8px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--ap-text2); }

/* C안 절충안 — 7장: "판은 하나지만 아래에 적립매장 목록이 함께 보입니다" */
.ap-st__list { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--ap-line); }
.ap-st__list > b { display: block; font-size: 12.5px; font-weight: 800; margin-bottom: 8px; }
.ap-st__row {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 0;
  font-size: 12px;
}
.ap-st__row em { font-style: normal; font-weight: 700; }
.ap-st__row i { font-style: normal; color: var(--ap-text2); }
.ap-st__row b {
  margin-left: auto;
  padding: 3px 8px;
  border-radius: 99px;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 10.5px;
  font-weight: 700;
}
.ap-st__row.is-ok b { background: var(--b-14); color: var(--b); }

/* ---------- 쿠폰 ---------- */
.ap-cp { padding: 16px; }
.ap-cp__h { display: flex; align-items: baseline; margin-bottom: 10px; }
.ap-cp__h b { font-size: 15px; font-weight: 800; letter-spacing: -.03em; }
.ap-cp__h span { margin-left: auto; font-size: 12.5px; font-weight: 700; color: var(--b); }
.ap-cp__i {
  display: flex; align-items: center; gap: 10px;
  padding: 12px;
  margin-bottom: 8px;
  border-radius: 12px;
  border: 1px dashed var(--ap-line);
}
.ap-cp__t { min-width: 0; }
.ap-cp__t b { display: block; font-size: 13.5px; font-weight: 700; letter-spacing: -.02em; }
.ap-cp__t em { font-style: normal; font-size: 11px; color: var(--ap-text2); }
.ap-cp__d {
  margin-left: auto;
  flex: none;
  padding: 4px 9px;
  border-radius: 99px;
  background: var(--b-14);
  color: var(--b);
  font-size: 11px;
  font-weight: 800;
}
.ap-cp__n { display: block; margin-top: 4px; font-size: 11.5px; line-height: 1.55; color: var(--ap-text2); }

/* ==========================================================================
   주문 상세 바텀시트 · 장바구니 (가이드북 11·12장)
   ⚠ 시트는 화면을 갈아치우지 않고 **덮는다.** 그래서 뒤 화면의 스크롤이 남는다.
     `position: absolute` 로 폰 안에만 갇히게 한다(`.ap` 가 relative 다).
   ========================================================================== */
.ap-sheet {
  position: absolute;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: flex-end;
  background: rgba(16, 16, 24, .42);
}
/* ⚠ 애니메이션은 **열 때 한 번만** 돈다. 늘 붙이면 옵션을 누를 때마다
   0.22초 슬라이드가 재생되어 깜빡인다(실측: 클릭마다 2회 재생). */
.ap-sheet.is-new { animation: apFade .16s ease; }
.ap-sheet__in {
  width: 100%;
  max-height: 86%;
  display: flex;
  flex-direction: column;
  border-radius: 22px 22px 0 0;
  background: #fff;
}
.ap-sheet.is-new .ap-sheet__in { animation: apUp .22s cubic-bezier(.22, .8, .3, 1); }
@keyframes apFade { from { opacity: 0 } to { opacity: 1 } }
@keyframes apUp { from { transform: translateY(100%) } to { transform: translateY(0) } }
@media (prefers-reduced-motion: reduce) {
  .ap-sheet.is-new, .ap-sheet.is-new .ap-sheet__in { animation: none; }
}

.ap-sheet__grab {
  width: 38px; height: 4px;
  margin: 8px auto 2px;
  border-radius: 99px;
  background: var(--ap-line);
  flex: none;
}
.ap-sheet__top {
  display: flex; gap: 12px; align-items: center;
  padding: 12px 16px 14px;
  flex: none;
}
.ap-sheet__top img { width: 64px; height: 64px; border-radius: 12px; object-fit: cover; flex: none; }
.ap-sheet__t { min-width: 0; }
.ap-sheet__t b { display: block; font-size: 16px; font-weight: 800; letter-spacing: -.03em; }
.ap-sheet__t em {
  display: block; font-style: normal; font-size: 11.5px; line-height: 1.45;
  color: var(--ap-text2); margin: 2px 0 4px;
}
.ap-sheet__t i { font-style: normal; font-size: 14px; font-weight: 800; }

.ap-sheet__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0 16px 8px;
  scrollbar-width: none;
  overscroll-behavior: contain;
}
.ap-sheet__body::-webkit-scrollbar { width: 0; }

.ap-opt { padding: 12px 0; border-top: 1px solid var(--ap-line); }
.ap-opt__h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 9px; }
.ap-opt__h b { font-size: 13.5px; font-weight: 800; }
.ap-opt__r { margin-left: auto; font-size: 11px; color: var(--ap-text3); }
.ap-opt__r.is-req { color: var(--b); font-weight: 700; }

.ap-opt__row { display: flex; flex-wrap: wrap; gap: 6px; }
.ap-opt__b {
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: -.02em;
}
.ap-opt__b i { font-style: normal; font-size: 11px; opacity: .7; margin-left: 4px; }
.ap-opt__b.is-on { background: var(--b); color: var(--b-on); }
.ap-opt__b.is-on i { opacity: .85; }

.ap-opt__step {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 700;
}
.ap-opt__step > span { margin-right: auto; }
.ap-opt__step i { font-style: normal; font-size: 11px; color: var(--ap-text2); font-weight: 600; }
.ap-opt__step b { min-width: 20px; text-align: center; font-size: 14px; font-weight: 800; }
.ap-opt__pm {
  width: 28px; height: 28px; flex: none;
  border-radius: 8px;
  border: 1px solid var(--ap-line);
  background: #fff;
  font-size: 15px; line-height: 1;
  color: var(--ap-text);
}
.ap-opt__pm:disabled { opacity: .32; }

.ap-sheet__foot {
  flex: none;
  display: flex; gap: 8px;
  padding: 10px 16px 16px;
  border-top: 1px solid var(--ap-line);
}
.ap-sheet__x {
  flex: none; padding: 0 16px;
  border-radius: 12px;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 13.5px; font-weight: 700;
}
.ap-sheet__go {
  flex: 1 1 auto;
  padding: 14px 0;
  border-radius: 12px;
  background: var(--b);
  color: var(--b-on);
  font-size: 14.5px; font-weight: 800;
  letter-spacing: -.02em;
  text-align: center;
}

/* ---------- 장바구니 ---------- */
.ap-cart { list-style: none; margin: 0; padding: 0; }
.ap-cart li {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--ap-line);
}
.ap-cart__t { min-width: 0; flex: 1 1 auto; }
.ap-cart__t b { display: block; font-size: 14px; font-weight: 700; letter-spacing: -.02em; }
.ap-cart__t em {
  display: block; font-style: normal; font-size: 11.5px; line-height: 1.45;
  color: var(--b); margin: 2px 0 1px;
}
.ap-cart__t i { font-style: normal; font-size: 11.5px; color: var(--ap-text2); }
.ap-cart__p { flex: none; font-size: 14px; font-weight: 800; }
.ap-cart__x {
  flex: none; width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 14px; line-height: 1;
}

.ap-pay { padding: 16px; }
.ap-pay__cp {
  display: flex; align-items: center; gap: 10px;
  padding: 12px;
  margin-bottom: 14px;
  border-radius: 12px;
  border: 1px dashed var(--ap-line);
}
.ap-pay__cpt { min-width: 0; }
.ap-pay__cpt b { display: block; font-size: 13.5px; font-weight: 700; }
.ap-pay__cpt em {
  display: block; font-style: normal; font-size: 11px; line-height: 1.45;
  color: var(--ap-text2); margin-top: 2px;
}
.ap-pay__cpb {
  flex: none; margin-left: auto;
  padding: 7px 12px;
  border-radius: 99px;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 11.5px; font-weight: 700;
  white-space: nowrap;
}
.ap-pay__cpb.is-on { background: var(--b); color: var(--b-on); }

.ap-pay__r { display: flex; align-items: baseline; padding: 6px 0; font-size: 13px; }
.ap-pay__r span { color: var(--ap-text2); }
.ap-pay__r b { margin-left: auto; font-weight: 700; }
.ap-pay__r.is-off b { color: var(--b); }
.ap-pay__r--sum {
  margin-top: 6px; padding-top: 12px;
  border-top: 1px solid var(--ap-line);
  font-size: 15px;
}
.ap-pay__r--sum span { color: var(--ap-text); font-weight: 700; }
.ap-pay__r--sum b { font-size: 18px; font-weight: 800; letter-spacing: -.03em; }

.ap-pay__go {
  width: 100%;
  margin-top: 14px;
  padding: 14px 0;
  border-radius: 12px;
  background: var(--b);
  color: var(--b-on);
  font-size: 14.5px; font-weight: 800;
  text-align: center;
}
.ap-pay__n {
  display: block; margin-top: 9px;
  font-size: 11px; line-height: 1.5; color: var(--ap-text3);
  text-align: center;
}

/* ==========================================================================
   나머지 화면들 (출석 · 패스 · 타임할인 · 주문내역 · 매장 · 공지 · QR · 내 정보)
   ⚠ 전체메뉴에서 눌렀을 때 빈 화면을 만나면 도구가 아니라 목업이 된다.
     실측: 전체메뉴 여섯 줄 중 넷이 '아직 만들지 않았습니다' 로 빠졌다.
   ========================================================================== */

/* 전체메뉴 맨 위 프로필 — 내 정보로 들어가는 자리 */
.ap-me {
  display: flex; align-items: center; gap: 11px;
  width: 100%;
  padding: 14px 16px;
  border-bottom: 8px solid var(--ap-bg2);
}
.ap-me__a {
  width: 42px; height: 42px; flex: none;
  border-radius: 50%;
  background: var(--b); color: var(--b-on);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; font-weight: 800;
}
.ap-me__t { min-width: 0; flex: 1 1 auto; }
.ap-me__t b { display: block; font-size: 15px; font-weight: 800; letter-spacing: -.03em; }
.ap-me__t em { display: block; font-style: normal; font-size: 11.5px; color: var(--ap-text2); margin-top: 1px; }
.ap-me__c { width: 17px; height: 17px; flex: none; color: var(--ap-text3); }

/* ---------- 출석체크 ---------- */
.ap-at { padding: 16px; }
.ap-at__h { display: flex; align-items: baseline; margin-bottom: 12px; }
.ap-at__h b { font-size: 15px; font-weight: 800; letter-spacing: -.03em; }
.ap-at__h span { margin-left: auto; font-size: 12.5px; font-weight: 700; color: var(--b); }
.ap-at__r { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.ap-at__d {
  aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--ap-bg2);
  color: var(--ap-text2);
  font-size: 12px; font-weight: 700;
}
.ap-at__d.is-on { background: var(--b); color: var(--b-on); }
.ap-at__d svg { width: 15px; height: 15px; }
.ap-at__b {
  width: 100%; margin-top: 14px; padding: 13px 0;
  border-radius: 12px;
  background: var(--b); color: var(--b-on);
  font-size: 14px; font-weight: 800; text-align: center;
}
.ap-at__n { display: block; margin-top: 9px; font-size: 11.5px; color: var(--ap-text2); }

/* ---------- 패스권 ---------- */
.ap-ps { padding: 16px; border-bottom: 8px solid var(--ap-bg2); }
.ap-ps__h { display: flex; gap: 11px; align-items: center; margin-bottom: 13px; }
.ap-ps__h img { width: 52px; height: 52px; border-radius: 11px; object-fit: cover; flex: none; }
.ap-ps__t b { display: block; font-size: 15px; font-weight: 800; letter-spacing: -.03em; }
.ap-ps__t em { display: block; font-style: normal; font-size: 11.5px; color: var(--ap-text2); margin-top: 2px; }
.ap-ps__bar { height: 9px; border-radius: 99px; background: var(--ap-bg2); overflow: hidden; }
.ap-ps__bar i { display: block; height: 100%; border-radius: 99px; background: var(--b); }
.ap-ps__n { display: flex; align-items: baseline; margin-top: 8px; }
.ap-ps__n b { font-size: 14px; font-weight: 800; color: var(--b); }
.ap-ps__n span { margin-left: auto; font-size: 11.5px; color: var(--ap-text2); }
.ap-ps__b {
  width: 100%; margin-top: 14px; padding: 13px 0;
  border-radius: 12px;
  background: var(--b); color: var(--b-on);
  font-size: 14px; font-weight: 800; text-align: center;
}

.ap-hl { padding: 14px 16px; }
.ap-hl__h { display: block; font-size: 13px; font-weight: 800; margin-bottom: 8px; }
.ap-hl__r { display: flex; gap: 10px; padding: 8px 0; font-size: 12px; border-top: 1px solid var(--ap-line); }
.ap-hl__r span { color: var(--ap-text2); }
.ap-hl__r em { font-style: normal; }
.ap-hl__r i { margin-left: auto; font-style: normal; font-weight: 700; }

/* ---------- 타임할인 (10장: 남은 시간을 큰 숫자로) ---------- */
.ap-dl { padding: 18px 16px; text-align: center; border-bottom: 1px solid var(--ap-line); }
.ap-dl__h { display: block; font-size: 13px; font-weight: 800; color: var(--b); }
.ap-dl__t { display: flex; justify-content: center; align-items: center; gap: 5px; margin: 9px 0 4px; }
.ap-dl__t span {
  min-width: 46px; padding: 8px 0;
  border-radius: 10px;
  background: var(--b); color: var(--b-on);
  font-size: 21px; font-weight: 800; letter-spacing: -.04em;
}
.ap-dl__t i { font-style: normal; font-size: 18px; font-weight: 800; color: var(--b); }
.ap-dl__d { font-style: normal; font-size: 11.5px; color: var(--ap-text2); }

/* ---------- 알림 ----------
   ⚠ 공지와 **다른 화면**이다. 공지는 브랜드가 모두에게 거는 글이고 알림은
     나에게 일어난 일이다. 그래서 줄마다 **무엇에 대한 알림인지** 아이콘으로 가른다.
   ⚠ 안 읽은 줄에만 옅은 바탕과 왼쪽 띠를 준다. 전부 칠하면 무엇이 새것인지
     안 보이고, 아무것도 안 칠하면 종을 누를 까닭이 없어진다. */
.ap-al { padding: 4px 0; }
.ap-al__r {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--ap-line);
}
.ap-al__r.is-new { background: var(--ap-bg2); box-shadow: inset 3px 0 0 var(--b); }
/* ⚠ **`.ap-i` 는 크기가 없다.** 색만 정하는 클래스라, 쓰는 자리마다
   `svg { width; height }` 를 따로 준다(`.ap-perkbox__row svg` 가 그 예다).
   `flex: none` 만 걸면 폭이 안 정해져 **SVG 가 줄을 통째로 먹는다** —
   실측 2026-09-15: 아이콘 358px · 글자 칸 0px · 시각이 26px 밖으로 나갔다
   (글이 통째로 안 보였는데 `visibility` 로는 안 잡힌다). */
.ap-al__r .ap-i { flex: none; width: 19px; height: 19px; margin-top: 1px; }
.ap-al__x { min-width: 0; flex: 1 1 auto; }
.ap-al__x b {
  display: block;
  font-size: 13px; font-weight: 800; line-height: 1.45; color: var(--ap-text);
}
.ap-al__x em {
  display: block; margin-top: 3px;
  font-style: normal; font-size: 11.5px; line-height: 1.55; color: var(--ap-text2);
}
/* ⚠ 시각은 **오른쪽 끝 한 줄**이다. 제목 옆에 붙이면 제목 길이마다 자리가
   달라져 세로 기준선이 깨진다. */
.ap-al__t {
  flex: none; margin-left: 2px;
  font-size: 10.5px; font-weight: 700; color: var(--ap-text3); white-space: nowrap;
}

/* ---------- 주문내역 (시뮬과 이어진다) ---------- */
.ap-hist { list-style: none; margin: 0; padding: 0; }
.ap-hist li { padding: 14px 16px; border-bottom: 8px solid var(--ap-bg2); }
.ap-hist__h { display: flex; align-items: baseline; margin-bottom: 8px; }
.ap-hist__h b { font-size: 13.5px; font-weight: 800; }
.ap-hist__s {
  margin-left: auto; padding: 3px 9px;
  border-radius: 99px;
  background: var(--b-14); color: var(--b);
  font-size: 10.5px; font-weight: 700;
}
.ap-hist__r { padding: 3px 0; font-size: 13px; }
.ap-hist__r em { display: block; font-style: normal; font-size: 11px; color: var(--b); }
.ap-hist__f { display: flex; align-items: center; margin-top: 9px; }
.ap-hist__f span { font-size: 15px; font-weight: 800; }
.ap-hist__b {
  margin-left: auto; padding: 7px 13px;
  border-radius: 99px;
  border: 1px solid var(--ap-line);
  background: #fff;
  font-size: 11.5px; font-weight: 700;
  color: var(--ap-text2);
}

/* ---------- 매장 찾기 ---------- */
.ap-st2 { list-style: none; margin: 0; padding: 0; }
.ap-st2 li {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--ap-line);
}
.ap-st2 li.is-on { background: var(--b-08); }
.ap-st2__t { min-width: 0; flex: 1 1 auto; }
.ap-st2__t b { display: block; font-size: 14px; font-weight: 700; }
.ap-st2__t em { display: block; font-style: normal; font-size: 11px; color: var(--ap-text2); margin: 2px 0 1px; }
.ap-st2__t i { font-style: normal; font-size: 11px; color: var(--ap-text3); }
.ap-st2__now {
  flex: none; padding: 4px 9px;
  border-radius: 99px;
  background: var(--b); color: var(--b-on);
  font-size: 10.5px; font-weight: 700;
}

/* ---------- 공지사항 ---------- */
.ap-nt { list-style: none; margin: 0; padding: 0; }
.ap-nt li { padding: 14px 16px; border-bottom: 1px solid var(--ap-line); }
.ap-nt__h { display: flex; align-items: baseline; gap: 8px; }
.ap-nt__h b { font-size: 14px; font-weight: 700; }
.ap-nt__h span { margin-left: auto; font-size: 11px; color: var(--ap-text3); }
.ap-nt li p { margin: 5px 0 0; font-size: 12px; line-height: 1.6; color: var(--ap-text2); }

/* ---------- QR · 결제 바코드 ----------
   ⚠ 그림은 인라인 SVG 다. 외부 파일을 쓰지 않는다(요청 0건). */
.ap-qr { padding: 26px 16px; text-align: center; }
.ap-qr__box {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 16px;
  border-radius: 16px;
  border: 1px solid var(--ap-line);
  color: var(--ap-text);
  background: #fff;
}
.ap-qr__box--bar { padding: 18px 16px; }
.ap-qr__h { display: block; margin-top: 16px; font-size: 16px; font-weight: 800; letter-spacing: -.03em; }
.ap-qr__d { display: block; margin-top: 5px; font-size: 12px; color: var(--ap-text2); }
.ap-qr__t {
  display: inline-block; margin-top: 14px;
  padding: 7px 13px;
  border-radius: 99px;
  background: var(--ap-bg2);
  font-size: 11.5px; font-weight: 700; color: var(--ap-text2);
}
.ap-qr__n {
  margin: 18px 0 0;
  padding: 11px 13px;
  border-radius: 10px;
  background: var(--b-08);
  font-size: 11.5px; line-height: 1.6; color: var(--ap-text2);
  text-align: left;
}

/* ---------- 내 정보 ---------- */
.ap-mi {
  display: flex; align-items: center; gap: 12px;
  padding: 20px 16px;
  border-bottom: 8px solid var(--ap-bg2);
}
.ap-mi__a {
  width: 52px; height: 52px; flex: none;
  border-radius: 50%;
  background: var(--b); color: var(--b-on);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 800;
}
.ap-mi__t b { display: block; font-size: 17px; font-weight: 800; letter-spacing: -.03em; }
.ap-mi__t em { display: block; font-style: normal; font-size: 12px; color: var(--ap-text2); margin-top: 2px; }

.ap-rows { padding: 6px 16px 12px; border-bottom: 8px solid var(--ap-bg2); }
.ap-rows:last-of-type { border-bottom: 0; }
.ap-rows__h { display: block; padding: 10px 0 4px; font-size: 13px; font-weight: 800; }
.ap-row {
  display: flex; align-items: center;
  padding: 11px 0;
  font-size: 13px;
  border-bottom: 1px solid var(--ap-line);
}
.ap-row:last-child { border-bottom: 0; }
.ap-row span { color: var(--ap-text2); }
.ap-row b { margin-left: auto; font-weight: 700; }
.ap-sw {
  margin-left: auto;
  width: 40px; height: 23px;
  border-radius: 99px;
  background: var(--ap-bg2);
  position: relative;
  flex: none;
}
.ap-sw i {
  position: absolute; top: 3px; left: 3px;
  width: 17px; height: 17px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(16, 16, 24, .2);
  transition: left .18s ease;
}
.ap-sw.is-on { background: var(--b); }
.ap-sw.is-on i { left: 20px; }

/* 쿠폰을 다 썼을 때 */
.ap-cp__e {
  margin: 0 0 8px;
  padding: 14px 12px;
  border-radius: 10px;
  background: var(--ap-bg2);
  font-size: 11.5px;
  color: var(--ap-text2);
  text-align: center;
}


/* ==========================================================================
   무엇이 바뀌었는지 알려주는 표시 (빌더 전용 · build.js markChange)

   셋을 가른다. 바뀐 양이 다른데 같은 표시를 쓰면 아무것도 안 도드라진다.
     .is-hl        블록 하나가 바뀜   → 테두리
     .is-hl--text  글자 한두 줄이 바뀜 → 형광펜
     .is-hl-all    화면이 통째로 바뀜 → 폰 전체를 짧게

   ⚠ 1.5초만 머문다. 계속 남으면 미리보기가 아니라 검사 화면이 된다.
   ⚠ 애니메이션은 한 번만 돈다. 반복하면 눈이 붙잡혀 다음 선택을 못 한다.
   ⚠ 움직임을 줄이라고 한 사용자에게는 깜빡임을 뺀다.
   ========================================================================== */

/* ---- 블록: 테두리 ----
   ⚠ `outline` 이다. `border` 는 자리를 차지해 그 순간 레이아웃이 흔들리고,
     `box-shadow` 는 overflow:hidden 인 `.ap-scroll` 에서 잘린다.
   ⚠ offset 을 음수로 준다. 폰이 좁아 바깥으로 그리면 잘린다. */
.ap .is-hl {
  outline: 2px solid var(--b, #6c3b8f);
  outline-offset: -2px;
  border-radius: 12px;
  animation: apHl .55s var(--ease, cubic-bezier(.22,1,.36,1)) 1;
}
@keyframes apHl {
  0%   { outline-color: transparent; }
  25%  { outline-color: var(--b, #6c3b8f); }
  55%  { outline-color: transparent; }
  100% { outline-color: var(--b, #6c3b8f); }
}

/* ---- 글자: 형광펜 ----
   적립 기준은 바뀌는 노드가 **하나**, 완성 혜택은 **둘**이다(실측).
   그 줄에 테두리를 두르면 오히려 글자가 안 읽힌다. 뒤를 칠한다.
   ⚠ 글자색을 바꾸지 않는다. 배경만 칠해야 원래 위계가 안 무너진다.
   ⚠ box-decoration-break 로 줄바꿈된 글자도 이어 칠한다. */
.ap .is-hl--text {
  background: var(--hl-bg, rgba(108, 59, 143, .16));
  box-shadow: 0 0 0 3px var(--hl-bg, rgba(108, 59, 143, .16));
  border-radius: 4px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  animation: apHlT .55s var(--ease, cubic-bezier(.22,1,.36,1)) 1;
}
@keyframes apHlT {
  0%   { background-color: transparent; box-shadow: 0 0 0 3px transparent; }
  30%  { background-color: rgba(108, 59, 143, .3); box-shadow: 0 0 0 3px rgba(108, 59, 143, .3); }
}

/* ---- 화면 전체 ----
   홈 타입·스탬프 방식은 노드가 143개·82개 바뀐다(실측). 한 곳을 가리킬 수 없다.
   ⚠ 폰을 덮지 않는다. 테두리만 한 번 돈다 — 덮으면 방금 바뀐 것을 못 본다. */
#phone.is-hl-all {
  animation: apHlAll .7s var(--ease, cubic-bezier(.22,1,.36,1)) 1;
  border-radius: 22px;
}
@keyframes apHlAll {
  0%   { box-shadow: 0 0 0 0 rgba(108, 59, 143, .5); }
  40%  { box-shadow: 0 0 0 6px rgba(108, 59, 143, .28); }
  100% { box-shadow: 0 0 0 0 rgba(108, 59, 143, 0); }
}

/* ---- 폰 밖에서 바뀌는 것 (위젯 · 앱 아이콘) ---- */
#widget.is-hl, #appicon.is-hl {
  outline: 2px solid var(--brand);
  outline-offset: 4px;
  border-radius: 14px;
  animation: apHl .55s var(--ease) 1;
}

/* ---- 무엇이 바뀌었는지 말해 주는 줄 ----
   ⚠ 반짝임만으로는 '뭔가 바뀌었다' 까지만 전달된다.
   ⚠ 폰을 가리지 않게 **아래 가운데**에 둔다. 위에 두면 상단바를 덮는다.
   ⚠ 한 번에 하나만 뜬다(build.js 가 같은 노드를 다시 쓴다). */
/* ⚠ 폰 안, **하단 탭(62px) 바로 위**에 선다. 스테이지 바닥에 두면 폰 아래
     설명 칩을 덮는다. .ph 가 기준 칸이다(position:relative). */
.bd-fx {
  position: absolute;
  left: 50%; bottom: 84px;
  transform: translateX(-50%);
  z-index: 40;
  max-width: min(92%, 340px);
  margin: 0;
  padding: 9px 14px;
  border-radius: 999px;
  background: rgba(22, 22, 26, .92);
  color: #fff;
  font-size: 13px; font-weight: 600; line-height: 1.45;
  text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  pointer-events: none;
  box-shadow: 0 6px 20px rgba(16, 16, 24, .22);
}
.bd-fx.is-on { animation: bdToast .26s var(--ease) 1; }
@keyframes bdToast {
  from { opacity: 0; transform: translate(-50%, 8px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .ap .is-hl, .ap .is-hl--text, #phone.is-hl-all,
  #widget.is-hl, #appicon.is-hl, .bd-fx.is-on { animation: none; }
}

/* ==========================================================================
   주문 시뮬레이션 자동재생 (가이드북 12장)
   ⚠ 자막은 **폰 위쪽**에 둔다. 아래는 알림(.bd-fx)이 쓰는 자리라 겹치면
     "담았습니다" 와 "장바구니에 담습니다" 가 서로를 가린다.
   ⚠ 상단바(.ap-top)를 덮지 않게 그 아래에 세운다.
   ========================================================================== */
.ap-play {
  position: absolute;
  /* ⚠ 상단바(.ap-top) **아래**에 세운다. 66px 에 두었더니 상단바를 34px 덮어
     브랜드명과 장바구니 아이콘을 가렸다(실측 2026-09-14).
     스크롤 칸이 폰 위에서 100px 에 시작한다. */
  /* ⚠ **`left: 50%` + `translateX(-50%)` 로 가운데 두지 말 것.**
     절대위치 상자의 shrink-to-fit 은 **`left` 부터 오른쪽 끝까지**를 쓸 수 있는
     폭으로 본다 — `left: 50%` 면 **폰의 절반**이다. `max-width` 를 아무리 넓게
     줘도 그 위로 못 자란다(실측 2026-09-16 · 390px: 폰 358px 인데 자막이
     **179px** 에서 멈춰 "장바구니에 / 담습니다" 로 접혔다).
     좌우를 **둘 다** 못 박고 `margin-inline: auto` 로 가운데 둔다. */
  left: 8px; right: 8px; top: 108px;
  z-index: 45;
  display: flex; align-items: center; gap: 7px;
  width: max-content; max-width: 100%;
  margin-inline: auto;
  padding: 7px 8px 7px 12px;
  border-radius: 999px;
  background: rgba(22, 22, 26, .94);
  color: #fff;
  font-size: 12.5px; line-height: 1.4;
  box-shadow: 0 8px 22px rgba(16, 16, 24, .28);
  animation: apPlayIn .24s var(--ease) 1;
  /* ⚠ 자막이 앱 위를 덮는다. 눌러서 멈추는 길을 막으면 안 된다 —
     탭은 그대로 통과시키고 [멈추기] 단추만 받는다(실측 2026-09-14:
     자막이 상단바를 가려 폰을 눌러도 재생이 안 멈췄다). */
  pointer-events: none;
}
/* ⚠ `translateX(-50%)` 를 안 쓰므로 여기서도 빼야 한다. 남겨 두면
   들어오는 동안만 자막이 왼쪽으로 반 칸 튄다. */
@keyframes apPlayIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
/* ⚠ **한 줄로 둔다**(사용자 지시 2026-09-16). 두 줄로 접으면 띠가
   49px 로 두꺼워져 상품 이름을 덮고, 숫자와 [멈추기] 의 줄맞춤도 흐트러진다.
   ⚠ 전에 한 줄이 "옵션을 하나 더 담..." 으로 잘렸던 것은 글자 탓이 아니라
     **자리잡기 탓**이었다(위 `left` 주석). 폭을 다 쓰면 열넷 다 들어간다 —
     가장 긴 "쓴 쿠폰이 쿠폰함에서 사라졌습니다" 도 잰 뒤에 맞췄다.
   ⚠ 그래도 넘치면 잘라 쓴다. 두 줄로 되돌리지 말 것 — 되돌리려거든
     `tests/v2play.mjs` 의 줄 수 검사를 먼저 보라. */
.ap-play__t {
  min-width: 0;
  font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ap-play__n { flex: none; opacity: .62; font-variant-numeric: tabular-nums; font-size: 11.5px; }
.ap-play__x {
  flex: none;
  pointer-events: auto;
  border: 0; border-radius: 999px;
  padding: 4px 9px;
  background: rgba(255, 255, 255, .18);
  color: #fff;
  font: inherit; font-size: 11.5px; font-weight: 700;
  cursor: pointer;
}
.ap-play__x:hover { background: rgba(255, 255, 255, .3); }

/* ⚠ **아주 좁은 폰에서만** 반 뼘 줄인다. 320px 에서는 폰이 288px 인데
   가장 긴 자막("쓴 쿠폰이 쿠폰함에서 사라졌습니다")이 290px 로 **3px 넘쳤다**
   (실측 2026-09-16 · 390 · 360px 은 여유 있다).
   ⚠ 글자를 줄이지 않는다. 이 문구들은 가이드북 12장의 동선과 6단계 절의
     안내 줄에 맞춰 둔 것이라, 여기만 바꾸면 둘이 다른 말을 하게 된다.
   ⚠ 재는 것은 뷰포트지만 폰 폭이 뷰포트를 따라가므로 짝이 맞는다
     (실측: 뷰포트 390 → 폰 358 · 360 → 328 · 320 → 288). */
@media (max-width: 340px) {
  .ap-play { gap: 6px; padding-left: 10px; padding-right: 7px; font-size: 12px; }
  .ap-play__n { font-size: 11px; }
  .ap-play__x { padding: 4px 8px; font-size: 11px; }
}

/* ⚠ **창이 낮아도 자막이 좁아진다.** 2026-09-17 에 폰 비율을 19.5:9 로 못
   박으면서, /v2 의 모바일 오버레이는 **폰 폭을 창 높이에서** 뽑는다
   (`(100dvh - 170px) / 2.1641`). 그래서 창이 낮으면 폰이 좁아지고 자막도 함께
   좁아져야 한다 — 창 **폭**만 보면 못 맞춘다
   (실측 2026-09-17 · 320x700: 폰 245px 인데 가장 긴 자막이 29px 넘쳤다).
   ⚠ 여기서는 **번호(3 / 14)를 뺀다.** 넣을 자리가 없을 때 먼저 버릴 것은
     번호다 — 무엇을 하는 중인지가 먼저이고, 몇 번째인지는 그 다음이다.
     자막 글을 줄이거나 두 줄로 접는 쪽이 더 나쁘다. */
@media (max-height: 760px) {
  .ap-play { gap: 5px; padding-left: 9px; padding-right: 6px; font-size: 11px; }
  .ap-play__n { display: none; }
  .ap-play__x { padding: 4px 7px; font-size: 10.5px; }
}

/* 자동재생이 지금 누른 자리. ⚠ 안 보이면 화면이 저절로 바뀌는 것으로만 보인다. */
.ap-tapped {
  position: relative;
  animation: apTap .6s var(--ease) 1;
  outline: 2px solid var(--b, #6a50f0);
  outline-offset: 1px;
  border-radius: 8px;
}
@keyframes apTap {
  0%   { box-shadow: 0 0 0 0 rgba(106, 80, 240, .45); }
  100% { box-shadow: 0 0 0 12px rgba(106, 80, 240, 0); }
}

/* 6단계의 재생 단추 */
.bd-play__row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 10px 0 0;
}
.bd-play {
  border: 0; border-radius: 999px;
  padding: 10px 18px;
  background: var(--brand, #4338ca);
  color: #fff;
  font: inherit; font-size: 14px; font-weight: 700;
  cursor: pointer;
}
.bd-play:hover { filter: brightness(1.06); }
.bd-play.is-on { background: #16161a; }
.bd-play__d { color: var(--ink-3, #6b7280); font-size: 12.5px; font-style: normal; }

@media (prefers-reduced-motion: reduce) {
  .ap-play, .ap-tapped { animation: none; }
}

/* 로고(미리보기용 · 2026-09-15).
   ⚠ 높이만 맞추고 폭은 비율대로 둔다. 억지로 늘이면 로고가 뭉개진다.
   ⚠ 상단바 높이를 넘지 않게 상한을 둔다 — 세로로 긴 로고가 오면 줄이 밀린다.
   ⚠ 심볼은 원형 버튼 안이라 `contain` 이다. `cover` 면 가장자리가 잘린다. */
.ap-top__logo--img { display: inline-flex; align-items: center; }
.ap-top__logo--img img { height: 20px; width: auto; max-width: 150px; display: block; }
.ap-tab__logo--img { display: inline-flex; align-items: center; justify-content: center; }
.ap-tab__logo--img img {
  width: 22px; height: 22px; object-fit: contain; display: block;
}


/* ==========================================================================
   짚기 — 어디를 말하는지 폰에서 손가락질한다
   ⚠ 어드민의 태스크 줄과 빌더 6단계의 요약 묶음이 **함께 쓴다.**
     admin.css 에 있던 것을 여기로 옮겼다(2026-09-17) — 두 곳에 두면
     한쪽만 고쳐져 화면마다 다른 색으로 짚는다.
   ========================================================================== */
.ph__screen .is-spot {
  outline: 2px solid rgba(139, 92, 246, .75);
  outline-offset: -1px;
  border-radius: 8px;
  background-color: rgba(139, 92, 246, .06);
  animation: ad-spot 1.6s ease both;
}
@keyframes ad-spot {
  0%   { outline-color: rgba(139, 92, 246, 0); background-color: rgba(139, 92, 246, 0); }
  12%  { outline-color: rgba(139, 92, 246, .85); background-color: rgba(139, 92, 246, .1); }
  75%  { outline-color: rgba(139, 92, 246, .7); background-color: rgba(139, 92, 246, .06); }
  100% { outline-color: rgba(139, 92, 246, 0); background-color: rgba(139, 92, 246, 0); }
}
@media (prefers-reduced-motion: reduce) {
  /* ⚠ 움직임은 끄되 **표시는 남긴다.** 테두리까지 없애면 어디를 짚었는지
     알 길이 사라진다. */
  .ph__screen .is-spot { animation: none; }
}
/* ⚠ **이 닫는 괄호를 지우지 말 것.** 2026-09-17 에 이 블록을 admin.css 에서
   옮겨 오면서 여기서는 닫는 줄을 빠뜨렸고(파일 끝이 열린 채), 저쪽에는 닫는
   줄만 남겨 그 고아가 뒤의 블록을 통째로 삼켰다. 한 번의 옮김이 두 파일을
   망가뜨렸다 — 규칙을 옮길 때는 **여는 줄과 닫는 줄을 짝으로** 본다.
 ⚠ 지금은 파일 끝이라 브라우저가 알아서 닫아 주지만, 뒤에 무엇을 더 적으면
   그것이 통째로 이 미디어 쿼리 안에 갇힌다(움직임을 끈 사람에게만 보인다).
   `tests/braces.mjs` 가 이것을 지킨다. */
