/* Unaccounted website. Dark by default, like the mockup, with a light theme
   from the header button (assets/theme.js); colors are the app's own
   (theme/colors.ts) and the serif is Newsreader, the app's display face.
   The phones stay dark in both: they hold real dark-mode screenshots. */

@font-face {
  font-family: "Newsreader";
  src: url("/assets/fonts/newsreader.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: dark;
  --bg: #0D1311;
  --bg-band: #0A100E;
  --surface: #151C1A;
  --surface-2: #1A2220;
  --border: rgba(237, 238, 234, 0.08);
  --border-strong: rgba(237, 238, 234, 0.14);
  --text: #EDEEEA;
  --text-2: #B4BAB6;
  --text-3: #8E9692;
  --accent: #8FC2B3;
  --accent-strong: #B3D8CC;
  --notice-bg: #1C1A12;
  --notice-border: rgba(199, 154, 61, 0.35);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 32px 64px -24px rgba(0, 0, 0, 0.7);

  --serif: "Newsreader", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --gutter: clamp(20px, 5vw, 48px);
  --max: 1160px;
}

/* The app's light theme. */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #F4F2EE;
  --bg-band: #EDEAE4;
  --surface: #FBFAF7;
  --surface-2: #F1EEE8;
  --border: rgba(27, 33, 31, 0.09);
  --border-strong: rgba(27, 33, 31, 0.16);
  --text: #1B211F;
  --text-2: #4E5552;
  --text-3: #6B716E;
  --accent: #245C50;
  --accent-strong: #1B4A40;
  --notice-bg: #F6EFDD;
  --notice-border: rgba(160, 118, 30, 0.35);
  --shadow: 0 1px 2px rgba(27, 33, 31, 0.08), 0 32px 64px -24px rgba(27, 33, 31, 0.25);
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--bg);
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  overflow-x: clip;
  /* Short pages (404) keep the footer at the bottom of the window. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
}
main { flex: 1 0 auto; }

img { display: block; max-width: 100%; height: auto; }

a { color: var(--accent); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { color: var(--accent-strong); text-decoration-thickness: 2px; }

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

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0;
  scroll-margin-top: 24px;
}
p { text-wrap: pretty; }

.skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 10;
  padding: 10px 16px;
  background: var(--surface-2);
  color: var(--text);
  border-radius: 10px;
}
.skip-link:focus { top: 16px; }

.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: max(var(--gutter), env(safe-area-inset-left)) max(var(--gutter), env(safe-area-inset-right));
}

/* Header */
.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-block: 20px;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  color: var(--text);
  text-decoration: none;
  font-family: var(--serif);
  font-size: 1.375rem;
}
.brand:hover { color: var(--text); }
.brand img { width: 32px; height: 32px; border-radius: 8px; }
.header-nav { display: flex; gap: 2px; margin-left: auto; }
.header-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 12px;
  color: var(--text-2);
  text-decoration: none;
  font-size: 0.9375rem;
  border-radius: 10px;
}
.header-nav a:hover { color: var(--text); background: var(--surface); }
.header-nav a[aria-current="page"] { color: var(--text); background: var(--surface); }
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: 2px;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
}
.theme-toggle:hover { color: var(--text); background: var(--surface); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }
/* Phones: every link stays (per the user: Overview and Features were
   hidden); the name gives way to the icon, the links tighten. */
@media (max-width: 559px) {
  .site-header .wrap { gap: 8px; }
  .site-header .brand span { display: none; }
  .header-nav a { padding-inline: 8px; font-size: 0.875rem; }
  .theme-toggle { width: 40px; }
  .brand { flex-shrink: 0; }
}
/* Narrow phones: all four links stay (per the user), tighter still. */
@media (max-width: 419px) {
  .site-header .wrap { gap: 4px; }
  .header-nav { gap: 0; }
  .header-nav a { padding-inline: 5px; font-size: 0.8125rem; }
  .theme-toggle { width: 34px; margin-left: 0; }
}
@media (max-width: 339px) {
  .header-nav a { padding-inline: 3px; font-size: 0.75rem; }
}

/* Home: full-screen slides. The browser's own scroll snapping moves one slide
   per swipe (no scroll hijacking, so touch, wheel, keys and the scrollbar all
   work) and CSS fades each slide with the scroll position. Sizes use
   svh, which doesn't change as Android's address bar shows and hides, so
   nothing relayouts mid-scroll. */
html.snap { scroll-snap-type: y mandatory; }
.home .site-header { position: absolute; top: 0; left: 0; right: 0; z-index: 5; }

/* A slide is as tall as the screen with the address bar hidden (lvh), so
   when Android hides the bar the next slide doesn't peek in at the bottom. */
.slide {
  position: relative;
  height: 100vh;
  height: 100lvh;
  min-height: 520px;
  /* clip, not hidden: hidden would make each slide its own scroll container,
     and the scroll-driven fade below would then watch the slide, not the page. */
  overflow: clip;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.slide:nth-of-type(even) { background: var(--bg-band); }
.slide > .wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(16px, 3svh, 32px);
  height: 100vh;
  height: 100svh;
  /* svh, not dvh: with dvh the phones were resized every time Android's
     address bar showed or hid (per the user's recording, they jumped in
     size mid-scroll). svh never changes; the content stays centred. */
  min-height: 520px;
  padding-block: clamp(20px, 4svh, 40px);
}
.slide-copy { flex: none; }
.slide-visual {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Lets the phone size itself to the space left after the text. */
  container-type: size;
}

/* Hero slide: text only. */
.slide-hero > .wrap {
  align-items: center;
  text-align: center;
  gap: 0;
  padding-top: 88px;
}
.eyebrow {
  margin: 0 0 16px;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
}
.slide-hero h1 { font-size: clamp(3.25rem, 11vw, 6.5rem); }
.slide-hero .lede {
  margin: 20px 0 0;
  max-width: 30ch;
  font-size: clamp(1.125rem, 2.4vw, 1.375rem);
  color: var(--text-2);
}
.soon {
  margin: 32px 0 0;
  font-size: 0.9375rem;
  color: var(--text-2);
}
/* Inline, so the dot stays beside the first word when the line wraps. */
.soon::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 10px;
  vertical-align: 0.1em;
  border-radius: 50%;
  background: var(--accent);
}
.scroll-cue {
  position: absolute;
  bottom: max(20px, env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 12px;
  color: var(--text-3);
  font-size: 0.875rem;
  text-decoration: none;
}
.scroll-cue::after {
  content: "";
  width: 1px;
  height: 40px;
  background: linear-gradient(var(--border-strong), transparent);
}
.scroll-cue:hover { color: var(--text); }

/* Text on the feature slides */
.step {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 12px;
  font-size: 0.875rem;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.step::after {
  content: "";
  width: 48px;
  height: 1px;
  background: var(--border-strong);
}
.slide-copy .eyebrow { margin-bottom: 12px; }
.slide h2 { font-size: clamp(2.125rem, 6vw, 3.75rem); }
.slide .intro {
  margin: 12px 0 0;
  max-width: 40ch;
  font-size: clamp(1rem, 2vw, 1.125rem);
  color: var(--text-2);
}

/* Phone frame: Android style, thin even bezel with a centred punch-hole
   camera. Its width is the largest that fits the slide's free space:
   the frame adds 18px across and 48px down (bezel + camera strip) to a
   720 x 1480 screenshot. */
.phone {
  --fit: min(100cqw, calc((100cqh - 48px) * 0.4865 + 18px));
  position: relative;
  width: min(var(--fit), 340px);
  padding: 9px;
  margin: 0;
  border-radius: 42px;
  background: #050807;
  box-shadow: inset 0 0 0 1px rgba(237, 238, 234, 0.12), inset 0 0 0 3px #111715, 0 24px 48px -24px rgba(0, 0, 0, 0.7);
}
.phone::before {
  content: "";
  position: absolute;
  top: 19px;
  left: 50%;
  width: 10px;
  height: 10px;
  margin-left: -5px;
  border-radius: 50%;
  background: #000;
  box-shadow: inset 0 0 0 2px #1a1f1d;
  z-index: 2;
}
/* The screenshots have their status bar cropped off; the top padding, in the
   app's background color, gives the punch-hole camera room above the app. */
.phone img {
  box-sizing: content-box;
  width: 100%;
  height: auto;
  padding-top: 30px;
  border-radius: 33px;
  background: #0D1311;
}
/* A shot with a sheet open is dimmed up to its top edge, so its band is too. */
.phone.dim img { background: #060B09; }
.phone.tilt { transform: rotate(3deg); }

/* A phone with a crop of one of its details overlapping its lower corner. */
.combo { position: relative; }
.combo .phone { width: min(var(--fit), 340px); }
.detail-card {
  position: absolute;
  right: -16%;
  bottom: 6%;
  width: 66%;
  margin: 0;
  border-radius: 20px;
  overflow: hidden;
  border: 1px solid var(--border-strong);
  box-shadow: 0 16px 32px -16px rgba(0, 0, 0, 0.8);
  background: #161D1B;
}
.detail-card img { width: 100%; }
/* Too cramped on short screens: the phone alone says enough. */
@media (max-height: 620px) {
  .detail-card { display: none; }
  .combo .phone { width: min(var(--fit), 340px); }
}

/* Card holding a crop of a real screenshot (not a recreation). It adds 40px
   across and 74px down (padding + caption) to an 800 x 720 image. */
.shot-card {
  width: min(100cqw, calc((100cqh - 74px) * 1.111 + 40px), 460px);
  margin: 0;
  padding: 20px;
  border-radius: 28px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 24px 48px -24px rgba(0, 0, 0, 0.7);
}
.shot-card img { width: 100%; border-radius: 16px; }
.shot-card figcaption { margin-top: 12px; font-size: 0.875rem; line-height: 22px; color: var(--text-3); }

/* Older Android browsers (Chrome before 105) have no container units: give the
   pictures a fixed size that fits a small phone instead of letting them grow. */
@supports not (width: 1cqh) {
  .phone, .combo .phone { width: min(230px, 58vw); }
  .shot-card { width: min(340px, 100%); }
}

/* Closing section: longer than a screen on phones, so it scrolls freely. */
.slide-end {
  scroll-snap-align: start;
  padding-block: clamp(64px, 10vw, 112px);
}
.also-title { font-size: clamp(1.75rem, 4vw, 2.25rem); }
/* Plain list, not chips: nothing here is clickable, so nothing should look it.
   Stacked and left-aligned on phones so long items wrap cleanly. */
.also {
  display: grid;
  gap: 10px;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
}
.also li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--text-2);
  font-size: 0.9375rem;
}
.also li::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  /* Centre the dot on the first line of text. */
  margin-top: calc(0.8em - 3px);
}
/* Google sign-in note (Google's verification wants the homepage to say which Google data the app uses) */
.data-note {
  display: grid;
  gap: 10px;
  margin-top: 48px;
  padding: clamp(24px, 4vw, 40px);
  border-radius: 28px;
  background: var(--surface);
  border: 1px solid var(--border);
}
.data-note h2 { font-size: clamp(1.75rem, 4vw, 2.25rem); }
.data-note p { margin: 0; max-width: 70ch; color: var(--text-2); }
.home .site-footer { scroll-snap-align: end; }

/* Footer */
.site-footer {
  border-top: 1px solid var(--border);
  background: var(--bg-band);
  padding-bottom: env(safe-area-inset-bottom);
}
.footer-top {
  display: grid;
  gap: 16px 48px;
  padding-block: 48px 32px;
}
.footer-top .brand { font-size: 1.5rem; }
.footer-top p { margin: 0; color: var(--text-3); font-size: 0.9375rem; max-width: 44ch; }
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 32px;
  padding-block: 20px 32px;
  border-top: 1px solid var(--border);
  font-size: 0.875rem;
  color: var(--text-3);
}
.footer-bottom ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer-bottom a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text-2);
  text-decoration: none;
}
.footer-bottom a:hover { color: var(--text); text-decoration: underline; }
.footer-bottom p { margin: 0; }

/* Legal pages */
.legal .wrap.narrow { max-width: 760px; }
.legal article { padding-block: clamp(16px, 4vw, 48px) clamp(64px, 10vw, 112px); }
.legal h1 { font-size: clamp(2.25rem, 6vw, 3.25rem); margin-top: 8px; }
.legal .meta { margin: 12px 0 32px; color: var(--text-3); font-size: 0.9375rem; }
.legal h2 {
  margin-top: 48px;
  padding-top: 32px;
  border-top: 1px solid var(--border);
  font-size: clamp(1.625rem, 4vw, 2rem);
}
.legal h2 + p, .legal h2 + ul { margin-top: 16px; }
.legal p, .legal li { color: var(--text-2); overflow-wrap: break-word; }
.legal strong { color: var(--text); font-weight: 600; }
.legal ul { padding-left: 1.25em; }
.legal li { margin-bottom: 12px; }
.legal li::marker { color: var(--text-3); }

/* 404 */
.not-found { padding-block: clamp(48px, 12vw, 144px); }
.not-found h1 { font-size: clamp(2.5rem, 7vw, 4rem); }
.not-found p { color: var(--text-2); max-width: 40ch; }

/* Slide fades, driven by the scroll position itself: halfway through a swipe
   a slide is half faded in, so the fade moves exactly with the finger at the
   screen's own refresh rate, with no script. Opacity only (no drift or zoom),
   so the page is the only thing that moves. Browsers without scroll-driven
   animations, and anyone who asks for reduced motion, just see the slides. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .slide > .wrap {
      animation: slide-fade linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
  }
}
@keyframes slide-fade {
  0% { opacity: 0; }
  38% { opacity: 1; }
  62% { opacity: 1; }
  100% { opacity: 0; }
}

/* Wider screens */
@media (min-width: 720px) {
  .also { display: flex; flex-wrap: wrap; gap: 8px 28px; }
  .footer-top { grid-template-columns: 1fr 1fr; align-items: end; }
  .footer-top p.about { justify-self: end; text-align: right; }
}
/* Side by side: text and picture in one row, alternating sides. */
@media (min-width: 880px) {
  .slide:not(.slide-hero) > .wrap {
    flex-direction: row;
    align-items: center;
    gap: 72px;
  }
  .slide-copy { flex: 1 1 0; }
  .slide-visual { flex: 1 1 0; height: min(84svh, 760px); }
  .slide.flip .slide-copy { order: 2; }
  .slide-solo .slide-visual { height: min(88svh, 800px); }
  .detail-card { right: -28%; }
}
