/* RekallMe landing page.
   Three acts, matching the line the app already uses on its own sign-in
   screen: Save, Remember, Search. Same tokens as the legal pages, and the
   same shape as the app — a blue block at the top, everything else on the
   soft canvas beneath it, so the site and the product read as one thing. */

:root {
  --brand: #2f3ac4;
  --accent: #3b4ce0;
  --ink: #1b1f3b;
  --body: #4c5375;
  --muted: #727788;
  --meta: #84899a;
  --rule: #f1f1f8;
  --border: #e7e8f2;
  --card: #ffffff;
  --tint: #ecedfb;

  /* The app's canvas: blue under the header, through lavender, to a soft teal
     and green floor. It never reaches white, so a card keeps its edge. */
  --canvas-1: #dfe7ff;
  --canvas-2: #eae6fc;
  --canvas-3: #e0edf1;
  --canvas-4: #e4efe8;

  --radius: 18px;
  --shadow: 0 4px 18px rgba(25, 40, 80, .07);

  /* The captures are 900x1873 after the status bar is cropped. The frame has
     to match, or the screenshot is subtly stretched and every line inside it
     leans. 900 wide so a phone drawn at up to 450px is still a true 2x. */
  --shot-ratio: 900 / 1873;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  color: var(--body);
  background: linear-gradient(180deg, var(--canvas-1) 0%, var(--canvas-2) 36%,
                              var(--canvas-3) 72%, var(--canvas-4) 100%);
  background-attachment: fixed;
  font: 16px/1.6 Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
}

.wrap { max-width: 62rem; margin: 0 auto; padding: 0 1.25rem; }
/* The narrow sections keep the page's full width and limit the *measure*
   instead, so their text starts on the same vertical line as the hero.
   Shrinking `.wrap` itself did not do that: it still carries `margin: 0 auto`,
   so a narrower box just centres, and the section begins further right than
   everything above it. That is what made the page read as two layouts
   stacked. */
.narrow > * { max-width: 44rem; }

h1, h2, h3 { color: var(--ink); letter-spacing: -.022em; text-wrap: balance; margin: 0; }
h1 { font-size: clamp(2rem, 5.5vw, 3.1rem); font-weight: 800; line-height: 1.1; }
h2 { font-size: clamp(1.5rem, 3.6vw, 2.1rem); font-weight: 800; line-height: 1.2; }
h3 { font-size: 1.02rem; font-weight: 700; }
p { margin: 0; }
a { color: var(--accent); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

/* ---- the blue block, as in the app ----------------------------------- */

.top { background: var(--brand); color: #fff; padding: 1.1rem 0 3rem; }
.nav { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }

/* The wordmark, drawn the way the app draws it: "Rekall" in the ink of
   whatever it sits on, "Me" in the accent. On the blue block both are white,
   because the ground is already carrying the colour. */
.mark { display: inline-flex; align-items: center; gap: .55rem; text-decoration: none; }
.mark img { display: block; }
.word { font-weight: 800; font-size: 1.12rem; letter-spacing: -.03em; color: #fff; }
.me { color: #fff; }
.mark.on-light .word { color: var(--ink); }
.mark.on-light .me { color: var(--accent); }

.nav-links { display: none; gap: 1.6rem; font-size: .92rem; }
.nav-links a { color: rgba(255, 255, 255, .82); text-decoration: none; }
.nav-links a:hover { color: #fff; }
@media (min-width: 46rem) { .nav-links { display: flex; } }

/* ---- the mobile menu ---------------------------------------------------- */

.menu { position: relative; }
@media (min-width: 46rem) { .menu { display: none; } }

.menu summary {
  list-style: none;
  display: grid; place-items: center;
  width: 42px; height: 42px;          /* a real tap target, not a 20px icon */
  margin-right: -8px;
  cursor: pointer;
  border-radius: 10px;
}
.menu summary::-webkit-details-marker { display: none; }
.menu summary:hover, .menu[open] summary { background: rgba(255, 255, 255, .14); }

/* The three lines, and the same three turned into a cross when open. */
.lines, .lines::before, .lines::after {
  content: ""; display: block;
  width: 20px; height: 2px; border-radius: 2px; background: #fff;
  transition: transform .18s ease, opacity .18s ease;
}
.lines { position: relative; }
.lines::before { position: absolute; top: -6px; }
.lines::after  { position: absolute; top: 6px; }
.menu[open] .lines { background: transparent; }
.menu[open] .lines::before { transform: translateY(6px) rotate(45deg); }
.menu[open] .lines::after  { transform: translateY(-6px) rotate(-45deg); }
@media (prefers-reduced-motion: reduce) {
  .lines, .lines::before, .lines::after { transition: none; }
}

.menu-panel {
  position: absolute; right: 0; top: calc(100% + .55rem); z-index: 20;
  min-width: 15rem;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 14px 34px rgba(15, 25, 60, .22);
  padding: .5rem;
  display: flex; flex-direction: column;
}
.menu-panel a {
  color: var(--ink); text-decoration: none;
  padding: .68rem .8rem; border-radius: 10px;
  font-size: .95rem; font-weight: 600;
}
.menu-panel a:hover { background: var(--tint); }
.menu-panel hr {
  border: 0; border-top: 1px solid var(--border);
  margin: .4rem .8rem;
}
/* The legal links are secondary: same panel, quieter. */
.menu-panel hr ~ a { font-weight: 500; font-size: .9rem; color: var(--body); }

/* Text and a phone, side by side. A hero that is text on the left and blue
   nothing on the right reads as unfinished, whatever the words say. */
.hero-row { display: grid; gap: 2rem; padding-top: 2.6rem; align-items: center; }
@media (min-width: 52rem) {
  .hero-row { grid-template-columns: 1fr minmax(0, 300px); gap: 3.5rem; }
}
.hero { max-width: 34rem; }

/* The product line, above the headline. Small and quiet: it names the thing,
   the headline says what it does for you. */
.kicker {
  color: rgba(255, 255, 255, .78);
  font-size: .92rem; font-weight: 600;
  letter-spacing: .01em; margin-bottom: 1rem;
}
.hero h1 { color: #fff; }
.hero .sub {
  color: rgba(255, 255, 255, .88);
  margin-top: 1.05rem; font-size: 1.08rem; max-width: 30rem;
}

/* On a phone it moves below the buttons rather than beside the text, and is
   drawn smaller — the point of it here is that you see what the app looks
   like before you scroll, not that you can read the cards. */
.hero-phone { display: block; }
@media (max-width: 51.99rem) {
  .hero-phone { display: flex; justify-content: center; margin-top: .4rem; }
  .hero-phone .phone { width: 232px; }
}

.tagline {
  display: flex; gap: .55rem; align-items: center; flex-wrap: wrap;
  margin-top: 1.6rem; color: rgba(255, 255, 255, .9);
  font-weight: 700; letter-spacing: .01em;
}
.tagline b { font-weight: 800; }
.tagline span { color: rgba(255, 255, 255, .45); }

/* Said before the buttons, not after: someone should know the app is not out
   yet before they reach for it, not after tapping a dead badge. */
.soon {
  margin-top: 1.9rem; margin-bottom: .55rem;
  font-size: .82rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: rgba(255, 255, 255, .72);
}
#pricing .soon { color: var(--muted); }

.stores { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: 0; }

/* Store badges in the shape both stores use: mark on the left, a small line
   over a large one on the right, black with white type. Drawn here rather
   than shipped as images so they stay sharp at any size and cost no request.
   Before launch these should be swapped for Apple's and Google's own badge
   artwork, which their brand guidelines require. */
.badge {
  display: inline-flex; align-items: center; gap: .6rem;
  background: #000; color: #fff; text-decoration: none;
  padding: .55rem 1rem .55rem .85rem;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, .28);
  line-height: 1;
}
.badge { opacity: .82; cursor: default; }
.badge:hover { background: #000; }
.badge-logo { width: 26px; height: 26px; flex: none; }
.badge-text { display: flex; flex-direction: column; gap: 2px; }
.badge-text small { font-size: .62rem; letter-spacing: .02em; opacity: .92; }
.badge-text strong { font-size: 1.02rem; font-weight: 600; letter-spacing: -.01em; }

/* On the light half of the page the hairline is unnecessary. */
#pricing .badge { border-color: transparent; }

.hero-note { color: rgba(255,255,255,.72); font-size: .85rem; margin-top: 1rem; }

/* ---- acts -------------------------------------------------------------- */

section { padding: 4rem 0; }
.act-head { max-width: 40rem; }
.eyebrow {
  color: var(--accent); font-size: .78rem; font-weight: 800;
  letter-spacing: .11em; text-transform: uppercase; margin-bottom: .6rem;
}
.lede { margin-top: .85rem; font-size: 1.02rem; }
.aside { margin-top: 1.1rem; font-size: .93rem; color: var(--muted); }

/* ---- the phone --------------------------------------------------------- */

/* An iPhone, drawn rather than photographed. No second asset, scales to any
   size, and the proportions are set here rather than baked into an image.
   The captures had their status bar cropped off, so the frame supplies it:
   a strip of the app's own header blue with the island sitting on it, which
   is exactly what the phone shows. Nothing here fakes the app itself — the
   screenshot inside is the real thing, and the iOS build renders the same
   screens because the app is Flutter. */
/* An iPhone, drawn rather than photographed: no second asset, and the
   proportions live here rather than baked into an image.

   `.phone` is the container, so it carries no `cqw` of its own — an element
   cannot query its own size, and a `cqw` written here would silently resolve
   against an ancestor container or the viewport. Every dimension below sits
   on a descendant, where it resolves against the phone as intended. */
.phone {
  position: relative;
  container-type: inline-size;
  filter: drop-shadow(0 14px 34px rgba(20, 30, 70, .22));
}

/* The metal edge and the black bezel in one element: a gradient for the rim,
   an inset ring for the bezel. Two separate boxes would need z-index against
   the screen, and the screen must stay on top. */
.phone::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: 13.5cqw;
  background: linear-gradient(145deg, #7a7d84 0%, #2c2e33 22%,
                                      #17181c 55%, #55585f 100%);
  box-shadow: inset 0 0 0 1.9cqw #0b0c0f;
}

/* Volume rocker, mute switch and power. Absolutely positioned so they sit
   proud of the edge without joining the layout — a button that widened the
   grid column would push the phones apart. */
.btn {
  position: absolute;
  /* Behind the rim, not on top of it. Painted over the bezel they read as
     grey rectangles stuck to the side of the phone; tucked underneath, only
     the rounded outer half shows, which is what a real button looks like. */
  z-index: -1;
  width: 2.2cqw;
  /* The rim's own metal, lit from the same side, so the button belongs to the
     frame rather than sitting against it. */
  background: linear-gradient(180deg, #8f929a, #4b4e55 55%, #303339);
  border-radius: 1.2cqw;
}
/* Offset by exactly half their width: half is hidden under the rim, half
   stands proud. */
.btn.mute  { left: -1.1cqw;  top: 15.8%; height: 2.6%; }
.btn.up    { left: -1.1cqw;  top: 21.8%; height: 6.2%; }
.btn.down  { left: -1.1cqw;  top: 29.6%; height: 6.2%; }
.btn.power { right: -1.1cqw; top: 25.5%; height: 9.8%; }

.screen {
  position: relative;
  container-type: inline-size;
  margin: 3.1cqw;
  border-radius: 10.6cqw;
  overflow: hidden;
  background: var(--brand);
  line-height: 0;
}

/* The status bar, in the header's own blue so it reads as one surface.
   It is a real element rather than a pseudo because it has contents. Sized
   with aspect-ratio, not a percentage height: `.screen` has no definite
   height of its own, so `height: 15%` on a normal-flow child resolves to
   auto — zero — and the strip vanishes, which is what put the island on top
   of the app's own header instead of above it. */
.status {
  width: 100%;
  aspect-ratio: 800 / 132;
  background: var(--brand);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 7.5cqw 0 8.5cqw;
  font-size: 4.4cqw;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1;
}

.status .bits { display: flex; align-items: center; gap: 1.6cqw; }
.status svg { display: block; height: 3.9cqw; width: auto; fill: #fff; }
.status .batt { height: 4.4cqw; }

/* The island, centred in that strip. Percentages of the screen's height are
   fine here: an absolutely positioned box resolves them against a containing
   block whose height is definite once laid out. */
.screen::after {
  content: "";
  position: absolute;
  top: 2.5%; left: 50%; transform: translateX(-50%);
  width: 29%; height: 2.35%;
  background: #08090c;
  border-radius: 999px;
  z-index: 2;
}

.phone img {
  display: block; width: 100%; height: auto;
  aspect-ratio: var(--shot-ratio);
}

/* The home indicator, over the app rather than beside it — where iOS puts it. */
.home {
  position: absolute; left: 50%; bottom: 1.1%;
  transform: translateX(-50%);
  width: 34%; height: 4px;
  border-radius: 999px;
  background: rgba(20, 25, 45, .32);
}

/* Above the phone, not below: the reader should know what they are looking
   at before they look at it, rather than after. */
.caption { margin-bottom: .9rem; }
.caption h3 { margin-bottom: .25rem; }
.caption p {
  font-size: .9rem; color: var(--muted); line-height: 1.45;
  /* Two lines' worth, always. The captions are one or two lines depending on
     the screen they describe, and without a floor the phones beside each
     other start at different heights — which reads as a broken row, not as
     text of different lengths. */
  min-height: 2.9em;
}

/* ---- a row of phones --------------------------------------------------- */

/* On a narrow screen these scroll sideways inside their own track, one phone
   at a time at a size where the card titles can actually be read. Three
   thumbnails nobody can parse is the usual way this fails. */
.phones {
  display: grid; grid-auto-flow: column; gap: 1.25rem;
  grid-auto-columns: min(330px, 82vw);
  margin-top: 2.2rem;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  padding: 0 1.25rem 1rem;
  margin-inline: -1.25rem;
  scrollbar-width: none;
}
.phones::-webkit-scrollbar { display: none; }
.phones > * { scroll-snap-align: center; }

.swipe-hint {
  font-size: .82rem; color: var(--meta); margin-top: .2rem;
}

@media (min-width: 52rem) {
  .phones {
    grid-auto-flow: row; grid-template-columns: repeat(3, 1fr);
    overflow: visible; padding: 0;
    /* Breaks out past the text column. The reading measure wants ~42rem; the
       phones want every pixel they can get, and tying them to the same width
       is what makes a three-across row look like thumbnails. */
    width: min(84rem, calc(100vw - 2.5rem));
    margin-inline: calc((min(62rem, 100vw - 2.5rem) - min(84rem, 100vw - 2.5rem)) / 2);
    gap: 2rem;
  }
  .phones.two {
    grid-template-columns: repeat(2, 1fr);
    width: min(60rem, calc(100vw - 2.5rem));
    margin-inline: calc((min(62rem, 100vw - 2.5rem) - min(60rem, 100vw - 2.5rem)) / 2);
  }
  .swipe-hint { display: none; }
}

/* Save is one phone beside its four inputs. */
.save-row { display: grid; gap: 2rem; margin-top: 2.2rem; align-items: center; }
@media (min-width: 52rem) {
  .save-row { grid-template-columns: minmax(0, 370px) 1fr; gap: 3.5rem; }
}

.ways { display: grid; gap: .9rem; grid-template-columns: repeat(2, 1fr); }

.way {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.15rem;
  box-shadow: var(--shadow);
}
.way h3 { margin-bottom: .3rem; }
.way p { font-size: .9rem; }

.glyph {
  width: 36px; height: 36px; border-radius: 11px;
  background: var(--tint); color: var(--accent);
  display: grid; place-items: center; margin-bottom: .75rem;
}
.glyph svg { width: 18px; height: 18px; stroke: currentColor; fill: none;
             stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ---- data and pricing --------------------------------------------------- */

.plain {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.5rem; box-shadow: var(--shadow);
  margin-top: 1.6rem;
}
.plain ul { margin: 1rem 0 0; padding-left: 1.1rem; }
.plain li { margin-bottom: .55rem; font-size: .95rem; }

/* ---- footer ------------------------------------------------------------- */

footer { border-top: 1px solid var(--border); padding: 2.5rem 0 3rem; margin-top: 2rem; }
.foot-links { display: flex; flex-wrap: wrap; gap: 1.1rem; margin: 1rem 0; font-size: .9rem; }
.legal { color: var(--meta); font-size: .82rem; }

/* ---- the reveal --------------------------------------------------------- */

/* Everything is visible by default. The script adds `js` to <html> and only
   then may anything be hidden — a page that hides its content and then fails
   to show it is worse than a page with no animation at all. */
.js .reveal { opacity: 0; transform: translateY(14px); }
.js .reveal.seen {
  opacity: 1; transform: none;
  transition: opacity .55s ease, transform .55s cubic-bezier(.2, .7, .3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .js .reveal, .js .reveal.seen { opacity: 1; transform: none; transition: none; }
}

/* ---- small screens ------------------------------------------------------ */

/* The two badges measure about 328px together. That fits a 390px phone and
   wraps on a 360px one, which leaves a lopsided second row with a single
   button on it. Below 27rem they stack full width instead, which reads as a
   decision rather than an accident — and gives a bigger tap target. */
@media (max-width: 27rem) {
  /* Stacked, but at the width of a real store badge rather than the width of
     the screen. A full-bleed black bar reads as a banner, not a button, and
     stretching it pushes the logo and the two lines of type apart. Both are
     given the same fixed width so their left edges and their baselines line
     up with each other and with the text above them. */
  .stores { flex-direction: column; align-items: flex-start; gap: .6rem; }
  .badge { width: 13.5rem; padding: .6rem 1rem .6rem .85rem; }
}

@media (max-width: 40rem) {
  /* 4rem top and bottom is a lot of empty on a short screen: it pushes the
     next section entirely out of view, so the page reads as one idea per
     scroll with nothing to pull you on. */
  section { padding: 2.75rem 0; }
  .top { padding-bottom: 2.5rem; }
  .hero-row { padding-top: 1.75rem; }

  h1 { line-height: 1.15; }
  .kicker { font-size: .85rem; margin-bottom: .75rem; }
  .hero .sub { font-size: 1rem; }

  /* The save phone is its own row here, so it does not need to fill the
     width — a 350px mock-up beside nothing looks stranded. The width has to
     be definite: the frame sizes its bezel and corners in container units,
     and an intrinsically-sized phone has nothing for them to resolve
     against. */
  .save-row { justify-items: center; }
  .save-row .phone { width: min(280px, 76vw); }

  /* Four cards two-up on a phone: they are one set of four choices, and a
     single column turns them into four separate scrolls. */
  .way { padding: .95rem .85rem; }
  .way p { font-size: .84rem; }
  .ways { gap: .7rem; }

  .plain { padding: 1.15rem; }
  .foot-links { gap: .75rem 1.1rem; }
}
