/* ============================================================
   DABBA v1.2 — mobile.css : full mobile responsiveness layer
   ============================================================
   Loaded AFTER screens.css (see index.html) so every rule here
   wins the cascade against base/components/screens on small
   viewports. Nothing here should affect desktop (>= 768px)
   unless wrapped in a (min-width:) guard — desktop v1.1 layout
   is stable and must not regress.

   Breakpoint plan:
     < 768px  — phone / small tablet: hamburger nav, bottom-sheet
                overlays, 1-column feed, touch-first sizing.
     < 600px  — true handset: tighten gutters, feed to 1 column.
     <= 414px / <= 375px / <= 320px — micro overrides so no line
                ever clips or overflows on the narrowest devices.

   Accessibility contract (senior, 60+):
     - body/reading text never below 18px
     - every tappable target >= 44 x 44 px
     - horizontal scroll eliminated (clip, not scroll container)
     - page-by-page navigation, no gesture dependence
   ============================================================ */

/* ------------------------------------------------------------
   0. Global overflow + text controls (phone)
   ------------------------------------------------------------
   overflow-x: clip (not hidden) — hidden turns html/body into a
   scroll container, which silently disables position:sticky on
   .topbar/.filter-bar/.wait-card. clip clips without creating a
   scrollport, so sticky chrome keeps working. */
@media (max-width: 767px) {
  html, body { overflow-x: clip; }
  body {
    /* keep any stray full-width element from widening the page */
    width: 100%;
    max-width: 100%;
  }
  /* never allow text to push a flex/grid row wider than the screen */
  p, h1, h2, h3, h4, li, dd, dt, .caption, .body, .body-sm, .h3 {
    overflow-wrap: break-word;
  }
  /* keep sticky app chrome working regardless of browser UI state */
  .app-shell { min-height: 100dvh; }
}

/* ------------------------------------------------------------
   1. Typography — maintain 18px body floor, comfortable scale
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  body { font-size: 1.125rem; }            /* 18px floor reasserted */
  /* Meta/captions stay ≥ 15px so labels remain readable at arm's length */
  .caption, .eyebrow { font-size: 0.875rem; letter-spacing: 0.03em; }
  .body-sm { font-size: 1rem; }            /* 16px meta (allowed) */
  /* Slightly larger tap-friendly numerals in price/total rows */
  .num, .countdown, .qty-value { font-size: 1.125rem; }
  /* Headings scale with the device but never below their semantic floor */
  .display { font-size: clamp(1.9rem, 6vw, 2.4rem); }
  .h1      { font-size: 1.6rem; }
  .h2      { font-size: 1.3rem; }
  .h3      { font-size: 1.2rem; }
  .wordmark-text { font-size: 1.35rem; }
}

/* ------------------------------------------------------------
   2. Safe-area insets (notched / gesture phones)
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  /* Top bar clears the notch in landscape/edge-to-edge */
  .topbar { padding-top: env(safe-area-inset-top); }
  .topbar-inner { min-height: 56px; }
  /* Bottom sheets and fixed bars clear the home indicator */
  .overlay-backdrop { padding-bottom: env(safe-area-inset-bottom); }
  .nav-drawer { padding-bottom: env(safe-area-inset-bottom); }
}

/* ------------------------------------------------------------
   3. Top bar + hamburger nav (< 768px)
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .topbar-inner {
    gap: var(--space-2);
    padding-left: calc(var(--gutter-mobile) + env(safe-area-inset-left));
    padding-right: calc(var(--gutter-mobile) + env(safe-area-inset-right));
  }
  .wordmark { gap: var(--space-2); }
  .wordmark-text { white-space: nowrap; }

  /* Desktop inline nav links are hidden; they live in the drawer on phones */
  .topnav { display: none; }

  /* mode toggle is relocated into the drawer to free the bar for
     wordmark + account + menu (see router.js renderModeToggle) */
  #topbar-actions .mode-toggle { display: none; }

  /* Hamburger button — 44px target, masculine flat icon */
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--min-touch);
    height: var(--min-touch);
    flex: none;
    border: 1px solid var(--cream-200);
    border-radius: var(--radius-input);
    background: var(--cream-50);
    color: var(--ink-900);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast);
    -webkit-tap-highlight-color: transparent;
  }
  .nav-toggle:hover { background: var(--cream-200); }
  .nav-toggle:active { background: var(--cream-300); }
  .nav-toggle[aria-expanded="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-strong); }
  .nav-toggle svg { width: 22px; height: 22px; display: block; }
  /* hamburger <-> X icon swap, driven by aria-expanded (state cue not colour) */
  .nav-toggle .icon-close { display: none; }
  .nav-toggle[aria-expanded="true"] .icon-menu { display: none; }
  .nav-toggle[aria-expanded="true"] .icon-close { display: block; }
  /* account chip: 40 -> 44 target on touch */
  .account-avatar { width: var(--min-touch); height: var(--min-touch); font-size: 1rem; }
}

/* ---- The mobile drawer (rendered links + mode control) ---- */
.nav-scrim,
.nav-drawer { display: none; }
@media (max-width: 767px) {
  .nav-scrim {
    display: block;
    position: fixed;
    inset: 60px 0 0 0;
    z-index: 24;                       /* below drawer(30), above content */
    background: rgba(28, 25, 23, 0.36);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur-base) var(--ease-out), visibility var(--dur-base);
  }
  .nav-scrim.open { opacity: 1; visibility: visible; }
  .nav-drawer {
    display: block;
    position: fixed;
    top: 60px; left: 0; right: 0;
    z-index: 30;                       /* above scrim + sticky, below overlay */
    background: var(--cream-100);
    border-bottom: 1px solid var(--cream-200);
    box-shadow: var(--shadow-lg);
    max-height: calc(100dvh - 60px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-4) var(--gutter-mobile) calc(var(--space-5) + env(safe-area-inset-bottom));
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out), visibility var(--dur-base);
    -webkit-overflow-scrolling: touch;
  }
  .nav-drawer.open { transform: translateY(0); opacity: 1; visibility: visible; }

  /* Mode control sits at the top of the drawer as a big segmented bar */
  .nav-drawer-actions { margin-bottom: var(--space-4); }
  .nav-drawer .mode-toggle { display: flex; width: 100%; }
  .nav-drawer .mode-toggle-btn {
    flex: 1 1 0;
    min-height: 48px;                  /* ≥ 44 target */
    font-size: 1rem;
    padding: 0 var(--space-3);
  }
  .nav-drawer-label {
    font-size: var(--fs-caption);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-500);
    margin: 0 0 var(--space-2);
  }

  /* Nav links: full-width stacked rows, 48px tall, 18px text */
  .nav-drawer-links { display: flex; flex-direction: column; gap: var(--space-1); }
  .nav-drawer-links a {
    display: flex;
    align-items: center;
    min-height: 48px;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-input);
    color: var(--ink-900);
    font-size: 1.125rem;               /* 18px */
    font-weight: 500;
    text-decoration: none;
  }
  .nav-drawer-links a:hover { background: var(--cream-200); text-decoration: none; }
  .nav-drawer-links a.active { background: var(--accent-soft); color: var(--accent-strong); font-weight: 600; }
  .nav-drawer-links a:focus-visible { outline: none; box-shadow: var(--ring-focus); }
}

/* ------------------------------------------------------------
   4. Overlays -> bottom sheets (< 768px)
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .overlay-backdrop { align-items: flex-end; }
  .overlay-panel {
    width: 100%;
    max-width: 100%;
    max-height: 88dvh;
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  /* Safety sheets that gate purchases get a little more headroom */
  .allergy-sheet { border-radius: var(--radius-sheet) var(--radius-sheet) 0 0; }
  .allergy-sheet-band { border-radius: var(--radius-sheet) var(--radius-sheet) 0 0; }
}

/* ------------------------------------------------------------
   5. Feed — guaranteed no overflow, comfortable single column
   ------------------------------------------------------------ */
@media (max-width: 599px) {
  .feed-grid { grid-template-columns: 1fr; }
}
@media (max-width: 767px) {
  .page { padding-bottom: calc(var(--space-16) + env(safe-area-inset-bottom)); }
  /* batch card price line must never clip on narrow screens */
  .batchcard-foot { flex-wrap: wrap; row-gap: var(--space-2); }
  .batchcard-price { white-space: normal; }
  .batchcard-price > .num { white-space: normal; overflow: visible; text-overflow: clip; }
  .batchcard-incentive { flex-basis: 100%; text-align: left; }
}

/* ------------------------------------------------------------
   6. Filter bar — sticky, no overlap, chips scroll + snap
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .filter-bar {
    /* keep the sticky rail tight under the 60px topbar; scroll-snap so a
       finger-flick lands chips cleanly (never half-cut) */
    top: 60px;
    margin-bottom: var(--space-4);
  }
  .filter-row {
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    margin: 0 calc(-1 * var(--gutter-mobile));
    padding-left: var(--gutter-mobile);
    padding-right: var(--gutter-mobile);
  }
  .filter-chip { scroll-snap-align: start; flex: none; }
  .filter-clear { min-height: var(--min-touch); display: inline-flex; align-items: center; }
  /* distance between sticky filter bar and following hero/content */
  .feed-section + .feed-section { margin-top: var(--space-8); }
}

/* ------------------------------------------------------------
   7. Carousel — allow vertical pan, bigger thumb targets
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .carousel { touch-action: pan-y; }        /* swipe horizontally, scroll vertically */
  .carousel-thumb {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 68px;
    min-height: 48px;                       /* ≥ 44 touch target */
    border-radius: var(--radius-input);
  }
  .carousel-thumb img { width: 60px; height: 44px; }
  .carousel-strip { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* ------------------------------------------------------------
   8. Sticky CTA — never hidden behind home indicator, room to breathe
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .sticky-cta {
    padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom));
  }
  /* content above the fixed CTA needs clearance so the last card is fully
     readable before the bar (page already adds space-16 at <768) */
  .batch-detail { padding-bottom: calc(var(--space-8) + env(safe-area-inset-bottom)); }
}

/* ------------------------------------------------------------
   9. Touch-target floor — anything tappable ≥ 44px (phone)
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .btn { min-height: var(--min-touch); }
  .btn-lg { min-height: 52px; }
  .mode-toggle-btn { min-height: var(--min-touch); }
  /* chef-strip rows and kitchen photos are tap nav affordances */
  .chefstrip { min-height: var(--min-touch); }
  .chefstrip-sm { min-height: var(--min-touch); }
  /* dish / chef / list selectable cards keep a ≥44px hit area */
  .dish-opt, .spice-opt, .chip-toggle, .fulfilment-option { min-height: var(--min-touch); }
  .chip-toggle, .allergen-chip, .filter-chip { min-height: var(--min-touch); }
  .input { min-height: var(--min-touch); }
  .qty-btn { min-width: var(--min-touch); min-height: var(--min-touch); }
  .allergen-chip.interactive, .filter-clear, .batchcard-track { min-height: var(--min-touch); }
  .carousel-thumb { min-height: 48px; }
  /* links that act as buttons (e.g. browse chef rows) get a floor */
  .batchcard-list-row, .batchcard-mini, .kitchen-batch-row, .login-chef-row { min-height: var(--min-touch); }
}

/* ------------------------------------------------------------
   10. Horizontal-overflow shields for specific layouts
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  /* price ladder: let cells compress instead of widening the page */
  .priceladder { overflow-x: auto; }
  /* dish meta line never forces width with long cuisine tags */
  .dish-meta { flex-wrap: wrap; }
  /* review/status copy wraps */
  .status-label, .review-body, .fillmeter-tiplabel { overflow-wrap: anywhere; }
  /* chef strips and dish tiles shrink, never overflow */
  .chefstrip, .dish-tile, .mini-list, .result-card, .chef-card { min-width: 0; }
  /* two-part action rows wrap (orders, past cards) */
  .order-actions, .past-card-main { flex-wrap: wrap; }
  /* stats rail that was inline-flex wraps to two clean lines */
  .profile-stats { flex-wrap: wrap; row-gap: var(--space-4); }
}

/* ------------------------------------------------------------
   11. Layout niceties for narrow handsets (<= 414)
   ------------------------------------------------------------ */
@media (max-width: 414px) {
  .page { padding-left: var(--gutter-mobile); padding-right: var(--gutter-mobile); }
  .kitchen-strip { gap: var(--space-2); }
  .preview-batchcard { max-width: 100%; }
  /* full-bleed bottom sheet photos */
  .lightbox, .share-sheet { padding: var(--space-4); }
  .sharecard { max-width: 100%; }
  .sharecard-incentive { font-size: 1.6rem; }
  .profile-hero-avatar { width: 76px; height: 76px; }
}

/* ------------------------------------------------------------
   11b. Senior text floor — finance/profile meta (audit §3B)
   mobile.css never lets money reads, option labels or chef-strip
   meta fall below the reading floor. This sits BEFORE the
   <=375/<=320 micro blocks so those narrower overrides still win.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  /* an empty sticky CTA must never leave a stray strip (router also clears it) */
  #sticky-cta:empty { display: none !important; }

  /* chef-strip meta + badges readable at arm's length (were 12.8 / 10.9px) */
  .chefstrip-meta { font-size: 0.9375rem; }   /* 15px min */
  .chefstrip-badge, .chefstrip-cert { font-size: 0.72rem; line-height: 1.45; padding: 2px 9px; } /* ~11.5px floor */
  .chefstrip-sm .chefstrip-meta { font-size: 0.9375rem; }

  /* price ladder — the tightest money read in the app; never below 16px
     (15px absolute floor enforced by the <=375 rule in section 12). */
  .priceladder-cell-price { font-size: 1rem; }
  .priceladder-cell-threshold { font-size: 0.78rem; }
  .priceladder-caption { font-size: 1rem; }

  /* fulfilment option rows — labels climb with their 44px+ hit area */
  .fulfilment-name { font-size: 1rem; }
  .fulfilment-detail { font-size: 0.9375rem; }

  /* composer chips — text must grow with the enlarged target */
  .chip-toggle, .spice-opt { font-size: 0.9375rem; }
  .dish-opt { font-size: 1rem; }

  /* dashboard "YOU KEEP" earnings label */
  .kbr-earn-label { font-size: 0.8125rem; }
}

/* ------------------------------------------------------------
   12. Micro overrides for the narrowest devices (<= 375 / 320)
   ------------------------------------------------------------ */
@media (max-width: 375px) {
  .wordmark-text { font-size: 1.25rem; }
  .sticky-inner { gap: var(--space-2); }
  .sticky-price { font-size: 1.1rem; }
  /* price ladder caption and calc cells stay legible, never truncate */
  .calc-grid { gap: var(--space-2); }
  /* money abs floor — audit §3B: the old 0.85rem (13.6px) read was too small.
     Kept at 0.9375rem (15px) ONLY as the narrowest-device floor; the general
     <=767 rule above holds it at 1rem (16px) from 376–767px. */
  .priceladder-cell-price { font-size: 0.9375rem; }
}
@media (max-width: 320px) {
  .topbar-inner { padding-left: var(--space-3); padding-right: var(--space-3); }
  .batchcard-incentive { flex-basis: 100%; }
  .mode-toggle-btn { padding: 0 var(--space-2); font-size: 0.95rem; }
  /* ensure the compact top bar still fits: wordmark + account + menu
     (targets stay ≥ 44px — the 44px touch floor is never compromised) */
  .wordmark-text { font-size: 1.15rem; }
}

/* ------------------------------------------------------------
   13. Carousel stage + prev/next arrows (< 768px)
   batchDetail.js adds the arrow buttons only when a batch has
   more than one photo, so a senior reader has a discoverable,
   non-gesture path to flip photos (audit §4 / §6.2).
   ------------------------------------------------------------ */
/* Hidden on desktop (>= 768px) where the thumbnail tabs already serve; the
   arrows are a mobile affordance for a senior reader. batchDetail.js creates
   them whenever a batch has >1 photo regardless of width, so CSS owns visibility. */
.carousel-arrow { display: none; }
@media (max-width: 767px) {
  .carousel-stage { position: relative; }
  .carousel-arrow {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: var(--min-touch); height: var(--min-touch);      /* 44px target */
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--cream-200); border-radius: 50%;
    background: rgba(253, 251, 247, 0.94); color: var(--ink-900);
    box-shadow: var(--shadow-md); cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .carousel-arrow.carousel-prev { left: var(--space-2); }
  .carousel-arrow.carousel-next { right: var(--space-2); }
  .carousel-arrow:hover { background: var(--cream-200); }
  .carousel-arrow:active { background: var(--cream-300); }
  .carousel-arrow-glyph { font-size: 1.7rem; line-height: 1; font-family: var(--font-body); margin-top: -2px; }
  /* room between the hero art and the thumbnail rail */
  .carousel-strip { padding-top: var(--space-2); }
}

/* ------------------------------------------------------------
   14. Pull-to-refresh reveal strip (< 768px)
   Grows under the top bar while a user pulls down on the feed /
   Orders (see app/pullrefresh.js). Installed only on /meals and
   /orders, and never under prefers-reduced-motion. Height is set
   inline from JS; this only styles its contents.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .ptr-indicator {
    position: fixed; top: 60px; left: 0; right: 0; z-index: var(--z-sticky);
    height: 0; overflow: hidden;
    background: var(--cream-100);
    display: flex; align-items: center; justify-content: center;
    border-bottom: 1px solid var(--cream-200);
  }
  .ptr-label { font-size: 0.9375rem; font-weight: 600; color: var(--accent-strong); white-space: nowrap; }
  /* chevron pointing up = "release" cue; drawn with borders (no emoji) */
  .ptr-arrow {
    flex: none; width: 10px; height: 10px; margin-right: var(--space-2); margin-top: -2px;
    border-right: 2px solid var(--accent-strong); border-bottom: 2px solid var(--accent-strong);
    transform: rotate(225deg);
  }
  .ptr-spin {
    flex: none; width: 16px; height: 16px; margin-right: var(--space-2);
    display: none; border: 2px solid var(--cream-300); border-top-color: var(--accent-strong);
    border-radius: 50%;
  }
  .ptr-indicator.refreshing .ptr-arrow { display: none; }
  .ptr-indicator.refreshing .ptr-spin { display: inline-block; animation: ptrspin 0.8s linear infinite; }
}
@keyframes ptrspin { to { transform: rotate(360deg); } }
