/* ─── SERVI Mobile Base — touch behavior + viewport tokens ──────────────────── */
/*                                                                              */
/* BEHAVIORAL ONLY. This file deliberately contains no colors, no fonts, no      */
/* spacing and no component styling, so it is safe to load on the standalone     */
/* dark-theme payment pages (pay/book/success/save/link-expired) which must not  */
/* be restyled. Visual mobile work belongs in shared-styles.css or the page.     */
/*                                                                              */
/* Requires `viewport-fit=cover` in the page's viewport meta, otherwise every    */
/* env(safe-area-inset-*) below resolves to 0.                                   */

:root {
  /* ── Safe-area insets (notch / Dynamic Island / iOS home indicator) ──────── */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);

  /* ── Bottom chrome height ────────────────────────────────────────────────── */
  /* Both default to 0, so bottom-anchored math is correct on pages that have no */
  /* bottom chrome at all. Never hard-code a bar height — read these instead.    */
  /*                                                                            */
  /*   --servi-bottom-chrome-h  height of whatever fixed bar owns the bottom     */
  /*                            edge, EXCLUDING the safe-area inset. Set by      */
  /*                            mobile-tabbar.js, or by a page that pins its own */
  /*                            CTA there (service.html). Exactly one owner per  */
  /*                            page — the tab bar is absent where a page CTA is.*/
  /*   --mobile-tabbar-h        total space the tab bar occupies, INCLUDING the  */
  /*                            inset. Only the tab bar sets this.               */
  /*                                                                            */
  /* Pad a scrolling page with the total (it must clear everything). Offset a    */
  /* *fixed* floating element with the chrome height plus --safe-b, so the inset */
  /* is added once rather than twice.                                            */
  --servi-bottom-chrome-h: 0px;
  --mobile-tabbar-h: 0px;

  /* ── One z-index scale for fixed/floating chrome ─────────────────────────── */
  /* Ends the pre-existing collision where the service.html booking CTA (100)   */
  /* sat underneath the active-order dock (120) on phones.                      */
  --z-tabbar: 90;      /* bottom tab bar — lowest, page chrome              */
  --z-cta: 100;        /* per-page sticky CTA (e.g. .svc-mobile-bar)        */
  --z-dock: 120;       /* floating active-order dock                        */
  --z-nav: 900;        /* site header                                       */
  --z-sheet: 1000;     /* modals / bottom sheets / drawers                  */
  --z-toast: 10002;    /* transient toasts — always on top                  */
}

/* ─── Touch behavior ──────────────────────────────────────────────────────── */
html {
  /* Stop iOS from re-flowing text after a rotate, without disabling pinch-zoom. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  /* Kills the grey/blue flash iOS and Android paint over every tapped element. */
  -webkit-tap-highlight-color: transparent;
  /* Stops a scroll gesture that reaches the end of the page from chaining into
     the browser's pull-to-refresh or overscroll bounce. */
  overscroll-behavior-y: contain;
}

/* `manipulation` opts out of double-tap-to-zoom, which is what causes the
   ~300ms delay between tapping a control and it responding. Pinch-zoom on the
   page as a whole is unaffected, so this does not hurt accessibility. */
button,
[role="button"],
a,
label,
summary,
input[type="checkbox"],
input[type="radio"],
input[type="submit"],
input[type="button"],
select {
  touch-action: manipulation;
}

/* Long-pressing a control shouldn't start a text selection or pop the
   iOS callout menu. Text content is untouched so copying still works. */
button,
[role="button"],
input[type="submit"],
input[type="button"] {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* ─── Press feedback ──────────────────────────────────────────────────────── */
/* Touch has no hover, so without an :active state a tap produces no
   acknowledgement until the next screen paints — the single biggest reason a
   web app "feels like a website". Transient interaction state only; it changes
   nothing about how a control looks at rest.
   Excluded: anything wrapping a third-party iframe (Stripe Elements), where a
   transform would create a containing block and can blur or mis-hit the frame. */
@media (hover: none) {
  button:active,
  [role="button"]:active,
  a.btn-primary:active,
  a.btn-secondary:active,
  a.btn-partner:active,
  input[type="submit"]:active,
  input[type="button"]:active {
    transform: scale(0.97);
  }

  /* Stripe Elements and any other embedded frame must never be transformed. */
  .card-control:active,
  .StripeElement:active,
  .__PrivateStripeElement:active,
  :has(> iframe):active {
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  button:active,
  [role="button"]:active,
  a.btn-primary:active,
  a.btn-secondary:active,
  a.btn-partner:active,
  input[type="submit"]:active,
  input[type="button"]:active {
    transform: none;
  }
}

/* ─── Scroll containers ───────────────────────────────────────────────────── */
/* Momentum scrolling inside modals/sheets/drawers, and no scroll chaining out
   of them into the page behind. Opt in by adding `data-scroll-contain`. */
[data-scroll-contain] {
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

/* ─── Tap-target floor ───────────────────────────────────────────────────── */
/* 44x44 CSS px is the documented minimum on both platforms. Applied only on
   touch pointers so desktop density is unchanged, and only to controls that
   opt in via `data-tap-target` — a blanket rule would break the many small
   inline icon buttons that are already visually correct inside dense rows. */
@media (pointer: coarse) {
  [data-tap-target] {
    min-width: 44px;
    min-height: 44px;
  }

  /* iOS zooms the entire page when a focused text field is under 16px, and the
     zoom is not undone on blur — the page just stays scaled and off-centre. This
     is the one input rule broad enough to belong here rather than per-page.
     `select` is excluded: it opens a native picker and never triggers the zoom,
     so widening it would change layout for no functional gain. */
  input:not([type]),
  input[type="text"],
  input[type="tel"],
  input[type="email"],
  input[type="number"],
  input[type="password"],
  input[type="search"],
  input[type="url"],
  input[type="date"],
  input[type="time"],
  textarea {
    font-size: 16px;
  }

  /* Checkboxes and radios render at ~13-15px by default, which is a demanding
     target for a thumb even when a <label for> widens the hit area. */
  input[type="checkbox"],
  input[type="radio"] {
    min-width: 20px;
    min-height: 20px;
  }
}
