/* ── mobile.css ──────────────────────────────────
   Mobile-only styles, split out from zoa.css so mobile-specific
   layout/behaviour (carousels, breakpoint overrides, etc.) lives in
   its own file rather than growing the shared stylesheet. Loaded on
   every viewport; individual rules are scoped with @media as needed. */

/* ── Kill the default mobile tap-highlight ──────────────────────
   Without this, tapping any link/button (e.g. a challenge checklist
   item) flashes the browser's built-in translucent blue highlight
   over the tapped element. Combined with the body scroll-lock the
   challenge modal applies, the highlight can fail to clear and is
   left looking like the page background got "stuck" blue. Harmless
   to set on non-touch devices, so it's not media-query gated. */
* {
  -webkit-tap-highlight-color: transparent;
}

/* ── Slightly smaller text site-wide on mobile ───────────────────
   Almost every font-size on the page — Tailwind's text-* utilities
   and zoa.css's custom classes alike — is set in rem, so scaling the
   root font-size scales all of them proportionally in one place
   instead of touching dozens of individual classes.
   This was briefly a fluid clamp() instead of a hard breakpoint jump,
   to smooth out resizing — but because virtually every element on the
   page inherits from it via rem, that made EVERY element's style
   recalculate on every pixel of viewport width change, not just the
   handful of headings that actually needed smoothing. Measured ~4x
   more style-recalc time and ~2.5x more layout time under a continuous
   resize than this static version. The individual .zoa-fluid-* heading
   classes in zoa.css carry the fluid smoothing instead — same visual
   goal, blast radius of a few elements rather than the whole page. */
@media (max-width: 767px) {
  html { font-size: 12.4px; }
}

/* ── Header — stays at the top of the page on mobile instead of
   following down as the user scrolls (desktop keeps its sticky nav). ── */

@media (max-width: 767px) {
  header.sticky {
    position: static;
  }

  /* img.zoa-header-logo (tag+class) rather than .zoa-header-logo alone —
     mobile.css loads before the Tailwind CDN <script>, so its injected
     h-[60px] utility rule lands later in the cascade and would win at
     equal specificity; the extra tag selector reliably beats it. */
  img.zoa-header-logo {
    height: 55px;
  }
}

/* ── Grid-overflow fix, applied site-wide ───────────────────────
   The page uses "grid ... lg:grid-cols-N" / "md:grid-cols-N" all over
   — meaning on mobile (below that breakpoint) it's display:grid with
   one implicit column, and grid items default to min-width:auto. If
   an item's content (long headings, wide images, etc.) needs more
   space than the viewport, the item — and the whole card around it —
   refuses to shrink and gets clipped at the right edge, exactly like
   the hero heading did. Resetting min-width to 0 on every direct
   child of a .grid container fixes this everywhere in one rule
   instead of patching each section individually. */
@media (max-width: 767px) {
  .grid > * {
    min-width: 0;
  }
}

/* ── One photo per section on mobile ─────────────────────────────
   A few sections show 2-3 decorative photos side by side (specialist
   services team photos, the Corby facility pair). On mobile that's a
   lot of scroll for images that aren't essential — keep just the
   first and drop the rest. Desktop is untouched. */
@media (max-width: 767px) {
  /* Targets direct children rather than "img" specifically — some of
     these are now wrapped in <picture> (see index.php) so the browser
     can skip fetching the full image on mobile entirely, rather than
     downloading it and then hiding it with CSS. */
  .zoa-photo-grid-mobile-single > *:not(:first-child) {
    display: none;
  }
}

/* ── Shorter facility photos on mobile ───────────────────────────
   The Operational coverage section's three facility photos are a
   fixed 272px tall (a literal pixel height, not rem, so they stay
   consistent with each other regardless of the mobile root font-size
   scaling above) — shortened here for mobile only, desktop keeps the
   full 272px. */
@media (max-width: 767px) {
  .zoa-coverage-photo {
    /* Tailwind's CDN stylesheet is injected later in the document
       than this file, so its h-[272px] utility wins the cascade at
       equal specificity without !important here. */
    height: 180px !important;
  }
}

/* ── Checklists are a plain stacked list on mobile ────────────────
   What we handle, Technology, Compliance and Solution's commercial
   models all use the same one-item-per-row checklist pattern — full
   width, stacked vertically. This used to auto-scroll as an infinite
   marquee ribbon on mobile; that read as tacky, so below `md` it's
   now just a static vertical list (desktop's grid, gated behind
   md:grid in the markup, is untouched). */
@media (max-width: 767px) {
  .zoa-checklist-row-mobile {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
  }
}

/* ── Lock the whole page to vertical panning on mobile — stops the
   page itself from sliding left/right on a touch swipe. Swipe
   carousels below are explicitly re-enabled for horizontal swipe. ── */

@media (max-width: 767px) {
  html,
  body {
    overflow-x: hidden;
    touch-action: pan-y;
  }

  /* pan-x alone locks touch on these to horizontal-only, which
     swallows any vertical drag that happens to start on a card
     instead of letting it scroll the page — allow both so the
     browser can route the gesture by its actual direction. */
  .zoa-swipe-track {
    touch-action: pan-x pan-y;
  }
}

/* ── Generic swipeable carousel — used for the hero cascade preview,
   the platform pillars, and the people-powered team photos. Desktop
   is untouched; each .zoa-swipe-track just renders as a normal grid
   there via its own (non-mobile.css) classes. ── */

@media (max-width: 767px) {
  .zoa-swipe-track {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .zoa-swipe-track::-webkit-scrollbar {
    display: none;
  }

  .zoa-swipe-slide {
    flex: 0 0 100%;
    min-width: 0;
    scroll-snap-align: center;
    /* Forces the browser to land on every snap point in sequence —
       without this, a fast/hard swipe can fling past several slides
       in one gesture instead of moving one at a time. */
    scroll-snap-stop: always;
    padding: 0 0.75rem;
    box-sizing: border-box;
  }

  /* Direction is communicated by the dots below on mobile instead. */
  .cascade-hero-arrow {
    display: none;
  }

  .zoa-swipe-dots {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1.5rem;
  }

  .zoa-swipe-dot {
    height: 8px;
    width: 8px;
    border-radius: 9999px;
    background: rgb(203 213 225); /* slate-300 — visible on light cards */
    transition: background-color 0.2s ease, transform 0.2s ease;
  }

  .zoa-swipe-dot.is-active {
    background: #06b6d4; /* cyan-500 */
    transform: scale(1.25);
  }

  /* On-dark variant for carousels sitting on navy backgrounds (hero). */
  .zoa-swipe-dots--on-dark .zoa-swipe-dot {
    background: rgba(255, 255, 255, 0.25);
  }

  .zoa-swipe-dots--on-dark .zoa-swipe-dot.is-active {
    background: #22d3ee; /* cyan-400 */
  }

  /* ── Boxed card-carousel — the ONE template for turning a grid of
     .zoa-card items into a swipeable mobile carousel. Every section
     that does this (Platform pillars, How it works, Specialist
     services, ...) must use .zoa-swipe-boxed and pick exactly one of
     its two indicator modifiers below — never invent a new one-off
     combination, and never both at once, or the page starts looking
     inconsistent again:

       .zoa-swipe-boxed                     → chevron arrows (default)
       .zoa-swipe-boxed .zoa-swipe-boxed--dots → dot indicators, no arrows

     Arrows are enough for short/simple carousels; reach for --dots
     when the row of items benefits from showing position/count (e.g.
     4+ substantial cards) — but pick one per section and be done.
     Add --dark on navy-background sections (pair with the dots row's
     own --on-dark modifier) — same shapes, recoloured. Add --top when
     slides lead with a photo, so content anchors to the top instead
     of vertically centring. */
  .zoa-swipe-boxed {
    position: relative;
    border-radius: 2rem;
    border: 1px solid rgb(226 232 240); /* slate-200, matches .zoa-card */
    background: #ffffff;
    /* Content is vertically centred (see .zoa-swipe-boxed .zoa-card
       below), and every slide is stretched to match the tallest one
       in the set — so the longest slide's card ends up exactly as
       tall as its own content, with none of the centring "slack"
       shorter slides get. That slide needs real padding here, not
       just a token trim, or it reads as squashed against the edges. */
    padding: 1.75rem 1.5rem 1.5rem;
    box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  }

  /* Subtle left/right chevrons hinting the card is swipeable, now
     that there's no dots row doing that job. Purely decorative, so
     plain text glyphs rather than an SVG/image — no extra markup
     needed, applies automatically to every .zoa-swipe-boxed card. */
  .zoa-swipe-boxed::before,
  .zoa-swipe-boxed::after {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1.5rem;
    line-height: 1;
    font-weight: 700;
    color: rgb(148 163 184); /* slate-400 */
    opacity: 0.5;
    pointer-events: none;
  }

  .zoa-swipe-boxed::before {
    content: "‹";
    left: 0.4rem;
  }

  .zoa-swipe-boxed::after {
    content: "›";
    right: 0.4rem;
  }

  /* "Dots" modifier — swap the chevrons for a dot row instead. Used
     when a carousel's item count/position is worth surfacing (e.g.
     Specialist services' 4 cards) rather than just "there's more". */
  .zoa-swipe-boxed--dots::before,
  .zoa-swipe-boxed--dots::after {
    content: none;
  }

  /* The base .zoa-swipe-boxed bottom padding is trimmed for the
     arrows variant, which has nothing sitting below the card. The
     dots row needs its own margin-top plus room for the dots
     themselves, so give it back the full top/bottom balance. */
  .zoa-swipe-boxed--dots {
    padding-bottom: 1.5rem;
  }

  .zoa-swipe-boxed--dots .zoa-swipe-dots {
    margin-top: 1.25rem;
  }

  /* "Dark" modifier — same template, recoloured for sections sitting
     on a navy background (e.g. The ecosystem's .zoa-dark-card grid),
     where the default white box and slate-400 chevrons would be
     invisible/wrong. Pair with .zoa-swipe-dots--on-dark for the dots
     themselves. */
  .zoa-swipe-boxed--dark {
    border-color: rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.05);
    box-shadow: none;
  }

  .zoa-swipe-boxed--dark::before,
  .zoa-swipe-boxed--dark::after {
    color: rgba(255, 255, 255, 0.5);
  }

  .zoa-swipe-boxed .zoa-swipe-slide .zoa-card,
  .zoa-swipe-boxed .zoa-swipe-slide .zoa-dark-card,
  .zoa-swipe-boxed .zoa-swipe-slide .zoa-contact-card {
    border: none;
    box-shadow: none;
    background: transparent;
    padding: 0;
    /* The track is display:flex with the default stretch behaviour,
       so every slide is stretched to match the height of the tallest
       one (e.g. a step with more copy). Shorter cards were then
       top-aligned inside that taller box, leaving dead space below
       them that reads as "content missing". Fill the stretched
       height and centre the actual content within it instead. */
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  /* "Top" modifier — for slides that lead with a photo (e.g.
     Operational coverage), vertical centring pushes the image down
     unevenly slide-to-slide. Anchor content to the top instead. */
  .zoa-swipe-boxed--top .zoa-swipe-slide .zoa-card,
  .zoa-swipe-boxed--top .zoa-swipe-slide .zoa-contact-card {
    justify-content: flex-start;
  }

  /* "First only" variant — no swipe at all on mobile, just show the
     first slide as a plain static image (used by the people-powered
     team photos, which are decorative rather than must-see content). */
  .zoa-swipe-first-only .zoa-swipe-track {
    display: block;
    overflow: visible;
    scroll-snap-type: none;
    /* This track no longer scrolls, so it shouldn't keep the
       horizontal-only touch restriction meant for actual swipe
       carousels — without this override, touching the image blocks
       normal vertical page scrolling. Match the page-wide policy
       (vertical pan only) instead of the swipe-track default. */
    touch-action: pan-y;
  }

  .zoa-swipe-first-only .zoa-swipe-slide {
    padding: 0;
  }

  .zoa-swipe-first-only .zoa-swipe-slide:not(:first-child) {
    display: none;
  }
}

@media (min-width: 768px) {
  .zoa-swipe-dots {
    display: none;
  }
}

/* ── Kill hover-effect "tap flash" on touch input ─────────────────
   hover.css and Tailwind's hover: utility are already gated behind
   (hover: hover) and (pointer: fine), so a plain finger tap shouldn't
   trigger them at all — but on hybrid devices (e.g. a touchscreen
   laptop/tablet that also has a mouse or trackpad paired) the browser
   can still report hover:hover as true, so a tap ends up applying and
   then "sticking" the hover box-shadow/border/colour/transform until
   the user taps elsewhere. (pointer: coarse) targets the input that
   was actually used — a finger — regardless of what else the device
   supports, so this forces every hover-affected property straight
   back to its resting value whenever a coarse (touch) pointer is
   the one interacting, with !important to win over any hover state. */
@media (pointer: coarse) {
  .cascade-logo-ring,
  .cascade-box,
  .zoa-glow-orange,
  .zoa-glow-green,
  .zoa-glow-cyan,
  .zoa-card,
  .zoa-checklist-item,
  .zoa-stat-tile,
  .zoa-shadow-hover {
    transform: none !important;
  }

  .zoa-card,
  .zoa-checklist-item,
  .zoa-stat-tile {
    border-color: rgb(226 232 240) !important;
  }

  .zoa-card,
  .zoa-checklist-item,
  .zoa-stat-tile,
  .zoa-shadow-hover {
    box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05) !important;
  }

  .cascade-logo-ring,
  .cascade-box,
  .zoa-glow-orange,
  .zoa-glow-green,
  .zoa-glow-cyan {
    box-shadow: none !important;
  }

  .zoa-ctr-link:hover::after,
  [data-zoa-link]:hover::after {
    transform: none !important;
  }

  .zoa-pill-trace svg rect {
    opacity: 0 !important;
  }

  .zoa-footer-logo-link {
    transform: none !important;
  }

  /* .zoa-swipe-boxed cards are deliberately de-boxed (their outer
     wrapper already provides the border/shadow/background — see the
     .zoa-swipe-boxed rules above) so the inner .zoa-card doesn't
     double up into a visible "card within a card". The plain .zoa-card
     reset above uses !important, which always beats a non-important
     rule regardless of specificity, so it was winning here and
     re-adding the inner box. This selector is also !important, so the
     tie is broken by specificity instead — three classes beats one. */
  .zoa-swipe-boxed .zoa-swipe-slide .zoa-card,
  .zoa-swipe-boxed .zoa-swipe-slide .zoa-contact-card {
    border-color: transparent !important;
    box-shadow: none !important;
  }
}
