/* ============================================================
   APP SHELL — device-frame containment. Zero-edit, drop in as-is.

   This is a small, specific piece of CSS that is very easy to get
   subtly wrong when re-derived from a written description instead of
   copied from working code — and when it's wrong, the failure mode
   is confusing: it can look completely fine in a narrow devtools
   mobile-emulation view (which already constrains the viewport to
   phone width) and only break at full desktop browser width, where
   the "phone" is just a decorative graphic sitting inside a page that
   is free to grow to any height. When it's wrong, the whole browser
   page scrolls instead of an inner region, and you can see the OS
   taskbar/other page chrome below the bottom of what should be a
   fixed-height phone frame.

   TEST THIS AT FULL DESKTOP BROWSER WIDTH, not just in a narrow
   devtools mobile emulator — that is exactly the gap that let this
   bug ship unnoticed.

   The chain, every level required, none of them optional:

     .device-shell     fixed/bounded height, NOT height:auto
       .app-surface     height:100%; overflow:hidden   <- clip boundary
         .app-root      height:100%; overflow:hidden   <- clip boundary
           .screen      height:100%; flex column
             .screen-scroll   flex:1; min-height:0; overflow-y:auto
                              ^^^^^^^^^^^^^^^^^^^^^
                              THE ONE MOST LIKELY TO GET DROPPED.
                              flex:1 alone is not enough — a flex
                              child's default min-height is `auto`,
                              which lets it grow to fit its content
                              and ignore the parent's height entirely.
                              min-height:0 is what forces it to
                              actually respect flex sizing and scroll
                              its own content instead of pushing the
                              whole page taller.

   Only .screen-scroll ever scrolls. Nothing above it should ever
   have overflow other than hidden, and nothing above it should ever
   have a height that isn't 100% or an explicit bounded value.
   ============================================================ */

:root {
  --shell-width: 390px;      /* override per project if the mockups imply a different device width */
  --safe-top: 54px;          /* status bar height */
  --bottom-nav-height: 84px; /* override to match the actual nav bar height */
}

html, body {
  margin: 0;
  min-height: 100%;
}

/* Centers the device frame on a desktop viewport. Purely presentational —
   safe to restyle the backdrop/centering, just don't touch the chain below. */
.prototype-stage {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 19px;
  box-sizing: border-box;
}

.device-shell {
  position: relative;
  width: var(--shell-width);
  height: min(900px, calc(100vh - 38px)); /* bounded — never height:auto */
  min-height: 690px;
  border-radius: 54px;
  overflow: hidden; /* belt-and-braces on top of app-surface's own clip */
}

.app-surface {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden; /* <-- required: clips anything that tries to escape the frame */
  border-radius: 45px;
  background: var(--bg, #fff);
}

/* Reserves vertical space for the device's real status bar. This must
   stay a transparent spacer with NO visible content -- no clock text,
   no battery icon, no signal bars. Mockup screenshots almost always
   show a fake "9:41 + full bars" status bar drawn in by the design
   tool purely for presentation; it is not part of the actual design
   and must never be recreated as real content. Confirmed as a real,
   shipped bug: a fake status bar rendered as literal DOM content
   produces two status bars stacked on a real device -- the phone's
   own real one, and a fake one underneath it permanently showing
   "9:41" regardless of the real time or battery level. */
.status-bar {
  position: absolute;
  z-index: 18;
  inset: 0 0 auto;
  height: var(--safe-top);
  pointer-events: none;
}

.app-root {
  height: 100%;
  padding-top: var(--safe-top);
  overflow: hidden; /* <-- required: same reason as app-surface */
}

/* One .screen per route/view. Only one is visible at a time (toggle a
   class or swap innerHTML — either works, this file doesn't care which).

   width: 100% here, always -- never add a per-screen max-width, margin,
   or extra wrapper that narrows one screen relative to the others.
   Confirmed as a real, shipped bug: one screen measured 124px narrower
   than another because it didn't correctly inherit this rule and had
   its own stray width constraint instead. Any screen-specific padding
   belongs inside .screen-scroll's own content, never on a wrapper that
   changes .screen's own width. */
.screen {
  position: relative;
  width: 100%;
  height: 100%; /* <-- required, not auto */
  display: flex;
  flex-direction: column;
  background: var(--bg, #fff);
}

/* THE scroll region. Every screen's actual content goes inside one of
   these, never directly inside .screen. */
.screen-scroll {
  flex: 1;
  min-height: 0; /* <-- see the big comment at the top of this file */
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0 14px calc(var(--bottom-nav-height) + 28px);
}

.screen-scroll::-webkit-scrollbar {
  width: 0;
  height: 0;
}

/* Bottom nav sits below the scroll region, inside .screen, so it never
   scrolls away — but it's still inside the height:100% chain, not
   fixed/absolute against the viewport (that would break once the
   device frame is centered in a larger desktop window). */
.bottom-nav {
  flex: 0 0 auto;
  height: var(--bottom-nav-height);
  display: flex;
  align-items: center;
  justify-content: space-around;
}

/* ============================================================
   REAL MOBILE VS DESKTOP PREVIEW — this is not optional.

   Everything above this point creates a decorative "phone" sitting
   inside a larger page: rounded corners, a bounded height, centered
   with padding around it. That's the right look on a desktop browser,
   where showing the mockup at actual device width — floating in the
   middle of a much larger window — is how you'd want to preview it.

   It is the WRONG look on an actual phone. A real device already has
   its own physical bezel; drawing a second decorative one around your
   content, with padding and rounded corners eating into the real
   screen, wastes space and looks like a broken app, not a considered
   one. On a real device this must become the actual full-bleed app:
   no bezel, no padding, no rounded corners, no centering — the app IS
   the screen.

   This query targets viewport width, not user-agent sniffing, so it
   correctly also fires for anyone resizing a desktop browser down to
   phone width, not just literal phone hardware.
   ============================================================ */
@media (max-width: 520px) {
  html, body {
    width: 100%;
    min-height: 100%;
    overflow: hidden;
  }

  .prototype-stage {
    display: block;
    width: 100%;
    min-height: 100dvh;
    padding: 0;
  }

  .device-shell {
    width: 100%;
    height: 100dvh;
    min-height: 0;
    padding: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .app-surface {
    border-radius: 0;
  }

  /* On a real device the OS's own status bar/notch already exists.
     Layer this app's decorative status-bar height on top of the
     REAL safe-area-inset-top rather than the fixed --safe-top value
     alone, or content will sit too high on notched devices. */
  .status-bar {
    height: calc(var(--safe-top) + env(safe-area-inset-top));
  }

  .app-root {
    padding-top: calc(var(--safe-top) + env(safe-area-inset-top));
  }

  .bottom-nav {
    height: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom));
  }

  .screen-scroll {
    padding-bottom: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom) + 28px);
  }
}
