/* ════════════════════════════════════════════════════════════════════════
   PYKE · app.css — shared architecture + default tokens
   Every page links this PLUS one theme override file.
   Adding a new theme = 1 JSON in /themes/<id>.json + 1 CSS in /css/themes/<id>.css.
   ════════════════════════════════════════════════════════════════════════ */

/* View Transitions API — smooth cross-fade between pages by default.
   Chrome 111+ / Safari 18+ / Firefox 130+ (with flag). No-op fallback elsewhere. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 260ms; }
::view-transition-old(root) { animation-timing-function: cubic-bezier(0.22,1,0.36,1); }
::view-transition-new(root) { animation-timing-function: cubic-bezier(0.22,1,0.36,1); }

/* Native color-scheme — form controls match theme automatically */
:root { color-scheme: light; }
body.theme-lounge, body.theme-modern { color-scheme: dark; }

/* Respect reduced-motion preference (a11y must-have) */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none !important; }
}

/* ── Default tokens (theme files override) ────────────────────────────── */
:root {
  --bg:           #F7F5F1;
  --card:         #FFFFFF;
  --ink:          #14110C;
  --body:         #3D3A35;
  --muted:        #8C857C;
  --ink-2:        #5C5750;
  --line:         #E8E0D0;
  --sunken:       #F2EDE3;
  --img-bg:       #F2EDE3;
  --accent:       #7A5C3F;
  --accent-soft:  #B89977;
  --hot:          #E11D2B;
  --tab-active:   #14110C;

  --sans:    'PingFang HK','PingFang TC','Microsoft JhengHei','Microsoft YaHei','Noto Sans HK','Noto Sans CJK TC',-apple-system,system-ui,sans-serif;
  --serif:   'Source Han Serif TC','Source Han Serif SC','Songti TC','Songti SC',Georgia,'Times New Roman',serif;
  --display: 'Source Han Serif TC','Songti TC',Georgia,serif;
  --num:     'SF Pro Display',-apple-system,'Inter','Helvetica Neue',sans-serif;

  --banner-aspect: 75/32;
  --banner-margin: 0;
  --banner-radius: 0;
  --banner-h-size: 22px;
  --banner-h-weight: 600;
  --card-aspect: 1/1;
  --card-radius: 10px;
  --card-border: none;
  --card-img-filter: none;
  --card-name-weight: 400;
  --card-name-font: var(--sans);
  --card-name-transform: none;
  --card-name-track: 0;
  --tile-radius: 14px;
  --feed-gap: 8px;
  --sec-transform: none;
  --sec-track: 0.02em;
  --flash-bg: linear-gradient(180deg, rgba(225,29,43,0.06), rgba(255,255,255,0.4));
  --flash-cd-bg: #14110C;
  --flash-cd-ink: #FFFFFF;
  --flash-ink: #14110C;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ── Reset ────────────────────────────────────────────────────────────── */
*,*::before,*::after { box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; }
html, body { margin: 0; padding: 0; min-height: 100vh; overscroll-behavior: none; }
body { font-family: var(--sans); background: var(--bg); color: var(--body); font-size: 14px; line-height: 1.5; -webkit-font-smoothing: antialiased; transition: background .3s ease; }
img, svg { display: block; max-width: 100%; }
a, button { color: inherit; text-decoration: none; font-family: inherit; }
button { background: none; border: 0; cursor: pointer; padding: 0; font-family: inherit; }
input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }

/* ── App shell — responsive across phone / iPad / desktop ────────────── */
/*
 * Mobile-first ladder. Each breakpoint widens the central app column so
 * iPad and desktop don't see a 430px phone-shape floating in empty space.
 *
 *   ≤ 520px  phone-app width (430px, fills viewport when narrower)
 *   521-767px  large phone / portrait iPad — small uplift to 560px
 *   768-1023px iPad portrait / landscape — grows to 720px, container-queried
 *              feeds switch from 2 → 3 cols
 *   ≥ 1024px desktop / iPad landscape — caps at 1100px, 4-col grids
 *
 * Pages that should stay narrow (login, signup, single-column forms) opt-in
 * via `.app.narrow` to keep the focused phone-form ergonomics.
 */
.app { width: 100%; min-height: 100vh; max-width: 430px; margin: 0 auto; background: var(--bg); position: relative; container-type: inline-size; }
@media (min-width: 521px) {
  .app { max-width: 560px; box-shadow: 0 0 60px rgba(0,0,0,0.12); }
}
@media (min-width: 768px) {
  .app { max-width: 720px; }
}
@media (min-width: 1024px) {
  .app { max-width: 1100px; box-shadow: 0 0 80px rgba(0,0,0,0.10); }
}
/* Opt-in narrow shell for auth/onboarding forms */
.app.narrow { max-width: 430px !important; }
@media (min-width: 521px) {
  .app.narrow { max-width: 460px !important; }
}

/* ── Top bar ──────────────────────────────────────────────────────────── */
.topbar { position: sticky; top: 0; z-index: 40; padding-top: env(safe-area-inset-top); background: var(--bg-topbar, var(--bg)); transition: all .25s ease; }
.topbar.scrolled { backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); box-shadow: 0 1px 0 var(--line); }
.topbar-row { display: flex; align-items: center; gap: 10px; padding: 10px 14px; min-height: 48px; }
.topbar-row.with-back { padding-left: 8px; }
.logo { width: 30px; height: 30px; border-radius: 50%; background: var(--ink); color: var(--bg); display: grid; place-items: center; font-family: var(--display); font-size: 15px; font-weight: 600; flex-shrink: 0; letter-spacing: -0.02em; }
.back-btn { width: 36px; height: 36px; display: grid; place-items: center; color: var(--ink); flex-shrink: 0; }
.back-btn svg { width: 22px; height: 22px; stroke-width: 1.5; }
.title { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--ink); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search { flex: 1; height: 38px; border-radius: 19px; background: var(--sunken); display: flex; align-items: center; padding: 0 12px; gap: 8px; min-width: 0; }
.search svg { width: 16px; height: 16px; color: var(--muted); flex-shrink: 0; }
.search input { flex: 1; border: 0; background: transparent; outline: none; font-size: 13px; color: var(--ink); min-width: 0; }
.search input::placeholder { color: var(--muted); }
.iconbtn { width: 32px; height: 32px; display: grid; place-items: center; color: var(--ink); position: relative; flex-shrink: 0; }
.iconbtn svg { width: 22px; height: 22px; stroke-width: 1.5; }
.iconbtn .dot { position: absolute; top: 4px; right: 4px; width: 6px; height: 6px; background: var(--hot); border-radius: 50%; }

/* ── Main scroll area ─────────────────────────────────────────────────── */
main { padding-bottom: calc(58px + env(safe-area-inset-bottom)); }
main.no-tabbar { padding-bottom: env(safe-area-inset-bottom); }

/* ── Banner ──────────────────────────────────────────────────────────── */
.banner { position: relative; overflow: hidden; background: var(--sunken); aspect-ratio: var(--banner-aspect); margin: var(--banner-margin); border-radius: var(--banner-radius); }
.banner-track { display: flex; height: 100%; transition: transform .5s var(--ease); touch-action: pan-y; }
.banner-slide { flex: 0 0 100%; height: 100%; position: relative; }
.banner-slide img { width: 100%; height: 100%; object-fit: cover; }
.banner-overlay { position: absolute; left: 22px; bottom: 22px; right: 22px; color: var(--banner-text, #fff); text-shadow: 0 1px 8px rgba(0,0,0,0.4); pointer-events: none; }
.banner-overlay .eyebrow { font-size: 10px; letter-spacing: 0.32em; text-transform: uppercase; opacity: 0.92; margin-bottom: 4px; font-weight: 600; font-family: var(--sans); }
.banner-overlay h2 { font-family: var(--display); font-size: var(--banner-h-size); font-weight: var(--banner-h-weight); margin: 0; max-width: 78%; line-height: 1.2; }
.banner-overlay h2 em { font-style: italic; color: var(--accent-soft); font-family: var(--display); }
.banner-dots { position: absolute; right: 14px; bottom: 12px; display: flex; gap: 4px; z-index: 2; }
.banner-dot { width: 6px; height: 6px; border-radius: 3px; background: rgba(255,255,255,0.4); transition: all .25s var(--ease); }
.banner-dot.on { background: #fff; width: 18px; }

/* ── Category grid ────────────────────────────────────────────────────── */
.cats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px 4px; padding: 18px 8px 8px; }
.cat { display: flex; flex-direction: column; align-items: center; gap: 6px; transition: transform .15s var(--ease); }
.cat:active { transform: scale(0.97); }
.cat-tile { width: 52px; height: 52px; border-radius: var(--tile-radius); background: var(--sunken); display: grid; place-items: center; color: var(--ink-2); overflow: hidden; }
.cat-tile svg { width: 28px; height: 28px; stroke-width: 1.4; fill: none; stroke: currentColor; }
.cat-label { font-size: 11px; color: var(--ink); font-weight: 500; letter-spacing: 0.02em; }

/* ── Flash sale ───────────────────────────────────────────────────────── */
.flash { margin: 8px 14px 4px; border-radius: 12px; background: var(--flash-bg); padding: 14px 0 12px; }
.flash[hidden] { display: none; }
.flash-head { display: flex; align-items: center; justify-content: space-between; padding: 0 14px 12px; }
.flash-h-l { display: flex; align-items: baseline; gap: 8px; }
.flash-h-l h3 { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--flash-ink); margin: 0; letter-spacing: 0.02em; }
.flash-h-l small { font-size: 11px; color: var(--ink-2); }
.countdown { display: flex; align-items: center; gap: 3px; font-family: var(--num); }
.cd-seg { background: var(--flash-cd-bg); color: var(--flash-cd-ink); min-width: 24px; height: 24px; padding: 0 4px; border-radius: 4px; display: grid; place-items: center; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cd-colon { color: var(--flash-ink); font-weight: 700; }
.flash-rail { display: flex; gap: 8px; padding: 0 14px 2px; overflow-x: auto; scrollbar-width: none; scroll-snap-type: x mandatory; }
.flash-rail::-webkit-scrollbar { display: none; }
.flash-card { flex: 0 0 96px; scroll-snap-align: start; display: block; }
.flash-card-img { width: 96px; height: 96px; border-radius: 10px; background: var(--card); overflow: hidden; margin-bottom: 8px; }
.flash-card-img img { width: 100%; height: 100%; object-fit: cover; }
.flash-card .name { font-size: 11px; color: var(--ink); line-height: 1.3; margin: 0 0 4px; height: 28px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.flash-card .price { font-family: var(--num); font-size: 13px; font-weight: 700; color: var(--hot); font-variant-numeric: tabular-nums; }
.flash-card .price::before { content: '¥'; font-size: 9px; font-weight: 500; margin-right: 1px; }
.flash-card .was { font-size: 10px; color: var(--muted); text-decoration: line-through; font-variant-numeric: tabular-nums; margin-left: 4px; font-family: var(--num); }

/* ── Section heading ─────────────────────────────────────────────────── */
.sec-h { display: flex; align-items: baseline; justify-content: space-between; padding: 24px 16px 12px; }
.sec-h h2 { font-family: var(--display); font-size: 18px; font-weight: 600; color: var(--ink); margin: 0; letter-spacing: var(--sec-track); text-transform: var(--sec-transform); }
.sec-h a { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 2px; }
.sec-h a svg { width: 12px; height: 12px; }

/* ── Product feed ────────────────────────────────────────────────────── */
/* container-type lets cards inside flash-rail respond to their inline size
   independently of the viewport */
.feed { display: grid; grid-template-columns: 1fr 1fr; gap: var(--feed-gap); padding: 0 8px 24px; container-type: inline-size; container-name: feed; }
.flash-rail { container-type: inline-size; container-name: flash-rail; }
.pcard { background: var(--card); border-radius: var(--card-radius); overflow: hidden; transition: transform .15s var(--ease), border-color .2s; display: block; position: relative; border: var(--card-border); }
/* Container query: when feed is wide enough (e.g. tablet/desktop preview), 3-up */
/* Feed grid — was container-query but those don't match the container itself.
   Replaced with viewport-driven media queries aligned to the app-shell breakpoints. */
@media (min-width: 521px)  { .feed { grid-template-columns: repeat(2, 1fr); gap: calc(var(--feed-gap) * 1.2); } }
@media (min-width: 768px)  { .feed { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .feed { grid-template-columns: repeat(4, 1fr); padding: 0 16px 32px; } }
.pcard:active { transform: scale(0.97); }
.pcard:hover { border-color: var(--accent); }
.pcard-img { width: 100%; aspect-ratio: var(--card-aspect); background: var(--img-bg); position: relative; overflow: hidden; }
.pcard-img img { width: 100%; height: 100%; object-fit: cover; filter: var(--card-img-filter); transition: filter .3s; }
.pcard:hover .pcard-img img { filter: none; }
.ribbon { position: absolute; top: 0; left: 0; background: var(--hot); color: #fff; font-size: 10px; font-weight: 600; padding: 3px 8px 3px 6px; clip-path: polygon(0 0, 100% 0, 92% 100%, 0 100%); letter-spacing: 0.04em; }
.ribbon.new { background: var(--accent); }
.pcard-info { padding: 10px 11px 12px; }
.pcard-name { font-size: 13px; color: var(--ink); line-height: 1.4; margin: 0 0 8px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; min-height: 36px; font-weight: var(--card-name-weight); font-family: var(--card-name-font); letter-spacing: var(--card-name-track); text-transform: var(--card-name-transform); }
.pcard-price-row { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; }
.pcard-price { display: flex; align-items: baseline; gap: 5px; min-width: 0; }
.pcard-price .now { font-family: var(--num); font-size: 17px; font-weight: 700; color: var(--hot); font-variant-numeric: tabular-nums; line-height: 1; }
.pcard-price .now::before { content: '¥'; font-size: 10px; font-weight: 500; margin-right: 1px; }
.pcard-price .was { font-size: 11px; color: var(--muted); text-decoration: line-through; font-variant-numeric: tabular-nums; font-family: var(--num); }

/* ── Editorial card ──────────────────────────────────────────────────── */
.ed-card { margin: 0 14px 8px; border-radius: 12px; overflow: hidden; position: relative; aspect-ratio: 16/10; background: var(--sunken); display: block; }
.ed-card[hidden] { display: none; }
.ed-card img { width: 100%; height: 100%; object-fit: cover; filter: var(--card-img-filter); }
.ed-card::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 50%, rgba(0,0,0,0.6)); }
.ed-card-text { position: absolute; left: 20px; bottom: 18px; right: 20px; color: #fff; z-index: 1; text-shadow: 0 1px 6px rgba(0,0,0,0.3); }
.ed-card-text .eyebrow { font-size: 10px; letter-spacing: 0.32em; text-transform: uppercase; opacity: 0.85; margin-bottom: 4px; }
.ed-card-text h3 { font-family: var(--display); font-size: 20px; font-weight: 500; margin: 0; line-height: 1.2; }
.ed-card-text h3 em { font-style: italic; color: var(--accent-soft); }

/* ── FAB / floating top ───────────────────────────────────────────────── */
.fab-top { position: fixed; right: 12px; bottom: calc(72px + env(safe-area-inset-bottom)); width: 38px; height: 38px; border-radius: 50%; background: rgba(20,17,12,0.5); color: #fff; display: none; align-items: center; justify-content: center; z-index: 30; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.fab-top.on { display: flex; }
.fab-top svg { width: 18px; height: 18px; }

/* ── Bottom tab bar ──────────────────────────────────────────────────── */
/* Tabbar matches the app shell's max-width at each breakpoint so it stays
   anchored under the actual content column, not pinned at 430px while the
   shell above is 1100px wide. Same breakpoint ladder reused by any fixed
   bottom bar (buy-bar on product page, checkout-bar on cart). */
.tabbar,
.fixed-bar { max-width: 430px; margin: 0 auto; }
@media (min-width: 521px) { .tabbar, .fixed-bar { max-width: 560px; } }
@media (min-width: 768px) { .tabbar, .fixed-bar { max-width: 720px; } }
@media (min-width: 1024px) { .tabbar, .fixed-bar { max-width: 1100px; } }
.tabbar { position: fixed; bottom: 0; left: 0; right: 0; z-index: 50; padding-bottom: env(safe-area-inset-bottom); background: var(--bg-tabbar, var(--bg)); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-top: 1px solid var(--line); }
.tabbar-row { display: flex; height: 50px; }
.tab { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; color: var(--muted); position: relative; }
.tab svg { width: 22px; height: 22px; stroke-width: 1.5; fill: none; stroke: currentColor; }
.tab svg.filled { fill: currentColor; stroke: currentColor; stroke-width: 1; }
.tab .label { font-size: 10px; font-weight: 500; }
.tab.is-active { color: var(--tab-active); }
.tab.is-active .label { font-weight: 600; }
.tab-badge { position: absolute; top: 3px; right: calc(50% - 22px); background: var(--hot); color: #fff; font-size: 9px; font-weight: 700; min-width: 16px; height: 14px; border-radius: 7px; padding: 0 4px; display: none; align-items: center; justify-content: center; line-height: 1; font-variant-numeric: tabular-nums; }
.tab .tab-badge.on { display: inline-flex; }

/* ── Skeleton ────────────────────────────────────────────────────────── */
.skel { background: linear-gradient(90deg, rgba(0,0,0,0.04) 0%, rgba(0,0,0,0.09) 50%, rgba(0,0,0,0.04) 100%); background-size: 200% 100%; animation: skel 1.6s linear infinite; }
@keyframes skel { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ── Theme preview switcher (dev only) ───────────────────────────────── */
.ts { position: fixed; top: calc(env(safe-area-inset-top) + 52px); right: 8px; z-index: 9999; background: rgba(0,0,0,0.88); color: #fff; backdrop-filter: blur(12px); border-radius: 20px; padding: 3px; display: none; gap: 2px; font-size: 9px; letter-spacing: 0.1em; font-family: 'Inter',sans-serif; font-weight: 600; flex-wrap: nowrap; white-space: nowrap; max-width: calc(100vw - 16px); overflow-x: auto; scrollbar-width: none; }
.ts::-webkit-scrollbar { display: none; }
.ts.on { display: flex; }
.ts a { color: rgba(255,255,255,0.55); padding: 5px 8px; border-radius: 13px; transition: all .15s; cursor: pointer; }
.ts a.is-active { background: #fff; color: #000; }

/* ── Native <dialog> (accessible modal — escape-key, backdrop close free) ── */
dialog {
  border: 0; padding: 0; margin: auto;
  background: var(--card); color: var(--ink);
  border-radius: 16px;
  max-width: min(90vw, 420px); width: 100%;
  box-shadow: 0 24px 64px rgba(0,0,0,0.32);
  font-family: inherit;
}
dialog::backdrop { background: rgba(0,0,0,0.45); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
dialog[open] { animation: dlg-in 220ms var(--ease); }
dialog[open]::backdrop { animation: bd-in 220ms var(--ease); }
@keyframes dlg-in { from { transform: translateY(20px) scale(0.98); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes bd-in { from { opacity: 0; } to { opacity: 1; } }
.dlg-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 18px 12px; }
.dlg-head h3 { font-family: var(--display); font-size: 17px; font-weight: 600; margin: 0; color: var(--ink); }
.dlg-close { width: 32px; height: 32px; display: grid; place-items: center; color: var(--muted); border-radius: 50%; }
.dlg-close:hover { color: var(--ink); background: var(--sunken); }
.dlg-body { padding: 0 18px 18px; }
.dlg-foot { padding: 0 18px 18px; display: flex; gap: 8px; }
.dlg-foot .btn { flex: 1; }

/* ── View-transition names for hero crossfade ────────────────────────── */
/* The product image gets a unique name so it morphs from card → detail page */
[data-view-transition-name] { view-transition-name: attr(data-view-transition-name); }
/* Fallback CSS for browsers that don't support attr() in view-transition-name (most don't yet):
   pages will set this inline via JS instead — see /js/theme.js */

/* ── LCP image hints ─────────────────────────────────────────────────── */
img[fetchpriority="high"] { /* hint to the browser; no visual change */ }
img:not([loading]) { /* explicit reminder — but we use loading="lazy" or eager attr in markup */ }

/* ── Generic page shell (for product, cart, orders, account) ─────────── */
.page { padding: 16px; }
.card { background: var(--card); border-radius: 12px; padding: 16px; margin-bottom: 12px; border: 1px solid var(--line); }
.row { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; font-size: 14px; }
.row .label { color: var(--muted); font-size: 13px; }
.row .val { color: var(--ink); }
.btn { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 20px; border-radius: 22px; font-size: 14px; font-weight: 600; transition: opacity .15s; cursor: pointer; }
.btn-primary { background: var(--ink); color: var(--bg); border: 1px solid var(--ink); }
.btn-primary:active { opacity: 0.85; }
.btn-secondary { background: var(--sunken); color: var(--ink); border: 1px solid var(--line); }
.btn-hot { background: var(--hot); color: #fff; border: 1px solid var(--hot); }
.btn-full { width: 100%; }
.input { width: 100%; height: 44px; padding: 0 14px; background: var(--sunken); border: 1px solid var(--line); border-radius: 10px; font-size: 14px; outline: none; color: var(--ink); }
.input:focus { border-color: var(--accent); }
.input::placeholder { color: var(--muted); }
.chip { display: inline-flex; align-items: center; padding: 4px 10px; border-radius: 12px; background: var(--sunken); color: var(--ink); font-size: 11px; font-weight: 500; }
.chip.hot { background: var(--hot); color: #fff; }
.chip.accent { background: var(--accent-soft); color: var(--ink); }
.empty { text-align: center; padding: 64px 24px; color: var(--muted); font-size: 13px; font-family: var(--display); font-style: italic; }
