/* css/home-mobile.css
   ────────────────────────────────────────────────────────────────────────────
   The mobile front page of airmango.com. Linked only from index.html, so every
   rule in here is page-scoped by virtue of where it loads.

   What this is: the CEO's three-screen mobile design (walkthrough video,
   2026-08-24). Landing on airmango.com from a phone gives a horizontal deck of
   three full-height slides — the pitch, the trip, the gigs — and an "Apply as
   a creator" button that fades in once you have read past the first slide. The
   desktop showcase is hidden rather than reflowed: he was explicit that the
   desktop page "doesn't fit for mobile at all", so it is a different page, not
   a narrower one.

   Two deliberate departures from his Figma prototype:

   1. The phone in the mockup shows REAL app screenshots
      (assets/images/phone-screen-hero.png = the feed,
       phone-screen-trip.jpg = the trip behind the clip), not the hand-drawn
      SVG landscape the prototype used. "This is just some AI bullshit here, we
      know what screen that is." phone-screen-hero.png is a JPEG carrying a
      .png name — harmless (browsers sniff the bytes) and left alone because
      the desktop page references the same path.

      The trip shot is the one that goes stale: it is the app's trip screen,
      which is still being redesigned. It is re-shot rather than redrawn —
      /trip.html?id=<published app_trips.id> runs the SAME renderer as the app
      and the creator's phone preview, so a 393x852 capture of it IS the
      current screen. See the comment on that <img> in index.html.

   2. Type and colour follow BRAND.md, not the prototype. The prototype ships
      Plus Jakarta Sans + JetBrains Mono and #ec1358; the brand is Poppins +
      Inter and #E8366D. Fonts are already loaded by css/app-index.css.

   The header is NOT rebuilt here. js/site-header.js already renders a mobile
   topbar of exactly this shape — wordmark left, burger right, working drawer —
   so it is only recoloured for a dark page. The breakpoint below matches that
   file's own 720px switch on purpose; if one moves, both move.
   ──────────────────────────────────────────────────────────────────────────── */

/* Desktop never sees the mobile page. Stated once, unconditionally, so a
   failure to match the media query below leaves it hidden rather than dumped
   at the bottom of the desktop layout. */
.m-front { display: none; }

@media (max-width: 720px) {

  /* ── the page becomes a fixed-height, non-scrolling shell ──────────────── */

  html { height: 100%; }

  body {
    height: 100vh;
    height: 100dvh;
    margin: 0;
    overflow: hidden;
    background: #07080a;
    color: #fff;
  }

  /* The desktop front page and the site footer are not reflowed, they are stood
     down — the mobile page carries its own ending (the CTA).

     Both selectors are needed. js/site-footer.js mounts with
     `ph.outerHTML = HTML`, which REPLACES the #airmango-footer placeholder, so
     that id stops existing the moment the script runs and a rule hung on it
     silently stops matching. footer.footer is the element that actually lands;
     #airmango-footer only covers the gap before the script fires. */
  body > .master-showcase-section,
  body > #airmango-footer,
  body > footer.footer { display: none !important; }

  /* The shared topbar, recoloured for a dark page and floated over the deck:
     its white fill would otherwise cut the sky in half, and the slides already
     reserve top padding for it. */
  .am-topbar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    background: transparent;
    border-bottom: 0;
    padding: 16px 24px 2px;
  }
  .am-topbar-logo { color: #fff; }
  .am-menu-btn { color: #fff; }

  /* Pinned to the viewport rather than sized as a flex item, so nothing another
     script appends to <body> can squeeze it. That is not hypothetical: the site
     footer above did exactly that, and the staging env banner, toasts and the
     apply modal all mount the same way. */
  .m-front {
    position: fixed;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    isolation: isolate;
  }

  /* ── backdrop: sky, low sun, three ridgelines ──────────────────────────── */

  .m-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; }

  .m-sky {
    position: absolute;
    inset: 0;
    background: linear-gradient(178deg, #b3bfc6 0%, #9dabb4 12%, #7e8d97 26%,
      #5b6872 40%, #3a444d 54%, #1e252b 70%, #0d1013 86%, #07080a 100%);
  }

  .m-sun {
    position: absolute;
    left: 50%;
    top: 26%;
    transform: translate(-50%, -50%);
    width: 300px;
    height: 190px;
    background: radial-gradient(ellipse at center, rgba(255,231,200,.28) 0%,
      rgba(255,214,170,.09) 45%, rgba(255,214,170,0) 72%);
  }

  .m-range { position: absolute; left: 0; width: 100%; }
  .m-range svg { display: block; width: 100%; height: 100%; }
  .m-r1 { top: 29%; height: 30%; opacity: .2; }
  .m-r2 { top: 40%; height: 32%; opacity: .32; }
  .m-r3 { top: 53%; height: 36%; opacity: .58; }

  /* Sinks the ridgelines into the page floor so the deck text always has a
     dark ground under it, whatever the slide. */
  .m-fade {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(7,8,10,0) 40%, rgba(7,8,10,.62) 68%,
      rgba(7,8,10,.96) 88%, #07080a 100%);
  }

  /* Driven from js/home-mobile.js — the daylight drains as you swipe toward
     the gigs, which are a dark-ground surface. */
  .m-dim { position: absolute; inset: 0; background: #07080a; opacity: 0; }

  /* ── the deck ──────────────────────────────────────────────────────────── */

  .m-deck {
    position: relative;
    z-index: 2;
    flex: 1;
    min-height: 0;
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .m-deck::-webkit-scrollbar { display: none; }

  /* js/home-mobile.js hangs this on the deck for the length of a gesture. A
     mandatory snap and a scrollLeft written frame by frame fight each other —
     the snap keeps yanking the deck back to the nearest slide, so a drag that
     should follow the thumb stutters. The class is taken off again once the
     settling scroll has come to rest, which is a snap point anyway. */
  .m-deck--free { scroll-snap-type: none; }

  .m-slide {
    min-width: 100%;
    scroll-snap-align: start;
    /* One flick, one slide. Without this, a hard native swipe hands the deck
       to momentum scrolling, which is free to fly past as many snap points as
       it has speed for — slide 1 straight to slide 3, the middle one never
       seen. `always` makes every slide a stop the fling has to honour, so how
       hard you throw it stops mattering. (The JS gesture in
       js/home-mobile.js:drive() holds the same line for the drag it drives
       itself, where snapping is switched off.) */
    scroll-snap-stop: always;
    display: flex;
    flex-direction: column;
    min-height: 0;
    /* Vertical drags on these two slides are the deck's, not the browser's:
       the page underneath cannot scroll anyway, and claiming the axis up front
       is what keeps the handover to a horizontal swipe instant. */
    touch-action: pan-x;
    /* Clears the fixed topbar (38px tall) and then some — at 46px the headline
       sat right under the wordmark and the two read as one block. */
    padding: 58px 24px 0;
  }

  /* ── type ──────────────────────────────────────────────────────────────── */

  .m-h1 {
    font-family: 'Poppins', sans-serif;
    font-size: 30px;
    line-height: 1.06;
    letter-spacing: -1.1px;
    font-weight: 700;
    margin: 0;
    color: #fff;
    text-shadow: 0 2px 18px rgba(0,0,0,.35);
  }
  .m-h1 b { color: var(--accent, #E8366D); font-weight: 700; }

  /* The gigs headline is a sentence, not a two-line slogan: a notch smaller so
     it does not swallow the slide, and balanced so no word is left on its own. */
  .m-h1-long {
    font-size: 28px;
    letter-spacing: -1px;
    text-wrap: balance;
  }

  .m-lede {
    font-family: 'Inter', sans-serif;
    font-size: 15px;
    line-height: 1.5;
    letter-spacing: -.1px;
    margin: 14px 0 0;
    color: rgba(255,255,255,.72);
    text-shadow: 0 1px 12px rgba(0,0,0,.35);
  }
  .m-lede b { font-weight: 600; color: #fff; }

  /* ── the phone, and the real screens inside it ─────────────────────────── */

  .m-stage {
    position: relative;
    flex: 1;
    min-height: 200px;
    margin-top: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .m-device {
    /* content-box, and the height stated net of the bezel, on purpose.

       aspect-ratio applies to whichever box box-sizing names, and the whole
       page inherits border-box. So under border-box this ratio described the
       OUTER frame, and .m-screen — the frame minus 5px of bezel on every side
       — came out at a different ratio from phone-screen-hero.png (427x924).
       object-fit: cover then quietly cropped 5.4px off the screenshot's width,
       which slid the Trip thumbnail ~2px right of where percentages say it is
       and left the pulse ring below hanging off its left edge.

       content-box makes the ratio describe .m-screen itself, so the screenshot
       fills it with no crop at all and every percentage measured off the file
       lands exactly. The 10px of calc/max-height is that bezel added back: the
       frame is still 100% of the stage, still capped at 440px tall. */
    box-sizing: content-box;
    height: calc(100% - 10px);
    max-height: 430px;
    aspect-ratio: 427 / 924;
    background: #0a0d10;
    border-radius: 32px;
    padding: 5px;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.18), 0 26px 54px rgba(0,0,0,.6);
  }

  .m-screen {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 27px;
    overflow: hidden;
    background: #10161b;
  }

  .m-shot {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* Glass, not content — sells the mockup as a device rather than a flat crop. */
  .m-glare {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(118deg, rgba(255,255,255,.09) 0%,
      rgba(255,255,255,.02) 30%, rgba(255,255,255,0) 52%);
  }

  /* ── the Trip button: "if it should have some type of attention around this" ──
     A transparent hit target sat exactly over the Trip thumbnail in the real
     screenshot, carrying the pink pulse ring. Centre and size are measured off
     phone-screen-hero.png by edge-scanning the file: the thumbnail's box is
     x 373-407, y 759-796 of 427x924, so its centre is (390/427, 778/924) and it
     is ~34px across. Percentages land exactly because .m-screen now carries the
     file's aspect ratio uncropped — see the note on .m-device. */
  .m-trip {
    position: absolute;
    left: 91.33%;
    top: 84.2%;
    transform: translate(-50%, -50%);
    /* Wider than the ring on purpose: on the biggest phone the screen is
       ~199px across, so this is a ~36px tap target over a 15px thumbnail. */
    width: 18%;
    aspect-ratio: 1;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  .m-trip::before {
    content: "";
    position: absolute;
    /* The thumbnail is 8.2% of the screen width (35 of 427); 26% inset on an
       18% box puts the ring at 8.64% — flush around it — so the resting state
       never covers the artwork and the growth reads as coming off the button. */
    inset: 26%;
    border-radius: 30%;
    box-shadow: 0 0 0 2px var(--accent, #E8366D);
    animation: m-pulse 2.4s ease-out infinite;
  }

  @keyframes m-pulse {
    0%   { transform: scale(.86); opacity: .9; }
    70%  { transform: scale(1.6); opacity: 0; }
    100% { opacity: 0; }
  }

  .m-trip:focus-visible { outline: 2px solid #fff; outline-offset: 3px; border-radius: 8px; }

  /* ── slide 3: the gigs ─────────────────────────────────────────────────── */

  /* Taller content than the other two slides on a short phone, so this one is
     allowed to scroll rather than crush the rail. */
  .m-slide-gigs {
    overflow-y: auto;
    overscroll-behavior-y: contain;
    scrollbar-width: none;
    /* The exception to the rule above: this slide has its own vertical scroll
       on a short phone, and it keeps it. The script yields to it and only takes
       the gesture over once the list has run out of room. */
    touch-action: pan-x pan-y;
  }
  .m-slide-gigs::-webkit-scrollbar { display: none; }

  .m-gigwrap { flex: 1; min-height: 0; display: flex; flex-direction: column; }

  /* The headline took the top edge and the rail the bottom, so on a tall phone
     every pixel of slack piled up in one hole between them — one ugly hole in
     the middle of the slide. The text block takes the slack instead and splits
     it 2:1 around itself, so the hero drops well clear of the topbar and the
     gap under it is a third of what it was. */
  .m-gigtext { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .m-gigtext::before { content: ''; flex: 2; }
  .m-gigtext::after  { content: ''; flex: 1; }

  /* Headline sits at the top like the other two slides; the rail is anchored to
     the bottom so the slack collects between them instead of leaving the cards
     floating mid-screen. padding-top is the floor on that gap once a long
     headline has eaten the slack — margin-top:auto alone collapses to nothing. */
  .m-railgroup { padding-top: 22px; }

  .m-railhead {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin: 0 0 12px;
  }
  .m-railhead b {
    font-family: 'Inter', sans-serif;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -.015em;
    color: #fff;
  }
  .m-railhead em {
    font-style: normal;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 10.5px;
    letter-spacing: .06em;
    color: rgba(255,255,255,.45);
  }

  .m-gigslot { padding-bottom: 24px; }

  /* js/home-mobile.js moves the one real .gigs block in from the desktop
     column — the gig content has a single home in index.html, so the day it
     starts reading from Supabase there is nothing here to keep in step.
     What is left to do is recolour it: those cards are a light-theme
     component landing on a near-black slide. */
  .m-gigslot .gigs { margin-top: 0; }
  .m-gigslot .gigs-head { display: none; }
  .m-gigslot .gigs-track { gap: 12px; padding-bottom: 4px; }

  /* Wider and taller than the desktop card (178px / 106px image): a thumbnail
     that reads at arm's length, and it lands the rail at ~1.6 cards visible so
     the half-card on the right is the thing that says "swipe". */
  .m-gigslot .gig {
    flex: 0 0 202px;
    background: rgba(255,255,255,.075);
    border-color: rgba(255,255,255,.14);
    border-radius: 13px;
  }
  .m-gigslot .gig-img { height: 126px; }
  .m-gigslot .gig-what { color: #fff; }
  .m-gigslot .gig-who { color: rgba(255,255,255,.5); }
  .m-gigslot .gig-amt { color: #fff; }
  .m-gigslot .gigs-empty h3 { color: #fff; }
  .m-gigslot .gigs-empty p { color: rgba(255,255,255,.6); }

  /* ── footer: progress bars + the CTA ──────────────────────────────────── */

  .m-foot {
    position: relative;
    z-index: 3;
    flex: none;
    padding: 0 24px calc(22px + env(safe-area-inset-bottom));
    background: linear-gradient(180deg, rgba(7,8,10,0) 0%, rgba(7,8,10,.9) 30%, #07080a 60%);
  }

  /* A mark, not a chrome bar. These were three flex:1 segments spanning 364 of
     the 412px width, sitting 30px under the phone mockup - big enough and near
     enough to read as part of the device. They are now three 26px dashes
     centred at the foot of the page, below the CTA (see index.html for the
     move). The fill inside each one is still painted from the deck's scroll
     position by js/home-mobile.js, so the middle dash still fills as slide 2
     comes across.

     Total height here is 3px LESS than the old block, so the phone gains a
     little rather than losing any: .m-stage is the flex:1 that pays for
     whatever this footer takes. */
  .m-bars { display: flex; justify-content: center; gap: 6px; padding: 18px 0 0; }
  .m-bar {
    position: relative;
    flex: none;
    width: 26px;
    height: 3px;
    border-radius: 3px;
    background: rgba(255,255,255,.24);
    border: 0;
    padding: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  /* The dash is 3px tall and no thumb can hit that. This is the tap target -
     32x27px around each one, which is why .m-bar can no longer clip its
     overflow (it never needed to: the fill is never wider than the track).

     -3px is half the 6px gap on purpose: any wider and the next dash's target
     starts before this one's visible right edge, so the last pixel of a dash
     would navigate somewhere else. The three targets meet, they do not
     overlap. */
  .m-bar::after { content: ""; position: absolute; inset: -12px -3px; }

  .m-bar span { display: block; height: 100%; width: 0; background: #fff; border-radius: 3px; }

  /* "<Hotel> invited you." — invite mode only; index.html adds it once the
     operator lookup has found the hotel. A row of the footer in its own right,
     ABOVE .m-ctaslot and never inside it: the slot is a fixed 54px, so a band
     in there shoved the button ~44px down onto the dots, whose tap targets
     then took the tap meant for "Join". Out here the footer grows by the band
     and the deck above gives up the room, whatever the phone's height and
     however many lines a long name wraps to.

     Ink on the pale pink, not pink: the accent on #FCE7EE is 3.4:1, too faint
     for 13px type. (It rendered white, in fact: this page does not load
     tokens.css, so the var(--accent) it had resolved to nothing and the
     page's white came through.) */
  .m-invband {
    margin: 0 0 10px;
    padding: 8px 12px;
    border-radius: 10px;
    background: #FCE7EE;
    color: #0F0F12;
    font: 600 13px/1.35 'Inter', system-ui, sans-serif;
    text-align: center;
  }

  /* Height is reserved whether or not the button is showing, so the deck does
     not resize under the reader's thumb when it fades in. */
  .m-ctaslot { height: 54px; }

  .m-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    font-family: 'Inter', sans-serif;
    font-size: 16px;
    font-weight: 600;
    border-radius: 14px;
    border: 0;
    background: var(--accent, #E8366D);
    color: #fff;
    text-decoration: none;
    letter-spacing: -.2px;
    opacity: 0;
    transform: translateY(10px);
    pointer-events: none;
  }
  .m-cta:active { background: var(--accent-hover, #c92d5b); }

  .m-front :focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

  /* Short phones (SE-class, and landscape): give the type back some room by
     letting the phone mockup shrink first. */
  @media (max-height: 700px) {
    .am-topbar { padding: 10px 24px 2px; }
    .m-slide { padding-top: 44px; }
    .m-h1 { font-size: 26px; letter-spacing: -.9px; }
    .m-h1-long { font-size: 24px; }
    .m-lede { font-size: 14px; margin-top: 10px; }
    .m-stage { margin-top: 12px; min-height: 150px; }
    .m-railgroup { padding-top: 18px; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .m-deck { scroll-behavior: auto !important; }
  .m-trip::before { animation: none !important; }
  .m-cta { transition: none !important; }
}
