/* VitalMen — App-feel base layer (loaded AFTER store.css on the 4 storefront pages).
   Only does what makes the H5 behave like a native app; all visual tokens stay in
   store.css so the design system keeps a single source of truth.

   1) safe-area (notch / home indicator)
   2) no browser affordances: tap highlight, long-press menu, text selection, zoom
   3) press feedback on every tappable thing
   4) no rubber-band / scroll chaining, hidden scrollbars
   5) iOS: 16px inputs so focusing a field never zooms the page

   Not loaded by admin-dashboard.html on purpose: the ops console is a desktop tool
   where selecting text and long-press menus are legitimate. */

:root{
  --sai-top: env(safe-area-inset-top, 0px);
  --sai-bottom: env(safe-area-inset-bottom, 0px);
  --sai-left: env(safe-area-inset-left, 0px);
  --sai-right: env(safe-area-inset-right, 0px);
}

/* ---------- 1. page / safe area ---------- */
html{
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  /* The rubber-band overscroll used to reveal html's white background past the
     end of the page — a very "web" tell. Match the page colour instead. */
  background: var(--bg, var(--surface));
}
body{
  min-height: 100vh;
  min-height: 100dvh;
  overscroll-behavior-y: contain;
  /* No double-tap-zoom (this is what makes a page feel like a document rather
     than an app). Panning is untouched so long pages still scroll. Pinch is
     already blocked by the locked viewport meta. */
  touch-action: manipulation;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  padding-left: var(--sai-left);
  padding-right: var(--sai-right);
}

/* sticky header clears the notch in an immersive/standalone shell */
.site-header{ padding-top: var(--sai-top); }
/* secondary category bar must stick directly under the notch-offset header */
.subnav{ top: calc(63px + var(--sai-top)); }
/* sticky side rails follow the taller viewport-safe header */
.order-summary, .detail-gallery{ top: calc(78px + var(--sai-top)); }

/* floating UI keeps clear of the home indicator */
.toast-wrap{ bottom: calc(22px + var(--sai-bottom)); }
.search-overlay{ padding-bottom: var(--sai-bottom); }
.drawer{ padding-bottom: var(--sai-bottom); }
.search-overlay .search-panel, .drawer-nav{ scroll-padding-bottom: var(--sai-bottom); }

/* ---------- 2. no browser affordances ---------- */
body, button, .btn, [data-href], .product-card{ -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
input, textarea, select, [contenteditable="true"]{ -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
img, svg{ -webkit-user-drag: none; user-select: none; }
button, .btn, [data-href], a, label, select{ touch-action: manipulation; }

/* Long-press on an image/card otherwise pops the iOS share sheet with a
   preview thumbnail — reads as "web page" instantly. */
img{ -webkit-touch-callout: none; pointer-events: auto; }

/* p a[href^="mailto:"] keeps its underline (it is body copy), but tapping it
   through a text selection is a browser behaviour we drop. */
p a{ -webkit-touch-callout: none; }

/* ---------- 3. press feedback (added on top of the design's own :active rules) ---------- */
button:not(:disabled):active, [data-href]:active, .product-card:active{ transform: scale(.98); }
/* small round controls keep their snappier 6% squeeze (needs the extra type
   selector to outrank the generic rule above) */
button.icon-btn:active, button.add-btn:active, button.cat-chip:active{ transform: scale(.94); }
@media (prefers-reduced-motion: no-preference){
  button, [data-href], .product-card{ transition: transform 90ms ease-out; }
}

/* ---------- 4. scroll behaviour ---------- */
html, body{ scrollbar-width: none; }
::-webkit-scrollbar{ width: 0; height: 0; }
/* keep momentum scrolling inside panes (filter chips, tables, drawers) */
.drawer-nav, .search-panel, .cat-chips, .summary-items{ -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }

/* ---------- 5. iOS: never zoom on focus ---------- */
/* iOS Safari zooms the whole page when a focused field has font-size < 16px,
   and you cannot zoom back out. The old rule lived inside
   `@supports (-webkit-touch-callout: none)`, but recent WebKit no longer reports
   support for that property, so 15.5px fields kept triggering the zoom.
   Fix: forget feature detection and just size every focusable field at 16px.
   `!important` is required because store.css's class rules (15.5px / 12.5px)
   load at the same specificity tier.
   Only text-entry controls need this — checkboxes/radios are skipped so their
   layout is untouched. */
input[type="text"],
input[type="search"],
input[type="email"],
input[type="tel"],
input[type="number"],
input[type="password"],
input[type="url"],
input[type="date"],
input[type="datetime-local"],
input[type="month"],
input[type="time"],
input:not([type]),
textarea,
select{
  font-size: 16px !important;
}

/* ---------- 6. standalone / in-app shell ---------- */
@media (display-mode: standalone){
  html{ background: #fff; }
}
body.in-app{ --sai-top: max(var(--sai-top), 8px); }

/* print sheets must stay 1:1 with the screen design */
@media print{
  body{ padding-left: 0; padding-right: 0; }
  .site-header{ padding-top: 0; }
  button, [data-href]{ transform: none !important; }
}

/* ---------- 7. bottom tab bar (mobile widths; hidden on desktop + print) ---------- */
/* The tab bar is the page's anchor: fixed to the viewport bottom, above page
   content, never scrolling away. Total height is 56px item + 1px hairline
   border + the home-indicator inset, exposed as --tabbar-h so body padding can
   match it exactly (a mismatch of even 1px lets the last row sit under the bar). */
.tabbar{
  position:fixed;left:0;right:0;bottom:0;z-index:50;display:none;
  background:rgba(255,255,255,.94);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  border-top:1px solid var(--line);
  padding-bottom:var(--sai-bottom);padding-left:var(--sai-left);padding-right:var(--sai-right);
  /* iOS/Android: stop the bar being dragged around with the page */
  transform:translateZ(0);
  -webkit-transform:translateZ(0);
  will-change:transform;
}
.tabbar .tb-item{
  flex:1;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  height:56px;border:0;background:none;color:var(--ink-3);font:inherit;font-size:10.5px;font-weight:700;
  letter-spacing:.02em;cursor:pointer;-webkit-tap-highlight-color:transparent
}
.tabbar .tb-item svg{width:22px;height:22px}
.tabbar .tb-item.is-active{color:var(--brand)}
.tabbar .tb-item .tb-badge{
  position:absolute;top:5px;left:calc(50% + 7px);min-width:16px;height:16px;padding:0 4px;border-radius:9px;
  background:var(--brand);color:#fff;font-size:10px;font-weight:800;display:none;place-items:center
}
.tabbar .tb-item .tb-badge.show{display:grid}
/* --tabbar-h accounts for the 1px top border, so content clears the bar
   exactly instead of by 56px against a 57px bar. */
:root{ --tabbar-h: 57px; }
:root{ --tabbar-total: calc(var(--tabbar-h) + var(--sai-bottom)); }
body.has-tabbar{padding-bottom:var(--tabbar-total)}
/* toasts sit above the bar, not behind it */
.toast-wrap{ bottom: calc(22px + var(--tabbar-total)) }
@media (min-width:961px){
  body.has-tabbar{ padding-bottom:0 }
  .toast-wrap{ bottom: calc(22px + var(--sai-bottom)) }
}
@media (max-width:960px){ .tabbar{display:flex} }

/* When the soft keyboard opens, a fixed bottom bar gets pushed up to sit right
   above the keyboard — hovering in the middle of the form. A native app hides
   the tab bar while typing, so do the same: slide it down and stop reserving
   its height. */
body.kb-open .tabbar{
  transform: translateY(110%);
  pointer-events: none;
  transition: transform 160ms var(--ease);
}
body.kb-open{ padding-bottom: 0 !important; }
@media (prefers-reduced-motion: reduce){ body.kb-open .tabbar{ transition: none } }
@media (min-width:961px){ body.has-tabbar{padding-bottom:0} }

/* ---------- 8. page transitions (multi-page origin: leave fade + enter slide) ---------- */
.vm-progress{position:fixed;top:0;left:0;height:2px;width:100%;transform:scaleX(0);transform-origin:0 50%;
  background:var(--brand,#0F2131);z-index:400;opacity:0;transition:transform 240ms ease-out,opacity 200ms ease}
.vm-progress.on{opacity:1;transform:scaleX(.72)}
@keyframes vmEnterFwd{from{opacity:0;transform:translate3d(12%,0,0)}to{opacity:1;transform:none}}
@keyframes vmEnterBack{from{opacity:0;transform:translate3d(-8%,0,0)}to{opacity:1;transform:none}}
@keyframes vmLeaveFade{to{opacity:0}}
html.vm-enter-fwd body{animation:vmEnterFwd 220ms cubic-bezier(.2,.8,.2,1) both}
html.vm-enter-back body{animation:vmEnterBack 200ms cubic-bezier(.2,.8,.2,1) both}
html.vm-leaving body{animation:vmLeaveFade 130ms ease-in both;pointer-events:none}
html.vm-leaving .tabbar{opacity:.6}
@media (prefers-reduced-motion: reduce){
  html.vm-enter-fwd body,html.vm-enter-back body,html.vm-leaving body{animation:none}
  .vm-progress{transition:none}
}

@media print{
  .tabbar{display:none!important}
  body.has-tabbar{padding-bottom:0}
  .vm-progress{display:none}
}

/* ---------- 9. header on scroll ---------- */
.site-header.is-scrolled{
  background:rgba(255,255,255,.985);
  box-shadow:0 6px 18px rgba(11,42,58,.08);
  border-bottom-color:transparent;
}

/* ---------- 10. offline / weak network banner (above the tab bar) ---------- */
.vm-net{
  position:fixed;left:0;right:0;bottom:calc(var(--tabbar-total) + 8px);z-index:320;
  margin:0 auto;max-width:520px;width:calc(100% - 24px);
  background:#7A4E05;color:#fff;border-radius:11px;padding:9px 14px;
  font-size:12.5px;font-weight:700;line-height:1.45;text-align:center;
  box-shadow:0 10px 26px rgba(9,20,32,.18);
  opacity:0;transform:translateY(10px);transition:opacity 200ms ease,transform 200ms ease;
  pointer-events:none
}
.vm-net.on{opacity:1;transform:none}
@media (min-width:961px){ .vm-net{bottom:calc(16px + var(--sai-bottom))} }


@media print{ .vm-net{display:none} }

/* ---------- 11. pull-to-refresh (hand-rolled; the browser's own is off) ---------- */
/* A WebView/browser fires its native pull-to-refresh (a grey spinner + the
   whole page bouncing) which is the loudest "this is a web page" signal left.
   overscroll-behavior kills the browser one; this replaces it with something
   that looks native: a brand mark that fills as you pull and spins on release. */
.vm-pull{
  position:fixed;left:50%;top:0;z-index:35;pointer-events:none;
  display:grid;place-items:center;
  width:44px;height:44px;margin-left:-22px;border-radius:50%;
  background:var(--surface,#fff);
  box-shadow:0 4px 14px rgba(15,33,49,.14);
  opacity:0;transform:translateY(-56px) scale(.8);
  transition:opacity 160ms var(--ease),transform 160ms var(--ease);
}
.vm-pull.on{opacity:1}
.vm-pull__ring{
  position:absolute;inset:0;border-radius:50%;
  background:conic-gradient(var(--brand-3,#14A283) calc(var(--p,0) * 360deg), var(--surface-3,#E4EBF3) 0);
  -webkit-mask:radial-gradient(circle, transparent 13px, #000 14px);
  mask:radial-gradient(circle, transparent 13px, #000 14px);
}
.vm-pull__mark{position:relative;display:grid;place-items:center;color:var(--brand,#0B5A4C);transition:transform 200ms var(--ease)}
.vm-pull__mark svg{width:18px;height:18px}
.vm-pull.busy .vm-pull__mark{animation:vmSpin 700ms linear infinite}
@keyframes vmSpin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){
  .vm-pull{transition:none}
  .vm-pull.busy .vm-pull__mark{animation:none}
}
@media print{ .vm-pull{display:none} }

/* ---------- 12. skeleton / shimmer (first paint, before the API answers) ---------- */
/* The static seed grid paints instantly, so we do not blank it out. What we do
   add is a soft shimmer on poster slots that have not decoded yet, plus a
   one-shot grid fade so the "pop-in" of real images reads as loading, not a
   browser reflow. */
.vm-sk{
  position:relative;overflow:hidden;
  background:linear-gradient(100deg, var(--surface-2,#EDF2F7) 20%, var(--surface-3,#E4EBF3) 38%, var(--surface-2,#EDF2F7) 56%);
  background-size:220% 100%;
  animation:vmShimmer 1.1s ease-in-out infinite;
}
@keyframes vmShimmer{to{background-position:-120% 0}}
.media-tile.vm-sk{padding:0}
.media-tile.vm-sk > *{visibility:hidden}

/* grid enters once, so a lazy image landing does not look like a page jump */
.vm-grid-in{animation:vmGridIn 260ms cubic-bezier(.2,.8,.2,1) both}
@keyframes vmGridIn{from{opacity:.55;transform:translateY(6px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion: reduce){
  .vm-sk{animation:none}
  .vm-grid-in{animation:none}
}
@media print{ .vm-sk{animation:none;background:none} }
.linklike{
  background:none;border:0;padding:0;margin:0;font:inherit;color:var(--brand-2);
  font-weight:700;cursor:pointer;text-decoration:underline;text-underline-offset:2px
}

/* ---------- 7. touch target sizes ---------- */
/* Breadcrumb links sit in running text, so their box is only as tall as the
   line (20px). Fingers need ~44px. This pads them into a proper tap target
   without changing the visual rhythm: negative margin keeps the text where it
   was and the extra height is invisible. */
.crumbs button,
.crumbs a{
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 6px 8px;
  margin: -6px -8px;
  border-radius: 8px;
}
.crumbs button:active,
.crumbs a:active{ background: var(--surface-2); }

/* Inline mailto links inside paragraph copy get the same treatment. */
p a[href^="mailto:"],
.fine-print a[href^="mailto:"]{
  display: inline-block;
  padding: 6px 0;
}

/* Under 400px the breadcrumb's second level is redundant with the page title. */
@media (max-width: 400px){
  .crumbs{ padding-top: 10px; }
}

/* ---------- 8. app-like page surface ---------- */
/* Nothing on the storefront should ever scroll horizontally.
   NEVER put overflow-x:hidden on html: per CSS spec a non-visible overflow-x
   forces overflow-y to compute to `auto`, which turns <html> into its own
   scroll container and stops the document from scrolling at all (the whole
   page freezes — exactly the bug this replaced). Clipping on <body> alone is
   enough: body's overflow-x:hidden propagates to the viewport only when html
   is `visible`, and here it simply clips the overflow without creating a
   nested scroller. */
body{ overflow-x: hidden; }

/* Kill the "flash of unstyled tap target" that browsers draw on a link while
   the press is being registered. */
a, button{ -webkit-tap-highlight-color: transparent; }

/* Text fields must not be spell-checked / auto-corrected like a document
   (iOS otherwise underlines every word and offers a big suggestion bar). */
input[type="text"], input[type="search"], input[type="email"], textarea{
  -webkit-autocapitalize: none;
  autocapitalize: none;
}
input[type="email"], input[type="url"], textarea{ spellcheck: false; }
input[type="tel"], input[type="number"]{ -webkit-text-security: none; }
