/* ============================================================================
   SOI · ซอย  —  Design System
   "รอบตัวคุณ / Around you"
   ---------------------------------------------------------------------------
   This file is the SINGLE SOURCE OF TRUTH for every screen.
   Pages only compose the classes below — never invent colours / sizes / radii.

   0. Tokens
   1. Base + atmosphere
   2. App Shell  (statusbar · screen · tabbar)
   3. Chrome     (topbar · pill · iconbtn · searchbar · chips · sections)
   4. Cards & media
   5. Feed / post
   6. Bento service modules
   7. Friends & chat
   8. Profile & lists
   9. Sheet / toast / states
  10. Motion
   ========================================================================== */

/* ---------------------------------------------------------------- 0. TOKENS */
:root {
  /* colour — 3 families only: ink · cobalt · mango (+ warm neutrals) */
  --ink:      #17181C;
  --ink-2:    #4A4F58;
  --ink-3:    #8A8F98;
  --ink-4:    #B7BBC2;

  --paper:    #F4F2ED;
  --surface:  #FFFFFF;
  --surface-2:#FAF9F6;

  --line:     #E8E5DE;
  --line-2:   #F1EFE9;

  --primary:      #2447F5;
  --primary-700:  #1A36CC;
  --primary-weak: #EDF0FF;

  --accent:       #FF7A2F;
  --accent-weak:  #FFF0E5;

  --success:  #0FA968;
  --danger:   #EE3D3D;
  --warn:     #F5B301;

  /* type */
  --f-display: "Sukhumvit Set", "Avenir Next", "Noto Sans Thai", "Leelawadee UI",
               -apple-system, "Segoe UI", sans-serif;
  --f-body:    -apple-system, BlinkMacSystemFont, "Sukhumvit Set", "Noto Sans Thai",
               "Leelawadee UI", "Helvetica Neue", sans-serif;
  --f-mono:    "SF Mono", ui-monospace, Menlo, monospace;

  /* radius */
  --r-xs: 8px;  --r-sm: 12px; --r-md: 16px; --r-lg: 20px;
  --r-xl: 24px; --r-2xl: 28px; --r-pill: 999px;

  /* shadow — layered & restrained */
  --sh-1: 0 1px 2px rgba(23,24,28,.05);
  --sh-2: 0 2px 10px rgba(23,24,28,.06);
  --sh-3: 0 10px 30px rgba(23,24,28,.10);
  --sh-up:0 -6px 24px rgba(23,24,28,.08);

  /* spacing (4px base) */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px; --s8:32px;
  --pad: 16px;                  /* page gutter */

  /* shell metrics — identical on every screen */
  --statusbar-h: 48px;
  --tabbar-h: 64px;
  --dnav-h: 54px;              /* sticky nav height — 分类 / 排序 / 分组头都靠它算偏移 */
  --catrail-h: 44px;           /* channel page: sticky category rail height */
}

/* ------------------------------------------------------------------ 1. BASE */
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body { height: 100%; }

body {
  font-family: var(--f-body);
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;                 /* the .screen element is the scroller */
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; border: none; background: none; outline: none; }
button { cursor: pointer; }
ul, ol { list-style: none; }

/* warm paper atmosphere behind the app chrome */
body::before {
  content: "";
  position: fixed; inset: 0;
  background:
    radial-gradient(760px 420px at 88% -8%, rgba(36,71,245,.10), transparent 62%),
    radial-gradient(620px 360px at -12% 4%, rgba(255,122,47,.10), transparent 60%);
  pointer-events: none; z-index: 0;
}

/* icons — injected from icons.js as inline SVG */
[data-ic] { display: inline-block; width: 20px; height: 20px; flex: 0 0 auto; vertical-align: -3px; }
[data-ic] svg { display: block; width: 100%; height: 100%; fill: none; stroke: currentColor;
                stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.i14 { width: 14px; height: 14px; } .i16 { width: 16px; height: 16px; }
.i18 { width: 18px; height: 18px; } .i22 { width: 22px; height: 22px; }
.i24 { width: 24px; height: 24px; } .i28 { width: 28px; height: 28px; }
.i32 { width: 32px; height: 32px; }

/* ------------------------------------------------------------- 2. APP SHELL */
.app { position: relative; z-index: 1; display: flex; flex-direction: column; height: 100dvh; }

.statusbar {
  flex: 0 0 calc(var(--statusbar-h) + env(safe-area-inset-top, 0px));
  display: flex; align-items: center; justify-content: space-between;
  padding: env(safe-area-inset-top, 0px) 22px 0; position: relative;
  font-family: var(--f-display); font-size: 14px; font-weight: 700; letter-spacing: .01em;
  color: var(--ink);
}
.statusbar__time { min-width: 54px; font-variant-numeric: tabular-nums; }
.statusbar__island {
  position: absolute; left: 50%; top: calc(env(safe-area-inset-top, 0px) + 8px); transform: translateX(-50%);
  width: 104px; height: 26px; border-radius: var(--r-pill); background: #0B0C0F;
}
.statusbar__icons { display: flex; align-items: center; gap: 6px; min-width: 54px; justify-content: flex-end; }
.statusbar__icons [data-ic] { width: 17px; height: 17px; }

.screen {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: var(--s8);
}
.screen::-webkit-scrollbar { display: none; }
/* chat: keeps the sticky composer flush with the tab bar, and lets the
   message list grow so the composer never floats mid-screen. */
.screen--chat { display: flex; flex-direction: column; padding-bottom: 0; }
.screen--chat .thread { flex: 1 0 auto; }

.tabbar {
  flex: 0 0 calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  display: grid; grid-template-columns: repeat(5, 1fr); align-items: center;
  background: rgba(255,255,255,.86);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--line);
  position: relative; z-index: 6;
}
.tab {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  color: var(--ink-3); font-size: 10px; font-weight: 600;
  font-family: var(--f-display);
  transition: color .18s ease, transform .18s ease;
}
.tab [data-ic] { width: 23px; height: 23px; }
.tab:active { transform: scale(.92); }

/* THE single active-state mechanism for the canonical nav:
   body[data-page] decides which tab is highlighted. Never hand-edit per page. */
body[data-page="nearby"]   .tabbar .tab[data-nav="nearby"],
body[data-page="friends"]  .tabbar .tab[data-nav="friends"],
body[data-page="services"] .tabbar .tab[data-nav="services"],
body[data-page="me"]       .tabbar .tab[data-nav="me"] { color: var(--primary); }

.tab--fab {
  width: 50px; height: 50px; margin: -14px auto 0; border-radius: var(--r-lg);
  background: var(--ink); color: #fff;
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--sh-3);
  transition: transform .18s ease, background .18s ease;
}
.tab--fab [data-ic] { width: 24px; height: 24px; }
.tab--fab:active { transform: scale(.9) rotate(90deg); }

/* ------------------------------------------------------------------ 3. CHROME */
/* 顶栏（定位 / 返回 / 图标那一行）吸顶常驻；底下那行搜索不吸顶，
   跟着内容一起滑走 —— 搜索不是每一屏都要用的，别占固定高度。 */
.topbar {
  position: sticky; top: 0; z-index: 5;
  padding: 2px var(--pad) 12px;
  background: linear-gradient(180deg, rgba(244,242,237,.97) 74%, rgba(244,242,237,0));
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
/* 搜索行：放在吸顶顶栏之外，所以自己带横向留白 */
.searchbar--row { margin: 0 var(--pad) 12px; }
.topbar__row { display: flex; align-items: center; gap: var(--s2); }
.topbar__title { font-family: var(--f-display); font-size: 26px; font-weight: 800; letter-spacing: -.02em; }
.topbar__spacer { flex: 1 1 auto; }

.loc { display: flex; align-items: center; gap: 7px; min-width: 0; }
.loc [data-ic] { width: 17px; height: 17px; color: var(--primary); }
.loc__text { font-family: var(--f-display); font-size: 16px; font-weight: 700; letter-spacing: -.01em; white-space: nowrap; }
.loc__sub { font-size: 12px; font-weight: 500; color: var(--ink-3); white-space: nowrap; }

.pill {
  display: inline-flex; align-items: center; gap: 5px; height: 30px; padding: 0 11px;
  border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--line);
  font-size: 12px; font-weight: 700; color: var(--ink-2); box-shadow: var(--sh-1);
  transition: background .18s ease, border-color .18s ease;
}
.pill [data-ic] { width: 14px; height: 14px; }
.pill.is-active { background: var(--ink); color: #fff; border-color: var(--ink); }
.pill--primary { background: var(--primary-weak); color: var(--primary); border-color: transparent; }
.pill--accent  { background: var(--accent-weak);  color: var(--accent);  border-color: transparent; }

.iconbtn {
  position: relative; width: 36px; height: 36px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid var(--line); color: var(--ink);
  box-shadow: var(--sh-1); transition: transform .18s ease, background .18s ease;
}
.iconbtn:active { transform: scale(.92); }
.iconbtn--plain { background: transparent; border-color: transparent; box-shadow: none; }
.iconbtn--onDark { color: #fff; border-color: rgba(255,255,255,.22); }
/* the scan action is the only tinted control in the top bar — ordering at a
   table is a one-tap job, so it earns the emphasis */
.iconbtn--scan { background: var(--primary-weak); border-color: transparent; color: var(--primary); }
/* used on dark surfaces (scan screen) where the paper-white button would glare */
.iconbtn--ghost { background: rgba(255,255,255,.12); border-color: transparent; color: #fff; box-shadow: none; }
.iconbtn.is-on { background: var(--primary-weak); border-color: var(--primary); color: var(--primary); }
.iconbtn__dot {
  position: absolute; top: 5px; right: 5px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: var(--r-pill); background: var(--accent); color: #fff;
  font-size: 10px; font-weight: 800; line-height: 16px; text-align: center;
  border: 2px solid var(--surface);
}

.searchbar.is-hidden { display: none; }
.searchbar {
  display: flex; align-items: center; gap: var(--s2);
  height: 44px; padding: 0 14px; margin-top: 12px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--sh-1);
  transition: border-color .2s ease, box-shadow .2s ease;
}
.searchbar:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-weak); }
.searchbar [data-ic] { color: var(--ink-3); }
.searchbar input { flex: 1 1 auto; min-width: 0; font-size: 14px; }
.searchbar input::placeholder { color: var(--ink-3); }
.searchbar__div { width: 1px; height: 20px; background: var(--line); }

.chips { display: flex; gap: var(--s2); margin-top: 12px; padding: 0 var(--pad) 2px; overflow-x: auto; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
.chip {
  flex: 0 0 auto; height: 34px; padding: 0 15px; border-radius: var(--r-pill);
  background: var(--surface); border: 1px solid var(--line);
  font-family: var(--f-display); font-size: 13px; font-weight: 600; color: var(--ink-2);
  display: inline-flex; align-items: center; gap: 6px;
  transition: all .18s ease;
}
.chip [data-ic] { width: 15px; height: 15px; }
.chip:active { transform: scale(.95); }
.chip.is-active { background: var(--ink); border-color: var(--ink); color: #fff; }
.chip--accent.is-active { background: var(--accent); border-color: var(--accent); color: #fff; }

.secthead {
  display: flex; align-items: baseline; justify-content: space-between;
  padding: var(--s6) var(--pad) var(--s3);
}
.secthead__title { font-family: var(--f-display); font-size: 18px; font-weight: 800; letter-spacing: -.015em; }
.secthead__sub { font-size: 12px; color: var(--ink-3); font-weight: 500; margin-top: 2px; }
/* compact header: one line + a count pill instead of a two-line block */
.secthead--slim { padding: var(--s4) var(--pad) var(--s2); align-items: center; }
.secthead--slim .secthead__title { font-size: 16px; }
.countpill {
  height: 20px; min-width: 20px; padding: 0 7px; border-radius: var(--r-pill);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; font-size: 11px; font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.secthead__more {
  font-size: 12px; font-weight: 700; color: var(--primary);
  display: inline-flex; align-items: center; gap: 3px;
  /* also rendered as a <button> when it opens a sheet */
  background: none; border: 0; padding: 0; font-family: inherit;
}
.secthead__more:active { opacity: .55; }
.secthead__more [data-ic] { width: 14px; height: 14px; }

/* distance / radius selector (Google-Maps style) */
/* five options now (全部 + 1/3/5/10) — wrap rather than squeeze so every
   option stays visible in all three languages */
.radiusbar { display: flex; flex-wrap: wrap; gap: var(--s2); padding: 0 var(--pad) var(--s3); }
.radiusbar .chip { flex: 0 0 auto; height: 30px; padding: 0 11px; font-size: 12px; }
.radiusbar .chip.is-active { background: var(--primary); border-color: var(--primary); }

/* ------------------------------------------------------------- 4. CARDS/MEDIA */
.card {
  margin: 0 var(--pad) var(--s3);
  background: var(--surface); border-radius: var(--r-xl);
  border: 1px solid var(--line); box-shadow: var(--sh-2);
  overflow: hidden;
}
.card--flat { box-shadow: none; }
.card--pad { padding: var(--s4); }
.card--ink { background: var(--ink); border-color: var(--ink); color: #fff; }

.sectline { height: 1px; background: var(--line-2); margin: 0 var(--pad); }

.media { position: relative; background: linear-gradient(135deg, #E7E3DA, #D9D4C9); overflow: hidden; }
.media img { width: 100%; height: 100%; object-fit: cover; }
.media--21x9 { aspect-ratio: 21 / 9; }
.media--16x9 { aspect-ratio: 16 / 9; }
.media--4x3  { aspect-ratio: 4 / 3; }
.media--1x1  { aspect-ratio: 1 / 1; }
.media--4x5  { aspect-ratio: 4 / 5; }
.media--free { height: 100%; }

.media__badge {
  position: absolute; top: var(--s3); left: var(--s3);
  display: inline-flex; align-items: center; gap: 5px;
  height: 26px; padding: 0 10px; border-radius: var(--r-pill);
  background: rgba(17,18,22,.62); color: #fff;
  font-size: 11px; font-weight: 700; backdrop-filter: blur(8px);
}
.media__badge [data-ic] { width: 13px; height: 13px; }
.media__badge--right { left: auto; right: var(--s3); }
.media__badge--light { background: rgba(255,255,255,.92); color: var(--ink); }

.media__play {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
  width: 54px; height: 54px; border-radius: var(--r-pill);
  background: rgba(17,18,22,.42); border: 1.5px solid rgba(255,255,255,.85);
  color: #fff; display: flex; align-items: center; justify-content: center;
  backdrop-filter: blur(4px);
}
.media__play [data-ic] { width: 22px; height: 22px; }
.media__grad {
  position: absolute; inset: auto 0 0 0; height: 62%;
  background: linear-gradient(180deg, rgba(0,0,0,0), rgba(0,0,0,.72));
  pointer-events: none;
}
.media__over {
  position: absolute; inset: auto 0 0 0; padding: var(--s4); color: #fff;
}
.media__over h3 { font-family: var(--f-display); font-size: 17px; font-weight: 800; line-height: 1.35; letter-spacing: -.01em; }
.media__over p { font-size: 12px; opacity: .82; margin-top: 4px; }

.thumbstrip { display: flex; gap: var(--s2); padding: var(--s3) var(--s4) var(--s4); overflow-x: auto; scrollbar-width: none; }
.thumbstrip::-webkit-scrollbar { display: none; }
.thumbstrip img { width: 62px; height: 62px; border-radius: var(--r-sm); object-fit: cover; flex: 0 0 auto; border: 1px solid var(--line); }

/* ------------------------------------------------------------------ 5. FEED */
.post { margin: 0 var(--pad) var(--s3); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl); box-shadow: var(--sh-2); overflow: hidden; }
.post__head { display: flex; align-items: center; gap: var(--s3); padding: var(--s4) var(--s4) var(--s3); }
.post__who { flex: 1 1 auto; min-width: 0; }
.post__name { font-family: var(--f-display); font-size: 14px; font-weight: 700; display: flex; align-items: center; gap: 5px; }
.post__name [data-ic] { width: 14px; height: 14px; color: var(--primary); }
.post__meta { font-size: 11.5px; color: var(--ink-3); margin-top: 2px; display: flex; align-items: center; gap: 5px; }
.post__meta [data-ic] { width: 12px; height: 12px; }
.post__body { padding: 0 var(--s4) var(--s3); font-size: 14px; color: var(--ink-2); line-height: 1.62; }
.post__body b { color: var(--ink); font-weight: 700; }
.post__foot { display: flex; align-items: center; gap: var(--s5); padding: var(--s3) var(--s4) var(--s4); }
.post__foot .act:first-child { margin-right: auto; }

.feedimgs { display: grid; gap: 3px; padding: 0 var(--s4) var(--s3); }
.feedimgs--3 { grid-template-columns: repeat(3, 1fr); }
.feedimgs--2 { grid-template-columns: repeat(2, 1fr); }
.feedimgs img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--r-xs); }

.act {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 600; color: var(--ink-3);
  transition: color .18s ease, transform .18s ease;
}
.act [data-ic] { width: 19px; height: 19px; }
.act:active { transform: scale(.9); }
.act.is-on { color: var(--accent); }
.act.is-on [data-ic] svg { fill: var(--accent); }
.act--save.is-on { color: var(--primary); }
.act--save.is-on [data-ic] svg { fill: var(--primary); }

/* good-find card — 好物分享 */
.goodbar {
  display: flex; align-items: center; gap: var(--s3);
  margin: 0 var(--s4) var(--s3); padding: var(--s3) var(--s4);
  background: var(--accent-weak); border-radius: var(--r-md);
}
.goodbar__ic {
  width: 38px; height: 38px; border-radius: var(--r-xs); flex: 0 0 auto;
  background: rgba(255,122,47,.18); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.goodbar__ic [data-ic] { width: 20px; height: 20px; }
.goodbar__n { display: block; font-family: var(--f-display); font-size: 13.5px; font-weight: 800; line-height: 1.4; }
.goodbar__m { display: flex; align-items: center; gap: 4px; font-size: 11.5px; color: var(--ink-2); opacity: .84; margin-top: 3px; }
.goodbar__m [data-ic] { width: 12px; height: 12px; }
.goodbar__r { flex: 0 0 auto; text-align: right; }
.goodbar__p { display: block; font-family: var(--f-display); font-size: 16px; font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; }
.goodbar__tag { display: inline-block; margin-top: 4px; font-size: 10px; font-weight: 700; padding: 2px 8px; border-radius: var(--r-pill); background: rgba(255,122,47,.18); color: var(--accent); }

/* worth-a-trip highlight — 好去处 */
.hlbar { margin: 0 var(--s4) var(--s3); padding: var(--s3) var(--s4); background: var(--primary-weak); border-radius: var(--r-md); }
.hlbar__t { display: flex; align-items: center; gap: 6px; font-family: var(--f-display); font-size: 13.5px; font-weight: 800; color: var(--primary); }
.hlbar__t [data-ic] { width: 15px; height: 15px; }
.hlbar__chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s2); }
.hlbar__chips span { font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: var(--r-pill); background: rgba(36,71,245,.12); color: var(--primary); }

/* comment preview */
.cmts { padding: 0 var(--s4) var(--s3); }
.cmt { font-size: 12.5px; color: var(--ink-2); line-height: 1.6; }
.cmt + .cmt { margin-top: 3px; }
.cmt b { color: var(--ink); font-weight: 700; margin-right: 5px; }
.cmts__more { display: inline-flex; align-items: center; gap: 3px; margin-top: 6px; font-size: 12px; font-weight: 600; color: var(--ink-3); }
.cmts__more [data-ic] { width: 13px; height: 13px; }

/* want-to-go bar */
.wantbar {
  display: flex; align-items: center; gap: var(--s2);
  margin: 0 var(--s4) var(--s3); padding: 8px 8px 8px var(--s4);
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-pill);
}
.wantbar__avs { display: flex; flex: 0 0 auto; }
.wantbar__avs img { width: 22px; height: 22px; border-radius: var(--r-pill); object-fit: cover; border: 2px solid var(--surface-2); margin-left: -8px; }
.wantbar__avs img:first-child { margin-left: 0; }
.wantbar__t { flex: 1 1 auto; min-width: 0; font-size: 12px; color: var(--ink-2); font-weight: 600; }
.wantbar__t b { color: var(--ink); font-weight: 800; }

/* topic chips on a text-only moment */
.topicrow { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 var(--s4) var(--s3); }
.topicrow span { font-size: 11.5px; font-weight: 700; padding: 5px 11px; border-radius: var(--r-pill); background: var(--line-2); color: var(--ink-2); }
.topicrow span.is-hot { background: var(--accent-weak); color: var(--accent); }

/* check-in card — “I've been here N times” */
.checkinbar {
  display: flex; align-items: center; gap: var(--s3);
  margin: 0 var(--s4) var(--s3); padding: var(--s3) var(--s4);
  background: var(--primary-weak); border-radius: var(--r-md);
}
.checkinbar__n { font-family: var(--f-display); font-size: 24px; font-weight: 800; letter-spacing: -.02em; color: var(--primary); line-height: 1; }
.checkinbar__t { display: block; font-family: var(--f-display); font-size: 13.5px; font-weight: 800; color: var(--primary); }
.checkinbar__d { display: block; font-size: 11.5px; color: var(--ink-2); opacity: .82; margin-top: 3px; }
.checkinbar__l { flex: 0 0 auto; font-size: 10.5px; font-weight: 700; padding: 4px 9px; border-radius: var(--r-pill); background: rgba(36,71,245,.14); color: var(--primary); }

/* coupon card — a deal shared by a neighbour */
.dealbar {
  display: flex; align-items: center; gap: var(--s3);
  margin: 0 var(--s4) var(--s3); padding: var(--s3) var(--s4);
  background: var(--accent); color: #fff; border-radius: var(--r-md);
  box-shadow: 0 6px 18px rgba(255,122,47,.24);
}
.dealbar__off { font-family: var(--f-display); font-size: 23px; font-weight: 800; letter-spacing: -.03em; line-height: 1; flex: 0 0 auto; }
.dealbar__t { display: block; font-family: var(--f-display); font-size: 13.5px; font-weight: 800; line-height: 1.35; }
.dealbar__m { display: block; font-size: 11px; opacity: .88; margin-top: 3px; }
.dealbar__side { flex: 0 0 auto; text-align: right; }
.dealbar__code { display: inline-block; font-family: var(--f-mono); font-size: 11px; font-weight: 700; letter-spacing: .05em; padding: 4px 9px; border-radius: var(--r-xs); background: rgba(255,255,255,.22); }
.dealbar__got { display: block; font-size: 10px; opacity: .85; margin-top: 4px; font-weight: 600; }

/* ---- 分享服务：一排一选 → 一发 → 评论 / 参与 / 前往 ---- */

/* “pick one” row — the four everyday services side by side */
.sharerow { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); padding: 0 var(--pad) var(--s3); }
.sharerow--flush { padding-left: 0; padding-right: 0; }
.sharepick {
  display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0;
  padding: var(--s3) 4px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--sh-1);
  transition: transform .18s ease, background .18s ease, border-color .18s ease;
}
.sharepick:active { transform: scale(.95); }
.sharepick__ic {
  width: 34px; height: 34px; border-radius: var(--r-xs);
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-weak); color: var(--primary);
}
.sharepick__ic [data-ic] { width: 18px; height: 18px; }
.sharepick__n { max-width: 100%; font-size: 11px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sharepick__m { max-width: 100%; font-size: 9.5px; font-weight: 600; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sharepick.is-active { background: var(--primary-weak); border-color: var(--primary); }
.sharepick.is-active .sharepick__ic { background: var(--primary); color: #fff; }
.sharepick.is-active .sharepick__n { color: var(--primary); }

/* the shared-service card that lands in the feed */
.svcblock {
  display: flex; align-items: center; gap: var(--s3);
  margin: 0 var(--s4) var(--s3); padding: var(--s3);
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md);
}
.svcblock--flush { margin-left: 0; margin-right: 0; }
.svcblock__img { width: 56px; height: 56px; border-radius: var(--r-sm); object-fit: cover; flex: 0 0 auto; }
.svcblock__b { flex: 1 1 auto; min-width: 0; }
.svcblock__type {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10px; font-weight: 800; padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--primary-weak); color: var(--primary);
}
.svcblock__type [data-ic] { width: 11px; height: 11px; }
.svcblock__n { display: block; font-family: var(--f-display); font-size: 13.5px; font-weight: 800; margin-top: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.svcblock__m { display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.svcblock__p { flex: 0 0 auto; font-family: var(--f-display); font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; }
.svcblock--link { cursor: pointer; }
.svcblock--link:active { background: var(--line-2); }
.svcblock__go { flex: 0 0 auto; margin-left: -6px; color: var(--ink-4); }
.svcblock__go [data-ic] { width: 16px; height: 16px; }

/* comment · join · go — identical on every shared service */
.svcacts { display: flex; gap: 6px; padding: 0 var(--s4) var(--s3); }
.svcact {
  flex: 1 1 0; min-width: 0; height: 38px; padding: 0 8px;
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  border-radius: var(--r-sm); background: var(--surface-2); border: 1px solid var(--line);
  font-size: 12.5px; font-weight: 700; color: var(--ink-2); white-space: nowrap;
  transition: transform .18s ease, background .18s ease, color .18s ease;
}
.svcact [data-ic] { width: 15px; height: 15px; }
.svcact:active { transform: scale(.97); }
.svcact.is-on { background: var(--accent-weak); border-color: transparent; color: var(--accent); }
.svcact--go { background: var(--ink); border-color: var(--ink); color: #fff; }

/* share scope picker inside the share sheet */
.sharescopes { display: flex; gap: 6px; }
.sharescope {
  flex: 1 1 0; min-width: 0; padding: 10px 6px; border-radius: var(--r-sm);
  display: inline-flex; flex-direction: column; align-items: center; gap: 5px;
  background: var(--surface-2); border: 1px solid var(--line);
  font-size: 11px; font-weight: 700; color: var(--ink-2); text-align: center;
}
.sharescope [data-ic] { width: 17px; height: 17px; color: var(--ink-3); }
.sharescope.is-active { background: var(--primary-weak); border-color: var(--primary); color: var(--primary); }
.sharescope.is-active [data-ic] { color: var(--primary); }
/* a space can offer four audiences, so they wrap two-up */
.sharescopes--wrap { flex-wrap: wrap; }
.sharescopes--wrap .sharescope {
  flex: 1 1 calc(50% - 3px); flex-direction: row; justify-content: center; gap: 6px; padding: 9px 6px;
}
/* one line that says where this post will actually go — exposure or relationship */
.posthint {
  display: flex; align-items: center; gap: 7px; margin-top: var(--s3);
  padding: 10px var(--s3); border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px dashed var(--line);
  font-size: 11.5px; font-weight: 600; color: var(--ink-2);
}
.posthint [data-ic] { width: 15px; height: 15px; flex: 0 0 auto; color: var(--primary); }

/* “N new posts” refresh pill */
.feednew {
  display: flex; align-items: center; justify-content: center; gap: var(--s2);
  width: calc(100% - var(--pad) * 2); margin: 0 var(--pad) var(--s3);
  height: 38px; border-radius: var(--r-pill);
  background: var(--ink); color: #fff; font-size: 12.5px; font-weight: 700;
  box-shadow: var(--sh-2); transition: transform .18s ease;
}
.feednew:active { transform: scale(.98); }
.feednew [data-ic] { width: 15px; height: 15px; }

/* feed pagination footer */
.loadmore { display: flex; align-items: center; justify-content: center; gap: 10px; padding: var(--s4) 0; }
.feedcount { text-align: center; font-size: 11.5px; font-weight: 600; color: var(--ink-4); margin-top: 10px; font-variant-numeric: tabular-nums; }
#mount-feedmore { padding: 0 var(--pad) var(--s4); }
#mount-feedmore .divider-note { padding-left: 0; padding-right: 0; }

/* friend moments rail — 朋友圈 */
.momentstrip { display: flex; gap: var(--s3); padding: 0 var(--pad) var(--s3); overflow-x: auto; scrollbar-width: none; }
.momentstrip::-webkit-scrollbar { display: none; }
.moment { flex: 0 0 auto; width: 68px; text-align: center; position: relative; transition: transform .18s ease; }
.moment:active { transform: scale(.96); }
.moment__thumb { position: relative; display: block; width: 68px; height: 68px; border-radius: var(--r-md); overflow: hidden; background: var(--line-2); }
.moment__thumb img { width: 100%; height: 100%; object-fit: cover; }
.moment__thumb--more { display: flex; align-items: center; justify-content: center; background: var(--surface); border: 1px dashed var(--line); color: var(--ink-3); }
.moment__thumb--more [data-ic] { width: 18px; height: 18px; }
.moment__badge {
  position: absolute; right: 4px; bottom: 4px; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--r-pill); background: var(--accent); color: #fff;
  font-size: 10px; font-weight: 800; line-height: 18px; text-align: center;
}
.moment__av { position: absolute; left: 6px; top: 6px; width: 22px; height: 22px; border-radius: var(--r-pill); object-fit: cover; border: 2px solid var(--surface); }
.moment--more .moment__n { color: var(--ink-3); font-weight: 600; }
.moment__n { display: block; font-size: 10.5px; font-weight: 700; color: var(--ink-2); margin-top: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.moment__w { display: block; font-size: 9.5px; color: var(--ink-4); margin-top: 1px; }

.avatar { border-radius: var(--r-pill); object-fit: cover; background: var(--line); flex: 0 0 auto; display: block; }
.avatar--32 { width: 32px; height: 32px; } .avatar--38 { width: 38px; height: 38px; }
.avatar--44 { width: 44px; height: 44px; } .avatar--52 { width: 52px; height: 52px; }
.avatar--64 { width: 64px; height: 64px; } .avatar--84 { width: 84px; height: 84px; }
.avatar-init {
  display: flex; align-items: center; justify-content: center;
  font-family: var(--f-display); font-weight: 800; color: #fff;
  background: var(--primary); border-radius: var(--r-pill); flex: 0 0 auto;
}

/* shop / venue row */
.shoprow { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); }
.shoprow img { width: 52px; height: 52px; border-radius: var(--r-sm); object-fit: cover; flex: 0 0 auto; }
.shoprow__body { flex: 1 1 auto; min-width: 0; }
.shoprow__name { font-family: var(--f-display); font-size: 14.5px; font-weight: 700; }
.shoprow__meta { font-size: 12px; color: var(--ink-3); margin-top: 3px; display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.shoprow__meta .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--ink-4); }
.rate { display: inline-flex; align-items: center; gap: 3px; font-weight: 800; color: var(--ink); }
.rate [data-ic] { width: 13px; height: 13px; color: var(--warn); }
.rate [data-ic] svg { fill: var(--warn); }

.btnrow { display: flex; gap: var(--s2); padding: var(--s3) var(--s4) var(--s4); }
.btn {
  height: 42px; padding: 0 18px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font-family: var(--f-display); font-size: 13.5px; font-weight: 700;
  white-space: nowrap;
  transition: transform .18s ease, background .18s ease, opacity .18s ease;
}
.btn [data-ic] { width: 16px; height: 16px; }
.btn:active { transform: scale(.97); }
.btn--fill { background: var(--primary); color: #fff; box-shadow: 0 4px 14px rgba(36,71,245,.28); }
.btn--ink  { background: var(--ink); color: #fff; }
.btn--accent { background: var(--accent); color: #fff; box-shadow: 0 4px 14px rgba(255,122,47,.28); }
.btn--out  { background: var(--surface); color: var(--ink); border: 1px solid var(--line); }
.btn--out-primary { background: var(--primary-weak); color: var(--primary); }
.btn--block { flex: 1 1 auto; width: 100%; }
.btn--glass { background: rgba(255,255,255,.2); color: #fff; }
.btn--sm { height: 34px; padding: 0 14px; font-size: 12.5px; border-radius: var(--r-xs); }
.btn[disabled] { background: var(--line-2); color: var(--ink-4); box-shadow: none; }

/* live / social-proof panel */
.livecard {
  margin: 0 var(--pad) var(--s3); border-radius: var(--r-xl); padding: var(--s5);
  background: var(--ink); color: #fff; position: relative; overflow: hidden;
  box-shadow: var(--sh-3);
}
.livecard::after {
  content: ""; position: absolute; right: -60px; top: -70px; width: 200px; height: 200px;
  border-radius: 50%; background: radial-gradient(circle, rgba(255,122,47,.55), transparent 68%);
}
.livecard__row { display: flex; align-items: center; justify-content: space-between; position: relative; z-index: 1; }
.livecard__t { font-family: var(--f-display); font-size: 13px; font-weight: 700; color: rgba(255,255,255,.72); }
.livecard__n { font-family: var(--f-display); font-size: 34px; font-weight: 800; letter-spacing: -.03em; line-height: 1.1; }
.livecard__n small { font-size: 13px; font-weight: 700; margin-left: 4px; color: rgba(255,255,255,.7); }
.livecard__d { font-size: 11.5px; color: rgba(255,255,255,.6); margin-top: var(--s3); position: relative; z-index: 1; }
.livecard__avs { display: flex; align-items: center; position: relative; z-index: 1; }
.livecard__avs img { width: 28px; height: 28px; border-radius: var(--r-pill); object-fit: cover; border: 2px solid var(--ink); margin-left: -9px; }
.livecard__avs img:first-child { margin-left: 0; }
.livecard__more { font-size: 11px; font-weight: 700; color: rgba(255,255,255,.66); margin-left: var(--s2); }

/* map teaser (Google nearby) */
.mapteaser {
  margin: 0 var(--pad) var(--s3); height: 148px; border-radius: var(--r-xl);
  position: relative; overflow: hidden; border: 1px solid var(--line);
  background: linear-gradient(135deg, #E4E8E3, #D6DAD5);
}
.mapteaser img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.mapteaser__ring {
  position: absolute; left: 50%; top: 50%; width: 92px; height: 92px; margin: -46px 0 0 -46px;
  border-radius: 50%; border: 1.5px solid var(--primary); background: rgba(36,71,245,.10);
}
.mapteaser__ring--2 { width: 148px; height: 148px; margin: -74px 0 0 -74px; background: rgba(36,71,245,.06); }
.mapteaser__pin {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-100%);
  width: 30px; height: 30px; border-radius: var(--r-pill);
  background: var(--primary); color: #fff; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 16px rgba(36,71,245,.45);
}
.mapteaser__pin [data-ic] { width: 16px; height: 16px; }
.mapteaser__foot {
  position: absolute; left: var(--s3); right: var(--s3); bottom: var(--s3);
  display: flex; align-items: center; gap: var(--s2);
  background: rgba(255,255,255,.94); backdrop-filter: blur(8px);
  border-radius: var(--r-md); padding: 9px 12px; box-shadow: var(--sh-2);
}
.mapteaser__foot .t { flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 700; }
.mapteaser__foot .t small { display: block; font-size: 11px; color: var(--ink-3); font-weight: 600; margin-top: 1px; }
.mapteaser__foot-ic { width: 30px; height: 30px; border-radius: var(--r-xs); background: var(--primary-weak); color: var(--primary); display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.mapteaser__foot-ic [data-ic] { width: 16px; height: 16px; }

/* embedded H5 module preview (admin-published modules open as WebView) */
.h5bar { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s4); }
.h5bar__url {
  flex: 1 1 auto; display: flex; align-items: center; justify-content: center; gap: 6px;
  height: 34px; padding: 0 12px; border-radius: var(--r-pill);
  background: var(--paper); border: 1px solid var(--line);
  font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-3); white-space: nowrap; overflow: hidden;
}
.h5bar__url b { color: var(--ink); }
.h5body { text-align: center; padding: var(--s4) var(--s2) 0; }
.h5body__hero { width: 64px; height: 64px; margin: 0 auto var(--s4); border-radius: var(--r-lg); background: var(--primary-weak); color: var(--primary); display: flex; align-items: center; justify-content: center; }
.h5body__hero [data-ic] { width: 30px; height: 30px; }
.h5body__t { font-family: var(--f-display); font-size: 18px; font-weight: 800; }
.h5body__d { font-size: 13px; color: var(--ink-3); margin-top: 5px; }
.h5body__note {
  display: flex; align-items: flex-start; gap: var(--s2); text-align: left;
  margin-top: var(--s5); padding: var(--s3) var(--s4); border-radius: var(--r-md);
  background: var(--surface-2); border: 1px dashed var(--line);
  font-size: 11.5px; color: var(--ink-2); line-height: 1.5;
}
.h5body__note [data-ic] { width: 15px; height: 15px; color: var(--primary); margin-top: 1px; }

/* the drawer reads its lines off the service registry record */
.h5rows { margin-top: var(--s5); border-top: 1px solid var(--line-2); }
.h5row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: 11px 0; border-bottom: 1px solid var(--line-2);
  font-size: 12.5px; color: var(--ink-2);
}
.h5row b { font-weight: 700; color: var(--ink); text-align: right; }

/* profile media grid */
.mycell { position: relative; aspect-ratio: 1 / 1; border-radius: var(--r-sm); overflow: hidden; background: var(--line-2); }
.mycell img { width: 100%; height: 100%; object-fit: cover; }
.mycell__play {
  position: absolute; top: 6px; right: 6px; width: 22px; height: 22px; border-radius: var(--r-pill);
  background: rgba(17,18,22,.5); color: #fff; display: flex; align-items: center; justify-content: center;
}
.mycell__play [data-ic] { width: 12px; height: 12px; }
/* which of my posts is public, and which is not — readable at a glance */
.mycell__vis {
  position: absolute; top: 6px; left: 6px; width: 22px; height: 22px; border-radius: var(--r-pill);
  background: rgba(17,18,22,.5); color: #fff; display: flex; align-items: center; justify-content: center;
}
.mycell__vis [data-ic] { width: 12px; height: 12px; }
.mycell__s {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 14px 8px 6px;
  display: flex; align-items: center; gap: 4px; color: #fff; font-size: 11px; font-weight: 700;
  background: linear-gradient(180deg, transparent, rgba(0,0,0,.62));
}
.mycell__s [data-ic] { width: 13px; height: 13px; }
.mycell__s [data-ic] svg { fill: #fff; }

/* shared-bill summary */
.billbar {
  display: flex; align-items: center; gap: var(--s3);
  margin: 0 var(--s4) var(--s3); padding: var(--s3) var(--s4);
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md);
}
.billbar__cell { flex: 1 1 0; min-width: 0; }
.billbar__n { font-family: var(--f-display); font-size: 16px; font-weight: 800; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.billbar__l { font-size: 11px; color: var(--ink-3); font-weight: 600; margin-top: 1px; }
.billbar__vr { width: 1px; align-self: stretch; background: var(--line); }

/* meetup / company ask row */
.askbar {
  display: flex; align-items: center; gap: var(--s3);
  margin: 0 var(--s4) var(--s3); padding: var(--s3) var(--s4);
  background: var(--accent-weak); border-radius: var(--r-md);
}
.askbar__t { font-family: var(--f-display); font-size: 13.5px; font-weight: 700; }
.askbar__d { font-size: 11.5px; color: var(--ink-2); opacity: .8; margin-top: 2px; }

/* promo deal card */
.hscroll { display: flex; gap: var(--s3); padding: 0 var(--pad) var(--s3); overflow-x: auto; scrollbar-width: none; }
.hscroll::-webkit-scrollbar { display: none; }
.promo {
  flex: 0 0 232px; border-radius: var(--r-xl); padding: var(--s4);
  display: flex; flex-direction: column; gap: var(--s3); color: #fff;
}
.promo--accent { background: var(--accent); box-shadow: 0 8px 24px rgba(255,122,47,.26); }
.promo--ink { background: var(--ink); box-shadow: var(--sh-3); }
.promo__ic { width: 36px; height: 36px; border-radius: var(--r-sm); background: rgba(255,255,255,.2); display: flex; align-items: center; justify-content: center; }
.promo__ic [data-ic] { width: 19px; height: 19px; }
.promo__t { font-family: var(--f-display); font-size: 15px; font-weight: 800; line-height: 1.35; }
.promo__s { font-size: 11.5px; opacity: .8; margin-top: 3px; }
.promo__code { align-self: flex-start; font-family: var(--f-mono); font-size: 11.5px; font-weight: 700; letter-spacing: .05em; padding: 5px 10px; border-radius: var(--r-xs); background: rgba(255,255,255,.22); }

/* ------------------------------------------------------------- 6. BENTO */
.bento { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s3); padding: 0 var(--pad); }
.bento > * { min-width: 0; }
.bento__wide { grid-column: span 2; }

.mod {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl);
  padding: var(--s4); min-height: 128px;
  display: flex; flex-direction: column; justify-content: space-between;
  box-shadow: var(--sh-2); transition: transform .18s ease, box-shadow .18s ease;
}
.mod:active { transform: scale(.975); }
.mod__ic {
  width: 40px; height: 40px; border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-weak); color: var(--primary);
}
.mod__ic [data-ic] { width: 21px; height: 21px; }
.mod__body { display: flex; flex-direction: column; flex: 1 1 auto; justify-content: flex-end; min-width: 0; }
.mod--wide .mod__body { justify-content: center; }
.mod__title { display: block; font-family: var(--f-display); font-size: 15.5px; font-weight: 800; letter-spacing: -.01em; margin-top: auto; padding-top: var(--s3); }
.mod__desc { display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 2px; line-height: 1.45; }
.mod__go { flex: 0 0 auto; align-self: center; color: var(--ink-4); }
.mod__go [data-ic] { width: 18px; height: 18px; }
.mod__tag {
  position: absolute; top: var(--s3); right: var(--s3);
  height: 20px; padding: 0 8px; border-radius: var(--r-pill);
  font-size: 10px; font-weight: 800; line-height: 20px;
  background: var(--line-2); color: var(--ink-3);
}
.mod__tag--h5 { background: var(--primary-weak); color: var(--primary); }
.mod__tag--soon { background: var(--surface-2); color: var(--ink-4); }

.mod--ink { background: var(--ink); border-color: var(--ink); color: #fff; }
.mod--ink .mod__ic { background: rgba(255,255,255,.14); color: #fff; }
.mod--ink .mod__desc { color: rgba(255,255,255,.66); }
.mod--accent { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 8px 24px rgba(255,122,47,.28); }
.mod--accent .mod__ic { background: rgba(255,255,255,.2); color: #fff; }
.mod--accent .mod__desc { color: rgba(255,255,255,.86); }
.mod--accent .mod__tag { background: rgba(255,255,255,.22); color: #fff; }
.mod--soon { border-style: dashed; box-shadow: none; }
.mod--soon .mod__ic { background: var(--line-2); color: var(--ink-4); }
.mod--soon .mod__title { color: var(--ink-3); }
.mod--wide { min-height: 104px; flex-direction: row; align-items: center; justify-content: flex-start; gap: var(--s3); }
.mod--wide .mod__title { padding-top: 0; margin-top: 0; }
.mod--wide .mod__ic { flex: 0 0 auto; }

/* --------------------------------------------------------- 7. FRIENDS & CHAT */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); padding: 0 var(--pad) var(--s3); }
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s3) var(--s2); text-align: center; box-shadow: var(--sh-1); }
.stat__n { font-family: var(--f-display); font-size: 19px; font-weight: 800; letter-spacing: -.02em; }
.stat__n span { font-size: 12px; color: var(--ink-3); font-weight: 700; }
.stat__l { font-size: 11px; color: var(--ink-3); margin-top: 1px; font-weight: 500; }

.storybar { display: flex; gap: var(--s3); overflow-x: auto; padding: 0 var(--pad) var(--s3); scrollbar-width: none; }
.storybar::-webkit-scrollbar { display: none; }
.story { flex: 0 0 auto; width: 62px; text-align: center; }
.story__wrap { position: relative; width: 58px; height: 58px; margin: 0 auto; border-radius: var(--r-pill); padding: 2px; }
.story__wrap.is-live { background: linear-gradient(140deg, var(--accent), var(--primary)); }
.story__wrap img { width: 100%; height: 100%; border-radius: var(--r-pill); object-fit: cover; border: 2.5px solid var(--paper); }
.story__nm { font-size: 10.5px; color: var(--ink-2); margin-top: 5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.story__dot { position: absolute; right: 2px; bottom: 2px; width: 13px; height: 13px; border-radius: 50%; background: var(--success); border: 2.5px solid var(--paper); }
.story--me .story__wrap { background: none; }
.story--me .story__wrap img { border-color: var(--line); }
.story__plus { position: absolute; right: -2px; bottom: -2px; width: 20px; height: 20px; border-radius: 50%; background: var(--ink); color: #fff; display: flex; align-items: center; justify-content: center; border: 2.5px solid var(--paper); }
.story__plus [data-ic] { width: 11px; height: 11px; }

.chatrow { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--pad); transition: background .18s ease; }
.chatrow:active { background: var(--surface-2); }
.chatrow__av { position: relative; flex: 0 0 auto; }
.chatrow__body { flex: 1 1 auto; min-width: 0; }
.chatrow__name { font-family: var(--f-display); font-size: 14.5px; font-weight: 700; display: flex; align-items: center; gap: 5px; }
.chatrow__msg { display: block; font-size: 13px; color: var(--ink-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chatrow__msg.is-unread { color: var(--ink); font-weight: 600; }
.chatrow__side { flex: 0 0 auto; text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.chatrow__time { font-size: 11px; color: var(--ink-4); font-weight: 600; }
.badge { min-width: 19px; height: 19px; padding: 0 6px; border-radius: var(--r-pill); background: var(--accent); color: #fff; font-size: 11px; font-weight: 800; line-height: 19px; text-align: center; }
.badge--primary { background: var(--primary); }

.reqrow { display: flex; align-items: center; gap: 10px; padding: var(--s3) var(--s4); }
.reqrow__body { flex: 1 1 auto; min-width: 0; }
.reqrow__n {
  display: block; font-family: var(--f-display); font-size: 14.5px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.reqrow__m {
  display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* buttons never take part in the squeeze — only the copy above them shrinks */
.reqrow__act { display: flex; gap: 6px; flex: 0 0 auto; }
.reqrow__act .btn { min-width: 56px; padding: 0 12px; }

/* nearby-people match row */
.matchcard { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line-2); }
.matchcard:last-child { border-bottom: none; }
.matchcard__b { flex: 1 1 auto; min-width: 0; }
.matchcard__n { font-family: var(--f-display); font-size: 14.5px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.matchcard__t { font-size: 11.5px; color: var(--ink-3); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* score block and the send button never take part in the squeeze */
.matchcard__score { flex: 0 0 auto; text-align: right; }
.matchcard .btn { flex: 0 0 auto; }
.matchcard__p { font-family: var(--f-display); font-size: 17px; font-weight: 800; color: var(--primary); text-align: right; font-variant-numeric: tabular-nums; }
.matchcard__pl { font-size: 10px; color: var(--ink-3); font-weight: 600; text-align: right; white-space: nowrap; }

/* online indicator (eat-together rail) */
.online-dot {
  position: absolute; right: 2px; bottom: 2px; width: 13px; height: 13px; border-radius: var(--r-pill);
  background: var(--success); border: 2.5px solid var(--surface);
}
.listrow__on { color: var(--success); font-weight: 600; }

/* quick action grid (profile) — 3 up, each tile shows an icon, a count and a label */
.qgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); padding: 0 var(--pad) var(--s3); }
.qitem {
  position: relative; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: var(--s3) 6px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--sh-1);
  font-size: 11px; font-weight: 600; color: var(--ink-2); text-align: center;
  transition: transform .18s ease;
}
.qitem:active { transform: scale(.95); }
.qitem [data-ic] { width: 20px; height: 20px; color: var(--primary); }
.qitem__n {
  position: absolute; top: 6px; right: 8px;
  font-size: 10px; font-weight: 800; color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.qitem__l { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* chat thread */
.chathead {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--pad) var(--s3);
  background: linear-gradient(180deg, rgba(244,242,237,.97) 78%, rgba(244,242,237,0));
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.chathead__body { flex: 1 1 auto; min-width: 0; }
.chathead__name { font-family: var(--f-display); font-size: 15.5px; font-weight: 800; letter-spacing: -.01em; }
.chathead__st { font-size: 11.5px; color: var(--ink-3); margin-top: 1px; display: flex; align-items: center; gap: 5px; }
.chathead__st i { width: 6px; height: 6px; border-radius: 50%; background: var(--success); display: inline-block; }

.thread { padding: var(--s2) var(--pad) var(--s2); display: flex; flex-direction: column; gap: var(--s2); }
.thread__day { align-self: center; font-size: 11px; font-weight: 700; color: var(--ink-3); background: var(--line-2); padding: 4px 12px; border-radius: var(--r-pill); margin: var(--s2) 0; }
.bub { max-width: 78%; padding: 10px 14px; border-radius: var(--r-lg); font-size: 14px; line-height: 1.5; position: relative; }
.bub--in { align-self: flex-start; background: var(--surface); border: 1px solid var(--line); border-bottom-left-radius: var(--r-xs); }
.bub--out { align-self: flex-end; background: var(--primary); color: #fff; border-bottom-right-radius: var(--r-xs); }
.bub img { border-radius: var(--r-sm); margin-top: 6px; width: 180px; }
.bub__time { font-size: 10.5px; color: var(--ink-4); align-self: center; font-weight: 600; }
.bubcard { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s3); display: flex; gap: var(--s3); align-items: center; align-self: flex-start; max-width: 86%; }
.bubcard img { width: 46px; height: 46px; border-radius: var(--r-xs); object-fit: cover; }

/* sticky bottom so the App Shell (statusbar · screen · tabbar) stays identical
   on every page — the composer lives inside the scroll container. */
.composer {
  position: sticky; bottom: 0; z-index: 4;
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--pad) var(--s3);
  background: rgba(255,255,255,.94);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid var(--line);
}
.composer__field {
  flex: 1 1 auto; display: flex; align-items: center; gap: var(--s2);
  height: 40px; padding: 0 14px; border-radius: var(--r-pill);
  background: var(--paper); border: 1px solid var(--line);
}
.composer__field input { flex: 1 1 auto; min-width: 0; font-size: 14px; }
.composer__send { width: 38px; height: 38px; border-radius: var(--r-pill); background: var(--primary); color: #fff; display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.composer__send [data-ic] { width: 18px; height: 18px; }

/* -------------------------------------------------------------------------
   chat detail: rows, message kinds, and the bar that can replace the composer.
   A row is [select circle?][bubble-or-card + time]; the row itself is the
   long-press target, so the gesture never depends on where the bubble ends.
   ---------------------------------------------------------------------- */
.msg { display: flex; gap: var(--s2); }
.msg--out { flex-direction: row-reverse; }
.msg__body { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; max-width: 84%; }
.msg--out .msg__body { align-items: flex-end; }
/* system lines (a recalled message) belong to neither side — they sit centred */
.msg--sys { justify-content: center; }
.msg--sys .msg__body { align-items: center; max-width: 100%; }
.msg__pick { align-self: center; flex: 0 0 auto; color: var(--ink-4); }
.msg__pick [data-ic] { width: 20px; height: 20px; }
.msg.is-on .msg__pick { color: var(--primary); }
.msg__body > .bub, .msg__body > .bubcard, .msg__body > .msgcard { max-width: 100%; }

/* voice — a mic, a level trace, and how long it runs */
.bub--voice { display: flex; align-items: center; gap: var(--s2); }
.vbars { display: inline-flex; align-items: center; gap: 3px; height: 16px; }
.vbars i { width: 2px; border-radius: var(--r-pill); background: currentColor; opacity: .55; }
.vbars i:nth-child(1) { height: 6px; }
.vbars i:nth-child(2) { height: 12px; }
.vbars i:nth-child(3) { height: 16px; }
.vbars i:nth-child(4) { height: 10px; }
.vbars i:nth-child(5) { height: 7px; }
.voice__n { font-size: 12px; font-weight: 700; }

/* video — a still, a play badge and a running time */
.bub--media { padding: 6px; }
.mwrap { position: relative; display: block; border-radius: var(--r-sm); overflow: hidden; }
.mwrap img { display: block; width: 200px; height: 132px; object-fit: cover; margin: 0; border-radius: 0; }
.mwrap__play { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; }
.mwrap__play [data-ic] { width: 34px; height: 34px; filter: drop-shadow(0 2px 6px rgba(0,0,0,.45)); }
.mwrap__dur {
  position: absolute; right: 6px; bottom: 6px; padding: 1px 7px; border-radius: var(--r-pill);
  background: rgba(0,0,0,.55); font-size: 10px; font-weight: 700;
}
.bub__cap { display: block; margin-top: 6px; font-size: 13.5px; }

/* rich messages: a place, an order, a footprint, a save, a review, a friend, a shop */
.msgcard {
  width: 252px; max-width: 100%; padding: var(--s3);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--sh-1);
}
.msgcard--out { align-self: flex-end; }
.msgcard__h { display: flex; align-items: center; gap: var(--s3); }
.msgcard__ic {
  display: grid; place-items: center; width: 34px; height: 34px; flex: 0 0 auto;
  border-radius: var(--r-xs); background: var(--primary-weak); color: var(--primary);
}
.msgcard__ic [data-ic] { width: 18px; height: 18px; }
.msgcard__ht { min-width: 0; flex: 1 1 auto; }
.msgcard__t { display: block; font-size: 13.5px; font-weight: 700; }
.msgcard__m { display: block; font-size: 11px; color: var(--ink-3); margin-top: 2px; }
.msgcard__img { display: block; width: 100%; height: 96px; object-fit: cover; border-radius: var(--r-sm); margin-top: var(--s3); }
.msgcard__q { margin-top: var(--s3); font-size: 12.5px; color: var(--ink-2); line-height: 1.55; }
.msgcard__stars { display: inline-flex; gap: 2px; margin-top: var(--s2); color: var(--warn); }
.msgcard__f { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-top: var(--s3); }
.msgcard__amount { font-family: var(--f-display); font-size: 16px; font-weight: 800; color: var(--primary); }
.msgcard__cta {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
  margin-top: var(--s3); padding: 9px 0; border-radius: var(--r-sm);
  background: var(--primary-weak); color: var(--primary); font-size: 12.5px; font-weight: 700;
}
.msgcard__cta [data-ic] { width: 15px; height: 15px; }

/* a message that was taken back — a system line, never attributed to a side */
.bub__recall {
  align-self: center; padding: 4px 12px; border-radius: var(--r-pill);
  background: var(--line-2); color: var(--ink-3); font-size: 11.5px; font-weight: 600;
}

/* multi-select bar — takes the composer's place while messages are selected */
.selbar { display: none; }
.selbar.is-on {
  position: sticky; bottom: 0; z-index: 4;
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--pad) var(--s3);
  background: rgba(255,255,255,.96);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid var(--line);
}
.composer.is-hidden { display: none; }
.selbar__n { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 700; color: var(--ink-2); }
.selbar__c {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--r-pill);
  background: var(--primary); color: #fff; font-size: 10.5px; font-weight: 800;
  line-height: 18px; text-align: center;
}
.selbar__acts { margin-left: auto; display: flex; gap: var(--s2); }
.selbar__act {
  display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 46px;
  font-family: var(--f-display); font-size: 10px; font-weight: 700; color: var(--ink-2);
}
.selbar__act [data-ic] { width: 19px; height: 19px; }

/* the “+” panel: four tiles per row, in three labelled groups (see §9) */
.sheet__label:first-child { margin-top: 0; }

/* message actions (long-press / right-click) */
.actgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s3); }
.actgrid__b { display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700; }
.actgrid__t { text-align: center; }
.actgrid__ic {
  display: grid; place-items: center; width: 46px; height: 46px;
  border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--line);
}
.actgrid__ic [data-ic] { width: 20px; height: 20px; }

/* chat ⋯ menu */
.actlist { display: flex; flex-direction: column; }
.actlist__r { display: flex; align-items: center; gap: var(--s3); padding: 13px 0; border-bottom: 1px solid var(--line-2); text-align: left; }
.actlist__r:last-child { border-bottom: none; }
.actlist__ic {
  display: grid; place-items: center; width: 34px; height: 34px; flex: 0 0 auto;
  border-radius: var(--r-xs); background: var(--primary-weak); color: var(--primary);
}
.actlist__ic [data-ic] { width: 17px; height: 17px; }
.actlist__t { font-size: 14px; font-weight: 600; }

/* forward / 群发 pick list — multi-select, so one send reaches several chats */
.picklist { max-height: 44vh; overflow-y: auto; }
.pickrow { display: flex; align-items: center; gap: var(--s3); width: 100%; padding: 9px 0; text-align: left; }
.pickrow__t { min-width: 0; flex: 1 1 auto; }
.pickrow__n { display: block; font-size: 13.5px; font-weight: 700; }
.pickrow__m { display: block; margin-top: 1px; font-size: 11.5px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pickrow__c { flex: 0 0 auto; color: var(--ink-4); }
.pickrow.is-on .pickrow__c { color: var(--primary); }

/* ------------------------------------------------------- 8. PROFILE & LISTS */
.hero { padding: var(--s2) var(--pad) var(--s4); }
.hero__card {
  background: var(--ink); color: #fff; border-radius: var(--r-2xl);
  padding: var(--s5); box-shadow: var(--sh-3); position: relative; overflow: hidden;
}
.hero__card::after {
  content: ""; position: absolute; right: -50px; top: -60px; width: 190px; height: 190px;
  border-radius: 50%; background: radial-gradient(circle, rgba(36,71,245,.55), transparent 68%);
}
.hero__top { display: flex; align-items: center; gap: var(--s3); position: relative; z-index: 1; }
.hero__name { font-family: var(--f-display); font-size: 19px; font-weight: 800; letter-spacing: -.015em; }
.hero__sub { font-size: 12px; color: rgba(255,255,255,.62); margin-top: 2px; }
.hero__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s4); position: relative; z-index: 1; }
.hero__tags span { font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: var(--r-pill); background: rgba(255,255,255,.12); }
.hero__kpis { display: flex; gap: var(--s5); margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid rgba(255,255,255,.12); position: relative; z-index: 1; }
.hero__kpi b { font-family: var(--f-display); font-size: 18px; font-weight: 800; display: block; }
.hero__kpi span { font-size: 11px; color: rgba(255,255,255,.6); }

.group { margin: 0 var(--pad) var(--s3); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--sh-1); }
.group__label { font-size: 11.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); padding: 0 var(--pad) var(--s2); }
.listrow { display: flex; align-items: center; gap: var(--s3); padding: 13px var(--s4); border-bottom: 1px solid var(--line-2); transition: background .18s ease; }
.listrow:last-child { border-bottom: none; }
.listrow:active { background: var(--surface-2); }
.listrow__ic { width: 32px; height: 32px; border-radius: var(--r-xs); display: flex; align-items: center; justify-content: center; background: var(--line-2); color: var(--ink-2); flex: 0 0 auto; }
.listrow__ic [data-ic] { width: 17px; height: 17px; }
.listrow__t { flex: 1 1 auto; min-width: 0; overflow: hidden; font-size: 14.5px; font-weight: 600; }
.listrow__t small { display: block; font-size: 11.5px; color: var(--ink-3); font-weight: 500; margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.listrow__v { font-size: 13px; color: var(--ink-3); font-weight: 600; display: inline-flex; align-items: center; gap: 5px; }
.listrow__v [data-ic] { width: 16px; height: 16px; color: var(--ink-4); }
.listrow__ic--primary { background: var(--primary-weak); color: var(--primary); }
.listrow__ic--accent  { background: var(--accent-weak);  color: var(--accent); }
.listrow__ic--success { background: #E6F7EF; color: var(--success); }
.listrow__ic--warn    { background: #FFF6E0; color: var(--warn); }

.wallet { display: grid; grid-template-columns: 1.25fr 1fr; gap: var(--s3); padding: 0 var(--pad) var(--s3); }
.wallet__main { background: linear-gradient(135deg, var(--primary), #4A66FF); color: #fff; border-radius: var(--r-xl); padding: var(--s4); box-shadow: 0 8px 24px rgba(36,71,245,.26); }
.wallet__main .lb { font-size: 11.5px; opacity: .8; font-weight: 600; }
.wallet__main .amt { font-family: var(--f-display); font-size: 25px; font-weight: 800; letter-spacing: -.02em; margin: 4px 0 10px; font-variant-numeric: tabular-nums; }
.wallet__main .ccy { font-size: 11px; font-weight: 700; background: rgba(255,255,255,.2); padding: 2px 8px; border-radius: var(--r-pill); }
.wallet__side { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl); padding: var(--s4); display: flex; flex-direction: column; justify-content: space-between; }
.wallet__side .n { font-family: var(--f-display); font-size: 18px; font-weight: 800; }
.wallet__side .lb { font-size: 11.5px; color: var(--ink-3); font-weight: 600; }

/* compact venue card (horizontal strip) */
.vcard {
  flex: 0 0 158px; border-radius: var(--r-lg); overflow: hidden;
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--sh-2);
  transition: transform .18s ease;
}
.vcard:active { transform: scale(.975); }
.vcard .media { aspect-ratio: 4 / 3; }
.vcard__b { display: block; padding: 10px 12px 12px; }
.vcard__n { display: block; font-family: var(--f-display); font-size: 13px; font-weight: 700; line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vcard__m { font-size: 11px; color: var(--ink-3); margin-top: 4px; display: flex; align-items: center; gap: 5px; }
.vcard__m .rate { font-size: 11px; }
.vcard__m .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--ink-4); flex: 0 0 auto; }

/* three-column media grid */
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 0 var(--pad) var(--s3); }

/* chat list inside a shared .group card */
.group .chatrow + .chatrow { border-top: 1px solid var(--line-2); }

/* ------------------------------------------------- 9. SHEET / TOAST / STATES */
.sheet { position: fixed; inset: 0; z-index: 40; display: none; }
.sheet.is-open { display: block; }
.sheet__backdrop { position: absolute; inset: 0; background: rgba(23,24,28,.44); backdrop-filter: blur(2px); animation: fade .22s ease both; }
.sheet__panel {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--surface); border-radius: var(--r-2xl) var(--r-2xl) 0 0;
  padding: var(--s3) var(--s5) var(--s6); box-shadow: var(--sh-up);
  animation: sheetUp .3s cubic-bezier(.22,.61,.36,1) both;
  max-height: 82%; overflow-y: auto;
}
.sheet__handle { width: 38px; height: 4px; border-radius: var(--r-pill); background: var(--line); margin: 0 auto var(--s4); }
.sheet__title { font-family: var(--f-display); font-size: 17px; font-weight: 800; margin-bottom: var(--s4); }
.sheet__label {
  font-size: 11.5px; font-weight: 800; letter-spacing: .06em; color: var(--ink-3);
  margin: var(--s5) 0 var(--s3);
}
.sheet__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); }
/* the chat “+” panel packs four per row — declared here, after the 3-up grid */
.sheet__grid--4 { grid-template-columns: repeat(4, 1fr); }
.sheet__grid--4 .sheet__opt { padding: var(--s3) 4px; font-size: 10.5px; }
.sheet__opt {
  display: flex; flex-direction: column; align-items: center; gap: var(--s2);
  padding: var(--s4) var(--s2); border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--line);
  font-size: 12px; font-weight: 700; transition: all .18s ease;
}
.sheet__opt:active { transform: scale(.95); }
.sheet__opt.is-active { background: var(--primary-weak); border-color: var(--primary); color: var(--primary); }
.sheet__opt [data-ic] { width: 22px; height: 22px; }
.sheet__opt--row { flex-direction: row; justify-content: space-between; padding: var(--s4); font-size: 14px; }
.sheet__opt--row [data-ic] { width: 18px; height: 18px; }
.sheet__opt--row:not(.is-active) [data-ic] { visibility: hidden; }
.sheet__row { display: flex; align-items: center; gap: var(--s3); padding: 14px 0; border-bottom: 1px solid var(--line-2); }
.sheet__row:last-child { border-bottom: none; }
.sheet__row .t { flex: 1 1 auto; font-size: 14.5px; font-weight: 600; }
.sheet__row .t small { display: block; font-size: 11.5px; color: var(--ink-3); font-weight: 500; margin-top: 2px; }

/* ------------------------------------------------- 9b. 全屏扫码 (scan screen)
   A camera is not a menu of choices — it is a viewfinder. So this sheet skips
   the panel chrome entirely: it starts right under the status bar and runs to
   the bottom edge, framing the viewer with the three scan actions below it. */
.sheet__panel--full {
  top: calc(var(--statusbar-h) + env(safe-area-inset-top, 0px));
  left: 0; right: 0; bottom: 0;
  border-radius: 0; padding: 0; max-height: none; overflow: hidden;
  animation: fade .2s ease both;
}
.scan {
  position: relative;
  display: flex; flex-direction: column; height: 100%;
  padding: var(--s3) var(--pad) calc(env(safe-area-inset-bottom, 0px) + var(--s5));
  background: radial-gradient(130% 70% at 50% 22%, #23262D, #0B0C0F 72%);
  color: #fff;
}
.scan__bar { display: flex; align-items: center; gap: var(--s2); }
.scan__title {
  flex: 1 1 auto; text-align: center; min-width: 0;
  font-family: var(--f-display); font-size: 16px; font-weight: 800; letter-spacing: .01em;
}

.scan__view {
  position: relative; flex: 1 1 auto; min-height: 0; margin-top: var(--s3);
  border-radius: var(--r-xl); overflow: hidden;
  /* the viewfinder is a dark lens rather than a photo: a soft off-centre glow
     reads as a live camera feed and never depends on an image being generated */
  background:
    radial-gradient(58% 38% at 50% 42%, rgba(255,255,255,.07), transparent 72%),
    radial-gradient(120% 90% at 50% 8%, #1C1F26, #0C0D11 72%);
}
.scan__frame {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(62vw, 230px); aspect-ratio: 1;
}
.scan__c { position: absolute; width: 30px; height: 30px; border: 3px solid #fff; border-radius: var(--r-xs); }
.scan__c:nth-child(1) { top: 0; left: 0; border-right: 0; border-bottom: 0; }
.scan__c:nth-child(2) { top: 0; right: 0; border-left: 0; border-bottom: 0; }
.scan__c:nth-child(3) { bottom: 0; left: 0; border-right: 0; border-top: 0; }
.scan__c:nth-child(4) { bottom: 0; right: 0; border-left: 0; border-top: 0; }
.scan__laser {
  position: absolute; top: 4%; left: 6px; right: 6px; height: 2px; border-radius: var(--r-pill);
  background: linear-gradient(90deg, transparent, var(--primary), transparent);
  box-shadow: 0 0 14px rgba(36,71,245,.95);
  animation: scanBeam 2.6s cubic-bezier(.45,0,.55,1) infinite alternate;
}

.scan__hint {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  margin: var(--s5) 0 var(--s2);
  font-size: 13px; font-weight: 600; color: rgba(255,255,255,.82); text-align: center;
}
.scan__hint [data-ic] { width: 16px; height: 16px; color: rgba(255,255,255,.6); }
/* not every QR belongs to SOI — say so up front, and say where links go */
.scan__sub {
  margin-bottom: var(--s4); text-align: center;
  font-size: 11.5px; font-weight: 600; color: rgba(255,255,255,.5);
}
.scan__acts { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3); }
.scan__act {
  display: flex; flex-direction: column; align-items: center; gap: var(--s2);
  font-family: var(--f-display); font-size: 12px; font-weight: 700; color: #fff;
  transition: transform .18s ease;
}
.scan__act:active { transform: scale(.94); }
.scan__act-ic {
  display: grid; place-items: center; width: 52px; height: 52px; border-radius: var(--r-pill);
  background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.16);
}
.scan__act-ic [data-ic] { width: 22px; height: 22px; }
.scan__act-t { text-align: center; }

/* what the beam read. It slides up over the hint + actions, and the beam parks
   itself — the screen stops looking for the next code while you deal with this one. */
.scan__found {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--s4) var(--pad) calc(env(safe-area-inset-bottom, 0px) + var(--s5));
  background: linear-gradient(180deg, rgba(11,12,15,0) 0%, rgba(11,12,15,.94) 20%, #0B0C0F 44%);
  opacity: 0; transform: translateY(16px); pointer-events: none;
  transition: opacity .26s ease, transform .26s cubic-bezier(.22,.61,.36,1);
}
.scan.is-found .scan__found { opacity: 1; transform: none; pointer-events: auto; }
.scan.is-found .scan__hint,
.scan.is-found .scan__sub,
.scan.is-found .scan__acts { opacity: 0; transition: opacity .2s ease; }
.scan.is-found .scan__laser { animation-play-state: paused; opacity: .3; }

/* the result card: what it is, where it goes, and the two things you can do */
.foundcard {
  background: var(--surface); color: var(--ink);
  border-radius: var(--r-lg); padding: var(--s4); box-shadow: var(--sh-3);
}
.foundcard__head { display: flex; align-items: center; gap: var(--s3); }
.foundcard__t { min-width: 0; flex: 1 1 auto; }
.foundcard__ico {
  display: grid; place-items: center; width: 42px; height: 42px; flex: 0 0 auto;
  border-radius: var(--r-sm); background: var(--primary-weak); color: var(--primary);
}
.foundcard__ico [data-ic] { width: 20px; height: 20px; }
.foundcard__k { display: block; font-family: var(--f-display); font-size: 15px; font-weight: 800; }
.foundcard__url {
  display: block; margin-top: 2px; word-break: break-all;
  font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-3);
}

.toast {
  position: fixed; left: 50%; bottom: 96px; transform: translate(-50%, 14px);
  z-index: 60; max-width: 84%;
  padding: 11px 18px; border-radius: var(--r-pill);
  background: rgba(23,24,28,.93); color: #fff; font-size: 13px; font-weight: 600;
  box-shadow: var(--sh-3); opacity: 0; pointer-events: none;
  transition: opacity .24s ease, transform .24s ease;
}
.toast.is-show { opacity: 1; transform: translate(-50%, 0); }

.empty { text-align: center; padding: var(--s8) var(--pad); }
.empty [data-ic] { width: 40px; height: 40px; color: var(--ink-4); }
.empty__t { font-family: var(--f-display); font-size: 15px; font-weight: 700; margin-top: var(--s3); }
.empty__d { font-size: 12.5px; color: var(--ink-3); margin-top: 4px; }

.skel { background: linear-gradient(90deg, var(--line-2) 25%, #E9E6DF 37%, var(--line-2) 63%); background-size: 400% 100%; animation: shimmer 1.3s ease infinite; border-radius: var(--r-xs); }

.divider-note { display: flex; align-items: center; gap: var(--s3); padding: 0 var(--pad) var(--s3); }
.divider-note .ln { flex: 1 1 auto; height: 1px; background: var(--line); }
.divider-note span { font-size: 11px; font-weight: 700; color: var(--ink-4); }

/* ==========================================================================
   9b. 服务详情页 — service.html?type=car|massage|food
   Third-party listing page: hero → stats → coupons → sticky sort → merchants
   (highest rating first) → rating breakdown → reviews → FAQ → action bar.
   ========================================================================== */
body[data-page="service"] .tabbar { display: none; }
body[data-page="service"] .screen { padding-bottom: var(--s5); }

/* two stacked sticky bars: the nav is always reachable, the sort bar docks
   under it once the hero has scrolled away */
.dnav {
  position: sticky; top: 0; z-index: 6;
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--pad);
  background: var(--paper);
}
.dback {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid var(--line); color: var(--ink); box-shadow: var(--sh-1);
  transition: transform .18s ease;
}
.dback:active { transform: scale(.94); }
.dback [data-ic] { width: 19px; height: 19px; }
.dnav__t { flex: 1 1 auto; min-width: 0; font-family: var(--f-display); font-size: 17px; font-weight: 800; letter-spacing: -.015em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* hero */
.dhero { position: relative; }
.dhero__img { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.dhero__grad { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(12,14,20,.46) 0%, rgba(12,14,20,0) 36%, rgba(12,14,20,.86) 100%); }
/* bottom offset clears the stat strip that overlaps the hero by 24px */
.dhero__b { position: absolute; left: var(--pad); right: var(--pad); bottom: 36px; color: #fff; }
.dhero__tag { display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 9px; border-radius: var(--r-pill); background: rgba(255,255,255,.22); backdrop-filter: blur(8px); font-size: 10.5px; font-weight: 800; }
.dhero__tag [data-ic] { width: 12px; height: 12px; }
.dhero__t { font-family: var(--f-display); font-size: 27px; font-weight: 800; letter-spacing: -.03em; margin-top: var(--s3); }
.dhero__s { font-size: 12.5px; line-height: 1.55; opacity: .84; margin-top: 6px; }

/* stat strip overlapping the hero */
.dstats {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  margin: -24px var(--pad) var(--s5);
  background: var(--line); border-radius: var(--r-md); overflow: hidden; box-shadow: var(--sh-2);
}
.dstat { background: var(--surface); padding: var(--s3) 4px; text-align: center; }
.dstat__n { font-family: var(--f-display); font-size: 17px; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.dstat__n--rate { color: var(--accent); }
.dstat__l { font-size: 10px; font-weight: 600; color: var(--ink-3); margin-top: 2px; }

/* coupon rail */
.couponrail { display: flex; gap: var(--s3); padding: 0 var(--pad) var(--s5); overflow-x: auto; scrollbar-width: none; }
.couponrail::-webkit-scrollbar { display: none; }
.coupon {
  flex: 0 0 auto; display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); border-radius: var(--r-md);
  background: var(--accent-weak); border: 1px dashed rgba(255,122,47,.45);
}
.coupon__off { flex: 0 0 auto; font-family: var(--f-display); font-size: 20px; font-weight: 800; letter-spacing: -.03em; color: var(--accent); }
.coupon__b { min-width: 0; }
.coupon__t { display: block; font-size: 12.5px; font-weight: 800; white-space: nowrap; }
.coupon__s { display: block; font-size: 10.5px; color: var(--ink-3); margin-top: 2px; }
.coupon__code {
  flex: 0 0 auto; align-self: center; font-family: var(--f-mono); font-size: 10px; font-weight: 700;
  letter-spacing: .04em; padding: 4px 8px; border-radius: var(--r-xs);
  background: rgba(255,122,47,.18); color: var(--accent);
}

/* sort + filter */
.sortbar {
  position: sticky; top: calc(var(--dnav-h) + var(--catrail-h)); z-index: 5;
  display: flex; align-items: center; gap: 6px;
  padding: var(--s2) var(--pad);
  background: var(--paper); border-bottom: 1px solid var(--line);
}
.sortbtn {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; height: 32px; padding: 0 12px;
  border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--line);
  font-size: 12.5px; font-weight: 700; color: var(--ink-2); white-space: nowrap;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.sortbtn [data-ic] { width: 14px; height: 14px; }
.sortbtn.is-active { background: var(--ink); border-color: var(--ink); color: #fff; }
.fchips { display: flex; gap: 6px; padding: var(--s3) var(--pad); overflow-x: auto; scrollbar-width: none; }
.fchips::-webkit-scrollbar { display: none; }
.fchips--flush { padding-left: 0; padding-right: 0; }
.fchip {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; height: 30px; padding: 0 12px;
  border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--line);
  font-size: 12px; font-weight: 600; color: var(--ink-2); white-space: nowrap;
}
.fchip [data-ic] { width: 13px; height: 13px; }
.fchip.is-active { background: var(--primary-weak); border-color: var(--primary); color: var(--primary); }

/* ------------------------------------------------------------ channel page
   分类 rail 与排序栏一起吸顶：选哪一类是这个页面最高频的动作，滚到第三屏
   也得够得着。高度写死在 --catrail-h，排序栏靠它算自己的 sticky 偏移。 */
.catrail {
  position: sticky; top: var(--dnav-h); z-index: 6;
  display: flex; align-items: center; gap: 6px;
  height: var(--catrail-h); padding: 0 var(--pad);
  background: var(--paper); overflow-x: auto; scrollbar-width: none;
}
.catrail::-webkit-scrollbar { display: none; }
.catchip {
  flex: 0 0 auto; height: 32px; padding: 0 14px; border-radius: var(--r-pill);
  background: var(--surface); border: 1px solid var(--line);
  font-family: var(--f-display); font-size: 12.5px; font-weight: 700; color: var(--ink-2);
  white-space: nowrap; transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.catchip.is-active { background: var(--ink); color: #fff; border-color: var(--ink); }

/* 内容卡：探店视频与优质点评 —— 列表之外的第二种发现方式 */
.ccard {
  flex: 0 0 208px; display: flex; flex-direction: column; gap: var(--s2);
  padding: var(--s3); border-radius: var(--r-lg); text-align: left;
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--sh-1);
}
.ccard--wide { flex: none; width: 100%; }
/* 列表里穿插的那张：宽度撑满，纵向间距由 .mlist 的 gap 负责 */
.mcontent { display: flex; }
.ccard__media { position: relative; display: block; border-radius: var(--r-sm); overflow: hidden; }
.ccard__media img { display: block; width: 100%; height: 116px; object-fit: cover; }
.ccard__play { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; }
.ccard__play [data-ic] { width: 30px; height: 30px; filter: drop-shadow(0 2px 6px rgba(0,0,0,.45)); }
.ccard__dur {
  position: absolute; right: 6px; bottom: 6px; padding: 1px 6px; border-radius: var(--r-pill);
  background: rgba(0,0,0,.55); color: #fff; font-size: 10px; font-weight: 700;
}
.ccard__n {
  font-size: 12.5px; font-weight: 600; color: var(--ink); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ccard--wide .ccard__n { -webkit-line-clamp: 3; }
.ccard__f { display: flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 600; color: var(--ink-3); }
.ccard__f [data-ic] { width: 13px; height: 13px; }
.ccard__by { margin-left: auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ccard__rate { display: flex; }
.ccard__rate .mcard__stars [data-ic] { width: 13px; height: 13px; }

/* 空状态：整片区域无入驻 / 筛选后为空。两条都必须给按钮 + 内容（标准 §3） */
.cvoid {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: var(--s6) var(--s4); border-radius: var(--r-xl);
  background: var(--surface); border: 1px dashed var(--line);
}
.cvoid__ic {
  display: grid; place-items: center; width: 52px; height: 52px; border-radius: var(--r-pill);
  background: var(--primary-weak); color: var(--primary);
}
.cvoid__ic [data-ic] { width: 24px; height: 24px; }
.cvoid__t { margin-top: var(--s4); font-family: var(--f-display); font-size: 15.5px; font-weight: 800; }
.cvoid__d { margin-top: 6px; font-size: 12.5px; color: var(--ink-3); line-height: 1.55; }
.cvoid__acts { display: flex; gap: var(--s2); margin-top: var(--s4); }
.cvoid__head { padding: var(--s5) 0 var(--s3); }
.cvoid__feed { display: flex; flex-direction: column; gap: var(--s3); }

.dcount { padding: 0 var(--pad) var(--s3); font-size: 12px; font-weight: 600; color: var(--ink-3); }
.dcount b { color: var(--ink); font-weight: 800; }

/* merchant card */
.mlist { display: flex; flex-direction: column; gap: var(--s3); padding: 0 var(--pad) var(--s5); }
.mcard {
  display: block; width: 100%; text-align: left; overflow: hidden; cursor: pointer;
  border-radius: var(--r-lg); background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--sh-1); transition: transform .18s ease;
}
.mcard:active { transform: scale(.99); }
.mcard__cover { position: relative; }
.mcard__cover img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.mcard__rank {
  position: absolute; left: var(--s3); top: var(--s3); height: 24px; padding: 0 9px;
  display: inline-flex; align-items: center; gap: 4px; border-radius: var(--r-pill);
  background: rgba(12,14,20,.6); backdrop-filter: blur(6px); color: #fff;
  font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.mcard__rank--top { background: var(--accent); }
.mcard__rank [data-ic] { width: 12px; height: 12px; }
.mcard__state {
  position: absolute; right: var(--s3); top: var(--s3); height: 24px; padding: 0 10px;
  display: inline-flex; align-items: center; border-radius: var(--r-pill);
  background: rgba(255,255,255,.94); color: var(--success); font-size: 10.5px; font-weight: 800;
}
.mcard__state--closed { color: var(--ink-3); }
.mcard__b { padding: var(--s3) var(--s4) var(--s4); }
.mcard__n { font-family: var(--f-display); font-size: 16.5px; font-weight: 800; letter-spacing: -.015em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mcard__rate { display: flex; align-items: center; gap: 5px; margin-top: 6px; }
.mcard__score { font-family: var(--f-display); font-size: 15px; font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; }
.mcard__stars { display: inline-flex; gap: 1px; }
.mcard__stars [data-ic] { width: 12px; height: 12px; color: var(--accent); }
.mcard__stars [data-ic].is-off { color: var(--line); }
.mcard__cnt { font-size: 11.5px; font-weight: 600; color: var(--ink-3); }
.mcard__tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: var(--s3); }
.mcard__tags span { font-size: 10.5px; font-weight: 600; padding: 3px 8px; border-radius: var(--r-xs); background: var(--line-2); color: var(--ink-2); white-space: nowrap; }
.mcard__foot { display: flex; align-items: flex-end; gap: var(--s3); margin-top: var(--s4); }
.mcard__price { flex: 1 1 auto; min-width: 0; }
.mcard__p { font-family: var(--f-display); font-size: 19px; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.mcard__pu { font-size: 11px; font-weight: 600; color: var(--ink-3); margin-left: 2px; }
.mcard__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 3px; font-size: 11.5px; font-weight: 600; color: var(--ink-3); }
.mcard__meta [data-ic] { width: 12px; height: 12px; }
.mcard__slots { display: inline-flex; align-items: center; gap: 4px; color: var(--success); font-weight: 700; }
.mcard__slots [data-ic] { width: 12px; height: 12px; }

/* rating breakdown + reviews + FAQ share one card shell */
.dcard { margin: 0 var(--pad) var(--s4); padding: var(--s4); background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--sh-1); }
.drate { display: flex; align-items: center; gap: var(--s5); }
.drate__big { flex: 0 0 auto; text-align: center; }
.drate__n { font-family: var(--f-display); font-size: 34px; font-weight: 800; letter-spacing: -.04em; line-height: 1; color: var(--accent); font-variant-numeric: tabular-nums; }
.drate__l { font-size: 10px; font-weight: 600; color: var(--ink-3); margin-top: 4px; }
.drate__bars { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.drate__row { display: flex; align-items: center; gap: 7px; font-size: 11px; font-weight: 600; color: var(--ink-3); }
.drate__row b { width: 10px; font-weight: 700; color: var(--ink-2); }
.drate__track { flex: 1 1 auto; height: 6px; border-radius: var(--r-pill); background: var(--line-2); overflow: hidden; }
.drate__fill { display: block; height: 100%; border-radius: var(--r-pill); background: var(--accent); }

.revrow { padding-top: var(--s4); }
.revrow + .revrow { margin-top: var(--s4); border-top: 1px solid var(--line); }
.revrow__h { display: flex; align-items: center; gap: var(--s3); }
.revrow__n { font-size: 13.5px; font-weight: 700; }
.revrow__m { display: flex; align-items: center; gap: 5px; margin-top: 3px; }
.revrow__t { font-size: 12.5px; line-height: 1.7; color: var(--ink-2); margin-top: var(--s3); }
.revrow__f { display: flex; align-items: center; gap: 5px; margin-top: var(--s3); font-size: 11.5px; font-weight: 600; color: var(--ink-3); }
.revrow__f [data-ic] { width: 13px; height: 13px; }
.dmore {
  display: flex; align-items: center; justify-content: center; gap: 4px; width: 100%;
  margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--line);
  font-size: 12.5px; font-weight: 700; color: var(--primary);
}
.dmore [data-ic] { width: 14px; height: 14px; }

.faq { padding-top: var(--s4); }
.faq + .faq { border-top: 1px solid var(--line); }
.faq__q { display: flex; align-items: center; gap: var(--s3); width: 100%; text-align: left; font-size: 13.5px; font-weight: 700; line-height: 1.5; }
.faq__q > span { flex: 1 1 auto; min-width: 0; }
.faq__q [data-ic] { width: 16px; height: 16px; flex: 0 0 auto; color: var(--ink-3); transition: transform .2s ease; }
.faq.is-open .faq__q [data-ic] { transform: rotate(180deg); }
.faq__a { display: none; padding-top: var(--s3); font-size: 12.5px; line-height: 1.7; color: var(--ink-2); }
.faq.is-open .faq__a { display: block; }

/* bottom action bar — replaces the tab bar on this page */
.actionbar {
  flex: 0 0 auto; position: relative; z-index: 6;
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4) calc(var(--s3) + env(safe-area-inset-bottom, 0px));
  background: rgba(255,255,255,.9);
  backdrop-filter: saturate(180%) blur(20px); -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--line);
}
.actionbar__ic {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: var(--r-sm);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--ink-2);
}
.actionbar__ic [data-ic] { width: 17px; height: 17px; }
.actionbar__ic span { font-size: 9px; font-weight: 700; }
.actionbar__ic.is-on { color: var(--primary); border-color: var(--primary); background: var(--primary-weak); }
.actionbar__price { flex: 1 1 auto; min-width: 0; }
.actionbar__p { font-family: var(--f-display); font-size: 20px; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.actionbar__pu { font-size: 10.5px; font-weight: 600; color: var(--ink-3); margin-left: 2px; }
.actionbar__l { display: block; font-size: 10.5px; font-weight: 600; color: var(--ink-3); margin-top: 1px; }

/* ==========================================================================
   9c. 商家详情页 — merchant.html?id=m-car-1
   Gallery → shop header → actions → packages → time slots → map → reviews
   → shop info → FAQ, with a live price in the bottom bar.
   ========================================================================== */
body[data-page="merchant"] .tabbar { display: none; }
body[data-page="merchant"] .screen { padding-bottom: var(--s5); }

/* photo grid: one big + two stacked */
.shgallery { position: relative; margin: 0 var(--pad) var(--s4); }
.shgallery__grid { display: grid; grid-template-columns: 2fr 1fr; gap: 4px; }
.shgallery__main { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--r-md); }
.shgallery__side { display: flex; flex-direction: column; gap: 4px; }
.shgallery__side img { display: block; width: 100%; flex: 1 1 0; min-height: 0; object-fit: cover; border-radius: var(--r-md); }
.shgallery__badge {
  position: absolute; right: var(--s2); bottom: var(--s2);
  display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 10px;
  border-radius: var(--r-pill); background: rgba(12,14,20,.64);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  color: #fff; font-size: 11px; font-weight: 700;
}
.shgallery__badge [data-ic] { width: 13px; height: 13px; }

/* shop header */
.shhead { margin: 0 var(--pad) var(--s4); }
.shhead__n { font-family: var(--f-display); font-size: 23px; font-weight: 800; letter-spacing: -.028em; line-height: 1.25; }
.shhead__rate { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: var(--s2); }
.shhead__score { font-family: var(--f-display); font-size: 19px; font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; }
.shhead__state {
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: var(--r-pill);
  background: rgba(15,169,104,.12); color: var(--success); font-size: 10.5px; font-weight: 800;
}
.shhead__state--closed { background: var(--line-2); color: var(--ink-3); }
.shhead__tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: var(--s3); }
.shhead__tags span { font-size: 10.5px; font-weight: 600; padding: 3px 8px; border-radius: var(--r-xs); background: var(--line-2); color: var(--ink-2); }
.shhead__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: var(--s3); font-size: 12px; font-weight: 600; color: var(--ink-3); }
.shhead__meta [data-ic] { width: 13px; height: 13px; }

/* four big actions */
.shacts { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); margin: 0 var(--pad) var(--s5); }
.shact {
  display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0;
  padding: var(--s3) 4px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--sh-1);
  font-size: 11px; font-weight: 700; color: var(--ink-2); white-space: nowrap;
  transition: transform .18s ease, background .18s ease, border-color .18s ease;
}
.shact [data-ic] { width: 19px; height: 19px; color: var(--primary); }
.shact > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.shact:active { transform: scale(.96); }
.shact.is-on { background: var(--primary-weak); border-color: var(--primary); color: var(--primary); }

/* selectable package card */
.pklist { display: flex; flex-direction: column; gap: var(--s3); padding: 0 var(--pad) var(--s5); }
.pkcard {
  position: relative; display: block; width: 100%; text-align: left; cursor: pointer;
  padding: var(--s4); border-radius: var(--r-lg);
  background: var(--surface); border: 1.5px solid var(--line); box-shadow: var(--sh-1);
  transition: border-color .18s ease, background .18s ease;
}
.pkcard.is-on { border-color: var(--primary); background: var(--primary-weak); }
.pkcard__h { display: flex; align-items: flex-start; gap: var(--s3); }
.pkcard__n { flex: 1 1 auto; min-width: 0; font-family: var(--f-display); font-size: 15.5px; font-weight: 800; letter-spacing: -.012em; }
.pkcard__hot { flex: 0 0 auto; font-size: 10px; font-weight: 800; padding: 2px 8px; border-radius: var(--r-pill); background: var(--accent); color: #fff; }
.pkcard__check {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: var(--r-pill);
  border: 1.5px solid var(--line); display: flex; align-items: center; justify-content: center; color: transparent;
}
.pkcard__check [data-ic] { width: 13px; height: 13px; }
.pkcard.is-on .pkcard__check { background: var(--primary); border-color: var(--primary); color: #fff; }
.pkcard__inc { display: flex; flex-wrap: wrap; gap: 5px; margin-top: var(--s3); }
.pkcard__inc span { display: inline-flex; align-items: center; gap: 3px; font-size: 10.5px; font-weight: 600; padding: 3px 8px; border-radius: var(--r-xs); background: var(--line-2); color: var(--ink-2); }
.pkcard.is-on .pkcard__inc span { background: rgba(36,71,245,.1); color: var(--primary); }
.pkcard__inc [data-ic] { width: 11px; height: 11px; }
.pkcard__f { display: flex; align-items: flex-end; gap: var(--s3); margin-top: var(--s4); }
.pkcard__price { flex: 1 1 auto; min-width: 0; }
.pkcard__p { font-family: var(--f-display); font-size: 22px; font-weight: 800; letter-spacing: -.03em; color: var(--accent); font-variant-numeric: tabular-nums; }
.pkcard__was { font-size: 12px; color: var(--ink-4); text-decoration: line-through; margin-left: 6px; }
.pkcard__meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; font-size: 11.5px; font-weight: 600; color: var(--ink-3); }
.pkcard__save { color: var(--accent); font-weight: 800; }
.pkcard__pick {
  flex: 0 0 auto; height: 32px; padding: 0 14px; border-radius: var(--r-pill);
  background: var(--line-2); color: var(--ink-2); font-size: 12.5px; font-weight: 700;
}
.pkcard.is-on .pkcard__pick { background: var(--primary); color: #fff; }

/* date + time picker */
.days { display: flex; gap: var(--s2); padding: 0 var(--pad) var(--s3); }
.day {
  flex: 1 1 0; min-width: 0; padding: 9px 4px; border-radius: var(--r-sm);
  background: var(--surface); border: 1px solid var(--line);
  font-size: 12.5px; font-weight: 700; color: var(--ink-2); text-align: center; white-space: nowrap;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.day.is-on { background: var(--ink); border-color: var(--ink); color: #fff; }
.slotgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); padding: 0 var(--pad) var(--s5); }
.slot {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  height: 46px; border-radius: var(--r-sm);
  background: var(--surface); border: 1px solid var(--line);
  font-size: 13px; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.slot small { font-size: 9.5px; font-weight: 700; }
.slot.is-on { background: var(--primary); border-color: var(--primary); color: #fff; }
.slot.is-full { background: var(--line-2); border-color: transparent; color: var(--ink-4); text-decoration: line-through; }
.slot.is-full small { text-decoration: none; }

/* mini map */
.shmap { position: relative; margin: 0 var(--pad); border-radius: var(--r-lg); overflow: hidden; }
.shmap img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.shmap__pin { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -100%); color: var(--accent); filter: drop-shadow(0 3px 6px rgba(12,14,20,.35)); }
.shmap__pin [data-ic] { width: 36px; height: 36px; }
.shmap__b {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
  background: linear-gradient(180deg, rgba(12,14,20,0) 0%, rgba(12,14,20,.8) 100%); color: #fff;
}
.shmap__b span { flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 600; line-height: 1.4; }

/* info rows */
.srow { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; }
.srow + .srow { border-top: 1px solid var(--line); }
.srow__ic { flex: 0 0 auto; width: 34px; height: 34px; border-radius: var(--r-xs); display: flex; align-items: center; justify-content: center; background: var(--line-2); color: var(--ink-2); }
.srow__ic [data-ic] { width: 17px; height: 17px; }
.srow__b { flex: 1 1 auto; min-width: 0; }
.srow__l { font-size: 11px; font-weight: 700; color: var(--ink-3); }
.srow__v { display: block; font-size: 13.5px; font-weight: 600; margin-top: 2px; word-break: break-word; }
.srow__go { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 3px; font-size: 12px; font-weight: 700; color: var(--primary); white-space: nowrap; }
.srow__go [data-ic] { width: 14px; height: 14px; }

/* ==========================================================================
   9d. 通讯录 contacts.html — 好友是重要板块，独立成页
   Shortcut tiles (on the friends page) → stat strip → eat-together rail →
   filters → sticky A–Z groups in grid or list form, with an index rail.
   ========================================================================== */
body[data-page="contacts"] .tabbar { display: none; }
body[data-page="contacts"] .screen { padding-bottom: var(--s5); }

/* four tiles above the chat list — tile 1 is the way into contacts */
.cshorts { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); padding: 0 var(--pad) var(--s4); }
.cshort {
  display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0;
  padding: var(--s3) 4px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--sh-1);
  transition: transform .18s ease;
}
.cshort:active { transform: scale(.95); }
.cshort__ic {
  position: relative; width: 34px; height: 34px; border-radius: var(--r-xs);
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-weak); color: var(--primary);
}
.cshort__ic [data-ic] { width: 18px; height: 18px; }
.cshort__n {
  position: absolute; top: -5px; right: -6px; min-width: 17px; height: 17px; padding: 0 5px;
  border-radius: var(--r-pill); background: var(--accent); color: #fff;
  font-size: 10px; font-weight: 800; line-height: 17px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.cshort__l { max-width: 100%; font-size: 11px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* stat strip */
.cstats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); padding: var(--s3) var(--pad) var(--s5); }
.cstat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s3) 4px; text-align: center; box-shadow: var(--sh-1); }
.cstat__n { font-family: var(--f-display); font-size: 18px; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.cstat__l { font-size: 10px; font-weight: 600; color: var(--ink-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* eat-together rail — the app's signature grouping */
.foodie { flex: 0 0 auto; width: 68px; text-align: center; }
.foodie__av { position: relative; display: block; width: 58px; height: 58px; margin: 0 auto; }
.foodie__av img { width: 100%; height: 100%; border-radius: var(--r-pill); object-fit: cover; }
.foodie__n { display: block; font-size: 10.5px; font-weight: 700; color: var(--ink-2); margin-top: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.foodie__m { display: block; font-size: 9.5px; font-weight: 700; color: var(--accent); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* sticky group header (sticks under the page's sticky nav) */
.cgroup__h {
  position: sticky; top: var(--dnav-h); z-index: 3;
  display: flex; align-items: center; gap: 6px;
  padding: var(--s2) var(--pad);
  background: var(--paper);
  font-family: var(--f-display); font-size: 12.5px; font-weight: 800; color: var(--ink-3);
  scroll-margin-top: calc(var(--dnav-h) + 4px);
}
.cgroup__c { font-size: 10.5px; font-weight: 700; color: var(--ink-4); font-variant-numeric: tabular-nums; }

/* A–Z index rail */
.azrail {
  position: fixed; right: 1px; top: 50%; transform: translateY(-50%); z-index: 8;
  display: flex; flex-direction: column; align-items: center;
  padding: 5px 1px; border-radius: var(--r-pill);
  background: rgba(244,242,237,.74);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.azrail button { width: 17px; height: 15px; border-radius: var(--r-pill); font-size: 9.5px; font-weight: 800; color: var(--ink-3); }
.azrail button:active { background: var(--primary); color: #fff; }

/* starred marker on a contact row */
.listrow__star { flex: 0 0 auto; color: var(--accent); }
.listrow__star [data-ic] { width: 15px; height: 15px; }
.listrow__star [data-ic] svg { fill: var(--accent); }

/* helpers */
.pad { padding: 0 var(--pad); }
.mt2 { margin-top: var(--s2); } .mt3 { margin-top: var(--s3); } .mt4 { margin-top: var(--s4); }
.mt5 { margin-top: var(--s5); } .mt6 { margin-top: var(--s6); }
.mb3 { margin-bottom: var(--s3); } .mb4 { margin-bottom: var(--s4); }
.row { display: flex; align-items: center; }
.between { justify-content: space-between; }
.gap2 { gap: var(--s2); } .gap3 { gap: var(--s3); }
.grow { flex: 1 1 auto; min-width: 0; }
.muted { color: var(--ink-3); }
.strong { font-weight: 700; }
.tnum { font-variant-numeric: tabular-nums; }
.clamp2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* ---------------------------------------------------------------- 10. MOTION */
@keyframes riseIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
@keyframes scanBeam { from { top: 4%; } to { top: 94%; } }

.reveal { animation: riseIn .5s cubic-bezier(.22,.61,.36,1) both; animation-delay: calc(var(--i, 0) * 55ms); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
