/* ---- Reset ---- */
*, *::before, *::after { box-sizing: border-box; }

/* Author display rules on .pre-prompt / .perm-dark otherwise beat the UA
   [hidden] rule (author styles win over UA regardless of specificity), so the
   attribute alone won't hide them. Make [hidden] authoritative. */
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; }
html { height: 100%; }
/* Lock the app to the DYNAMIC viewport (dvh) — the currently visible area.
   This page never scrolls (body is fixed, screens scroll internally), so in
   Safari the toolbar never auto-hides and dvh stays equal to svh: bottom
   controls (e.g. the checklist "Continue to Guide" button) are never covered.
   Installed to the Home Screen there is no toolbar at all, so dvh is the whole
   screen — whereas svh stopped short and left a dead strip at the bottom that
   pushed the floating tab bar up. Falls back to vh where dvh is unsupported. */
body {
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  position: fixed;
  inset: 0;
}
* { -webkit-tap-highlight-color: transparent; }

html {
  font-family: var(--font-family);
  color: var(--color-ink);
  /* White by default, so nothing dark can show through around the app on a
     phone (this previously rendered as a black bar under the home indicator).
     The dark surround is restored on wide screens below, where it deliberately
     frames the centered phone-width column. */
  background: var(--color-white);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  font-size: 16px;
  line-height: 1.5;
  background: var(--color-white);
  overscroll-behavior: none;
}

/* Desktop only: dark backdrop around the centered phone-width column. */
@media (min-width: 500px) {
  html, body { background: var(--color-ink); }
}

img, svg, video, canvas { display: block; max-width: 100%; }
button { font-family: inherit; cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, p { margin: 0; }

/* ---- App frame: center a phone-width column on desktop, full-bleed on phone ---- */
#app {
  position: relative;
  width: 100%;
  max-width: 440px;
  height: 100vh;
  height: 100dvh;
  margin: 0 auto;
  background: var(--color-white);
  overflow: hidden;
  box-shadow: 0 0 60px rgba(0,0,0,0.25);
}

/* ============================================================
   Viewport adaptation
   Everything below keys off the VIEWPORT (width, height, orientation) rather
   than device names, so it adapts to any screen — including sizes that don't
   exist yet, iPad Split View, and resized desktop windows.
   ============================================================ */

/* SHORT viewports: landscape phones, Split View, small windows. The layout is
   portrait-shaped, so the risk is bottom-anchored actions being pushed under
   the fold. Compressing the vertical rhythm buys that space back without
   touching the horizontal design. */
@media (max-height: 560px) {
  :root {
    --space-5: 16px;
    --space-6: 18px;
    --space-8: 22px;
    --space-10: 26px;
  }
  .display { font-size: clamp(22px, 3px + 5.5vw, 26px); }
  .h1      { font-size: clamp(19px, 3px + 4.5vw, 22px); }
}

/* Landscape on a short screen: let any screen that has no dedicated internal
   scroll region scroll itself, so nothing becomes unreachable. Screens that do
   own a scroll region are unaffected — this only adds a fallback. */
@media (orientation: landscape) and (max-height: 560px) {
  .screen { overflow-y: auto; -webkit-overflow-scrolling: touch; }
}

/* NOTE: screen-specific short-viewport overrides live at the END of
   screens.css, not here — screens.css loads last and some of its rules
   (e.g. `.welcome__hero .display`) outrank anything set at this level. */

/* LARGE viewports: tablets and desktop. #app already caps at 440px and centres
   horizontally, so the app never stretches into an unreadable full-width
   column. What's missing is vertical centring and framing, so it reads as a
   deliberate layout rather than a phone screenshot pinned to the top of a dark
   field. Gated on height too, so landscape phones (wide but short) never match. */
@media (min-width: 768px) and (min-height: 700px) {
  body { display: grid; place-items: center; }
  #app {
    max-width: 460px;
    height: min(100svh - 48px, 940px);
    border-radius: 28px;
    box-shadow: 0 24px 70px rgba(0, 0, 0, 0.35);
  }
}

/* ---- Typography helpers ---- */
/* Fluid type. The lower bound protects narrow phones (the 320-375pt class,
   where a fixed 34px display line wraps badly or overflows). Scaling is driven
   by viewport width, so it adapts continuously rather than at device
   breakpoints. Each curve is tuned to reach its ORIGINAL size at ~400px wide
   (every modern iPhone), so the primary target is pixel-identical to before; it
   only shrinks below that, and the max stops it growing on iPad/desktop where
   #app is capped at 440px anyway. */
.display   { font-weight: 700; font-size: clamp(28px, 4px + 7.5vw, 34px); line-height: 1.15; letter-spacing: -0.01em; }
.h1        { font-weight: 700; font-size: clamp(23px, 3px + 6.25vw, 28px); line-height: 1.2; letter-spacing: -0.01em; }
.h2        { font-weight: 600; font-size: clamp(18px, 10px + 2.5vw, 20px); line-height: 1.3; }
.body      { font-weight: 400; font-size: 16px; line-height: 1.5; }
.body-sm   { font-weight: 400; font-size: 14px; line-height: 1.5; }
.eyebrow   { font-weight: 500; font-size: 12px; line-height: 1.4; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-gray-text); }

.text-muted { color: var(--color-gray-text); }

/* ---- Focus states (accessibility floor) ---- */
:focus-visible {
  outline: 2px solid var(--color-blue);
  outline-offset: 2px;
}
:focus:not(:focus-visible) { outline: none; }

/* ---- Screen system ---- */
.screen {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--color-white);
  visibility: hidden;
  transform: translateX(100%);
  pointer-events: none;
  overflow: hidden;
}

.screen--active {
  visibility: visible;
  transform: translateX(0);
  pointer-events: auto;
  z-index: 2;
}

/* Slide transitions driven by app.js adding direction classes. Pure transform
   (no opacity) — a straight slide reads far crisper than a slide+cross-fade,
   and stays fully GPU-composited. will-change is scoped to just the animating
   window so it doesn't leave a stray compositor layer sitting around after. */
.screen--animating {
  transition: transform var(--duration-slow) var(--ease-out);
  will-change: transform;
}

.screen--leaving-left  { transform: translateX(-30%); z-index: 1; }
.screen--leaving-right { transform: translateX(100%); z-index: 1; }
.screen--entering-right { transform: translateX(100%); }
.screen--entering-left  { transform: translateX(-30%); }

@media (prefers-reduced-motion: reduce) {
  .screen { transform: none !important; }
  .screen--active { transform: none !important; }
  .screen--leaving-left, .screen--leaving-right { transform: none !important; }
}

/* ---- Scroll regions ---- */
.scroll-y {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* Safe-area padding for notch / home indicator */
.safe-top    { padding-top: max(var(--space-4), calc(env(safe-area-inset-top) + var(--space-2))); }
.safe-bottom { padding-bottom: max(var(--space-4), env(safe-area-inset-bottom)); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
