/*
 * The whole site's stylesheet.
 *
 * It used to be app-page.css, shared by the generated pages only, while the
 * five hand-written pages each carried their own inline <style> block. That
 * meant the nav, header, footer and buttons existed in six places, and they
 * had already drifted: four near-identical off-whites, five greys, and eight
 * font sizes inside a 0.2rem band.
 *
 * The rules here are in three layers, and the order matters:
 *
 *   1. Tokens          every color, size and shadow, named once
 *   2. Shared          chrome and components every page uses
 *   3. Page overrides  scoped under a .page-* class on <body>
 *
 * Layer 3 exists because some pages genuinely differ - contact's .card has no
 * accent border, /apps uses a dark store button where an app page uses a white
 * one - and scoping those is what lets layers 1 and 2 stay single copies.
 *
 * Nothing here may style a bare element selector outside a .page-* scope. The
 * contact and privacy blocks used to style label, textarea, h2, p and a
 * globally, which was safe only while nothing else loaded them.
 *
 * Colors come from tokens, with three deliberate exceptions that must NOT be
 * tokenized, because they have to stay put when the theme flips:
 *
 *   - ink on the amber button and on the CTA gradient. Both sit on a fixed
 *     background, so ink that followed the theme would vanish in one of them.
 *   - the phone mockup on the home page (.phone-card and inside it). It is a
 *     picture of an app screen. A screenshot does not repaint itself because
 *     the reader prefers dark mode, and neither should a drawing of one.
 *   - the pair of greens on .compare .yes, which need different values in each
 *     theme to stay legible and are written as a light value plus one override.
 */

/* ===========================================================================
 * 1. Tokens
 * ======================================================================== */

/* Newsreader, self-hosted, for headings only. An editorial serif because most
   of what this site publishes is arithmetic shown in the open - payout rates,
   costs, sources - and it should read like a report rather than a SaaS landing
   page. Latin subset, variable weight, OFL (see /fonts/Newsreader-OFL.txt).
   Body copy stays on the system stack, so the font costs one request and
   swap only ever changes the headings. */
@font-face {
    font-family: "Newsreader";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("../fonts/newsreader-latin.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;
}

:root {
    color-scheme: light dark;

    /* Brand. The gradient pair is the header and the CTA; amber is the one
       accent, reserved for the primary action and the left edge of a card. */
    --brand: #2563eb;
    --brand-deep: #1e3a8a;
    --accent: #f5a623;
    /* A darker amber for anything carrying meaning rather than decorating -
       #f5a623 only reaches 2.1:1 on white. */
    --accent-ink: #b45309;

    /* Ink, lightest to darkest. */
    --ink-soft: #6b7280;
    --ink-muted: #4b5563;
    --ink-body: #374151;
    --ink: #1f2937;
    --ink-strong: #111827;

    /* Surfaces. */
    --surface: #f4f5f8;
    --surface-raised: #ffffff;
    --surface-sunken: #f8fafc;
    --surface-input: #f9fafb;
    --border: #e5e7eb;
    --border-soft: #eef1f6;

    /* On the dark header. */
    --on-brand: #ffffff;
    --on-brand-soft: #bfdbfe;
    --on-brand-tagline: #e0e7ff;
    /* The header is night with one lamp in it - the amber spark from the logo,
       lit. It is dark in both themes, so the on-brand inks above never move. */
    --night: #0d111c;
    --night-2: #161c2c;
    --header-bg:
        radial-gradient(ellipse 70% 90% at 88% 0%, rgba(245, 166, 35, 0.22), transparent 60%),
        radial-gradient(ellipse 60% 70% at 0% 100%, rgba(37, 99, 235, 0.18), transparent 65%),
        linear-gradient(160deg, var(--night-2), var(--night));
    --lamp-glow: radial-gradient(circle, rgba(245, 166, 35, 0.28), rgba(245, 166, 35, 0) 68%);

    --link: #2563eb;
    --footer-bg: #0d111c;
    --footer-ink: #ffffff;
    --footer-link: #93c5fd;

    --ok-bg: #dcfce7;
    --ok-ink: #14532d;
    --ok-edge: #16a34a;
    --bad-bg: #fee2e2;
    --bad-ink: #7f1d1d;
    --bad-edge: #dc2626;
    --bad-strong: #b91c1c;
    --bad-tint: #fef2f2;

    --chip-bg: #e0e7ff;
    --chip-ink: #1e3a8a;
    --screenshot-bg: #0b1020;

    /* Type. The system stack renders as SF on an iPhone or a Mac, which is
       what this audience looks at all day, Segoe on Windows and Roboto on
       Android - and it costs no network request and no layout shift. */
    --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, sans-serif;
    --font-display: "Newsreader", "Iowan Old Style", "Palatino Linotype",
                    Georgia, serif;

    --text-xs: 0.85rem;
    --text-sm: 0.9375rem;
    --text-base: 1.0625rem;
    --text-lg: 1.1875rem;
    --text-xl: 1.4rem;
    --text-2xl: 1.75rem;
    --text-3xl: 2.125rem;
    --text-4xl: 3rem;

    --leading-tight: 1.15;
    --leading-snug: 1.5;
    --leading-normal: 1.6;
    --leading-relaxed: 1.75;

    --radius-sm: 10px;
    --radius: 14px;
    --radius-lg: 18px;
    --radius-xl: 22px;
    --radius-2xl: 32px;
    --radius-pill: 999px;

    --shadow-sm: 0 1px 2px rgba(13, 17, 28, 0.04), 0 6px 16px rgba(13, 17, 28, 0.05);
    --shadow: 0 1px 2px rgba(13, 17, 28, 0.05), 0 10px 28px rgba(13, 17, 28, 0.07);
    --shadow-lg: 0 14px 34px rgba(0, 0, 0, 0.12);
    --shadow-xl: 0 25px 60px rgba(0, 0, 0, 0.25);
    --shadow-btn: 0 10px 25px rgba(0, 0, 0, 0.15);

    --measure: 760px;
    --page: 1150px;
}

/* Dark mode. Only the tokens move - not one rule below this block knows which
   theme it is in. The night header and the CTA are already dark, so
   they carry over unchanged; what has to change is every white card. */
@media (prefers-color-scheme: dark) {
    :root {
        --ink-soft: #94a3b8;
        --ink-muted: #b4c0d0;
        --ink-body: #cbd5e1;
        --ink: #e2e8f0;
        --ink-strong: #f1f5f9;

        --surface: #0f172a;
        --surface-raised: #1b2537;
        --surface-sunken: #172033;
        --surface-input: #131c2e;
        --border: #334155;
        --border-soft: #263243;

        --link: #8ab4ff;
        --footer-bg: #0a0f1c;
        --footer-link: #a9c8ff;

        --accent-ink: #fbbf24;

        --ok-bg: #06301c;
        --ok-ink: #b8f5d0;
        --bad-bg: #3b1116;
        --bad-ink: #ffd3d3;
        --bad-strong: #ff9d9d;
        --bad-tint: #2a1114;

        --chip-bg: #1e2a52;
        --chip-ink: #c7d6ff;

        /* Shadows read as dirt on a dark ground; borders do the lifting. */
        --shadow-sm: 0 8px 20px rgba(0, 0, 0, 0.4);
        --shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
        --shadow-lg: 0 14px 34px rgba(0, 0, 0, 0.5);
        --shadow-xl: 0 25px 60px rgba(0, 0, 0, 0.6);
    }
}

/* ===========================================================================
 * 2. Base
 * ======================================================================== */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background: var(--surface);
    color: var(--ink);
    font-family: var(--font-sans);
    /* Stops iOS inflating text in landscape without disabling zoom. */
    -webkit-text-size-adjust: 100%;
}

/* Form controls do not inherit the font by default. */
input,
select,
textarea,
button {
    font-family: inherit;
}

img {
    max-width: 100%;
}

/* The two element rules the "no bare selectors" rule allows, because they set
   defaults rather than styling one page's markup, and :where() gives them zero
   specificity so every scoped rule below still wins.

   Links had no default at all, so any link a scoped rule missed rendered in
   the browser's own #0000EE - on the home page's feature cards, among others,
   and unreadable on a dark-mode card. */
:where(a) {
    color: var(--link);
    text-underline-offset: 0.18em;
    text-decoration-thickness: 1px;
}

:where(h1, h2, h3) {
    font-family: var(--font-display);
    font-weight: 600;
    font-optical-sizing: auto;
    letter-spacing: -0.005em;
    text-wrap: balance;
}

/* Figures line up in every table and stat on the site - most of what it
   publishes is a column of rates and totals. */
:where(table, .stat, .stats) {
    font-variant-numeric: tabular-nums;
}

/* The ring is --accent-ink, not --accent: the bright amber is 1.9:1 on the
   light page and fails WCAG's 3:1 for a focus indicator. The darker amber is
   4.6:1 on the page and 3.4:1 on the night header, and dark mode swaps it
   for #fbbf24. */
:where(a, button, summary, input, select, textarea):focus-visible {
    outline: 3px solid var(--accent-ink);
    outline-offset: 2px;
    border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Available to screen readers, out of the visual flow. Used for the comparison
   table's caption, which a sighted reader gets from the surrounding heading. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ===========================================================================
 * 3. Chrome - header, nav, footer
 * ======================================================================== */

/*
 * Every container on the site is `max-width: var(--page)` with a 20px gutter
 * INSIDE it, so each one resolves to the same left edge.
 *
 * The header used to carry that gutter as its own padding, outside the 1150px
 * container its contents then centred within. That put the h1 20px to the left
 * of the body text below it on every page - small enough to look like nothing
 * in particular and wrong enough to see once anything else lines up.
 */
.page-header {
    background: var(--header-bg);
    color: var(--on-brand);
    padding: 40px 0 90px;
    position: relative;
    overflow: hidden;
}

.nav,
.crumbs,
.hero,
.header-content,
.content,
.hero-content {
    padding-inline: 20px;
}

.page-header::after {
    content: "";
    position: absolute;
    width: 420px;
    height: 420px;
    background: var(--lamp-glow);
    border-radius: 50%;
    pointer-events: none;
    right: -120px;
    top: 40px;
}

.nav {
    max-width: var(--page);
    margin: auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: relative;
    z-index: 2;
    gap: 20px;
}

.logo {
    font-size: var(--text-xl);
    font-weight: bold;
}

/* The mark and the wordmark sit on one line. Both selectors are needed because
   the home page renders the pair bare and every other page wraps it in a link
   back to /. */
.logo,
.logo a {
    display: flex;
    align-items: center;
    gap: 12px;
}

.logo a {
    color: var(--on-brand);
    text-decoration: none;
}

.logo-mark {
    width: 38px;
    height: 38px;
    flex-shrink: 0;
    display: block;
}

/* 18px, down from 24px on 9 September 2026, and it is a fix rather than a
   preference. `Costs` was the ninth item and it pushed the row over: measured
   on the live site at a 1535px viewport, the links needed about 786px against
   the 765px left beside the wordmark, so `Contact` wrapped under the logo on
   every page at every width above the 1150px stacking breakpoint. 20px is the
   widest value that fits and 18px leaves about 20px of headroom, which is
   roughly one more short item. The stacking rule below is unchanged. */
.nav a {
    color: var(--on-brand);
    text-decoration: none;
    margin-left: 18px;
    font-weight: 600;
    /* An amber underline that grows in on hover, the lamp's colour. */
    background: linear-gradient(var(--accent), var(--accent)) no-repeat 0 100% / 0 2px;
    padding-bottom: 3px;
    transition: background-size 0.2s ease;
}

.nav a:hover,
.nav a[aria-current="page"] {
    background-size: 100% 2px;
}

.crumbs {
    max-width: var(--page);
    margin: 40px auto 0;
    position: relative;
    z-index: 2;
    font-size: var(--text-sm);
    color: var(--on-brand-soft);
}

.crumbs a {
    color: var(--on-brand-soft);
    text-decoration: none;
    margin: 0;
}

.crumbs a:hover {
    text-decoration: underline;
}

footer {
    border-top: 1px solid rgba(245, 166, 35, 0.35);
    background: var(--footer-bg);
    color: var(--footer-ink);
    padding: 30px 20px;
    text-align: center;
}

footer p {
    margin-bottom: 8px;
}

footer a {
    color: var(--footer-link);
    text-decoration: none;
    margin: 0 10px;
}

footer a:hover {
    text-decoration: underline;
}

/* ===========================================================================
 * 4. Hero (generated pages)
 * ======================================================================== */

.hero {
    max-width: var(--page);
    margin: 24px auto 0;
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: 140px 1fr;
    gap: 34px;
    align-items: start;
}

.hero-icon {
    width: 140px;
    height: 140px;
    border-radius: var(--radius-2xl);
    display: block;
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.28);
}

.hero h1 {
    font-size: var(--text-4xl);
    line-height: var(--leading-tight);
    margin-bottom: 14px;
    /* Long review titles break better with a slightly tighter track. */
    letter-spacing: -0.015em;
}

.hero.no-icon {
    grid-template-columns: 1fr;
}

.hero.no-icon h1 {
    max-width: 900px;
}

.tagline {
    font-size: var(--text-lg);
    line-height: var(--leading-normal);
    max-width: 660px;
    margin-bottom: 24px;
    color: var(--on-brand-tagline);
}

/* "Early version · Coming soon to ..." leading the tagline of a game that is
   playable here and not in a store yet - on its hero, its play page's hero and
   its /games/ card. A span, because on the heroes it sits inside the
   template's <p class="tagline">, so it is made a block to get its own line.
   Amber with fixed dark ink, the pairing .tag.new uses: it sits on the dark
   header and on a white card, and has to read on both in either theme. */
.soon-badge {
    display: block;
    width: fit-content;
    margin-bottom: 12px;
    padding: 5px 12px;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: #1f2937;
    font-size: var(--text-sm);
    font-weight: bold;
    line-height: 1.4;
}

.hero-meta {
    margin-top: 16px;
    font-size: var(--text-sm);
    color: var(--on-brand-soft);
}

.article-meta {
    color: var(--on-brand-soft);
    font-size: var(--text-sm);
    margin-top: 18px;
}

/* The byline sits on the dark hero, so it follows .crumbs rather than the
   body link color - underlined on hover only, so the meta line stays meta. */
.article-meta a {
    color: var(--on-brand);
    text-decoration: none;
    font-weight: 600;
}

.article-meta a:hover {
    text-decoration: underline;
}

/* ===========================================================================
 * 5. Layout and buttons
 * ======================================================================== */

main {
    display: block;
}

.section {
    max-width: var(--page);
    margin: auto;
    padding: 64px 20px 0;
}

.section:last-of-type {
    padding-bottom: 70px;
}

.section h2 {
    font-size: var(--text-3xl);
    margin-bottom: 18px;
    letter-spacing: -0.01em;
}

.section > p {
    color: var(--ink-muted);
    line-height: var(--leading-relaxed);
    font-size: var(--text-base);
    max-width: 800px;
    margin-bottom: 18px;
}

/* Amber, picked up from the spark in the logo. It is the one accent the palette
   has, so it is reserved for the primary action on a page. */
.btn {
    display: inline-block;
    background: var(--accent);
    color: #1f2937;
    padding: 15px 30px;
    border-radius: var(--radius-sm);
    text-decoration: none;
    font-weight: bold;
    box-shadow: var(--shadow-btn), 0 0 0 0 rgba(245, 166, 35, 0);
    margin-top: 26px;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.btn:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-btn), 0 0 28px 2px rgba(245, 166, 35, 0.35);
}

.store-btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    background: var(--surface-raised);
    color: var(--brand-deep);
    padding: 14px 26px;
    border-radius: var(--radius-sm);
    text-decoration: none;
    font-weight: bold;
    font-size: 1rem;
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.18);
}

/* Same trap the .page-apps button below is commented for, in the other
   direction: --surface-raised is a *surface* token used here as the background
   of something sitting on the dark header, and it inverts to #1b2537 in dark
   mode, leaving --brand-deep ink at #1e3a8a on top of it. The hero gradient
   does not invert, so the button has to stay white to keep its blue label. It
   was unreadable in dark mode on all five detail pages. */
@media (prefers-color-scheme: dark) {
    .store-btn {
        background: #ffffff;
        color: #1e3a8a;
    }
}

.store-btn .apple {
    font-size: 1.3rem;
    line-height: 1;
}

/* Google Play, on the two listings that ship there. Sized down from .apple because
   the play glyph has no descender and sits optically larger at the same size. */
.store-btn .play {
    font-size: 1rem;
    line-height: 1;
}

/* Two store buttons need to wrap and space on a narrow screen; a single one is
   unaffected, since the margin only applies to a button that follows another. */
.store-btn + .store-btn {
    margin-left: 12px;
}

@media (max-width: 520px) {
    .store-btn + .store-btn {
        margin-left: 0;
        margin-top: 12px;
    }
}

/* The home hero offers two ways in - the apps that pay you, and the games that
   do not - so it is the first place on the site with two .btn side by side.
   Same rule and same breakpoint as the store buttons above; the ghost variant
   the second one uses was already defined for /404. */
.btn + .btn {
    margin-left: 14px;
}

@media (max-width: 520px) {
    .btn + .btn {
        margin-left: 0;
    }
}

.cta {
    background: var(--header-bg);
    color: #ffffff;
    text-align: center;
    padding: 70px 20px;
    margin-top: 70px;
}

.cta h2 {
    font-size: var(--text-3xl);
    margin-bottom: 15px;
}

.cta p {
    max-width: 650px;
    margin: auto;
    line-height: var(--leading-normal);
    font-size: var(--text-base);
}

/* The CTA sits on its own gradient in both themes, so its ink is fixed rather
   than tokenized - --ink-strong going pale in dark mode would erase it. */
@media (prefers-color-scheme: dark) {
    .cta {
        background: var(--header-bg);
    }
}

/* ===========================================================================
 * 6. Cards, lists and FAQ
 * ======================================================================== */

.card {
    background: var(--surface-raised);
    border-radius: var(--radius-lg);
    padding: 34px;
    box-shadow: var(--shadow);
    border: 1px solid var(--border-soft);
    border-left: 4px solid var(--accent);
}

.steps {
    counter-reset: step;
    list-style: none;
    display: grid;
    gap: 18px;
}

.steps li {
    counter-increment: step;
    position: relative;
    padding-left: 54px;
    line-height: 1.65;
    color: var(--ink-body);
    font-size: var(--text-base);
}

.steps li::before {
    content: counter(step);
    position: absolute;
    left: 0;
    top: -2px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--accent);
    color: #1f2937;
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 700;
    font-variant-numeric: lining-nums;
    padding-bottom: 2px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.checklist {
    list-style: none;
    display: grid;
    gap: 12px;
}

.checklist li {
    color: var(--ink-body);
    line-height: var(--leading-normal);
    font-size: var(--text-base);
}

.checklist li::before {
    content: "✓";
    color: var(--accent-ink);
    font-weight: bold;
    margin-right: 10px;
}

/* The sources block at the foot of a review. Numbered rather than ticked:
   .checklist's tick next to a competitor's own documentation reads as a
   verdict on the source, and these are citations, not endorsements. */
.sources {
    list-style: decimal;
    padding-left: 1.4rem;
    display: grid;
    gap: 10px;
}

.sources li {
    color: var(--ink-body);
    line-height: 1.55;
    font-size: var(--text-sm);
}

.faq {
    display: grid;
    gap: 16px;
}

.faq details {
    background: var(--surface-raised);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    /* Vertical padding lives on the summary so the whole ~48px strip is
       tappable, rather than just the 21px line of text. */
    padding: 6px 24px;
}

.faq summary {
    font-weight: bold;
    font-size: var(--text-base);
    cursor: pointer;
    list-style: none;
    padding: 14px 0;
}

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

.faq summary::after {
    content: "+";
    float: right;
    color: var(--brand);
    font-size: var(--text-xl);
    line-height: 1;
}

.faq details[open] summary::after {
    content: "–";
}

.faq p {
    margin-top: 2px;
    padding-bottom: 14px;
    color: var(--ink-muted);
    line-height: var(--leading-relaxed);
}

.faq a {
    color: var(--link);
}

/* An AdSense unit, between the article and its FAQ and again below it. Only
   the competitor pages carry these - reviews, payouts, alternatives, costs,
   articles - and never our own app pages, where the ad would be competing
   with the download button next to it.

   min-height is the whole point of this block. An ad arrives a beat after the
   text does, and without space already reserved for it the paragraph a reader
   has started moves down the screen when it lands. That is a Cumulative
   Layout Shift penalty, on a set of pages whose only job is to rank. The
   figures are the shortest an in-article and a responsive display unit are
   allowed to render at, so the reserved box is never larger than the ad. */
.ad-slot {
    margin: 40px auto;
    max-width: var(--measure);
    padding: 0 24px;
    min-height: 280px;
    text-align: center;
}

/* Google writes data-ad-status="unfilled" on the <ins> when the auction
   returns nothing, which happens often on a small site. Without this the
   reader gets a 280px hole with the word "Advertisement" sitting in it. */
.ad-slot:has(> .adsbygoogle[data-ad-status="unfilled"]) {
    display: none;
}

/* Labeled because a native in-article unit takes this page's own type and
   spacing, and an ad a reader cannot tell from our own sentences is the one
   thing that would undo the disclosure at the top of every review. Small and
   grey, not hidden: AdSense policy requires it be legible. */
.ad-slot-label {
    display: block;
    font-size: 0.7rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-muted);
    opacity: 0.7;
    margin-bottom: 8px;
}

@media (max-width: 700px) {
    .ad-slot {
        margin: 32px auto;
        padding: 0 16px;
        /* A mobile responsive unit is allowed to come back as a 100px banner,
           so reserving 280px here would leave a gap under most of them. */
        min-height: 100px;
    }
}

.other-apps {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.other-app {
    background: var(--surface-raised);
    border-radius: 16px;
    padding: 22px;
    box-shadow: var(--shadow-sm);
    display: flex;
    align-items: center;
    gap: 18px;
    text-decoration: none;
    color: var(--ink);
}

.other-app:hover {
    box-shadow: var(--shadow-lg);
}

.other-app img {
    width: 64px;
    height: 64px;
    border-radius: 15px;
    display: block;
}

.other-app strong {
    display: block;
    font-size: 1.1rem;
    margin-bottom: 4px;
}

.other-app span {
    color: var(--ink-soft);
    font-size: var(--text-sm);
}

/* ===========================================================================
 * 7. Prose (articles, reviews, explainers)
 * ======================================================================== */

/*
 * Left-aligned, deliberately, and it was tried the other way.
 *
 * A 2,600-word review does hug the left of a wide window with dead space
 * beside it, and centring the measure looks better in a screenshot of one
 * paragraph. It does not survive a whole page: this site aligns everything to
 * the left edge of a single 1150px container, so a centred .prose leaves the
 * h1 above it and the FAQ below it on the old edge and the article floating
 * between them. Scoping the centring to prose-with-no-siblings only moved the
 * seam onto pages that mix prose with a card list or a comparison table.
 *
 * One edge for every block beats a better-looking measure. If this is ever
 * revisited, the change is to center the whole container - hero, prose, FAQ
 * and all - not this one block inside it.
 */
.prose {
    max-width: var(--measure);
}

.prose h2 {
    font-size: var(--text-2xl);
    margin: 46px 0 14px;
    letter-spacing: -0.01em;
    scroll-margin-top: 24px;
}

.prose h3 {
    font-size: 1.25rem;
    margin: 30px 0 10px;
}

.prose p {
    color: var(--ink-body);
    line-height: var(--leading-relaxed);
    font-size: var(--text-base);
    margin-bottom: 16px;
}

.prose ul {
    margin: 0 0 18px 22px;
}

.prose li {
    color: var(--ink-body);
    line-height: var(--leading-relaxed);
    font-size: var(--text-base);
    margin-bottom: 9px;
}

.prose a {
    color: var(--link);
}

.prose .lead {
    font-size: var(--text-lg);
    line-height: var(--leading-relaxed);
    color: var(--ink-muted);
}

/* A quotation from the company being reviewed. Set apart because the whole
   credibility of a review page is that these are their words, not ours. */
.prose blockquote {
    margin: 24px 0;
    padding: 4px 0 4px 22px;
    border-left: 4px solid var(--accent);
}

.prose blockquote p {
    font-size: var(--text-lg);
    line-height: var(--leading-normal);
    color: var(--ink);
    margin-bottom: 0;
}

.callout {
    background: var(--surface-raised);
    border-left: 5px solid var(--accent);
    border-radius: var(--radius);
    padding: 24px 28px;
    margin: 28px 0;
    box-shadow: var(--shadow-sm);
}

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

/* The contents box on a long review. These pages answer one question and are
   read by someone who wants a specific part of the answer. */
.toc {
    background: var(--surface-raised);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 22px 26px;
    margin: 0 0 30px;
}

.toc h2 {
    font-size: var(--text-sm);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin: 0 0 12px;
}

.toc ol {
    margin: 0;
    padding-left: 1.2rem;
    display: grid;
    gap: 7px;
}

.toc li {
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    color: var(--ink-muted);
}

.toc a {
    color: var(--link);
    text-decoration: none;
}

.toc a:hover {
    text-decoration: underline;
}

.article-list {
    display: grid;
    gap: 22px;
    max-width: 860px;
}

.article-card {
    background: var(--surface-raised);
    border-radius: var(--radius-lg);
    padding: 30px;
    box-shadow: var(--shadow);
    border-left: 5px solid var(--accent);
    text-decoration: none;
    display: block;
    color: inherit;
}

.article-card:hover {
    box-shadow: var(--shadow-lg);
}

.article-card h2 {
    font-size: var(--text-xl);
    margin-bottom: 10px;
    color: var(--ink);
}

.article-card p {
    color: var(--ink-muted);
    line-height: 1.65;
    margin-bottom: 12px;
}

.article-card .read {
    color: var(--link);
    font-weight: 600;
}

/* ===========================================================================
 * 8. App screenshots
 * ======================================================================== */

/* Four phone screenshots across on a wide screen, two on a phone. auto-fit
   with a real minimum is what makes them wrap; minmax(0, 1fr) would force
   every shot onto one row however many there are. */
.shots {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 24px;
    max-width: 1000px;
}

.shot figure {
    margin: 0;
}

.shot img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: var(--radius-xl);
    background: var(--screenshot-bg);
    box-shadow: 0 14px 34px rgba(17, 24, 39, 0.22);
}

.shot figcaption {
    margin-top: 12px;
    color: var(--ink-soft);
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    text-align: center;
}

/* Preview video: a poster and a play button until pressed (build-app-pages.py
 * VIDEOS). hqdefault is 4:3 with black bars, so the 16:9 box crops them. */
.video {
    max-width: 760px;
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-xl);
    overflow: hidden;
    background: #000;
    box-shadow: 0 14px 34px rgba(17, 24, 39, 0.22);
}

.video-facade {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: #000;
    cursor: pointer;
}

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

.video-play {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 72px;
    height: 72px;
    margin: -36px 0 0 -36px;
    border-radius: 50%;
    background: rgba(17, 24, 39, 0.78);
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.85);
}

.video-play::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -14px 0 0 -8px;
    border-style: solid;
    border-width: 14px 0 14px 24px;
    border-color: transparent transparent transparent #fff;
}

.video-facade:hover .video-play,
.video-facade:focus-visible .video-play {
    background: var(--accent-ink);
}

.video-frame {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}

.video-note {
    margin-top: 10px;
    color: var(--ink-soft);
    font-size: var(--text-sm);
}

/* ===========================================================================
 * 9. Comparison table
 * ======================================================================== */

/* Wide tables must scroll inside their own box rather than pushing the page
   sideways on a phone - the same rule the screenshot grid follows. */
.table-wrap {
    overflow-x: auto;
    /* Sits outside .prose so the columns get the full section width; the prose
       either side of it stays at its readable measure. */
    margin: 6px 0 26px;
    border-radius: 16px;
    box-shadow: var(--shadow);
    background: var(--surface-raised);
}

.compare {
    border-collapse: collapse;
    width: 100%;
    min-width: 620px;
    font-size: var(--text-sm);
}

.compare th,
.compare td {
    padding: 14px 16px;
    text-align: left;
    border-bottom: 1px solid var(--border-soft);
    line-height: var(--leading-snug);
    vertical-align: top;
}

.compare thead th {
    background: var(--surface-sunken);
    font-size: 0.8rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ink-muted);
    border-bottom: 2px solid var(--border);
    white-space: nowrap;
}

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

.compare th[scope="row"] {
    font-weight: bold;
    white-space: nowrap;
}

.compare th[scope="row"] a {
    color: var(--link);
    text-decoration: none;
}

.compare th[scope="row"] a:hover {
    text-decoration: underline;
}

.compare .app-cell {
    display: flex;
    align-items: center;
    gap: 11px;
}

.compare .app-cell img {
    width: 34px;
    height: 34px;
    border-radius: 9px;
    display: block;
    flex-shrink: 0;
}

.compare .yes {
    color: #15803d;
    font-weight: bold;
}

@media (prefers-color-scheme: dark) {
    .compare .yes {
        color: #6ee7a8;
    }
}

.table-note {
    color: var(--ink-soft);
    font-size: var(--text-sm);
    line-height: 1.55;
    margin: -14px 0 26px;
}

/* A "best for X" pick, so the page answers the question rather than only
   tabulating it. */
.picks {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
    margin: 6px 0 26px;
}

.pick {
    background: var(--surface-raised);
    border-radius: 16px;
    padding: 22px 24px;
    box-shadow: var(--shadow-sm);
    border-left: 5px solid var(--accent);
}

.pick h3 {
    font-size: var(--text-base);
    margin-bottom: 8px;
}

.pick p {
    color: var(--ink-muted);
    line-height: var(--leading-normal);
    font-size: var(--text-sm);
    margin: 0;
}

.pick a {
    color: var(--link);
    font-weight: 600;
    text-decoration: none;
}

/* ===========================================================================
 * 10. Suggestion form (/make-extra-pocket-money)
 *
 * Scoped under .suggest-form rather than styling bare input and label
 * elements, because this stylesheet is loaded by every page on the site and
 * most of them have no form at all.
 * ======================================================================== */

.suggest-form .field {
    margin-bottom: 20px;
}

.suggest-form label {
    display: block;
    font-weight: bold;
    margin-bottom: 8px;
    font-size: var(--text-sm);
}

.suggest-form .hint {
    display: block;
    font-weight: normal;
    color: var(--ink-soft);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    margin: 3px 0 0;
}

.suggest-form .required {
    color: var(--bad-edge);
}

.suggest-form input[type="text"],
.suggest-form input[type="email"],
.suggest-form select,
.suggest-form textarea {
    width: 100%;
    padding: 13px 15px;
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 1rem;
    background: var(--surface-input);
    color: var(--ink);
}

.suggest-form input:focus,
.suggest-form select:focus,
.suggest-form textarea:focus {
    outline: none;
    border-color: var(--brand);
    background: var(--surface-raised);
}

.suggest-form textarea {
    min-height: 150px;
    resize: vertical;
    line-height: var(--leading-snug);
}

/* Hidden from people, filled in by most bots - see the honeypot note in
   google-apps-script/README.md. */
.suggest-form .hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.suggest-form .submit-btn {
    background: var(--accent);
    color: #1f2937;
    border: none;
    padding: 16px 34px;
    border-radius: var(--radius-sm);
    font-size: var(--text-base);
    font-weight: bold;
    cursor: pointer;
    box-shadow: var(--shadow-btn);
}

.suggest-form .submit-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.suggest-form .form-note {
    color: var(--ink-soft);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    margin-top: 18px;
    overflow-wrap: anywhere;
}

.suggest-form .form-note a {
    color: var(--link);
}

.suggest-form fieldset {
    border: 0;
    padding: 0;
    margin: 0 0 20px;
}

.suggest-form legend {
    font-weight: bold;
    font-size: var(--text-sm);
    margin-bottom: 10px;
    padding: 0;
}

.suggest-form .choices {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

.suggest-form .choices-inline {
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}

/* The whole tile is the label, so the tap target is the tile rather than the
   14px box - the same reason the nav links carry padding on mobile. */
.suggest-form .choice {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    margin: 0;
    padding: 13px 15px;
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-input);
    font-weight: normal;
    font-size: var(--text-sm);
    line-height: 1.45;
    cursor: pointer;
}

.suggest-form .choice:hover {
    border-color: var(--on-brand-soft);
    background: var(--surface-sunken);
}

.suggest-form .choice:focus-within {
    border-color: var(--brand);
    background: var(--surface-raised);
}

.suggest-form .choice input {
    width: 18px;
    height: 18px;
    margin: 2px 0 0;
    flex-shrink: 0;
    accent-color: var(--brand);
}

.suggest-form .choice strong {
    display: block;
}

.suggest-form .choice-note {
    display: block;
    color: var(--ink-soft);
    font-size: var(--text-xs);
}

.suggest-form .counter {
    color: var(--ink-soft);
    font-size: var(--text-xs);
    margin-top: 6px;
    text-align: right;
}

.suggest-form .field-error {
    display: none;
    color: var(--bad-strong);
    font-size: var(--text-sm);
    font-weight: bold;
    margin-top: 7px;
}

.suggest-form .field-error.show {
    display: block;
}

.suggest-form [aria-invalid="true"] {
    border-color: var(--bad-edge);
    background: var(--bad-tint);
}

.status {
    display: none;
    padding: 16px 18px;
    border-radius: var(--radius-sm);
    margin-bottom: 24px;
    line-height: 1.55;
    overflow-wrap: anywhere;
}

.status.show {
    display: block;
}

.status.success {
    background: var(--ok-bg);
    color: var(--ok-ink);
    border-left: 5px solid var(--ok-edge);
}

.status.error {
    background: var(--bad-bg);
    color: var(--bad-ink);
    border-left: 5px solid var(--bad-edge);
}

.status a {
    color: inherit;
    font-weight: bold;
}

/* The app grid appears inside prose on /make-extra-pocket-money, where it needs
   the breathing room a bare <p> would otherwise have supplied. */
.prose .other-apps {
    margin: 6px 0 26px;
}

/* ===========================================================================
 * 11. Page overrides
 *
 * Everything below is scoped to one page. A rule only belongs here if that
 * page genuinely differs from the shared version above.
 * ======================================================================== */

/* --- Home ---------------------------------------------------------------- */

/* Gutter lives on .nav and .hero-content, as it does on .page-header. */
.home-hero {
    min-height: 620px;
    background: var(--header-bg);
    color: var(--on-brand);
    padding: 40px 0 80px;
    position: relative;
    overflow: hidden;
}

.home-hero::after {
    content: "";
    position: absolute;
    width: 420px;
    height: 420px;
    background: var(--lamp-glow);
    border-radius: 50%;
    pointer-events: none;
    right: -120px;
    top: 80px;
}

.hero-content {
    max-width: var(--page);
    margin: 90px auto 0;
    display: grid;
    grid-template-columns: 1.1fr 0.9fr;
    gap: 50px;
    align-items: center;
    position: relative;
    z-index: 2;
}

.hero-content h1 {
    font-size: clamp(2.5rem, 5vw, 3.6rem);
    line-height: 1.05;
    margin-bottom: 22px;
    letter-spacing: -0.015em;
}

.hero-content > div > p {
    font-size: var(--text-lg);
    max-width: 620px;
    line-height: var(--leading-normal);
    margin-bottom: 30px;
    color: var(--on-brand-tagline);
}

.hero-content .btn {
    margin-top: 0;
}

.phone-card {
    background: #ffffff;
    color: #1f2937;
    border-radius: 35px;
    padding: 25px;
    max-width: 320px;
    margin: auto;
    box-shadow: var(--shadow-xl);
}

.phone-top {
    width: 80px;
    height: 6px;
    background: #d1d5db;
    border-radius: var(--radius-sm);
    margin: 0 auto 25px;
}

.app-screen {
    background: #f8fafc;
    border-radius: 25px;
    padding: 25px;
    text-align: center;
}

/* The shelf inside the mockup. It replaced a green balance card reading
   "$2.40", which drew one of the six apps and implied all of them - the whole
   reason this page was rewritten in September 2026. Fixed colors, like
   everything else inside .phone-card: this is a picture of a screen, and a
   screenshot does not repaint itself for dark mode. */
.shelf {
    text-align: left;
}

.shelf-title {
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #6b7280;
    margin-bottom: 16px;
}

.shelf-list {
    list-style: none;
    margin: 0 0 18px;
    padding: 0;
}

.shelf-list li {
    border-left: 3px solid #f5a623;
    margin-bottom: 15px;
}

/* Each row goes somewhere: the four reward apps, the four games, the one with
   no advertising in it. The link carries the padding rather than the li, so the
   whole strip is the target and not just the two lines of text. */
.shelf-list a {
    display: block;
    padding: 4px 10px 5px 12px;
    text-decoration: none;
    transition: background-color 0.2s ease;
}

.shelf-list a:hover {
    background: #ffffff;
}

.shelf-list a:hover strong {
    text-decoration: underline;
}

.shelf-list strong {
    display: block;
    font-size: var(--text-sm);
    color: #1f2937;
}

.shelf-list span {
    font-size: var(--text-xs);
    color: #6b7280;
}

.shelf-foot {
    text-align: center;
    font-size: var(--text-sm);
    font-weight: 600;
    color: #1f2937;
    border-top: 1px solid #e5e7eb;
    padding-top: 16px;
}

.page-home .section {
    padding: 80px 20px;
    text-align: center;
}

.page-home .section h2 {
    font-size: var(--text-3xl);
    margin-bottom: 15px;
}

.section-intro {
    max-width: 760px;
    margin: 0 auto 45px;
    font-size: var(--text-base);
    color: var(--ink-muted);
    line-height: var(--leading-normal);
}

.features {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 28px;
}

.feature {
    background: var(--surface-raised);
    padding: 35px 28px;
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-soft);
    box-shadow: var(--shadow);
    transition: transform 0.25s ease, border-color 0.25s ease;
    text-align: left;
}

.feature:hover {
    transform: translateY(-4px);
    border-color: var(--accent);
}

/* Real SVG rather than an emoji. An emoji is a different picture on every
   platform, and on the three that matter it is somebody else's illustration
   style sitting in the middle of ours. */
.feature .icon {
    width: 44px;
    height: 44px;
    margin-bottom: 18px;
    color: var(--accent-ink);
    display: block;
}

.feature h3 {
    font-size: 1.35rem;
    margin-bottom: 12px;
}

.feature p {
    color: var(--ink-muted);
    line-height: var(--leading-snug);
}

.feature p + p {
    margin-top: 12px;
}

.design-section {
    background: var(--surface-raised);
}

.design-grid {
    max-width: var(--page);
    margin: auto;
    padding: 80px 20px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 55px;
    /* Was centered, which read fine against five panels and stopped when a
       sixth arrived in September 2026 - the heading sank most of a screen
       below the first panel it introduces. The right column is a stack that
       will keep growing; the left one is a fixed block that belongs at the
       top of it. */
    align-items: start;
}

.design-text h2 {
    font-size: var(--text-3xl);
    margin-bottom: 18px;
}

.design-text p {
    color: var(--ink-muted);
    line-height: var(--leading-relaxed);
    margin-bottom: 22px;
    font-size: var(--text-base);
}

.page-home .checklist li {
    font-weight: 600;
}

.app-panels {
    display: grid;
    gap: 18px;
}

.panel {
    background: var(--surface);
    border-radius: var(--radius-lg);
    padding: 24px;
    border-left: 5px solid var(--accent);
}

.panel h3 {
    margin-bottom: 6px;
}

.panel p {
    color: var(--ink-muted);
    line-height: var(--leading-normal);
}

.panel a {
    color: var(--link);
    font-weight: 600;
    text-decoration: none;
}

.panel a:hover {
    text-decoration: underline;
}

.page-home .cta {
    padding: 80px 20px;
    margin-top: 0;
}

/* --- Apps ---------------------------------------------------------------- */

.header-content {
    max-width: var(--page);
    margin: 70px auto 0;
    position: relative;
    z-index: 2;
}

.header-content h1 {
    font-size: 3.4rem;
    line-height: var(--leading-tight);
    margin-bottom: 18px;
    letter-spacing: -0.02em;
}

.header-content p {
    font-size: var(--text-lg);
    max-width: 680px;
    line-height: var(--leading-normal);
    color: var(--on-brand-tagline);
}

.page-apps .section {
    padding: 70px 20px;
}

.app-list {
    display: grid;
    gap: 30px;
}

.app-card {
    background: var(--surface-raised);
    border-radius: 20px;
    padding: 35px;
    box-shadow: var(--shadow);
    display: grid;
    grid-template-columns: 110px 1fr;
    gap: 30px;
    align-items: start;
    border-left: 5px solid var(--accent);
}

.app-icon {
    width: 110px;
    height: 110px;
    border-radius: 26px;
    display: block;
    object-fit: cover;
    box-shadow: 0 10px 25px rgba(17, 24, 39, 0.22);
}

.app-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 12px;
}

.app-card h2 {
    font-size: 1.7rem;
}

.app-card h2 a {
    color: inherit;
    text-decoration: none;
}

.app-card h2 a:hover {
    color: var(--brand);
}

/* The icon anchor is the grid item, so it has to size like the image did. */
.app-card > a {
    display: block;
    width: 110px;
    height: 110px;
}

.app-card > div > p {
    color: var(--ink-muted);
    line-height: 1.65;
    margin-bottom: 18px;
    font-size: var(--text-base);
}

.more-link {
    display: inline-block;
    margin-left: 18px;
    color: var(--link);
    font-weight: 600;
    text-decoration: none;
}

.more-link:hover {
    text-decoration: underline;
}

.tag {
    background: var(--chip-bg);
    color: var(--chip-ink);
    font-size: 0.75rem;
    font-weight: bold;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    padding: 6px 12px;
    border-radius: var(--radius-pill);
}

/* Marks a just-released app. Amber, so it reads as the accent rather than as a
   second category chip, with the same ink the amber buttons use (6.9:1). */
.tag.new {
    background: var(--accent);
    color: #1f2937;
}

.page-apps .checklist {
    margin-bottom: 22px;
}

/* The dark store button belongs to /apps; the app detail pages use the white
   one defined above, on their dark header. */
.page-apps .store-btn {
    background: var(--ink-strong);
    color: #ffffff;
    padding: 12px 22px;
    font-size: var(--text-sm);
    margin-bottom: 14px;
    box-shadow: none;
}

.page-apps .store-btn:hover {
    background: var(--ink);
}

/* Both rules above use an *ink* token as a *background*, which inverts in dark
   mode: --ink-strong becomes #f1f5f9 and the white label on it disappears. Same
   trap the .cta gradient is commented for, and the same fix - fixed values,
   because the button has to stay dark in both themes to keep its white ink.
   The label was invisible on /apps in dark mode for as long as the page has
   had a store button. */
@media (prefers-color-scheme: dark) {
    .page-apps .store-btn {
        background: #0b1020;
    }

    .page-apps .store-btn:hover {
        background: #18213a;
    }
}

.page-apps .store-btn .apple {
    font-size: 1.25rem;
}

.page-apps .store-btn .play {
    font-size: 0.95rem;
}

/* "Play in your browser", the third button and the only one that asks nothing
   of the reader - no store, no install, no account. It is the accent color
   rather than a third white or dark rectangle so the row reads as one primary
   action followed by two stores. --accent is one of the few tokens that does
   not invert, so unlike the two rules above this needs no dark-mode repeat -
   but the ink is a fixed value for the same reason .btn's is, since the swatch
   stays yellow in both themes. */
.store-btn.play-now,
.page-apps .store-btn.play-now {
    background: var(--accent);
    color: #1f2937;
}

.store-btn.play-now:hover,
.page-apps .store-btn.play-now:hover {
    background: #e09612;
}

.store-btn .browser {
    font-size: 0.95rem;
}

.meta {
    color: var(--ink-soft);
    font-size: var(--text-sm);
}

.page-apps .cta {
    padding: 80px 20px;
    margin-top: 0;
}

/* --- Contact ------------------------------------------------------------- */

.page-contact .section {
    padding: 70px 20px;
    display: grid;
    grid-template-columns: 1.15fr 0.85fr;
    gap: 40px;
    align-items: start;
}

/* No accent edge here - the form card is the page, not a highlight within it. */
.page-contact .card {
    padding: 38px;
    border-left: 0;
}

.page-contact .card h2 {
    font-size: 1.8rem;
    margin-bottom: 10px;
}

.card-intro {
    color: var(--ink-muted);
    line-height: var(--leading-normal);
    margin-bottom: 28px;
}

.page-contact .field {
    margin-bottom: 20px;
}

.page-contact label {
    display: block;
    font-weight: bold;
    margin-bottom: 8px;
    font-size: var(--text-sm);
}

.page-contact .required {
    color: var(--bad-edge);
}

.page-contact input[type="text"],
.page-contact input[type="email"],
.page-contact select,
.page-contact textarea {
    width: 100%;
    padding: 13px 15px;
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 1rem;
    background: var(--surface-input);
    color: var(--ink);
}

.page-contact input:focus,
.page-contact select:focus,
.page-contact textarea:focus {
    outline: none;
    border-color: var(--brand);
    background: var(--surface-raised);
}

.page-contact textarea {
    min-height: 160px;
    resize: vertical;
    line-height: var(--leading-snug);
}

.page-contact .hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.page-contact .submit-btn {
    background: var(--header-bg);
    color: #ffffff;
    border: none;
    padding: 16px 34px;
    border-radius: var(--radius-sm);
    font-size: var(--text-base);
    font-weight: bold;
    cursor: pointer;
    box-shadow: 0 10px 25px rgba(37, 99, 235, 0.25);
}

.page-contact .submit-btn:hover:not(:disabled) {
    transform: translateY(-2px);
}

.page-contact .submit-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.page-contact .form-note {
    color: var(--ink-soft);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    margin-top: 18px;
}

.page-contact .form-note a {
    color: var(--link);
}

.side-card {
    background: var(--surface-raised);
    border-radius: 20px;
    padding: 32px;
    box-shadow: var(--shadow);
    border-left: 5px solid var(--accent);
    margin-bottom: 24px;
}

.side-card h3 {
    font-size: 1.25rem;
    margin-bottom: 12px;
}

.side-card p,
.side-card li {
    color: var(--ink-muted);
    line-height: 1.65;
}

.side-card ul {
    padding-left: 20px;
    margin-top: 10px;
}

.side-card li {
    margin-bottom: 8px;
}

.side-card a {
    color: var(--link);
    font-weight: 600;
    text-decoration: none;
}

.side-card a:hover {
    text-decoration: underline;
}

.email-line {
    font-size: var(--text-base);
    margin-top: 8px;
}

/*
 * Our support addresses are long enough to be wider than a phone screen, and
 * an email address has no break opportunity, so it sets a min-content floor
 * that pushed the whole grid wider than the viewport.
 */
.email-line,
.side-card a,
.page-contact .form-note a {
    overflow-wrap: anywhere;
}

.faq-section {
    background: var(--surface-raised);
    padding: 70px 20px;
}

.faq-inner {
    max-width: 900px;
    margin: auto;
}

.faq-inner h2 {
    font-size: var(--text-3xl);
    margin-bottom: 12px;
}

.faq-intro {
    color: var(--ink-muted);
    line-height: 1.65;
    margin-bottom: 30px;
}

/* On contact the FAQ sits on a white band, so the panels invert: tinted fill
   and an accent edge instead of a white card and a shadow. */
.page-contact .faq {
    gap: 14px;
}

.page-contact .faq details {
    background: var(--surface);
    border-left: 5px solid var(--accent);
    box-shadow: none;
}

/* --- Privacy ------------------------------------------------------------- */

.page-privacy {
    line-height: var(--leading-relaxed);
}

.page-privacy header {
    background: var(--header-bg);
    color: #ffffff;
    text-align: center;
    padding: 50px 20px;
}

.page-privacy header h1 {
    margin: 0;
    font-size: var(--text-3xl);
}

.page-privacy .container {
    max-width: 1000px;
    margin: 40px auto;
    background: var(--surface-raised);
    padding: 40px;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm);
}

.page-privacy h2 {
    color: var(--brand);
    margin-top: 35px;
    font-size: var(--text-xl);
}

/* Scoped to .container, not the page: the subtitle under the h1 is a bare <p>
   sitting on the dark header, and body ink on that gradient is unreadable. */
.page-privacy p {
    margin-bottom: 15px;
}

.page-privacy .container p,
.page-privacy .container li {
    color: var(--ink-body);
}

.page-privacy ul {
    padding-left: 25px;
}

.page-privacy li {
    margin-bottom: 8px;
}

.page-privacy .last-updated {
    color: var(--ink-soft);
    font-style: italic;
}

.page-privacy a {
    color: var(--link);
    text-decoration: none;
}

.page-privacy a:hover {
    text-decoration: underline;
}

.page-privacy footer {
    margin-top: 40px;
    padding: 30px;
}

.page-privacy footer a {
    margin: 0 4px;
    display: inline-block;
    padding: 10px 8px;
}

/* Long policy URLs and support addresses have no break opportunity, so
   without this they force the page wider than a narrow phone. */
.page-privacy .container a,
.page-privacy .container li,
.page-privacy .container p {
    overflow-wrap: anywhere;
}

/* --- 404 ----------------------------------------------------------------- */

.page-404 {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.page-404 .page-header {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.page-404 .nav {
    width: 100%;
}

.content {
    max-width: var(--page);
    width: 100%;
    margin: 90px auto auto;
    position: relative;
    z-index: 2;
}

.code {
    font-size: 1rem;
    font-weight: bold;
    letter-spacing: 0.18em;
    color: var(--on-brand-soft);
    margin-bottom: 14px;
}

.content h1 {
    font-size: 3.4rem;
    line-height: var(--leading-tight);
    margin-bottom: 18px;
    letter-spacing: -0.02em;
}

.content p {
    font-size: var(--text-lg);
    max-width: 620px;
    line-height: var(--leading-normal);
    margin-bottom: 32px;
    color: var(--on-brand-tagline);
}

.page-404 .btn {
    margin-top: 0;
    margin-right: 14px;
    margin-bottom: 14px;
}

.btn.ghost {
    background: transparent;
    color: #ffffff;
    border: 1px solid rgba(255, 255, 255, 0.5);
    box-shadow: none;
}

/* /arcade. The floor is dark in both themes, on purpose: like the phone
   mockup on the home page it is a picture of a place (a row of cabinets under
   the lights), and a picture does not repaint for the reader's theme. So the
   colors below are literal, not tokens. Marquee colors cycle by position. */
.page-arcade .arcade-floor {
    background: radial-gradient(ellipse at top, #1b1f4a 0%, #0b0d1f 60%, #07080f 100%);
    padding: 40px 20px 64px;
}

.page-arcade .arcade-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
    max-width: 1180px;
    margin: 0 auto 32px;
}

.page-arcade .chip {
    font: inherit;
    font-size: var(--text-sm);
    font-weight: 700;
    padding: 9px 18px;
    border-radius: 999px;
    border: 2px solid #3b3f7a;
    background: #12143a;
    color: #c7cbff;
    cursor: pointer;
}

.page-arcade .chip:hover,
.page-arcade .chip:focus-visible {
    border-color: #7c83ff;
    color: #ffffff;
}

.page-arcade .chip.on {
    background: #7c83ff;
    border-color: #7c83ff;
    color: #0b0d1f;
}

.page-arcade .chip.random {
    background: #f5a623;
    border-color: #f5a623;
    color: #1f1300;
}

.page-arcade .cabinets {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 28px;
    max-width: 1180px;
    margin: 0 auto;
}

.page-arcade .cabinet {
    --glow: #ff4fd8;
    display: flex;
    flex-direction: column;
    background: linear-gradient(180deg, #1c1f45 0%, #111331 100%);
    border: 3px solid #2c2f66;
    border-radius: 18px 18px 10px 10px;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
    overflow: hidden;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.page-arcade .cabinet:nth-child(5n+2) { --glow: #3ee6ff; }
.page-arcade .cabinet:nth-child(5n+3) { --glow: #ffd23e; }
.page-arcade .cabinet:nth-child(5n+4) { --glow: #6dff8a; }
.page-arcade .cabinet:nth-child(5n+5) { --glow: #ff7a45; }

.page-arcade .cabinet:hover,
.page-arcade .cabinet.picked {
    transform: translateY(-4px);
    box-shadow: 0 0 0 3px var(--glow), 0 22px 48px rgba(0, 0, 0, 0.6);
}

.page-arcade .cabinet[hidden] {
    display: none;
}

.page-arcade .marquee {
    padding: 14px 12px;
    text-align: center;
    background: #0b0d1f;
    border-bottom: 3px solid var(--glow);
}

.page-arcade .marquee h2 {
    margin: 0;
    font-size: var(--text-lg);
    letter-spacing: 0.04em;
    /* A marquee is neon sans, not the site's serif. */
    font-family: var(--font-sans);
    font-weight: 700;
    text-transform: uppercase;
    color: #ffffff;
    text-shadow: 0 0 8px var(--glow), 0 0 18px var(--glow);
}

.page-arcade .screen {
    position: relative;
    display: block;
    margin: 16px 16px 0;
    aspect-ratio: 3 / 4;
    border-radius: 10px;
    overflow: hidden;
    background: #000000;
    border: 6px solid #05060d;
    box-shadow: inset 0 0 24px rgba(0, 0, 0, 0.8);
}

.page-arcade .screen img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center top;
    display: block;
}

/* A landscape game's shots are cropped from the middle, where the play is,
   rather than from the left edge. */
.page-arcade .screen.wide img {
    object-position: center;
}

.page-arcade .sticker {
    position: absolute;
    top: 20px;
    right: -44px;
    transform: rotate(35deg);
    width: 170px;
    text-align: center;
    padding: 4px 0;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
}

.page-arcade .sticker.soon {
    background: #ffd23e;
    color: #1f1300;
}

.page-arcade .sticker.new {
    background: #ff4fd8;
    color: #ffffff;
}

.page-arcade .cab-panel {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 14px 16px 18px;
    flex: 1;
}

.page-arcade .pitch {
    margin: 0;
    color: #e6e8ff;
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    flex: 1;
}

.page-arcade .who {
    margin: 0;
    color: #9aa0d6;
    font-size: var(--text-xs);
}

.page-arcade .play {
    display: block;
    text-align: center;
    margin-top: 6px;
    padding: 11px 0;
    border-radius: 10px;
    background: var(--glow);
    color: #0b0d1f;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-decoration: none;
    box-shadow: 0 4px 0 rgba(0, 0, 0, 0.45);
}

.page-arcade .play:hover,
.page-arcade .play:focus-visible {
    filter: brightness(1.12);
}

.page-arcade .play:active {
    transform: translateY(2px);
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.45);
}

.page-arcade .about {
    text-align: center;
    color: #9aa0d6;
    font-size: var(--text-xs);
}

@media (prefers-reduced-motion: reduce) {
    .page-arcade .cabinet {
        transition: none;
    }

    .page-arcade .cabinet:hover,
    .page-arcade .cabinet.picked {
        transform: none;
    }
}

/* ===========================================================================
 * 12. Responsive
 *
 * Two breakpoints rather than one. The site had only 850px, which left the
 * 850-1150px range - most tablets in landscape, and a half-width desktop
 * window - rendering two-column layouts inside a container narrower than they
 * were designed for.
 * ======================================================================== */

@media (max-width: 1150px) {
    .hero-content,
    .design-grid {
        gap: 34px;
    }

    .features {
        grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    }

    .page-contact .section {
        gap: 28px;
    }

    /* The nav stacks here rather than at 850px, because it stopped fitting on
       one line when /payouts/ and /alternatives/ joined it on 26 August 2026.
       Eight items need about 1,035px against the 960px a 1,000px window has, so
       between 851px and roughly 1,075px the links used to run under the logo
       and off the edge. Moved to this breakpoint rather than a new one at 1,075:
       the site deliberately has two, and at 1,150px the row still fits with
       75px to spare. `wrap` is belt and braces for a future ninth item and for
       a large accessibility text size, which no breakpoint can predict. */
    .nav {
        flex-direction: column;
        gap: 15px;
    }

    .nav > div:last-child {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
    }

    .nav a {
        display: inline-block;
        margin: 0 2px;
        padding: 12px 10px;
    }
}

@media (max-width: 850px) {
    footer a {
        display: inline-block;
        padding: 10px 8px;
    }

    .hero {
        grid-template-columns: 1fr;
        text-align: center;
    }

    .hero-icon {
        margin: 0 auto;
    }

    .hero h1 {
        font-size: 2.3rem;
    }

    .tagline {
        text-align: left;
    }

    .other-apps {
        grid-template-columns: 1fr;
    }

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

    .picks {
        grid-template-columns: 1fr;
    }

    .suggest-form .choices {
        grid-template-columns: 1fr;
    }

    /* Home */
    .hero-content,
    .design-grid {
        grid-template-columns: 1fr;
        text-align: center;
    }

    .hero-content h1 {
        font-size: 2.8rem;
    }

    .features {
        grid-template-columns: 1fr;
    }

    .feature {
        text-align: center;
    }

    .feature .icon {
        margin-inline: auto;
    }

    .page-home .checklist li {
        text-align: left;
    }

    /* Apps */
    .header-content h1 {
        font-size: 2.5rem;
    }

    .app-card {
        grid-template-columns: 1fr;
        text-align: center;
    }

    .app-card > a,
    .app-icon {
        margin: 0 auto;
    }

    .more-link {
        display: block;
        margin-left: 0;
        margin-top: 4px;
    }

    .app-head {
        justify-content: center;
    }

    .page-apps .checklist li {
        text-align: left;
    }

    /* Contact */
    .page-contact .section {
        grid-template-columns: 1fr;
    }

    /* Grid items default to min-width:auto, so they refuse to shrink below
       their content. Let them. */
    .page-contact .section > * {
        min-width: 0;
    }

    .page-contact .card {
        padding: 28px;
    }

    /* 404 */
    .content h1 {
        font-size: 2.5rem;
    }
}

/* "Coming soon to the App Store", in the button row of an app with no listing
   yet. A span, not a link, so it keeps the button's shape but drops the shadow
   and goes translucent: it should read as news rather than as something to
   press. Same look in dark mode, since it sits on the hero gradient, which does
   not invert. */
.store-btn.soon {
    background: rgba(255, 255, 255, 0.16);
    color: #ffffff;
    border: 2px dashed rgba(255, 255, 255, 0.6);
    box-shadow: none;
    cursor: default;
}

.page-apps .store-btn.soon,
.page-apps .store-btn.soon:hover {
    background: transparent;
    color: var(--ink-strong);
    border-color: var(--ink-soft);
}
