:root {
  --bg: #11151f;
  --panel: #1e2537;
  --ink: #ffffff;
  --muted: #a2b0d0;
  --gold: #ffd183;
  --gold-mid: #ffe0ac;
  --gold-deep: #e1ab50;
  --on-gold: #1e2537;
}

@font-face {
  font-family: Kanit;
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/kanit-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Kanit;
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/kanit-600.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  /* dvh, not 100%: 100% resolves against the large viewport, so with a visible
     browser toolbar the document outgrew .page and left a strip below it. dvh
     is the height actually on screen, and it cannot shift mid-gesture here
     because the root does not scroll, so the toolbar never collapses.
     Measured on Firefox for Android: dvh and innerHeight both 539 with the
     toolbar shown, against 593 for lvh and vh. The 100vh fallback is the large
     viewport, so it only centers the card for UAs without dvh; those UAs keep
     document scrolling (see the @supports below) to reach the overhang. */
  height: 100vh;
  height: 100dvh;
}

/* .page is the only scroller, and this is what actually holds the layout
   still: iOS gives the document a scroll range up to the large viewport even
   when the document is shorter, and rubber-banding into that range is what
   exposed bare background under .page. Gated on dvh: without it every height
   here falls back to the large viewport, so locking the root would clip the
   toolbar-height strip the CTA sits in with no way to scroll to it. */
@supports (height: 100dvh) {
  html {
    overflow: hidden;
  }
}

body {
  font-family: Kanit, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--ink);
  /* Centers .page vertically once its height cap leaves slack. */
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.page {
  /* 430px is the phone breakpoint below, so phones fill the width and only
     desktop gets the centered card. */
  width: min(100%, 430px);
  /* --u caps at 1px, so the mock is at most 649px tall (20 top + 629). Past
     923px of page height the hero card would show a flat band under the mock,
     so cap here rather than on the row: 12 + 649 + 10 gap + 242 panel + 10.
     The panel now runs taller than that 242px artboard (see the .lede gap), so
     at the cap the hero is shorter than the mock and clips its bottom edge
     under the fade instead of showing a band. The env() form adds the same
     insets that padding consumes, so a home-indicator tablet still fits the
     mock; UAs without env() keep the 923px line above. */
  height: min(100vh, 923px);
  height: min(100dvh, 923px);
  height: min(
    100dvh,
    calc(
      923px + env(safe-area-inset-top, 0px) + env(safe-area-inset-bottom, 0px)
    )
  );
  margin: 0 auto;
  /* Thin, even inset. viewport-fit=cover is required for non-zero
     env(safe-area-inset-*); without it the home-indicator term is always 0.
     Only the vertical insets are added: this column is centered and at most
     430px wide, so the landscape notch never reaches its sides. */
  padding: 12px 10px 10px;
  padding:
    calc(12px + env(safe-area-inset-top, 0px)) 10px
    calc(10px + env(safe-area-inset-bottom, 0px));
  display: grid;
  /* Hero takes leftover height (taller phones show more of the mock). The
     panel is at least the 242px artboard and grows to fit its content, so the
     CTA gap and zoomed text take height from the hero rather than clipping. */
  grid-template-rows: minmax(0, 1fr) minmax(242px, auto);
  gap: 10px;
  background: var(--bg);
  overflow-x: hidden;
  overflow-y: auto;
}

.hero,
.panel {
  position: relative;
  border-radius: 5px;
  background: var(--panel);
  overflow: hidden;
}

/* Mock geometry is Figma px times --u, so the frame, screenshot, chrome, and
   hero fade scale as one unit. --u caps at 1px, the artboard size. */
.hero {
  --u: 1px;
}

.phone {
  position: absolute;
  top: calc(20 * var(--u));
  left: 50%;
  width: calc(291 * var(--u));
  height: calc(629 * var(--u));
  transform: translateX(-50%);
  border-radius: calc(22 * var(--u));
  background: #3a4245;
  box-shadow: 0 var(--u) var(--u) rgb(0 0 0 / 0.25);
}

/* 0.28169cqw keeps the mock at the artboard ratio of 291/355 of the card,
   so narrow screens shrink it instead of cropping its sides. */
@supports (container-type: inline-size) {
  .hero {
    container-type: inline-size;
    --u: min(1px, 0.28169cqw);
  }
}

.phone::before {
  content: "";
  position: absolute;
  inset: calc(4.4 * var(--u));
  border-radius: calc(18 * var(--u));
  background: #121515;
}

.screen {
  position: absolute;
  top: calc(9.5 * var(--u));
  left: calc(9.5 * var(--u));
  width: calc(272 * var(--u));
  height: calc(603 * var(--u));
  border-radius: calc(20 * var(--u));
  overflow: hidden;
  background: #121515;
}

.screen img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.screen-status {
  position: absolute;
  top: calc(9 * var(--u));
  left: calc(15 * var(--u));
  right: calc(14 * var(--u));
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: #fff;
  font-size: calc(11 * var(--u));
  line-height: calc(12 * var(--u));
}

.android-status {
  display: flex;
  align-items: flex-end;
  gap: calc(5 * var(--u));
  height: calc(11 * var(--u));
}

.android-status i {
  display: block;
}

.wifi {
  width: calc(10 * var(--u));
  height: calc(8 * var(--u));
  background: #fff;
  clip-path: polygon(0 20%, 50% 0, 100% 20%, 50% 100%);
}

.signal {
  width: calc(10 * var(--u));
  height: calc(10 * var(--u));
  background: #fff;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}

.battery {
  width: calc(7 * var(--u));
  height: calc(10 * var(--u));
  border-radius: var(--u);
  background: #fff;
}

.camera {
  position: absolute;
  top: calc(16.8 * var(--u));
  left: 50%;
  width: calc(15.4 * var(--u));
  height: calc(15.4 * var(--u));
  transform: translateX(-50%);
  border: calc(4.8 * var(--u)) solid #121515;
  border-radius: 50%;
  background: #262c2d;
}

.camera::after {
  content: "";
  position: absolute;
  top: calc(2 * var(--u));
  left: calc(2 * var(--u));
  width: calc(1.9 * var(--u));
  height: calc(1.9 * var(--u));
  border-radius: 50%;
  background: rgb(99 111 115 / 0.4);
}

.side-buttons,
.side-buttons::before {
  position: absolute;
  right: calc(-2 * var(--u));
  width: calc(2 * var(--u));
  border-radius: 0 var(--u) var(--u) 0;
  background: #3a4245;
}

.side-buttons {
  top: calc(122 * var(--u));
  height: calc(72 * var(--u));
}

.side-buttons::before {
  content: "";
  top: calc(107 * var(--u));
  right: 0;
  height: calc(38 * var(--u));
}

.hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: min(calc(179 * var(--u)), 100%);
  background: linear-gradient(to bottom, transparent, var(--panel));
  pointer-events: none;
}

.panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Text shorter than the 242px row floor leaves slack above and below
     the block. The steps are taller than that floor, so the hero gives up
     the extra height. */
  justify-content: center;
  text-align: center;
  padding: 21px 12px 22.5px;
}

h1 {
  margin: 0;
  max-width: 100%;
  font-size: clamp(23px, 6.72vw, 26px);
  line-height: 28px;
  font-weight: 600;
  letter-spacing: -0.5px;
  overflow-wrap: break-word;
}

h1 span {
  display: block;
}

h1 em {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
  font-size: 1em;
  background: linear-gradient(180deg, var(--gold) 14%, var(--gold-mid) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.steps {
  width: min(290px, 100%);
  /* Gap under the headline. Real margins below let the panel grow past the
     242px floor; the hero row gives up that height. */
  margin: 20px 0 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 21px;
  text-align: left;
}

.step {
  margin: 0;
}

/* Desktop / unknown / JS-off: the combined store line. A platform class
   swaps in that store only, matching which CTA is visible. */
.when-ios,
.when-android {
  display: none;
}

.store-ios .when-ios,
.store-android .when-android {
  display: inline;
}

.store-ios .when-either,
.store-android .when-either,
.store-ios .when-not-ios {
  display: none;
}

.button {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  text-align: center;
  white-space: normal;
}

.button.primary {
  flex-shrink: 0;
  box-sizing: border-box;
  width: min(290px, 100%);
  min-height: 44px;
  padding: 0 12px;
  border-radius: 5px;
  font-size: 15px;
  font-weight: 600;
  color: var(--on-gold);
  background: linear-gradient(180deg, var(--gold) 0%, var(--gold-deep) 100%);
}

/* CSS cannot read the UA. Parse-time html.store-ios / html.store-android
   hides the other listing. No platform class (desktop, unknown UA, JS-off)
   keeps both. */
.store-fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 10px 0 18px;
}

.steps .setup {
  width: 100%;
  margin: 10px 0 18px;
}

.steps .setup button.button {
  border: none;
  cursor: pointer;
  font-family: inherit;
}

.store-fallback .button.primary {
  width: 100%;
}

.store-ios #get-app-play,
.store-android #get-app {
  display: none;
}

/* Both listings stay visible without a platform class. Name the store on
   each button so the two CTAs are not identical. A known platform shows
   the single short label. The span is a flex item, so a leading space
   inside it collapses; the margin is the gap before the store name. */
.store-mention {
  margin-left: 0.25em;
}

.store-ios .store-mention,
.store-android .store-mention {
  display: none;
}

@media (min-width: 431px) {
  body {
    padding: 24px 0;
  }

  .page {
    height: min(100vh - 48px, 923px);
    height: min(100dvh - 48px, 923px);
    height: min(
      100dvh - 48px,
      calc(
        923px + env(safe-area-inset-top, 0px) + env(safe-area-inset-bottom, 0px)
      )
    );
  }
}

/* A phone in landscape is wide enough for the card treatment above but has no
   height to spare: the 48px inset alone clipped the CTA on Firefox for Android
   at ~294px of viewport. Height is the constraint here, not width, so drop the
   inset rather than move the width breakpoint. */
@media (min-width: 431px) and (max-height: 500px) {
  body {
    padding: 0;
  }

  .page {
    height: 100vh;
    height: 100dvh;
  }
}
