/* ============================================================
   assets/mobile.css
   Loads AFTER assets/tailwind-generated.css so single-class rules
   here win against equal-specificity Tailwind utilities.
   Do not merge this back into app.css — app.css is linked BEFORE
   the Tailwind build, where these rules lose the cascade.
   ============================================================ */

/* ============================================================
   MISSING UTILITIES
   Classes used in markup that the prebuilt Tailwind subset
   (assets/tailwind-generated.css) does not emit.
   ============================================================ */
.ml-1{margin-left:.25rem}
.align-middle{vertical-align:middle}
.inline{display:inline}
.w-4\.5{width:1.125rem}
.h-4\.5{height:1.125rem}
.bg-white\/8{background-color:rgb(255 255 255 / .08)}
.hover\:bg-white\/12:hover{background-color:rgb(255 255 255 / .12)}
.bg-\[hsl\(var\(--accent-orange\)\)\]\/8{background-color:hsl(var(--accent-orange) / .08)}
.hover\:shadow-soft-lg:hover{box-shadow:0 10px 40px -4px rgba(0,0,0,.06)}
.shadow-\[0_12px_32px_-14px_rgba\(249\,58\,7\,0\.4\)\]{box-shadow:0 12px 32px -14px rgba(249,58,7,.4)}
.shadow-\[0_20px_50px_-20px_rgba\(249\,58\,7\,0\.35\)\]{box-shadow:0 20px 50px -20px rgba(249,58,7,.35)}
.hover\:shadow-\[0_8px_24px_-4px_rgba\(249\,58\,7\,0\.4\)\]:hover{box-shadow:0 8px 24px -4px rgba(249,58,7,.4)}

/* ============================================================
   MOBILE FIXES
   ============================================================ */
body{overflow-wrap:break-word}
a[href^="mailto:"],a[href^="tel:"]{overflow-wrap:anywhere}

@media (max-width:639px){
  /* Home: app cards grow with their content instead of clipping the
     mock UI when titles wrap at narrow widths. Flex stretch keeps
     every card the same height. */
  [data-carousel-track] > a{height:auto;min-height:480px}

  /* Home: "Trusted by store owners" mock — text + chart stack
     instead of squeezing into a 92px column. */
  .trust-card{padding:1.75rem}
  .trust-mock-split{flex-direction:column;align-items:flex-start;gap:1rem}
  .trust-mock-split > div{width:100%}
  .trust-mock-split > div + div{justify-content:flex-start}

  /* Afterpay: flow diagram nodes — tighten chrome and let the
     status labels wrap instead of being cut off. */
  .ap-node{gap:.7rem;padding:.7rem}
  .ap-node .ap-icon{width:2.5rem;height:2.5rem}
  .ap-node .ap-label{font-size:.8125rem;line-height:1.25;white-space:normal}
  .ap-node .ap-badge{font-size:.625rem;padding:.2rem .4rem;gap:.25rem}
  .ap-node .ap-badge svg{width:.75rem;height:.75rem}

  /* Contact: long support address must not push the page sideways.
     The <wbr> after the @ is its only break point, so it splits
     "appsupport@ / snapperapps.com" instead of mid-word. */
  .contact-email{font-size:1rem;overflow-wrap:normal;word-break:normal}
}

/* Very narrow phones (320–359px): the Afterpay flow nodes drop their
   status badge onto a second row so the label keeps a readable column. */
@media (max-width:359px){
  .ap-node{flex-wrap:wrap;row-gap:.4rem}
  .ap-node > .flex-1{flex:1 1 calc(100% - 3.2rem)}
  .ap-node > .shrink-0:last-child{margin-left:3.2rem}
}

/* Footer nav links are 24px tall on mobile — pad them out to a
   comfortable touch target without changing the visual rhythm. */
@media (max-width:639px){
  footer nav{gap:0}
  footer nav a{min-height:44px;display:flex;align-items:center}
}

/* Narrow phones: the 16:9 walkthrough placeholder is shorter than its
   centered play-button stack, which clipped top and bottom. Let the
   frame grow to its content instead of enforcing the ratio. */
/* Phones: the 16:9 walkthrough placeholder is shorter than its centered
   play-button stack at narrow widths, which clipped top and bottom.
   Below 390px let the frame grow to its content instead. */
@media (max-width:389px){
  .video-frame.aspect-video{aspect-ratio:auto;padding:1.75rem 0}
}

/* ============================================================
   CONTACT CARDS
   The icon + p-8 padding leave the address a ~115px column on a
   320px screen, so it fragments mid-word. Stack the card on phones
   and give the address the full width.
   ============================================================ */
@media (max-width:479px){
  .contact-card{flex-direction:column;gap:1rem;padding:1.5rem}
  .contact-card > div:last-child{width:100%}
}

/* ============================================================
   MOBILE RESPONSIVE SYSTEM
   Site-wide density, rhythm, type and touch-target rules for
   phones. These are deliberately utility-level: the pages are
   built from Tailwind classes, and this stylesheet loads after
   the Tailwind build, so re-declaring a utility inside a media
   query retunes it for small screens only. Desktop is untouched.
   ============================================================ */
@media (max-width:639px){
  /* Section rhythm — 60px bands are too tall on a phone. */
  :root{--section-spacing-mobile:48px}

  /* Header — shorter bar, gutters aligned with section content. */
  header .h-20{height:64px}
  header .max-w-7xl,footer .max-w-7xl{padding-left:1.5rem;padding-right:1.5rem}

  /* Card padding — 28-40px of chrome leaves too little content width. */
  .p-8{padding:1.25rem}
  .p-7,.p-10{padding:1.5rem}
  .px-7{padding-left:1.25rem;padding-right:1.25rem}
  .px-8,.px-10{padding-left:1.5rem;padding-right:1.5rem}

  /* Stacked grids don't need 40-64px between rows. */
  .gap-10,.gap-12,.gap-16{row-gap:2rem}

  /* Feature-card body copy: 12px is below comfortable reading size. */
  .text-xs.leading-relaxed{font-size:.875rem;line-height:1.6}

  /* Touch targets — 44px minimum for anything tapped. */
  button[data-menu-open],button[data-menu-close]{min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
  footer a.w-10.h-10{width:44px;height:44px}
  a.w-8.h-8{width:40px;height:40px}
  [data-filter-tabs] button,[data-resource-filters] button{min-height:44px}
  [data-carousel-prev],[data-carousel-next]{min-width:44px;min-height:44px}

  /* Breadcrumb / inline content links — widen the hit area vertically
     without moving the text or breaking the single-line row. */
  nav[aria-label="Breadcrumb"] a,nav[aria-label="Breadcrumb"] + * a[href="/"]{display:inline-block;padding:.45rem 0}
  .contact-card a[href^="mailto:"],.contact-card a[href^="tel:"]{display:inline-block;padding:.4rem 0}
}

/* Small phones (≤399px): trim the next padding step down too. */
@media (max-width:399px){
  .p-6{padding:1rem}
  .px-6{padding-left:1rem;padding-right:1rem}
}

/* ============================================================
   MULTI STORE SYNC — dashboard activity log row overflow
   The page's own inline styles already hide the message column and
   compact the grid below 900px (a deliberate content decision — the
   message column carries the least essential info of the five, so we
   leave that hidden). But even without it the row still didn't fit:
   `grid-template-columns: auto 66px 92px 1fr 84px` gives the route
   column (e.g. "AU Flagship → UK Store") no `min-width`, and a grid
   track's implicit minimum is its content's min-content size, not 0 —
   so unbreakable route text pushed the whole row 22px past the card,
   silently absorbed by the card's rounded clipping.

   FIRST FIX (superseded): adding min-width:0 alone stopped the overflow,
   but the three fixed-px columns (time/module/trigger) held their width
   and squeezed the 1fr route track down to almost nothing — route text
   still had nowhere to wrap except one character per line ("A / U / F /
   l / a / g..."), which reads far worse than the clipped overflow did.

   ACTUAL FIX: reflow the row onto two lines instead of shrinking it to
   fit one. icon/time/module/trigger keep row 1; route — the one column
   with genuinely variable-length content — gets its own full-width row
   2, where it has real room to wrap on word boundaries. Cell order is
   fixed (icon, time, module, route, trigger, message) and every cell
   shares the generic .dash-log-cell class rather than a distinguishing
   one, so cells are targeted by position via nth-child. The header
   legend row (.hidden.md\:grid, visible 768-899px) uses the same 6-cell
   order, so this rule covers both without touching either's HTML.
   ============================================================ */
@media (max-width:899px){
  .dash-log-row{
    grid-template-columns:auto 52px 1fr auto;
    grid-template-areas:
      "icon time module trigger"
      "route route route route";
    row-gap:.35rem;
    column-gap:.5rem;
  }
  .dash-log-row > *:nth-child(1){grid-area:icon}
  .dash-log-row > *:nth-child(2){grid-area:time}
  .dash-log-row > *:nth-child(3){grid-area:module}
  .dash-log-row > *:nth-child(4){grid-area:route}
  .dash-log-row > *:nth-child(5){grid-area:trigger}
  .dash-log-row > *{min-width:0}
}

/* ============================================================
   HOME — "Connecting your tools" comparison pair
   Two flex-1 stat cards ("Typical integration / 2 weeks" and
   "With Snapper Apps / 10 min" + a "No code" badge) sat side by side.
   Flex items default to min-width:auto, so neither could shrink below
   its content: the row measured 313px inside a 283px box and the right
   card, badge and all, spilled outside the rounded panel. Roughly 120px
   per column is not enough for 30px numerals plus a badge, so stack them
   — each then gets the full width.

   Note the range: this is worse at tablet than on a phone. From 768px the
   parent grid goes two-up (md:grid-cols-2), so the card holding this pair
   is narrower there than at 375px — measured 49px of overflow at 768 vs
   30px at 375. The stack therefore has to run all the way to the lg
   breakpoint, where the column is finally wide enough for a row again.
   ============================================================ */
@media (max-width:1023px){
  .mt-auto.flex.gap-4{flex-direction:column}
  .mt-auto.flex.gap-4 > .flex-1{min-width:0}
}

/* ============================================================
   TOUCH TARGETS — TABLET RANGE
   The rules above stop at 639px, but the site keeps its mobile
   hamburger nav all the way to the lg breakpoint (1024px). That
   left every touch target between 640-1023px — i.e. every tablet,
   all of them touch devices — at its untuned desktop size.
   This block restates them for the whole below-lg range so the
   layout that ships a touch nav also ships touch-sized controls.
   Desktop (>=1024px) is untouched.
   ============================================================ */
@media (max-width:1023px){
  /* Brand lockup in header, mobile drawer and footer: the 40px mark
     was the whole hit area. */
  header a.flex.items-center.gap-3,
  footer a.flex.items-center.gap-3{min-height:44px}

  /* Drawer open/close. */
  button[data-menu-open],button[data-menu-close]{
    min-width:44px;min-height:44px;
    display:inline-flex;align-items:center;justify-content:center;
  }

  /* Any nav link — footer columns, breadcrumbs, in-page section navs.
     inline-flex keeps them on their existing row; only the hit area grows. */
  nav a{min-height:44px;display:inline-flex;align-items:center}
  footer nav{gap:0}

  /* Circular icon links: footer social (40px) and article share (32px). */
  footer a.w-10.h-10{width:44px;height:44px}
  a.w-8.h-8{width:44px;height:44px}

  /* Filter chips and carousel arrows. Multi Store Sync's 14-module grid
     uses its own [data-modpill] buttons (not [data-filter-tabs]) and was
     missed by the rule below — 37px tall. */
  [data-filter-tabs] button,[data-resource-filters] button,.modpill{min-height:44px}
  [data-carousel-prev],[data-carousel-next]{min-width:44px;min-height:44px}

  /* Multi Store Sync interactive demos: topology module chips, the rule-
     builder chips ("Price", "Inventory", etc.), and the sync button were
     34/34/42px.
     .topo-remove is deliberately NOT resized here — it used to be, but a
     visible 32x32 box (vs. its original ~22px) grew tall enough to overlap
     the "DESTINATION"/"SOURCE" badge label sitting right below it. It
     already gets a correct invisible 44x44 ::after hit-area further down,
     matching every other small demo control — that's the right fix, not
     enlarging the visible button. */
  .topo-chip,[data-rule-chip]{min-height:44px}
  .topo-sync{min-height:44px}

  /* .topo-remove ("x" to remove a destination store) is opacity:0 by
     default and only revealed via `.topo-node:hover` or the page's own
     `@media (pointer: coarse)` check — but real-device testing showed
     that check doesn't reliably detect touch on every phone/browser
     (hybrid devices, some Android WebViews), leaving the button
     permanently invisible and untappable there — hover isn't a real
     input on touch. Below the same lg breakpoint every other touch
     target on this page is tuned for, force it visible unconditionally
     instead of trusting pointer-type detection. This file loads after
     the page's own inline <style>, so it wins at equal specificity
     without needing !important. Desktop (>=1024px) keeps the original
     hover-to-reveal behavior untouched. */
  .topo-remove{opacity:1}

  /* Contact cards: mail/phone links sit on their own row.
     These are inline anchors, and min-height does nothing on an inline
     box — the display change is what actually grows the hit area. */
  .contact-card a[href^="mailto:"],.contact-card a[href^="tel:"]{
    display:inline-flex;align-items:center;min-height:44px;
  }

  /* Standalone CTA / section-nav links that sit outside a <nav>:
     "View app" on the apps grid, and the in-page section nav on the
     product pages. Both were 20px tall. */
  a.flex.items-center.gap-1,
  a.text-sm.font-medium.text-slate-500{
    display:inline-flex;align-items:center;min-height:44px;
  }
}

/* ============================================================
   SMALL DEMO CONTROLS — HIT AREA WITHOUT RESIZING
   The product pages embed mock dashboards whose controls are
   deliberately small: 24px schedule switches, 32px colour swatches,
   the "x" on a sync destination, badge pills. Scaling them up would
   wreck the mock they belong to, so instead each gets a transparent
   pseudo-element that extends the pressable area to ~44px. The control
   looks identical; only the touch region grows.

   NOTE — .sched-toggle is handled separately below, NOT in this group.
   It already uses ::after for its own knob (multi-store-sync.html:
   `.sched-toggle::after{top:2px;left:2px;width:1.1rem;height:1.1rem;
   background:#fff;...}`, slid via `.sched-on::after{transform:
   translateX(1.25rem)}`). A first pass added .sched-toggle to this same
   ::after rule — same pseudo-element, so instead of adding an overlay
   it partially overwrote the knob's own styling (width/height/position,
   which only the base rule declares, so the later mobile.css rule won
   on source order) while the higher-specificity `.sched-on::after`
   selector still won the slide `transform`. Net effect: the knob became
   a 44x44 circle, still slid by the "on" transform, so it bled out past
   the card edge — visibly broken, not just a missed touch target. Since
   the element's ::after is taken, its hit area uses ::before instead.
   ============================================================ */
@media (max-width:1023px){
  /* .topo-remove is deliberately excluded here. It already declares
     position:absolute (with top/right anchoring it to its card's corner)
     in its own base rule in multi-store-sync.html. Adding position:relative
     to it here — same specificity, this stylesheet loads later — silently
     overwrote that absolute with relative. A position:relative element
     stays in normal document flow (just visually offset), so the button
     rendered near its unshifted in-flow position — top-left, ahead of the
     "DESTINATION"/"SOURCE" badge that follows it in the DOM — and visually
     overlapped that badge's text. Its own position:absolute already
     qualifies it as a positioning context for the ::after below; it never
     needed this rule. */
  .rule-remove,
  .faq-item button,
  button[data-dv-toggle],
  [class*="w-8"][class*="h-8"].cursor-pointer,
  .flex.gap-3 > button[class*="w-8"][class*="h-8"]{position:relative}

  .topo-remove::after,
  .rule-remove::after,
  button[data-dv-toggle]::after,
  [class*="w-8"][class*="h-8"].cursor-pointer::after,
  .flex.gap-3 > button[class*="w-8"][class*="h-8"]::after{
    content:"";position:absolute;left:50%;top:50%;
    width:44px;height:44px;transform:translate(-50%,-50%);
  }

  .sched-toggle::before{
    content:"";position:absolute;left:50%;top:50%;
    width:44px;height:44px;transform:translate(-50%,-50%);
  }
}

/* ============================================================
   STEP ROW — TABLET OVERFLOW
   storefront-discounts' 4-step "How it works" row is `hidden md:flex`,
   so it switches on at 768px. Each step carries a hard-coded inline
   `style="width:180px"`, which flex cannot shrink — the four steps plus
   their connectors measured ~45px wider than the viewport at 768px, so
   the last step was clipped. Inline styles need !important to override.
   Let the steps size themselves and cap them with the existing max-width.
   ============================================================ */
@media (min-width:768px) and (max-width:1023px){
  /* Four steps across a tablet leaves ~150px per column, which fits but
     breaks headings mid-word ("conversio/ns"). Lay them out 2x2 instead:
     each step gets roughly double the width and the copy reads normally.
     The dotted connectors only make sense on a single row, so they are
     dropped here. */
  .md\:flex.items-start{
    display:grid!important;
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:2rem;row-gap:2.5rem;
  }
  .md\:flex.items-start > .flex-1.h-2{display:none}
  .md\:flex.items-start > .flex-1.flex.flex-col{min-width:0}
  .md\:flex.items-start > .flex-1.flex.flex-col > h3,
  .md\:flex.items-start > .flex-1.flex.flex-col > p{width:auto!important;max-width:32ch!important}
}

/* ============================================================
   READABLE TYPE FLOOR — PHONES
   Meta/caption text in the product-page mock UIs bottomed out at 11px,
   which is below a comfortable reading size on a phone. Lifted to ~12.5px
   and given a little more leading. Deliberately scoped to these specific
   labels rather than all `.text-xs`, because badges and pills rely on
   12px to keep their shape.
   ============================================================ */
@media (max-width:639px){
  .topo-tip,
  .text-\[11px\]{font-size:12.5px;line-height:1.45}

  /* .topo-tip is an absolutely-positioned nowrap tooltip. At 11px it just
     cleared a 320px viewport; at the larger size above it did not. Let it
     wrap and bound it to its (position:relative) node instead. */
  .topo-tip{white-space:normal;max-width:100%}
  .dv-caption,
  .text-xs.text-slate-400.italic,
  .text-center.text-xs.text-slate-400{font-size:13px;line-height:1.5}
}
