/* ═══════════════════════════════════════════════════════════════════════
   Responsive.css — scaling ladder + the mobile layout.
   ⚠️ Must load LAST. It overrides everything above it.
   ═══════════════════════════════════════════════════════════════════════ */

/* The mobile layout is hidden by default; the media query below reveals it. */
.Mobile{ display: none; }


/* ── Desktop fallback ladder ────────────────────────────────────────────
   Main.js sets --stage-scale precisely using Math.min across both axes.
   These rules only matter if JS fails to load — width-only, deliberately,
   because a two-axis CSS ladder resolves ties by source order rather than
   by the smaller value, which can make a short window render LARGER.
   ───────────────────────────────────────────────────────────────────── */
@media (max-width: 1180px){ :root{ --stage-scale: .9; } }
@media (max-width: 1040px){ :root{ --stage-scale: .8; } }
@media (max-width: 920px) { :root{ --stage-scale: .7; } }


/* ── Mobile ─────────────────────────────────────────────────────────────
   A fake macOS desktop genuinely doesn't work on a phone, so it's replaced
   rather than squashed. .Mobile shows a scaled copy of the app window instead,
   bleeding off the left edge, with the name, signup and an app rail below.
   ───────────────────────────────────────────────────────────────────── */
@media (max-width: 768px){

  /* `body{ overflow: hidden }` was removed from Base.css when the page became
     scrollable, so there's nothing to re-enable here any more. Deliberately
     NOT re-adding overflow-x: hidden — that would make <body> a scroll
     container and fight html{ overflow-x: clip }, which is what lets Module 2
     and the album scatter bleed past the viewport edge. */

  /* The fake desktop is hidden outright on mobile — it was never usable at
     this width, and now that the page scrolls, the old tricks that made it
     "disappear" (position:static + height:0, and a position:fixed wallpaper)
     would be actively harmful: a fixed wallpaper would sit behind the ENTIRE
     scrolling page, modules and footer included. */
  .Desktop{ display: none; }

  /* The wallpaper moves onto .Hero so it stays confined to the first screen. */
  .Hero{
    height: auto;
    min-height: 100svh;
    background:
      #2E6FC4 url('/Assets/Images/Wallpaper.jpg') center center / cover no-repeat;
  }

  /* There is deliberately NO scrim over the mobile wallpaper. One used to live
     here — `.Hero::after` at rgba(0,0,0,.24) — because mobile puts text
     straight onto the wallpaper with no window behind it, and it lifted every
     mobile text element to >= 5.2:1 contrast.

     Eddy removed it on purpose: the mobile hero should show the wallpaper at
     the same brightness and saturation as the desktop breakpoint, and a flat
     black layer over the whole image was visibly dulling it. That is a design
     call about his own landing page, made with the contrast numbers in hand.

     ⚠️ So don't "fix" the contrast by dimming the image again. If a future
     wallpaper makes the text genuinely unreadable, reach for something that
     leaves the artwork alone — a text-shadow on .Mobile, or a gradient behind
     the copy only — and re-measure rather than restoring this block. */

  /* ── Mobile hero ──────────────────────────────────────────────────────
     Built to Eddy's mockups at 390×844pt; every number below was measured off
     them, not estimated. Horizontal sizes scale with the screen width through
     --m-win-scale (set by MobileHero.js); vertical slack is shared between
     three spacers (see .Mobile::before), so at 844pt tall everything lands
     exactly where it was drawn. */
  .Mobile{
    display: flex;
    flex-direction: column;
    position: relative;
    z-index: var(--z-windows);
    /* svh, not dvh: dvh changes as the URL bar collapses, which would now
       reflow a long page mid-scroll rather than just one screen. */
    min-height: 100svh;
    padding: 0 0 26.25px;
    box-sizing: border-box;
    text-align: left;
    /* .5532 = the window's scale at 390pt wide, inside 23.5pt margins.
       MobileHero.js rescales it to the real screen; this is the no-JS
       fallback. */
    --m-win-scale: .5532;
  }

  /* Three spacers share whatever height is left over, in the mockup's
     100 : 87.5 : 66.5 ratio — exact at 844pt tall, and on a shorter phone
     (iPhone SE) they all give a little so the app rail stays on screen.
     The top one is ::before so the markup only needs the other two. */
  .Mobile::before{ content: ""; flex: 100 1 0; min-height: 24px; }
  .Mobile-gap{ flex-basis: 0; flex-shrink: 1; }
  .Mobile-gap--a{ flex-grow: 87.5; min-height: 28px; }
  .Mobile-gap--b{ flex-grow: 66.5; min-height: 24px; }

  /* The real app window, scaled by MobileHero.js to fit the screen's width
     and, on shorter phones, its height too. */
  .MobileWindow{
    position: relative;
    flex: none;
    height: calc(566px * var(--m-win-scale));
    pointer-events: none;
  }
  /* Centred. (It used to bleed off the left edge, as in the original
     mockups; Eddy changed that after living with it on his phone.) */
  .MobileWindow .Window{
    left: calc(50% - 310px * var(--m-win-scale));
    transform: scale(var(--m-win-scale));
    transform-origin: 0 0;
    /* Thinner, greyer glass than the desktop's — sampled off the mockup,
       where the wallpaper shows through the panel noticeably more. */
    background: rgba(246,246,246,.34);
    -webkit-backdrop-filter: blur(42px) saturate(90%);
            backdrop-filter: blur(42px) saturate(90%);
  }

  /* ── Name, beta tag, signup ─────────────────────────────────────────── */
  /* Sits above the app rail: the rail's invisible headroom (below) can reach
     up over the signup field on a short phone, and the field must win taps
     there. While a "Coming Soon" tooltip shows, the rail is lifted above
     instead (.is-tipping) so the tooltip isn't hidden behind the field. */
  .MobileIntro{ position: relative; z-index: 1; padding: 0 23.5px; }

  .MobileIntro-row{
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 21.5px;
    margin-bottom: 16.5px;
  }
  .Mobile-title{
    margin: 0 0 0 3.9px;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: 0;
    line-height: 1;
    color: #fff;
  }

  .BetaTag{
    display: inline-flex;
    align-items: center;
    height: 21.5px;
    margin: 0;
    padding: 0 9.5px 0 6.7px;
    border: 1px solid rgba(134,192,242,.8);
    border-radius: 999px;
    box-sizing: border-box;
    font-size: 11px;
    line-height: 1;
    white-space: nowrap;
  }
  .BetaTag-icon{ width: 11px; height: 11px; color: #C0F6FA; margin-right: 4.2px; }
  .BetaTag-platform{ font-weight: 500; color: #C0F6FA; margin-right: 3.6px; }
  .BetaTag-label{ font-weight: 400; color: #86C0F2; }

  /* The field. ⚠️ These override the base form AND keep the footer's shared
     geometry out — the mobile hero is its own control now, not the footer's. */
  .SignupForm--mobile{ margin: 0; }
  .SignupForm--mobile .SignupForm-input{
    height: 57px;
    padding: 0 24px;
    border: .5px solid rgba(255,255,255,.22);
    border-radius: 10px;
    background: rgba(0,0,0,.12);
    box-sizing: border-box;
    /* ⚠️ 16px minimum, or iOS Safari zooms the page on focus. */
    font-size: 18px;
    font-weight: 400;
    color: #fff;
    caret-color: #007BFF;
  }
  /* Room for the button only while it's showing, so the placeholder isn't
     cut short on a 320pt-wide phone. */
  .SignupForm--mobile.is-ready .SignupForm-input{ padding-right: 112px; }
  .SignupForm--mobile .SignupForm-input::placeholder{ color: #A4D2FA; opacity: 1; }
  .SignupForm--mobile .SignupForm-input:hover{ background: rgba(0,0,0,.12); }
  /* Focused: a 2pt #007BFF ring that sits half outside the hairline border,
     and the placeholder dims. */
  .SignupForm--mobile .SignupForm-input:focus{
    background: rgba(0,0,0,.12);
    border-color: #007BFF;
    box-shadow: 0 0 0 1.5px #007BFF;
  }
  .SignupForm--mobile .SignupForm-input:focus::placeholder{ color: #6494D0; }
  /* Once the address is valid the ring goes and the button takes over as the
     focal point (mockup 3). */
  .SignupForm--mobile.is-ready .SignupForm-input:focus{
    border-color: rgba(255,255,255,.22);
    box-shadow: none;
  }
  .SignupForm--mobile.is-invalid .SignupForm-input{
    border-color: #FF6B60;
    box-shadow: 0 0 0 1.5px #FF6B60;
  }

  /* The button only exists once the address looks valid — exactly as drawn. */
  .SignupForm--mobile .SignupForm-button{
    position: absolute;
    top: 50%;
    right: 16px;
    transform: translateY(-50%);
    display: none;
    height: 24px;
    margin: 0;
    padding: 0 9px;
    border-radius: 6px;
    font-size: 11.5px;
    font-weight: 600;
    line-height: 24px;
    white-space: nowrap;
  }
  .SignupForm--mobile.is-ready .SignupForm-button{
    display: block;
    background: #0088F8;
    color: #fff;
    box-shadow: none;
  }
  .SignupForm--mobile .SignupForm-button:active{ transform: translateY(-50%) scale(.97); }
  /* ⚠️ The pill is 24pt tall in a 57pt field; this stretches the TAP area to
     44pt without changing anything visible. Horizontal inset stays 0 so it
     never reaches over the text and steals taps meant for the field. */
  .SignupForm--mobile .SignupForm-button::after{
    content: "";
    position: absolute;
    inset: -10px 0;
  }

  /* After signing up the field goes and the message takes its place, at the
     field's own height so nothing below shifts. */
  .SignupForm--mobile.is-done .SignupForm-field{ display: none; }
  .SignupForm--mobile .SignupForm-status{
    margin: 0;
    padding: 0 3.9px;
    color: rgba(255,255,255,.85);
    font-size: 15px;
    line-height: 1.35;
    text-align: left;
  }
  .SignupForm--mobile .SignupForm-status:not(:empty){ margin-top: 10px; }
  .SignupForm--mobile.is-done .SignupForm-status{
    display: flex;
    align-items: center;
    min-height: 57px;
    margin-top: 0;
    /* Overrides the base form's centred, 14px done message. */
    text-align: left;
    font-size: 15px;
  }
  .SignupForm--mobile .SignupForm-status.is-error  { color: #ffd2cd; }
  .SignupForm--mobile .SignupForm-status.is-success{ color: #c8f5d8; }

  /* ── App rail ───────────────────────────────────────────────────────────
     Squircles are 82pt at rest, 94pt when centred, 16.5pt apart, all sitting
     on one baseline. The icon PNGs carry ~10% transparent padding (the
     squircle is 79.69% of the image), so the <img> is drawn larger than its
     slot and scaled about the squircle's bottom edge, not the image's.

     ⚠️ The scroller has a tall top padding pulled back with a matching
     negative margin. A horizontal scroller clips vertically, and that space is
     what lets the centred icon grow and the "Coming Soon" tooltip appear above
     it without being cut off. */
  .AppRail{ position: relative; z-index: 0; flex: none; }
  .AppRail.is-tipping{ z-index: 2; }
  .AppRail-list{
    position: relative;
    display: flex;
    gap: 16.5px;
    margin: -88px 0 0;
    padding: 100px 0 0;
    list-style: none;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* ⚠️ Never pointer-events:none here. iOS Safari decides what to scroll
       from the scroller itself, so with it set the rail could be tapped but
       not swiped — shipped once, caught on Eddy's phone. The overlap with the
       field is handled by stacking instead (see .MobileIntro). */
  }
  .AppRail-list::-webkit-scrollbar{ display: none; }
  /* Spacers so the first and last icons can come to rest in the centre.
     (Padding on a flex scroller is unreliable at the far end in Safari.) */
  .AppRail-list::before,
  .AppRail-list::after{
    content: "";
    flex: 0 0 calc(50% - 41px - 16.5px);
  }
  .AppRail-item{
    position: relative;
    flex: 0 0 82px;
    height: 94.25px;              /* 82 squircle + 8.25 gap + 4 dot */
    scroll-snap-align: center;
  }
  /* The whole slot is the tap target. MobileHero.js moves this sideways to
     make room for the magnified icon; the <li> itself never moves, so the
     snap points stay put. */
  .AppRail-app{
    position: absolute;
    inset: 0;
    display: block;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .AppRail-app:focus-visible{ outline: 2px solid rgba(255,255,255,.9); outline-offset: 4px; border-radius: 20px; }
  .AppRail-icon{
    position: absolute;
    top: -10.45px;
    left: -10.45px;
    width: 102.9px;
    height: 102.9px;
    max-width: none;
    transform-origin: 50% 89.84%;  /* the squircle's bottom edge */
    filter: drop-shadow(0 2px 4px rgba(0,0,0,.18));
    pointer-events: none;
  }
  .AppRail-dot{
    position: absolute;
    top: 90.25px;
    left: 50%;
    width: 4px;
    height: 4px;
    margin-left: -2px;
    border-radius: 50%;
    background: #8EA2E9;
  }

  /* "Coming Soon" — the desktop dock's tooltip, shown on tap. Both gaps
     copy the desktop dock (Dock.css): 14px between the name pill and the top
     of the fully magnified icon (it grows 12pt above the slot, so 12 + 14 =
     26), and 11px between the pills (the 38px difference between the two
     margins is the name pill's 27px height plus that gap). */
  .AppRail .Tip--name { margin-bottom: 26px; }
  .AppRail .Tip--upper{ margin-bottom: 64px; }

  /* A slow cascade, bottom-up: the name pill drifts up and fades in, and
     "Coming Soon" follows 140ms behind it. Leaving runs top-down and quicker.
     ⚠️ Keep the curves gentle. An expo-style ease-out does ~90% of the change
     in the first quarter of the duration, so even a long transition reads as
     a pop — that's what the first version did.
     The delays work because a transition takes its timing from the state
     it's heading INTO: the resting rules hold the LEAVING timing, the
     .is-tipped rules hold the ARRIVING timing. */
  .AppRail .Tip{
    transform: translateX(-50%) translateY(12px);
    transition:
      opacity   .32s cubic-bezier(.55, 0, .75, .4),
      transform .32s cubic-bezier(.55, 0, .75, .4);
  }
  .AppRail .Tip--upper{ transition-delay: 0s; }
  .AppRail .Tip--name { transition-delay: .09s; }

  .AppRail-item.is-tipped .Tip{
    opacity: 1;
    transform: translateX(-50%) translateY(0);
    transition:
      opacity   .55s cubic-bezier(.33, 0, .25, 1),
      transform .7s  cubic-bezier(.25, .46, .45, .94);
  }
  .AppRail-item.is-tipped .Tip--name { transition-delay: 0s; }
  .AppRail-item.is-tipped .Tip--upper{ transition-delay: .14s; }

  /* ⚠️ No tooltip transitions until the page has settled. While Safari is
     still putting a reloaded page together it can style the pills as
     visible for a moment before their opacity: 0 lands — and with a
     transition in place, that one frame becomes the slow fade-OUT above, so
     every tooltip visibly appears and fades away on refresh. MobileHero.js
     adds .is-ready two frames after it runs; until then any change snaps.
     Must stay AFTER the rules above (same specificity as .is-tipped). */
  .AppRail:not(.is-ready) .Tip{ transition: none; }
}


/* ── Reduced motion ─────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  .Windows{ transition: none; }
  /* Magnification is skipped entirely by Main.js under reduced-motion, so
     there's nothing to override here — the icons simply never transform. */
  .Tip{ transition: opacity .01s linear; }
  /* The mobile rail's cascade: no rise, no stagger, just an instant swap. */
  .AppRail .Tip,
  .AppRail-item.is-tipped .Tip{
    transform: translateX(-50%);
    transition: opacity .01s linear;
    transition-delay: 0s;
  }
}
