@charset "utf-8";

/* ==========================================================================
   AuraSpend — website stylesheet
   --------------------------------------------------------------------------
   The "Quiet Ledger" language, lifted verbatim from the app so the site and
   the product are visibly the same object:

     · warm paper, near-black ink, ONE violet accent
     · no gradients, no glows, no drop shadows on content surfaces
     · 1px hairlines carry every separation
     · colour is reserved for data (income, over-budget, category identity)
     · Plus Jakarta Sans throughout, tabular figures on every number

   Tokens mirror app/src/main/java/.../ui/theme/Color.kt and
   docs/design/interface-concept/index.html exactly. If a value changes in the
   app, it changes here in the same commit.
   ========================================================================== */

/* ── 1. Font ───────────────────────────────────────────────────────────── */

@font-face {
    font-family: "Plus Jakarta Sans";
    src: url("../fonts/plus-jakarta-sans.ttf") format("truetype");
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
}

/* ── 2. Tokens ─────────────────────────────────────────────────────────── */

:root {
    color-scheme: light;

    /* Surfaces */
    --stage: #ebe7de;
    --paper: #f7f5f0;
    --surface: #ffffff;
    --surface-2: #f1ede4;
    --surface-3: #eae5d9;

    /* Ink */
    --ink: #17160f;
    --ink-2: #3b382e;
    --muted: #6e6a5c;
    --faint: #918c7d;

    /* Lines */
    --line: #e3ded1;
    --line-2: #efebe0;
    --track: #e8e3d6;

    /* The one accent */
    --violet: #4a2e7a;
    --violet-soft: #ede6f8;
    --violet-line: #d6c8ee;

    /* Data colours */
    --green: #1c6b4a;
    --green-soft: #e2efe7;
    --brick: #a8402f;
    --brick-soft: #f7e3de;
    --amber: #a66a1e;

    /* Chrome */
    --focus: #4a2e7a;

    /* The theme switch is a tiny day/night sky. Its two states are the two
       themes themselves, so these are not theme tokens: they must look the
       same whichever theme the page is currently in. Day is a lavender
       paper sky, night is the warm near-black ink. The `--toggle-*`
       variables after them are the *resolved* state, set by the theme
       blocks below; the component CSS reads only those, so the switch is
       painted correctly before site.js runs and with scripting off. */
    --toggle-day: #d8caee;
    --toggle-day-edge: #c3b2e2;
    --toggle-night: #17160f;
    --toggle-night-edge: #2b2a25;
    --toggle-sun: #f3c450;
    --toggle-moon: #f7f5f0;
    --toggle-crater: #8b8677;
    --toggle-cloud: #fdfbf6;
    --toggle-cloud-shade: #e4ddcf;
    --toggle-star: #f7f5f0;

    /* Daylight: the pill is the sky, the knob the sun, no craters, no stars. */
    --toggle-track: var(--toggle-day);
    --toggle-track-edge: var(--toggle-day-edge);
    --toggle-knob: var(--toggle-sun);
    --toggle-knob-x: 0rem;
    --toggle-craters: 0;
    --toggle-stars: 0;
    --toggle-stars-y: -2rem;

    /* Type */
    --font: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
        system-ui, sans-serif;
    --fs-display: clamp(2.5rem, 6.2vw, 4.625rem);
    --fs-h1: clamp(2rem, 4.6vw, 3.25rem);
    --fs-h2: clamp(1.625rem, 3.2vw, 2.25rem);
    --fs-h3: 1.25rem;
    --fs-h4: 1rem;
    --fs-lead: clamp(1.0625rem, 1.2vw, 1.1875rem);
    --fs-body: 1rem;
    --fs-small: 0.875rem;
    --fs-micro: 0.78125rem;
    --fs-eyebrow: 0.6875rem;

    /* Space — the app's 4dp grid */
    --sp-xxs: 0.125rem;
    --sp-xs: 0.25rem;
    --sp-sm: 0.5rem;
    --sp-md: 0.75rem;
    --sp-lg: 1rem;
    --sp-xl: 1.25rem;
    --sp-2xl: 1.5rem;
    --sp-3xl: 2rem;
    --sp-4xl: 3rem;
    --sp-5xl: 4rem;
    --sp-6xl: 6rem;

    /* Shape */
    --r-xs: 0.5rem;
    --r-sm: 0.75rem;
    --r-md: 0.875rem;
    --r-lg: 1.25rem;
    --r-xl: 1.75rem;
    --r-pill: 999px;

    /* Layout */
    --max: 1180px;
    --prose: 46rem;
    --nav-h: 4.25rem;

    /* The one shadow in the system: the floating device frame only. It is a
       drop-shadow rather than a box-shadow, so it follows the bezel PNG's
       silhouette instead of casting a rectangle. */
    --lift: 0 2rem 3.5rem -1.5rem rgba(35, 30, 20, 0.45);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;
        --stage: #080807;
        --paper: #0f0f0d;
        --surface: #181815;
        --surface-2: #1a1a17;
        --surface-3: #24231f;
        --ink: #f4f1e8;
        --ink-2: #d6d2c6;
        --muted: #9c978a;
        --faint: #78746a;
        --line: #2b2a25;
        --line-2: #22211d;
        --track: #26251f;
        --violet: #c9b3f2;
        --violet-soft: #241c33;
        --violet-line: #3a2f52;
        --green: #7bcba2;
        --green-soft: #15251d;
        --brick: #e89a8a;
        --brick-soft: #2e1c18;
        --amber: #e5b072;
        --focus: #c9b3f2;
        --lift: 0 2rem 3.5rem -1.5rem rgba(0, 0, 0, 0.8);

        /* Nightfall: the pill is the sky, the knob the moon, craters and
           stars appear. */
        --toggle-track: var(--toggle-night);
        --toggle-track-edge: var(--toggle-night-edge);
        --toggle-knob: var(--toggle-moon);
        --toggle-knob-x: 1.625rem;
        --toggle-craters: 1;
        --toggle-stars: 1;
        --toggle-stars-y: 0rem;
    }
}

:root[data-theme="dark"] {
    color-scheme: dark;
    --stage: #080807;
    --paper: #0f0f0d;
    --surface: #181815;
    --surface-2: #1a1a17;
    --surface-3: #24231f;
    --ink: #f4f1e8;
    --ink-2: #d6d2c6;
    --muted: #9c978a;
    --faint: #78746a;
    --line: #2b2a25;
    --line-2: #22211d;
    --track: #26251f;
    --violet: #c9b3f2;
    --violet-soft: #241c33;
    --violet-line: #3a2f52;
    --green: #7bcba2;
    --green-soft: #15251d;
    --brick: #e89a8a;
    --brick-soft: #2e1c18;
    --amber: #e5b072;
    --focus: #c9b3f2;
    --lift: 0 2rem 3.5rem -1.5rem rgba(0, 0, 0, 0.8);

    /* Nightfall — see the media-query block above. */
    --toggle-track: var(--toggle-night);
    --toggle-track-edge: var(--toggle-night-edge);
    --toggle-knob: var(--toggle-moon);
    --toggle-knob-x: 1.625rem;
    --toggle-craters: 1;
    --toggle-stars: 1;
    --toggle-stars-y: 0rem;
}

/* ── 3. Base ───────────────────────────────────────────────────────────── */

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

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
}

body {
    margin: 0;
    background: var(--stage);
    color: var(--ink);
    font-family: var(--font);
    font-size: var(--fs-body);
    line-height: 1.65;
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

/* `height: auto` matters: the <img> elements carry width/height attributes so
   the browser reserves the right aspect ratio before the file loads, and
   without it the attribute's height wins over the CSS width. */
img {
    max-width: 100%;
    height: auto;
    display: block;
}

a {
    color: var(--violet);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

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

::selection {
    background: var(--violet-soft);
    color: var(--ink);
}

.skip-link {
    position: absolute;
    left: var(--sp-lg);
    top: -4rem;
    z-index: 200;
    background: var(--ink);
    color: var(--paper);
    padding: 0.75rem 1.25rem;
    border-radius: var(--r-sm);
    font-size: var(--fs-small);
    font-weight: 700;
    transition: top 0.18s ease;
}

.skip-link:focus {
    top: var(--sp-lg);
    text-decoration: none;
}

.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;
}

/* ── 4. Type ───────────────────────────────────────────────────────────── */

h1,
h2,
h3,
h4 {
    margin: 0;
    color: var(--ink);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.1;
    text-wrap: balance;
}

h1 {
    font-size: var(--fs-h1);
    letter-spacing: -0.028em;
}

h2 {
    font-size: var(--fs-h2);
    letter-spacing: -0.022em;
}

h3 {
    font-size: var(--fs-h3);
    font-weight: 700;
    letter-spacing: -0.012em;
    line-height: 1.25;
}

h4 {
    font-size: var(--fs-h4);
    font-weight: 700;
    line-height: 1.35;
}

p {
    margin: 0 0 var(--sp-lg);
}

p:last-child {
    margin-bottom: 0;
}

.lead {
    font-size: var(--fs-lead);
    line-height: 1.55;
    color: var(--muted);
    max-width: 34rem;
}

.eyebrow {
    display: block;
    font-size: var(--fs-eyebrow);
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--faint);
    margin-bottom: var(--sp-md);
}

.eyebrow--violet {
    color: var(--violet);
}

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

.faint {
    color: var(--faint);
}

code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.8125em;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--r-xs);
    padding: 0.1em 0.4em;
    word-break: break-word;
}

/* Every number in the system: tabular so columns never jitter. */
.num,
.money {
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.03em;
    font-weight: 700;
}

/* ── 5. Layout ─────────────────────────────────────────────────────────── */

.container {
    width: 100%;
    max-width: var(--max);
    margin-inline: auto;
    padding-inline: var(--sp-2xl);
}

.container--prose {
    max-width: var(--prose);
}

.section {
    padding-block: var(--sp-6xl);
    scroll-margin-top: calc(var(--nav-h) + var(--sp-xl));
}

.section--tight {
    padding-block: var(--sp-5xl);
}

.section--paper {
    background: var(--paper);
}

.section--ink {
    background: var(--ink);
    color: var(--paper);
}

.section--ink h1,
.section--ink h2,
.section--ink h3,
.section--ink h4 {
    color: var(--paper);
}

.section--ink .eyebrow {
    color: var(--violet);
}

.section--ink .lead,
.section--ink .muted {
    color: color-mix(in srgb, var(--paper) 70%, transparent);
}

.rule {
    height: 1px;
    background: var(--line);
    border: 0;
    margin: 0;
}

.section-head {
    max-width: 42rem;
    margin-bottom: var(--sp-4xl);
}

.section-head--center {
    margin-inline: auto;
    text-align: center;
}

.section-head h2 {
    margin-bottom: var(--sp-md);
}

.grid {
    display: grid;
    gap: var(--sp-lg);
}

.grid--2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.grid--3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.grid--4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* ── 6. Header ─────────────────────────────────────────────────────────── */

.site-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: color-mix(in srgb, var(--stage) 88%, transparent);
    backdrop-filter: saturate(1.4) blur(14px);
    -webkit-backdrop-filter: saturate(1.4) blur(14px);
    border-bottom: 1px solid var(--line);
}

.site-header__inner {
    height: var(--nav-h);
    display: flex;
    align-items: center;
    gap: var(--sp-lg);
}

.logo {
    display: inline-flex;
    align-items: baseline;
    gap: 0.375rem;
    color: var(--ink);
    font-size: 1.125rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    white-space: nowrap;
}

.logo:hover {
    text-decoration: none;
}

.logo em {
    font-style: normal;
    color: var(--violet);
}

.logo__dot {
    width: 0.25rem;
    height: 0.25rem;
    border-radius: 50%;
    background: var(--violet);
    align-self: center;
    margin-left: 0.125rem;
}

.nav {
    margin-left: auto;
}

.nav ul {
    display: flex;
    align-items: center;
    gap: var(--sp-lg);
    list-style: none;
    margin: 0;
    padding: 0;
}

.nav a {
    color: var(--ink-2);
    font-size: var(--fs-small);
    font-weight: 600;
    letter-spacing: -0.005em;
}

.nav a:hover {
    color: var(--ink);
    text-decoration: none;
}

.header-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-sm);
    margin-left: var(--sp-xl);
}

.icon-btn {
    width: 2.5rem;
    height: 2.5rem;
    display: grid;
    place-items: center;
    flex: none;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--surface);
    color: var(--ink-2);
    cursor: pointer;
    padding: 0;
    transition: border-color 0.16s ease, color 0.16s ease;
}

.icon-btn:hover {
    border-color: var(--ink-2);
    color: var(--ink);
}

.icon-btn svg {
    width: 1.125rem;
    height: 1.125rem;
}

/* The theme switch: a 60×34 pill whose knob is the sun by day and the moon
   by night, with clouds drifting across it and stars that come out after
   dark. Structure and motion follow RiccardoRapelli's MIT-licensed Uiverse
   switch "jolly-chicken-91" (notice: docs/licenses/MIT-RiccardoRapelli-
   ThemeSwitch.txt); the colours are the Quiet Ledger tokens above, so the
   control belongs to this site rather than sitting on top of it. */

.theme-toggle {
    position: relative;
    display: inline-flex;
    flex: none;
    width: 3.75rem;
    height: 2.125rem;
    cursor: pointer;
}

/* The real control covers the whole pill: the pill is paint, the checkbox is
   what the browser and assistive technology operate. `opacity: 0` rather than
   `display: none` keeps it focusable and clickable. */
.theme-toggle__input {
    position: absolute;
    inset: 0;
    z-index: 3;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}

/* A 44px-tall tap target without making the pill look 44px tall. */
.theme-toggle::before {
    content: "";
    position: absolute;
    inset: -0.3125rem -0.25rem;
}

.theme-toggle__track {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    border: 1px solid var(--toggle-track-edge);
    border-radius: var(--r-pill);
    background: var(--toggle-track);
    transition: background-color 0.4s ease, border-color 0.4s ease;
}

.theme-toggle__input:focus-visible + .theme-toggle__track {
    outline: 2px solid var(--focus);
    outline-offset: 3px;
}

/* The knob: the sun in daylight, the moon at night. The craters, rays and
   clouds inside it are the Uiverse component's own drawing. */
.theme-toggle__sun-moon {
    position: absolute;
    left: 0.25rem;
    bottom: 0.25rem;
    width: 1.625rem;
    height: 1.625rem;
    border-radius: 50%;
    background: var(--toggle-knob);
    transform: translateX(var(--toggle-knob-x));
    transition: transform 0.4s ease, background-color 0.4s ease;
}

.theme-toggle__moon-dot {
    position: absolute;
    fill: var(--toggle-crater);
    opacity: var(--toggle-craters);
    transition: opacity 0.4s ease;
}

.theme-toggle__moon-dot--1 {
    left: 0.625rem;
    top: 0.1875rem;
    width: 0.375rem;
    height: 0.375rem;
    z-index: 4;
}

.theme-toggle__moon-dot--2 {
    left: 0.125rem;
    top: 0.625rem;
    width: 0.625rem;
    height: 0.625rem;
    z-index: 4;
}

.theme-toggle__moon-dot--3 {
    left: 1rem;
    top: 1.125rem;
    width: 0.1875rem;
    height: 0.1875rem;
    z-index: 4;
}

.theme-toggle__light-ray {
    position: absolute;
    z-index: -1;
    fill: var(--toggle-moon);
    opacity: 0.1;
}

.theme-toggle__light-ray--1 {
    left: -0.5rem;
    top: -0.5rem;
    width: 2.6875rem;
    height: 2.6875rem;
}

.theme-toggle__light-ray--2 {
    left: -50%;
    top: -50%;
    width: 3.4375rem;
    height: 3.4375rem;
}

.theme-toggle__light-ray--3 {
    left: -1.125rem;
    top: -1.125rem;
    width: 3.75rem;
    height: 3.75rem;
}

.theme-toggle__cloud {
    position: absolute;
    animation: theme-toggle-cloud 6s ease-in-out infinite;
}

.theme-toggle__cloud--pale {
    fill: var(--toggle-cloud);
}

.theme-toggle__cloud--shade {
    fill: var(--toggle-cloud-shade);
    animation-delay: 1s;
}

.theme-toggle__cloud--1 { left: 1.875rem; top: 0.9375rem; width: 2.5rem; }
.theme-toggle__cloud--2 { left: 2.75rem; top: 0.625rem; width: 1.25rem; }
.theme-toggle__cloud--3 { left: 1.125rem; top: 1.5rem; width: 1.875rem; }
.theme-toggle__cloud--4 { left: 2.25rem; top: 1.125rem; width: 2.5rem; }
.theme-toggle__cloud--5 { left: 3rem; top: 0.875rem; width: 1.25rem; }
.theme-toggle__cloud--6 { left: 1.375rem; top: 1.625rem; width: 1.875rem; }

@keyframes theme-toggle-cloud {
    0% { transform: translateX(0); }
    40% { transform: translateX(0.25rem); }
    80% { transform: translateX(-0.25rem); }
    100% { transform: translateX(0); }
}

/* The stars belong to the track, not the knob: they rise into the empty
   left half as the moon slides right. */
.theme-toggle__stars {
    display: block;
    height: 0;
    opacity: var(--toggle-stars);
    transform: translateY(var(--toggle-stars-y));
    transition: transform 0.4s ease, opacity 0.4s ease;
}

.theme-toggle__star {
    position: absolute;
    fill: var(--toggle-star);
    animation: theme-toggle-twinkle 2s ease-in-out infinite;
}

.theme-toggle__star--1 { width: 1.25rem; top: 0.125rem; left: 0.1875rem; animation-delay: 0.3s; }
.theme-toggle__star--2 { width: 0.375rem; top: 1rem; left: 0.1875rem; }
.theme-toggle__star--3 { width: 0.75rem; top: 1.25rem; left: 0.625rem; animation-delay: 0.6s; }
.theme-toggle__star--4 { width: 1.125rem; top: 0; left: 1.125rem; animation-delay: 1.3s; }

@keyframes theme-toggle-twinkle {
    0% { transform: scale(1); }
    40% { transform: scale(1.2); }
    80% { transform: scale(0.8); }
    100% { transform: scale(1); }
}

.menu-toggle {
    display: none;
}

/* ── 7. Buttons ────────────────────────────────────────────────────────── */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 3rem;
    padding: 0.75rem 1.375rem;
    border-radius: var(--r-pill);
    border: 1px solid transparent;
    font-family: inherit;
    font-size: 0.9375rem;
    font-weight: 700;
    letter-spacing: -0.008em;
    line-height: 1;
    cursor: pointer;
    text-align: center;
    transition: background-color 0.16s ease, border-color 0.16s ease,
        color 0.16s ease;
}

.btn:hover {
    text-decoration: none;
}

.btn svg {
    width: 1.0625rem;
    height: 1.0625rem;
    flex: none;
}

.btn--primary {
    background: var(--ink);
    color: var(--paper);
}

.btn--primary:hover {
    background: var(--ink-2);
    color: var(--paper);
}

:root[data-theme="dark"] .btn--primary {
    background: var(--paper);
    color: var(--ink);
}

:root[data-theme="dark"] .btn--primary:hover {
    background: var(--ink-2);
    color: var(--ink);
}

.btn--violet {
    background: var(--violet);
    color: #fff;
}

.btn--violet:hover {
    background: color-mix(in srgb, var(--violet) 88%, #000);
    color: #fff;
}

.btn--ghost {
    background: var(--surface);
    border-color: var(--line);
    color: var(--ink);
}

.btn--ghost:hover {
    border-color: var(--ink-2);
    color: var(--ink);
}

.btn--sm {
    min-height: 2.375rem;
    padding: 0.5rem 0.875rem;
    font-size: var(--fs-small);
}

.btn--block {
    width: 100%;
}

.btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-sm);
    align-items: center;
}

/* A text link with an arrow, the app's "section action" pattern. */
.link-arrow {
    color: var(--violet);
    font-size: var(--fs-small);
    font-weight: 600;
}

.link-arrow::after {
    content: " →";
}

/* ── 8. Chips & badges ─────────────────────────────────────────────────── */

.chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    height: 1.75rem;
    padding: 0 0.625rem;
    border-radius: var(--r-pill);
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink-2);
    font-size: var(--fs-micro);
    font-weight: 600;
    letter-spacing: -0.004em;
    white-space: nowrap;
}

.chip--violet {
    background: var(--violet-soft);
    border-color: transparent;
    color: var(--violet);
}

.chip--green {
    background: var(--green-soft);
    border-color: transparent;
    color: var(--green);
}

.chip--ink {
    background: var(--ink);
    border-color: transparent;
    color: var(--paper);
}

.chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-sm);
}

/* The trust ledger: a hairline row of facts under the hero. */
.fact-strip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-sm) var(--sp-xl);
    padding-top: var(--sp-xl);
    border-top: 1px solid var(--line);
    margin-top: var(--sp-2xl);
    list-style: none;
    margin-block: var(--sp-2xl) 0;
    padding-inline: 0;
}

.fact-strip li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    list-style: none;
    font-size: var(--fs-small);
    color: var(--ink-2);
    font-weight: 600;
}

.fact-strip svg {
    width: 1rem;
    height: 1rem;
    color: var(--green);
    flex: none;
}

/* ── 9. Hero ───────────────────────────────────────────────────────────── */

.hero {
    padding-block: var(--sp-6xl) var(--sp-6xl);
    position: relative;
    overflow: hidden;
}

.hero__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: var(--sp-5xl);
    align-items: center;
}

.hero h1 {
    font-size: var(--fs-display);
    letter-spacing: -0.035em;
    line-height: 1.03;
    margin-bottom: var(--sp-xl);
}

.hero h1 em {
    font-style: normal;
    color: var(--violet);
}

.hero .lead {
    margin-bottom: var(--sp-2xl);
    max-width: 30rem;
}

.hero__meta {
    font-size: var(--fs-small);
    color: var(--faint);
    margin-top: var(--sp-lg);
}

/* ── 10. The iPhone frame ───────────────────────────────────────────────
   The same device the Play Store deck uses, built from the same numbers:
   the skill template's `mockup.png` (1022×2082) with the capture dropped
   into the screen rect that was measured for it (PHONE_SCREEN in
   `docs/store/src/lib/constants.ts`), the Android chrome cropped away, and
   the concept's own iOS chrome drawn in its place (IPHONE_CHROME). The site
   and the store deck are therefore the same picture.

   The capture is nudged down by (46 − 24)px — 46 is the height of the drawn
   iOS status bar, 24 the height of the Android one the captures carry — so
   the Android row lands exactly behind the drawn band, and the gesture pill
   falls off the bottom. The band is painted in the app's own background
   colour, so the strip above the shifted capture reads as the device rather
   than as a gap. */

.iphone {
    position: relative;
    width: 100%;
    max-width: 21rem;
    margin-inline: auto;
    aspect-ratio: 1022 / 2082;
    filter: drop-shadow(var(--lift));
}

.iphone__bezel {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    z-index: 0;
}

.iphone__screen {
    position: absolute;
    left: 5.088%;
    top: 2.209%;
    width: 89.824%;
    height: 95.581%;
    overflow: hidden;
    border-radius: 13.725% / 6.332%;
    background: var(--paper);
    z-index: 1;
}

.iphone__capture {
    position: absolute;
    left: 0;
    top: 2.607%;
    width: 100%;
    height: auto;
    display: block;
}

/* The band that hides the capture's own Android status bar. */
.iphone__band {
    position: absolute;
    inset: 0 0 auto 0;
    height: 5.451%;
    background: var(--paper);
    z-index: 2;
}

.iphone__chrome {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: auto;
    display: block;
    font-family: var(--font);
    color: var(--ink);
    z-index: 3;
}

/* A stadium, not a circle: `border-radius: 50%` on a 4:1 box draws an
   ellipse, and the island is the one shape that tells the eye it is an
   iPhone before it has read a single word. */
.iphone__island {
    position: absolute;
    top: 1.303%;
    left: 50%;
    transform: translateX(-50%);
    width: 26.667%;
    aspect-ratio: 104 / 26;
    border-radius: 999px;
    background: #000;
    z-index: 4;
}

.iphone--sm {
    max-width: 15.5rem;
}

/* ── 11. Cards ─────────────────────────────────────────────────────────── */

.card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-2xl);
}

.card--flat {
    background: transparent;
}

.card--paper {
    background: var(--paper);
}

.card--ink {
    background: var(--ink);
    border-color: transparent;
    color: var(--paper);
}

.card--ink h3,
.card--ink h4 {
    color: var(--paper);
}

.card__icon {
    width: 2.75rem;
    height: 2.75rem;
    display: grid;
    place-items: center;
    border-radius: var(--r-md);
    background: var(--violet-soft);
    color: var(--violet);
    margin-bottom: var(--sp-lg);
}

.card__icon svg {
    width: 1.375rem;
    height: 1.375rem;
}

.card h3 {
    margin-bottom: var(--sp-sm);
}

.card p {
    color: var(--muted);
    font-size: var(--fs-small);
    line-height: 1.6;
    margin: 0;
}

/* A card that links somewhere. */
.card--link {
    display: block;
    color: inherit;
    transition: border-color 0.16s ease, background-color 0.16s ease;
}

.card--link:hover {
    text-decoration: none;
    border-color: var(--ink-2);
}

/* ── 12. Feature tour ──────────────────────────────────────────────────── */

.feature {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--sp-4xl);
    align-items: center;
    padding-block: var(--sp-5xl);
    border-top: 1px solid var(--line);
}

.feature:first-of-type {
    border-top: 0;
    padding-top: 0;
}

.feature--flip .feature__media {
    order: -1;
}

.feature__body h3 {
    font-size: var(--fs-h2);
    letter-spacing: -0.022em;
    margin-bottom: var(--sp-md);
}

.feature__body .lead {
    margin-bottom: var(--sp-xl);
    max-width: 30rem;
}

/* The app's own checklist: a small ink dot, no ring, no gradient. */
.checklist {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--sp-md);
}

.checklist li {
    position: relative;
    padding-left: 1.75rem;
    color: var(--ink-2);
    font-size: var(--fs-small);
    line-height: 1.6;
}

.checklist li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.5em;
    width: 0.4375rem;
    height: 0.4375rem;
    border-radius: 50%;
    background: var(--violet);
}

.checklist strong {
    color: var(--ink);
    font-weight: 700;
}

.feature__media {
    display: grid;
    place-items: center;
}

/* ── 13. The transformation (SMS → ledger) ─────────────────────────────── */

.transform {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr);
    gap: var(--sp-lg);
    align-items: stretch;
}

.transform__step {
    display: flex;
    flex-direction: column;
    gap: var(--sp-md);
    min-width: 0;
}

.transform__label {
    font-size: var(--fs-eyebrow);
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--faint);
}

.transform__arrow {
    display: grid;
    place-items: center;
    color: var(--faint);
    padding-top: 1.75rem;
}

.transform__arrow svg {
    width: 1.5rem;
    height: 1.5rem;
}

/* An SMS bubble, drawn in HTML. */
.sms {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-lg);
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--sp-sm);
}

.sms__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-md);
    font-size: var(--fs-micro);
    font-weight: 700;
    color: var(--ink-2);
}

.sms__head span {
    color: var(--faint);
    font-weight: 500;
}

.sms__body {
    margin: 0;
    font-size: var(--fs-small);
    line-height: 1.6;
    color: var(--ink-2);
}

.sms__foot {
    margin: auto 0 0;
    padding-top: var(--sp-lg);
    border-top: 1px solid var(--line-2);
    font-size: var(--fs-micro);
    color: var(--faint);
    line-height: 1.5;
}

/* The parsed fields, as the app's own detail rows. */
.parse {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-lg);
    flex: 1;
    display: grid;
    align-content: start;
    gap: var(--sp-md);
}

.parse__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-md);
    font-size: var(--fs-small);
    border-bottom: 1px solid var(--line-2);
    padding-bottom: var(--sp-md);
}

.parse__row:last-child {
    border-bottom: 0;
    padding-bottom: 0;
}

.parse__row dt {
    color: var(--faint);
    font-weight: 500;
}

.parse__row dd {
    margin: 0;
    color: var(--ink);
    font-weight: 700;
    text-align: right;
}

/* A transaction row, exactly as the app renders it. */
.ledger {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-md) var(--sp-lg);
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--sp-md);
}

.txn {
    display: flex;
    align-items: center;
    gap: var(--sp-md);
}

.txn + .txn {
    border-top: 1px solid var(--line-2);
    padding-top: var(--sp-md);
}

.txn__avatar {
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    display: grid;
    place-items: center;
    flex: none;
    background: color-mix(in srgb, var(--cat, var(--violet)) 14%, transparent);
    color: var(--cat, var(--violet));
}

.txn__avatar svg {
    width: 1.125rem;
    height: 1.125rem;
}

.txn__body {
    min-width: 0;
    flex: 1;
}

.txn__title {
    display: block;
    font-size: 0.84375rem;
    font-weight: 600;
    letter-spacing: -0.012em;
    color: var(--ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.txn__meta {
    display: block;
    font-size: 0.71875rem;
    color: var(--muted);
    line-height: 1.4;
}

.txn__amount {
    font-size: 0.84375rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
    white-space: nowrap;
    color: var(--ink);
}

.txn__amount--in {
    color: var(--green);
}

.txn__amount--out {
    color: var(--ink);
}

.ledger__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-md);
    font-size: var(--fs-micro);
    color: var(--faint);
    border-top: 1px solid var(--line-2);
    padding-top: var(--sp-md);
}

/* ── 14. The triage card ───────────────────────────────────────────────── */

.triage {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    overflow: hidden;
}

.triage__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-md);
    padding: var(--sp-lg);
    border-bottom: 1px solid var(--line);
}

.triage__count {
    font-size: var(--fs-small);
    font-weight: 700;
    color: var(--ink);
}

.triage__row {
    display: flex;
    align-items: center;
    gap: var(--sp-md);
    padding: var(--sp-lg);
    border-bottom: 1px solid var(--line-2);
}

.triage__row:last-child {
    border-bottom: 0;
}

.triage__actions {
    display: flex;
    gap: var(--sp-sm);
    margin-left: auto;
    flex: none;
}

.triage__btn {
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    display: grid;
    place-items: center;
    border: 1px solid var(--line);
    background: transparent;
    color: var(--muted);
}

.triage__btn svg {
    width: 1rem;
    height: 1rem;
}

.triage__btn--save {
    color: var(--green);
    border-color: color-mix(in srgb, var(--green) 34%, transparent);
}

.triage__btn--skip {
    color: var(--faint);
}

.triage__foot {
    padding: var(--sp-md) var(--sp-lg);
    background: var(--surface-2);
    font-size: var(--fs-micro);
    color: var(--muted);
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-md);
    justify-content: space-between;
}

/* ── 15. The privacy ledger (a two-column table) ───────────────────────── */

.ledger-table {
    width: 100%;
    border-collapse: collapse;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--surface);
}

.ledger-table caption {
    text-align: left;
    font-size: var(--fs-small);
    color: var(--muted);
    padding: 0 0 var(--sp-lg);
}

.ledger-table th,
.ledger-table td {
    text-align: left;
    padding: var(--sp-lg);
    vertical-align: top;
    border-bottom: 1px solid var(--line-2);
    font-size: var(--fs-small);
    line-height: 1.6;
}

.ledger-table thead th {
    font-size: var(--fs-micro);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--faint);
    font-weight: 700;
    border-bottom: 1px solid var(--line);
}

.ledger-table tbody tr:last-child td {
    border-bottom: 0;
}

.ledger-table td:first-child {
    color: var(--ink);
    font-weight: 700;
    width: 30%;
}

/* A five-column comparison needs more room than the 46rem prose measure.
   The table breaks out of the column symmetrically, so the text stays
   readable without changing the page's grid. */
.prose > .ledger-table {
    width: min(64rem, calc(100vw - 3rem));
    margin-inline: calc((100% - min(64rem, calc(100vw - 3rem))) / 2);
    margin-block: var(--sp-2xl);
}

.prose > .ledger-table td:first-child {
    width: 18%;
}

.ledger-table--two thead th:nth-child(1) {
    width: 50%;
}

/* A row that says "this stays here" versus "this can leave". */
.stays {
    color: var(--green);
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.leaves {
    color: var(--amber);
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.stays svg,
.leaves svg {
    width: 0.9375rem;
    height: 0.9375rem;
    flex: none;
}

/* ── 16. Open-source proof ─────────────────────────────────────────────── */

.proof {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1px;
    background: var(--line);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    overflow: hidden;
}

.proof__cell {
    background: var(--surface);
    padding: var(--sp-2xl);
}

.proof__cell dt {
    font-size: var(--fs-eyebrow);
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--faint);
    margin-bottom: var(--sp-sm);
}

.proof__cell dd {
    margin: 0;
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

.proof__cell p {
    margin: var(--sp-sm) 0 0;
    font-size: var(--fs-micro);
    color: var(--muted);
    line-height: 1.5;
}

/* ── 17. Distribution channels ─────────────────────────────────────────── */

.channel {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-2xl);
    display: flex;
    flex-direction: column;
    gap: var(--sp-md);
}

.channel__head {
    display: flex;
    align-items: center;
    gap: var(--sp-md);
}

.channel__head h3 {
    font-size: 1.0625rem;
}

.channel__logo {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--r-sm);
    display: grid;
    place-items: center;
    background: var(--surface-2);
    border: 1px solid var(--line);
    color: var(--ink);
    flex: none;
}

.channel__logo svg {
    width: 1.25rem;
    height: 1.25rem;
}

.channel p {
    color: var(--muted);
    font-size: var(--fs-small);
    margin: 0;
}

.channel .chip {
    align-self: flex-start;
}

.channel .btn {
    margin-top: auto;
    align-self: flex-start;
}

.channel__note {
    font-size: var(--fs-micro);
    color: var(--faint);
    line-height: 1.5;
}

/* ── 18. FAQ ───────────────────────────────────────────────────────────── */

.faq {
    display: grid;
    gap: 0;
    border-top: 1px solid var(--line);
}

/* A group heading inside a page that is not a .prose block. */
.qhead {
    margin: var(--sp-4xl) 0 var(--sp-lg);
    font-size: 1.5rem;
    letter-spacing: -0.02em;
}

.qhead:first-child {
    margin-top: 0;
}

/* A numbered section in a legal or reference page. */
.lsec {
    padding-top: var(--sp-3xl);
    margin-top: var(--sp-3xl);
    border-top: 1px solid var(--line);
}

.lsec:first-of-type {
    padding-top: 0;
    margin-top: 0;
    border-top: 0;
}

.lsec > h2 {
    font-size: 1.5rem;
    margin-bottom: var(--sp-md);
    scroll-margin-top: calc(var(--nav-h) + var(--sp-xl));
}

.lsec > h3 {
    margin-top: var(--sp-2xl);
    margin-bottom: var(--sp-sm);
    scroll-margin-top: calc(var(--nav-h) + var(--sp-xl));
}

.lsec > p,
.lsec > ul,
.lsec > ol {
    margin-bottom: var(--sp-lg);
}

.lsec > ul,
.lsec > ol {
    padding-left: 1.25rem;
}

.lsec li {
    margin-bottom: var(--sp-sm);
    font-size: var(--fs-small);
    line-height: 1.7;
    color: var(--ink-2);
}

.lsec li strong {
    color: var(--ink);
}

.faq details {
    border-bottom: 1px solid var(--line);
}

.faq summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-lg);
    padding: var(--sp-xl) 0;
    cursor: pointer;
    list-style: none;
    font-size: 1.0625rem;
    font-weight: 700;
    letter-spacing: -0.012em;
    color: var(--ink);
}

.faq summary::-webkit-details-marker {
    display: none;
}

.faq summary::after {
    content: "";
    width: 0.875rem;
    height: 0.875rem;
    flex: none;
    border-right: 2px solid var(--faint);
    border-bottom: 2px solid var(--faint);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform 0.18s ease;
    /* The 3px that gave the FAQ list a horizontal scroll.
     *
     * A 14×14 box rotated 45° does not paint 14×14 — it paints its
     * *diagonal*, 19.8×19.8, which is 2.9px wider than the box on each
     * side. A rotated box's painted area counts towards the scrollable
     * overflow of its container, so the summary was 3px wider than the
     * column it sat in (323 in 320) even though nothing was clipped and
     * the page never scrolled sideways.
     *
     * The margin gives the box the room its own rotation needs: the flex
     * item's outer box becomes 20px, the element sits in the middle of it,
     * and the painted diamond lands exactly on the column's edge. The
     * chevron is the same size and shape as before — it moves 3px left,
     * which is where it should have been all along.
     */
    margin: 3px;
}

.faq details[open] summary::after {
    transform: rotate(-135deg) translate(-2px, -2px);
}

.faq summary:hover {
    color: var(--violet);
}

.faq__answer {
    padding-bottom: var(--sp-xl);
    max-width: 44rem;
    color: var(--muted);
    font-size: var(--fs-small);
    line-height: 1.65;
}

.faq__answer p:last-child {
    margin-bottom: 0;
}

/* ── 19. Screenshots gallery ───────────────────────────────────────────── */

.shots {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-4xl) var(--sp-2xl);
}

.shot {
    display: grid;
    gap: var(--sp-md);
    justify-items: center;
    text-align: center;
}

/* The bezel *is* the frame here, so there is no card around it — the phone
   fills its column and the caption sits under it. */
.shot .iphone {
    max-width: 100%;
}

.shot figcaption {
    font-size: var(--fs-small);
    font-weight: 700;
    color: var(--ink);
}

.shot p {
    margin: 0;
    font-size: var(--fs-micro);
    color: var(--muted);
    line-height: 1.5;
    max-width: 22ch;
}

/* ── 20. Legal pages ───────────────────────────────────────────────────── */

.page-head {
    padding-block: var(--sp-5xl) var(--sp-4xl);
    border-bottom: 1px solid var(--line);
    margin-bottom: var(--sp-4xl);
}

.page-head h1 {
    font-size: var(--fs-h1);
    margin-bottom: var(--sp-md);
}

.page-head .lead {
    max-width: 40rem;
}

.page-head .updated {
    font-size: var(--fs-micro);
    color: var(--faint);
    margin: var(--sp-lg) 0 0;
}

.prose {
    max-width: var(--prose);
}

.prose h2 {
    font-size: 1.5rem;
    margin-top: var(--sp-4xl);
    margin-bottom: var(--sp-md);
    scroll-margin-top: calc(var(--nav-h) + var(--sp-xl));
}

.prose h3 {
    font-size: 1.0625rem;
    margin-top: var(--sp-2xl);
    margin-bottom: var(--sp-sm);
}

.prose p,
.prose li {
    color: var(--ink-2);
    font-size: var(--fs-small);
    line-height: 1.7;
}

.prose ul,
.prose ol {
    padding-left: 1.25rem;
    margin: 0 0 var(--sp-lg);
}

.prose li {
    margin-bottom: var(--sp-sm);
}

.prose strong {
    color: var(--ink);
}

.prose code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.8125em;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--r-xs);
    padding: 0.1em 0.4em;
    word-break: break-word;
}

.prose a {
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

.note {
    background: var(--violet-soft);
    border-left: 2px solid var(--violet);
    border-radius: 0 var(--r-sm) var(--r-sm) 0;
    padding: var(--sp-lg);
    margin: 0 0 var(--sp-lg);
}

.note p {
    color: var(--ink-2);
    margin: 0;
}

.summary {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-2xl);
    margin-bottom: var(--sp-4xl);
}

.summary h2 {
    font-size: 1.125rem;
    margin: 0 0 var(--sp-md);
}

.summary ul {
    margin: 0;
}

.summary li {
    color: var(--ink-2);
    font-size: var(--fs-small);
}

.toc {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-xl);
    margin-bottom: var(--sp-4xl);
}

.toc h2 {
    font-size: var(--fs-micro);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--faint);
    margin: 0 0 var(--sp-md);
}

.toc ol {
    margin: 0;
    padding-left: 1.25rem;
    columns: 2;
    column-gap: var(--sp-xl);
}

.toc li {
    font-size: var(--fs-small);
    color: var(--ink-2);
    margin-bottom: var(--sp-xs);
    break-inside: avoid;
}

.toc a {
    color: var(--ink-2);
}

.toc a:hover {
    color: var(--violet);
}

.table-wrap {
    overflow-x: auto;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    margin-bottom: var(--sp-lg);
}

.table-wrap table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-small);
}

.table-wrap th,
.table-wrap td {
    text-align: left;
    padding: var(--sp-md) var(--sp-lg);
    border-bottom: 1px solid var(--line-2);
    vertical-align: top;
    color: var(--ink-2);
}

.table-wrap thead th {
    background: var(--surface-2);
    font-size: var(--fs-micro);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--faint);
    border-bottom: 1px solid var(--line);
}

.table-wrap tbody tr:last-child td {
    border-bottom: 0;
}

/* ── 21. Changelog ─────────────────────────────────────────────────────── */

.release {
    display: grid;
    grid-template-columns: 12rem minmax(0, 1fr);
    gap: var(--sp-3xl);
    padding-block: var(--sp-3xl);
    border-top: 1px solid var(--line);
    scroll-margin-top: calc(var(--nav-h) + var(--sp-xl));
}

.release:first-of-type {
    border-top: 0;
    padding-top: 0;
}

.release__meta {
    position: sticky;
    top: calc(var(--nav-h) + var(--sp-xl));
    align-self: start;
}

.release__version {
    font-size: 1.375rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.release__date {
    font-size: var(--fs-micro);
    color: var(--faint);
    margin-top: var(--sp-xs);
}

.release__body h3 {
    font-size: var(--fs-micro);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--faint);
    margin: var(--sp-lg) 0 var(--sp-md);
}

.release__body h3:first-child {
    margin-top: 0;
}

.release__body ul {
    margin: 0;
    padding-left: 1.125rem;
}

.release__body li {
    color: var(--ink-2);
    font-size: var(--fs-small);
    line-height: 1.65;
    margin-bottom: var(--sp-sm);
}

.release__body p {
    color: var(--ink-2);
    font-size: var(--fs-small);
    line-height: 1.65;
}

.release__body code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.8125em;
    background: var(--surface-2);
    border-radius: var(--r-xs);
    padding: 0.1em 0.35em;
}

/* ── 22. CTA band ──────────────────────────────────────────────────────── */

.cta {
    text-align: center;
}

.cta h2 {
    font-size: var(--fs-h1);
    letter-spacing: -0.028em;
    margin-bottom: var(--sp-md);
}

.cta .lead {
    margin-inline: auto;
    margin-bottom: var(--sp-2xl);
    max-width: 36rem;
}

.cta .btn-row {
    justify-content: center;
}

/* ── 23. Footer ────────────────────────────────────────────────────────── */

.site-footer {
    border-top: 1px solid var(--line);
    padding-block: var(--sp-4xl) var(--sp-2xl);
    margin-top: var(--sp-5xl);
}

.footer-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
    gap: var(--sp-3xl);
}

.footer-grid p {
    font-size: var(--fs-small);
    color: var(--muted);
    margin: var(--sp-md) 0 0;
    max-width: 22rem;
}

.footer-grid h3 {
    font-size: var(--fs-micro);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--faint);
    margin: 0 0 var(--sp-md);
}

.footer-grid ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    /* Paired with the links' own padding below: 6px of gap plus 1px of
       padding is the 8px it was before, so the column keeps its rhythm. */
    gap: 6px;
}

.footer-grid a {
    color: var(--ink-2);
    font-size: var(--fs-small);
    /* A link in a sentence is exempt from the target-size rule, because the
       line-height of the text around it constrains it. A list of links is
       not — these were a 23px line box, one pixel under the 24px minimum,
       and a thumb on a phone is not 23px either. Inline-block makes the
       link's own box its line box, so the padding is what carries it over. */
    display: inline-block;
    padding-block: 1px;
}

.footer-grid a:hover {
    color: var(--violet);
}

.footer-bottom {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-md);
    justify-content: space-between;
    border-top: 1px solid var(--line);
    margin-top: var(--sp-3xl);
    padding-top: var(--sp-xl);
    font-size: var(--fs-micro);
    color: var(--faint);
}

/* ── 24. Scroll reveal ─────────────────────────────────────────────────── */

/* The hidden state only applies when the script that reveals it has run.
   Without JavaScript the content must simply be there. */
.js .reveal {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.5s ease, transform 0.5s ease;
}

.js .reveal.is-in {
    opacity: 1;
    transform: none;
}

/* ── 27. The 404 ──────────────────────────────────────────────────────────
   GitHub Pages serves this for any address that does not exist, so a
   stranger who follows a stale link lands here rather than on GitHub's own
   page. The numeral is set in the track colour — the same colour an empty
   progress bar is — so it reads as part of the system rather than as an
   alarm. */

.notfound {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--sp-4xl);
    align-items: center;
}

.notfound__body {
    max-width: 32rem;
}

.notfound__body h1 {
    font-size: var(--fs-h1);
    margin-bottom: var(--sp-md);
}

.notfound__body .lead {
    margin-bottom: var(--sp-2xl);
}

.notfound__numeral {
    font-size: clamp(6rem, 16vw, 13rem);
    font-weight: 800;
    letter-spacing: -0.05em;
    line-height: 0.8;
    color: var(--track);
    font-variant-numeric: tabular-nums;
    user-select: none;
}

/* ── 25. Responsive ────────────────────────────────────────────────────── */

@media (max-width: 1080px) {
    .grid--4,
    .proof {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .shots {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 960px) {
    :root {
        --sp-6xl: 4.5rem;
        --sp-5xl: 3.5rem;
    }

    .hero__grid,
    .feature {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--sp-3xl);
    }

    .feature--flip .feature__media {
        order: 0;
    }

    .feature__media {
        order: -1;
    }

    .grid--3 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .transform {
        grid-template-columns: minmax(0, 1fr);
    }

    .transform__arrow {
        padding-top: 0;
        transform: rotate(90deg);
        justify-self: center;
    }

    .footer-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .release {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--sp-lg);
    }

    .release__meta {
        position: static;
    }
}

@media (max-width: 860px) {
    .nav {
        display: none;
    }

    .nav.is-open {
        display: block;
        position: absolute;
        top: var(--nav-h);
        left: 0;
        right: 0;
        background: var(--stage);
        border-bottom: 1px solid var(--line);
        padding: var(--sp-lg) var(--sp-2xl) var(--sp-xl);
    }

    .nav.is-open ul {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--sp-lg);
    }

    .nav.is-open a {
        font-size: 1rem;
    }

    .header-actions {
        margin-left: auto;
    }

    .menu-toggle {
        display: grid;
    }
}

@media (max-width: 480px) {
    /* The nav already carries Download, and the hero repeats the call to
       action, so on a narrow phone the header keeps its logo, the theme
       switch and the menu — rather than wrapping "Get the app" onto two
       lines and squeezing the menu's tap target. */
    .header-cta {
        display: none;
    }
}

@media (max-width: 720px) {
    :root {
        --sp-6xl: 3.5rem;
        --sp-5xl: 3rem;
        --sp-4xl: 2.5rem;
    }

    .notfound {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--sp-2xl);
    }

    .container {
        padding-inline: var(--sp-xl);
    }

    .grid--2,
    .grid--3,
    .grid--4,
    .proof,
    .shots,
    .footer-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .toc ol {
        columns: 1;
    }

    .iphone {
        max-width: 15rem;
    }

    .btn {
        width: 100%;
    }

    .btn-row .btn {
        width: auto;
        flex: 1 1 auto;
    }

    .card {
        padding: var(--sp-xl);
    }
}

/* ── 26. Motion & print ────────────────────────────────────────────────── */

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

    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }

    .reveal,
    .js .reveal {
        opacity: 1;
        transform: none;
    }
}

@media print {
    .site-header,
    .site-footer,
    .skip-link {
        display: none;
    }

    body {
        background: #fff;
    }
}
