/* =========================================================
   Tokens copied verbatim from the product's style.css so the
   page and the app cannot drift apart. The page commits to
   the dark palette on purpose: Flow is dark-first.
   ========================================================= */
:root {
    --bg: #050505;
    --surface: #0F0F0F;
    --surface-2: #171717;
    --surface-hover: #1C1C1C;

    --primary: #00E87B;
    --primary-light: rgba(0, 232, 123, 0.1);
    --accent: #3B82F6;
    --accent-light: rgba(59, 130, 246, 0.1);
    --violet: #7c3aed;
    --violet-light: rgba(124, 58, 237, 0.14);

    --text: #EDEDED;
    --text-secondary: #bdbdbd;
    --text-tertiary: #8d8d8d;

    --warning: #FFB800;
    --warning-light: rgba(255, 184, 0, 0.1);
    --danger: #FF4757;
    --danger-light: rgba(255, 71, 87, 0.1);

    --divider: #1A1A1A;
    --border: #1F1F1F;

    --radius-sm: 12px;
    --radius-md: 16px;
    --radius-lg: 20px;
    --radius-pill: 100px;

    --ease-spring: cubic-bezier(0.32, 0.72, 0, 1);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

    --masthead-h: 68px;
    --gutter: clamp(20px, 5vw, 64px);
    --measure: 1280px;
}

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

html {
    scroll-behavior: smooth;
}

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

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: 'Space Grotesk', -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 16px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
}

h1,
h2,
h3,
h4,
p,
dl,
dd,
figure {
    margin: 0;
}

a {
    color: inherit;
    text-decoration: none;
}

button {
    font: inherit;
    color: inherit;
}

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

.shell {
    width: 100%;
    max-width: var(--measure);
    margin: 0 auto;
    padding-inline: var(--gutter);
}

.lede {
    font-size: clamp(28px, 4.2vw, 44px);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.14;
    max-width: 18ch;
}

.lede .soft {
    color: var(--text-tertiary);
}

.body-copy {
    color: var(--text-secondary);
    font-size: clamp(15px, 1.6vw, 17px);
    line-height: 1.65;
    max-width: 56ch;
}

/* ---------------------------------------------------------
   Masthead
   --------------------------------------------------------- */
.masthead {
    position: sticky;
    top: 0;
    z-index: 40;
    height: var(--masthead-h);
    display: flex;
    align-items: center;
    background: rgba(5, 5, 5, 0.74);
    backdrop-filter: blur(18px) saturate(150%);
    -webkit-backdrop-filter: blur(18px) saturate(150%);
    border-bottom: 1px solid transparent;
    transition: border-color 200ms ease;
}

.masthead[data-stuck="true"] {
    border-bottom-color: var(--border);
}

.masthead .shell {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
}

.wordmark {
    display: flex;
    align-items: center;
    gap: 7px;
    font-weight: 700;
    font-size: 15px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.wordmark i {
    color: var(--primary);
    font-size: 17px;
}

.masthead nav {
    display: flex;
    align-items: center;
    gap: 28px;
}

.masthead nav a {
    font-size: 14px;
    color: var(--text-secondary);
    transition: color 160ms ease;
}

.masthead nav a:hover {
    color: var(--text);
}

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

.launch {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 9px 16px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border);
    background: var(--surface-2);
    color: var(--text);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: transform 160ms var(--ease-out), background 160ms ease, border-color 160ms ease;
}

.launch:hover {
    background: var(--surface-hover);
    border-color: #2A2A2A;
}

.launch:active {
    transform: scale(0.97);
}

.launch.is-primary {
    background: var(--primary);
    border-color: var(--primary);
    color: #050505;
}

.launch.is-primary:hover {
    background: #16f28c;
    border-color: #16f28c;
}

/* ---------------------------------------------------------
   Hero
   --------------------------------------------------------- */
.hero {
    position: relative;
    overflow: hidden;
    height: 100dvh;
}

/* Direct child of .hero, not of the shell div below -- .shell caps its
   own width at --measure and pads its edges, which is exactly what kept
   this from ever reaching the true right edge of the viewport before.
   .hero has neither, so right:0/bottom:0 here mean the actual screen
   edges. The mask fades its own top-left corner out rather than relying
   on opacity, so the page's real background shows through instead of a
   dimmed rectangle — it reads as one dark surface, not an image dropped
   on top of one. */
.hero-bg {
    position: absolute;
    right: 0;
    bottom: 0;
    z-index: 0;
    width: auto;
    height: 90vh;
    pointer-events: none;
    user-select: none;
}

.hero-content {
    position: relative;
    z-index: 1;
    padding-block: clamp(86px, 21vh, 178px) clamp(44px, 7vh, 84px);
}

.hero h1 {
    font-size: clamp(40px, 6.4vw, 76px);
    font-weight: 700;
    letter-spacing: -0.045em;
    line-height: 1.02;
    max-width: 26ch;
}

.hero h1 .accent {
    color: var(--primary);
    display: block;
}

.hero p {
    margin-top: 22px;
    max-width: 48ch;
    color: var(--text-secondary);
    font-size: clamp(16px, 1.8vw, 18px);
    line-height: 1.6;
}

.hero-actions {
    margin-top: 32px;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

/* Sits in normal flow right after the button, at the same level as the
   button itself -- not floated above it -- so it can never land on top
   of the paragraph the way an absolutely-positioned note could. The
   loop is a true circle (drawn from the standard 4-point bezier
   circle approximation, not eyeballed), left open at one point so the
   pen stroke can flow straight out of it into the arrowhead. */
.hero-note {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.hero-note-arrow {
    display: none;
    margin-top: 150px;
    margin-left: -70px;
    flex-shrink: 0;
    color: var(--primary);
    opacity: 0.85;
    transform: rotate(-3deg);
}

.hero-note-text {
    font-family: 'Caveat', cursive;
    font-weight: 700;
    font-size: 26px;
    line-height: 1;
    color: var(--primary);
    white-space: nowrap;
    transform: rotate(-2deg);
}

@media (max-width: 720px) {
    

    /* Text has no room to stay narrow here (p's 48ch cap exceeds the
       viewport itself), so it now runs the full width the image sits
       behind. Shrunk into the corner rather than hidden outright --
       still a hint of the peak, not a competitor to the CTA in front
       of it. */
    .hero-bg {
        -webkit-mask-image: linear-gradient(135deg, transparent 0%, transparent 22%, #000 58%);
        mask-image: linear-gradient(135deg, transparent 0%, transparent 22%, #000 58%);
            position: absolute;
        right: -250px;
        bottom: 0;
         z-index: 0;
    }
}

/* ---------------------------------------------------------
   Story. One device, pinned for the whole section. Each step
   frames a single moment rather than opening the whole app,
   so nothing half-finished is ever on display.
   --------------------------------------------------------- */
.story {
    padding-bottom: clamp(60px, 9vw, 120px);
}

.story-head {
    padding-block: clamp(24px, 4vw, 48px) clamp(8px, 2vw, 24px);
    scroll-margin-top: var(--masthead-h);
    margin-bottom: -150px;
}

.story-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
    gap: clamp(28px, 5vw, 88px);
    align-items: start;
}

.story-steps {
    min-width: 0;
}

.story-step:last-child {
    min-height: 110vh;
}

.story-step {
    min-height: 84vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-block: 36px;
    opacity: 0.34;
    transition: opacity 420ms var(--ease-out);
}

.story-step.is-active {
    opacity: 1;
}

.story-step h3 {
    font-size: clamp(23px, 3vw, 33px);
    font-weight: 700;
    letter-spacing: -0.028em;
    line-height: 1.15;
    max-width: 17ch;
}

.story-step p {
    margin-top: 16px;
    color: var(--text-secondary);
    font-size: clamp(15px, 1.6vw, 17px);
    line-height: 1.65;
    max-width: 44ch;
}

.pointers {
    margin-top: 18px;
    display: grid;
    gap: 9px;
}

.pointer {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    font-size: 14.5px;
    color: var(--text-secondary);
}

.pointer i {
    color: var(--primary);
    font-size: 15px;
    margin-top: 2px;
    flex-shrink: 0;
}

.story-device {
    position: sticky;
    top: 0;
    height: 100dvh;
    display: grid;
    place-items: center;
}

@media (prefers-reduced-motion: reduce) {
    .story-step {
        opacity: 1;
        transition: none;
    }
}

/* ---------------------------------------------------------
   Below 940px the sticky-scroll pairing has nowhere to work:
   a phone shown at a readable size leaves no room for prose
   beside it, and pinning it while text scrolls behind just
   traps the reader under a screen they cannot finish reading.
   So the desktop grid is swapped outright for a flat list of
   five independent phones, each with its own caption right
   above it. Nothing is hijacked or synchronised: it is the
   page's own scroll, behaving the way it always does.
   --------------------------------------------------------- */
.story-mobile {
    display: none;
}

@media (max-width: 940px) {
    .story-grid {
        display: none;
    }

    .story-mobile {
        display: block;
    }
    .story-head {
    margin-bottom:40px;
    }
}


.mob-feature {
    padding-block: 44px;
    border-top: 1px solid var(--border);
}

.mob-feature:first-child {
    border-top: none;
    padding-top: 4px;
}

.mob-feature h3 {
    font-size: clamp(21px, 5.6vw, 25px);
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.18;
}

.mob-feature p {
    margin-top: 12px;
    color: var(--text-secondary);
    font-size: 15px;
    line-height: 1.6;
}

.mob-feature .pointers {
    margin-top: 16px;
}

.mob-feature .device {
    margin-top: 28px;
}

/* ---------------------------------------------------------
   Device
   --------------------------------------------------------- */
.device {
    --device-w: 350px;
    width: min(var(--device-w), 100%);
    margin-inline: auto;
border-radius: 40px;
    padding: 5px;
    background: linear-gradient(160deg, #232326, #131313 55%);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07), 0 40px 90px -34px rgba(0, 0, 0, 0.9);
    position: relative;
}

.device::after {
    content: '';
    position: absolute;
    inset: 11px;
    border-radius: 36px;
    pointer-events: none;
    z-index: 5;
}

.screen {
    position: relative;
    border-radius: 36px;
    background: var(--bg);
    overflow: hidden;
    height: min(640px, 76dvh);
    display: flex;
    flex-direction: column;
}

.notch {
    position: absolute;
    top: 9px;
    left: 50%;
    transform: translateX(-50%);
    width: 88px;
    height: 22px;
    border-radius: var(--radius-pill);
    background: #0a0a0c;
    /* A flat near-black pill on a near-black screen had no edge to
       read by. Same restraint as the bezel's own rim (device::after,
       ~0.05-0.07 alpha): a thin outer line so the shape separates
       from the background, plus a faint inner top highlight for the
       glass-catching-light look real hardware has. */
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), inset 0 1px 1px rgba(255, 255, 255, 0.09);
    z-index: 4;
}

/* iOS status bar. Sits above the offline banner (z-index 3) and the
   notch pill (z-index 4) alike, because the real thing never
   disappears either -- not when a call banner drops down, not when
   the phone loses signal. 9:41 is Apple's own convention for every
   marketing screenshot, not a placeholder. */
.status-bar {
    position: absolute;
    top: 9px;
    left: 0;
    right: 0;
    height: 22px;
    z-index: 6;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 22px;
    color: var(--text);
    pointer-events: none;
}

.status-time {
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
}

.status-icons {
    display: flex;
    align-items: center;
    gap: 5px;
}

.status-icon {
    display: block;
    flex-shrink: 0;
}

.device.is-offline .status-bar {
    color: #fff;
}

/* Screens are framed to fit, but a long system font or a
   short viewport must never clip content outright.

   On desktop, .p-panel children are stacked absolutely (see below)
   so the outgoing and incoming screen can cross-fade instead of one
   vanishing before the other appears. inset:0 on those panels reads
   as an offset from this element's padding edge, so the padding set
   here still clears the notch/status bar for them automatically --
   nothing extra needed on .p-panel itself. Mobile's five phones
   don't use .p-panel at all, so this padding is what positions
   their content directly. */
.screen-body {
    flex: 1;
    position: relative;
    overflow: hidden;
    padding-top: 40px;
    padding-bottom: 8px;
}

@media (max-width: 940px) {

    /* These rules now style the five standalone mobile phones
     only: the desktop's single device is inside .story-grid,
     which is display:none at this width. Height is left to
     auto rather than clipped to a viewport fraction, because
     nothing here is pinned or scrubbed by scroll any more --
     a static phone should never need an internal scrollbar to
     show what it is holding. */
    .device {
        --device-w: min(300px, 82vw);
        border-radius: 36px;
    }

    .screen {
        border-radius: 31px;
        height: auto;
    }

    .device::after {
        border-radius: 29px;
    }

    .screen-body {
        padding-top: 40px;
        padding-bottom: 12px;
        overflow: visible;
    }

    .status-bar {
        padding: 0 18px;
    }
}

/* ---- product surfaces, mirrored from style.css ---- */
.p-hero {
    padding: 14px 16px 12px;
}

.p-brand {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-tertiary);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-bottom: 7px;
}

.p-brand em {
    font-style: normal;
    color: var(--primary);
}

.p-amount {
    font-size: 31px;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.05;
    font-variant-numeric: tabular-nums;
}

.p-amount-sub {
    font-size: 11.5px;
    color: var(--text-secondary);
    margin-top: 3px;
}

/* Dashboard stat tiles carry a coloured rule on the leading
   edge, exactly as the app draws them. */
.p-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 7px;
    padding: 2px 16px;
}

.p-tile {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 8px 9px 9px 11px;
    position: relative;
    overflow: hidden;
}

.p-tile::before {
    content: '';
    position: absolute;
    left: 0;
    top: 8px;
    bottom: 8px;
    width: 2.5px;
    border-radius: 2px;
    background: var(--accent);
}

.p-tile.g::before {
    background: var(--primary);
}

.p-tile.v::before {
    background: var(--violet);
}

.p-tile.a::before {
    background: var(--warning);
}

.p-tile-k {
    font-size: 8px;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

.p-tile-v {
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.02em;
    margin-top: 2px;
    font-variant-numeric: tabular-nums;
    color: var(--accent);
}

.p-tile.g .p-tile-v {
    color: var(--primary);
}

.p-tile.v .p-tile-v {
    color: var(--violet);
}

.p-tile.a .p-tile-v {
    color: var(--warning);
}

.p-tile-s {
    font-size: 8.5px;
    color: var(--text-tertiary);
    margin-top: 1px;
}

.p-netrow {
    margin: 7px 16px 0;
    padding: 10px 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.p-netrow span {
    font-size: 11.5px;
    color: var(--text-secondary);
}

.p-netrow strong {
    font-size: 14px;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
}

.p-chart {
    padding: 12px 16px 0;
}

.p-chart-t {
    font-size: 11px;
    font-weight: 600;
    margin-bottom: 8px;
}

.p-bars {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 54px;
}

.p-bars span {
    flex: 1;
    background: var(--accent);
    border-radius: 2px 2px 0 0;
    min-height: 2px;
}

.p-section-title {
    font-size: 10px;
    font-weight: 700;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 0 16px;
    margin: 14px 0 6px;
}

.p-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    overflow: hidden;
    margin: 0 16px;
}

.p-row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 11px;
    border-bottom: 1px solid var(--divider);
}

.p-row:last-child {
    border-bottom: none;
}

.p-icon {
    width: 30px;
    height: 30px;
    border-radius: 9px;
    display: grid;
    place-items: center;
    flex-shrink: 0;
    font-size: 14px;
    background: var(--accent-light);
    color: var(--accent);
    border: 1px solid rgba(59, 130, 246, 0.2);
}

.p-icon.v {
    background: var(--violet-light);
    color: #a78bfa;
    border-color: rgba(124, 58, 237, 0.28);
}

.p-icon.a {
    background: var(--warning-light);
    color: var(--warning);
    border-color: rgba(255, 184, 0, 0.22);
}

.p-icon.r {
    background: var(--danger-light);
    color: var(--danger);
    border-color: rgba(255, 71, 87, 0.2);
}

/* These rows are built from spans so the markup stays inert.
   Each one still has to stack, hence the explicit blocks. */
.p-row-body {
    flex: 1;
    min-width: 0;
}

.p-row-title {
    display: block;
    font-size: 12.5px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.p-row-meta {
    font-size: 10.5px;
    color: var(--text-secondary);
    margin-top: 2px;
    display: flex;
    align-items: center;
    gap: 5px;
}

.p-row-right {
    text-align: right;
    flex-shrink: 0;
}

.p-row-amount {
    display: block;
    font-size: 12.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.p-row-status {
    display: block;
    font-size: 9.5px;
    font-weight: 600;
    margin-top: 1px;
}

.p-row-status.paid {
    color: var(--primary);
}

.p-row-status.due {
    color: var(--warning);
}

.p-badge {
    display: inline-flex;
    padding: 1px 6px;
    border-radius: var(--radius-pill);
    font-size: 9px;
    font-weight: 600;
    background: var(--surface-2);
    color: var(--text-secondary);
}

.p-badge.b {
    background: var(--accent-light);
    color: var(--accent);
}

.p-badge.v {
    background: var(--violet-light);
    color: #a78bfa;
}

.p-badge.a {
    background: var(--warning-light);
    color: var(--warning);
}

.p-badge.g {
    background: var(--primary-light);
    color: var(--primary);
}

/* client header */
.p-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 16px 6px;
    font-size: 12px;
}

.p-topbar .t {
    font-weight: 700;
    font-size: 14px;
}

.p-topbar .a {
    color: var(--primary);
    font-weight: 600;
    font-size: 11.5px;
}

.p-topbar .b {
    width: 24px;
    height: 24px;
    border-radius: 8px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    display: grid;
    place-items: center;
    color: var(--text-secondary);
    font-size: 12px;
}

.p-cavatar {
    width: 46px;
    height: 46px;
    border-radius: 14px;
    margin: 4px auto 8px;
    display: grid;
    place-items: center;
    font-size: 15px;
    font-weight: 700;
    color: var(--primary);
    background: linear-gradient(135deg, var(--primary-light), var(--accent-light));
    border: 1.5px solid rgba(0, 232, 123, 0.2);
}

.p-cname {
    text-align: center;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.p-trio {
    display: flex;
    justify-content: center;
    gap: 20px;
    margin: 10px 0 12px;
}

.p-trio div {
    text-align: center;
}

.p-trio b {
    display: block;
    font-size: 15px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.p-trio b.g {
    color: var(--primary);
}

.p-trio b.a {
    color: var(--warning);
}

.p-trio span {
    font-size: 8px;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

.p-actions {
    display: flex;
    gap: 6px;
    padding: 0 16px 4px;
}

.p-act {
    flex: 1;
    text-align: center;
    padding: 8px 4px;
    border-radius: var(--radius-pill);
    font-size: 11px;
    font-weight: 600;
}

.p-act.pri {
    background: var(--primary);
    color: #050505;
}

.p-act.sec {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text);
}

.p-act.dan {
    background: var(--danger-light);
    color: var(--danger);
}

/* invoice */
.p-inv {
    margin: 0 16px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 12px;
}

.p-inv-top {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 10px;
}

.p-k {
    display: block;
    font-size: 9.5px;
    color: var(--text-secondary);
}

.p-v {
    display: block;
    font-weight: 700;
    font-size: 12.5px;
    margin-top: 1px;
}

.p-v.big {
    font-size: 16px;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
}

.p-dates {
    display: flex;
    justify-content: space-between;
    font-size: 10.5px;
    color: var(--text-secondary);
    margin-top: 10px;
}

.p-hr {
    height: 1px;
    background: var(--divider);
    margin: 11px 0;
}

.p-line {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    padding: 7px 0;
    border-bottom: 1px solid var(--divider);
    font-size: 11.5px;
}

.p-line:last-child {
    border-bottom: none;
}

.p-line .q {
    display: block;
    color: var(--text-secondary);
    font-size: 9.5px;
    margin-top: 1px;
}

.p-line strong {
    font-variant-numeric: tabular-nums;
}

.p-btns {
    padding: 10px 16px 0;
    display: grid;
    gap: 6px;
}

.p-btn {
    padding: 9px;
    border-radius: 11px;
    text-align: center;
    font-size: 11.5px;
    font-weight: 600;
    background: var(--primary);
    color: #050505;
}

.p-btn.ghost {
    background: var(--surface-2);
    color: var(--text);
    border: 1px solid var(--border);
}

.p-btn-pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
}

/* expenses summary */
.p-sum {
    margin: 0 16px 8px;
    padding: 10px 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    display: flex;
    justify-content: space-between;
}

.p-sum span {
    font-size: 11px;
    color: var(--text-secondary);
}

.p-sum strong {
    font-size: 13px;
    font-variant-numeric: tabular-nums;
}

/* Offline banner, copied from the real app's #offline-banner:
   a full-width red strip pinned to the very top edge, sliding
   down from behind the notch rather than fading in as a card.
   The screen's own overflow:hidden clips it to the rounded
   top corners, so it reads as one continuous surface. */
.p-offline {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    z-index: 3;
    height: 58px;
    background: var(--danger);
    color: #fff;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding-bottom: 5px;
    font-size: 10.5px;
    font-weight: 600;
    text-align: center;
    transform: translateY(-100%);
    transition: transform 280ms var(--ease-out);
    pointer-events: none;
}

.device.is-offline .p-offline {
    transform: translateY(0);
}

/* Apple-style notification banner. Shape, material and stack
   order follow the iOS banner, so it reads as a system alert
   rather than as page furniture. */
.p-notif {
    position: absolute;
    left: 8px;
    right: 8px;
    top: 45px;
    z-index: 8;
    display: flex;
    gap: 9px;
    align-items: flex-start;
    padding: 10px 11px;
    border-radius: 18px;
    background: rgba(44, 44, 46, 0.72);
    backdrop-filter: blur(22px) saturate(180%);
    -webkit-backdrop-filter: blur(22px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 12px 34px -10px rgba(0, 0, 0, 0.7);
    opacity: 0;
    /* Exit state: a calm fade-and-collapse upward, no spring -- this is
       what's in effect when .is-in is removed, since that transition
       lives here on the base class rather than on .is-in. Before, both
       directions shared .is-in's bouncy entrance transition below, so
       the dismiss inherited a spring overshoot that reads as "arriving"
       rather than "leaving" -- when it was even noticed, since 16px
       was a small enough move to miss. */
    transform: translateY(-22px) scale(0.9);
    transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out);
    pointer-events: none;
}

.p-notif.is-in {
    opacity: 1;
    transform: none;
    transition: opacity 260ms var(--ease-out), transform 420ms var(--ease-spring);
}

.p-notif img {
    width: 38px;
    height: 38px;
    border-radius: 8px;
    flex-shrink: 0;
}

.p-notif-b {
    flex: 1;
    min-width: 0;
}

.p-notif-app {
    display: block;
    font-size: 8.5px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
}

.p-notif-t {
    display: block;
    font-size: 11.5px;
    font-weight: 700;
    color: #fff;
    margin-top: 1px;
}

.p-notif-d {
    display: block;
    font-size: 11px;
    color: rgba(255, 255, 255, 0.72);
    line-height: 1.35;
    margin-top: 1px;
}

.p-notif-time {
    font-size: 9px;
    color: rgba(255, 255, 255, 0.45);
    flex-shrink: 0;
    position: absolute;
    top: 8px;
    right: 20px;
}

@media (prefers-reduced-motion: reduce) {
    .p-notif,
    .p-notif.is-in {
        transition: opacity 200ms linear;
        transform: none;
    }

    .p-offline {
        transition: none;
    }
}

/* Panels cross-fade instead of one popping in after the other cuts
   out. Both stay in the DOM and in place (position:absolute, stacked)
   for the whole transition, which is what a swap-based display:none
   toggle can't do -- display can't be transitioned, so the outgoing
   screen used to vanish in the same frame the incoming one started.
   The scale is deliberately tiny: real iOS tab switches dissolve,
   they don't slide or bounce. */
.p-panel {
    /* top/bottom set explicitly rather than inset:0: inset offsets
       are measured from the containing block's padding edge, which
       sits at .screen-body's outer edge -- so inset:0 ignored its
       40px/8px padding entirely and let every panel's content start
       flush under the status bar instead of below it. */
    position: absolute;
    top: 40px;
    right: 0;
    bottom: 8px;
    left: 0;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
    opacity: 0;
    transform: scale(0.98);
    pointer-events: none;
    transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out);
}

.p-panel::-webkit-scrollbar {
    display: none;
}

.p-panel.is-on {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
    .p-panel {
        transition: opacity 160ms linear;
        transform: none;
    }
}

/* The tab bar is chrome here, not navigation: the visitor is
   never dropped into a screen this page has not framed. */
.p-tabs {
    display: flex;
    border-top: 1px solid var(--border);
    background: rgba(10, 10, 10, 0.94);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    padding-bottom: 5px;
    flex-shrink: 0;
}

.p-tab {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    color: #b7b7b7;
    font-size: 8.5px;
    font-weight: 500;
    padding: 7px 0 4px;
    transition: color 250ms ease;
}

.p-tab[data-on="true"] {
    color: var(--primary);
}

.p-tab svg {
    width: 18px;
    height: 18px;
}

/* ---------------------------------------------------------
   QR band. One large artifact, presentational only.
   --------------------------------------------------------- */
.qr-band {
    padding-block: clamp(60px, 9vw, 120px);
    scroll-margin-top: var(--masthead-h);
}
.qr-band .shell {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.qr-stage {
    margin-top: clamp(34px, 5vw, 64px);
    display: grid;
    place-items: center;
}

/* A real rendered slip now, not a hand-built recreation -- scales as one
   flat image, so none of the old two-column grid/dashed-divider/canvas
   machinery this used to need is required any more. */
.qr-slip-img {
    display: block;
    width: min(760px, 100%);
    height: auto;
    border-radius: var(--radius-lg);
    box-shadow: 0 40px 90px -40px rgba(0, 0, 0, 0.9);
}

/* ---------------------------------------------------------
   FAQ. Native disclosure elements: keyboard and screen-reader
   behaviour come for free and cost no script.
   --------------------------------------------------------- */
.faq {
    padding-block: clamp(60px, 9vw, 120px);
    scroll-margin-top: var(--masthead-h);
}

.faq-list {
    margin-top: clamp(28px, 4vw, 52px);
    max-width: 820px;
    border-top: 1px solid var(--border);
}

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

.faq summary {
    list-style: none;
    cursor: pointer;
    padding: 20px 40px 20px 0;
    position: relative;
    font-size: clamp(16px, 1.9vw, 18.5px);
    font-weight: 600;
    letter-spacing: -0.015em;
    transition: color 160ms ease;
}

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

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

.faq summary::after {
    content: '';
    position: absolute;
    right: 8px;
    top: 50%;
    width: 9px;
    height: 9px;
    border-right: 2px solid var(--text-tertiary);
    border-bottom: 2px solid var(--text-tertiary);
    transform: translateY(-70%) rotate(45deg);
    transition: transform 260ms var(--ease-out), border-color 160ms ease;
}

.faq details[open] summary::after {
    transform: translateY(-25%) rotate(225deg);
    border-color: var(--primary);
}

.faq .answer {
    padding: 0 40px 22px 0;
    color: var(--text-secondary);
    font-size: 15.5px;
    line-height: 1.68;
    max-width: 62ch;
}

.faq .answer strong {
    color: var(--text);
    font-weight: 600;
}

/* ---------------------------------------------------------
   Close
   --------------------------------------------------------- */
.close-band {
    border-top: 1px solid var(--border);
}

.close-inner {
    padding-block: clamp(60px, 9vw, 104px);
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 34px;
    align-items: end;
}

@media (max-width: 700px) {
    .close-inner {
        grid-template-columns: 1fr;
        align-items: start;
    }
}

.colophon {
    border-top: 1px solid var(--border);
    padding-block: 24px 40px;
    display: flex;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    font-size: 13px;
    color: var(--text-tertiary);
}

.colophon a {
    color: var(--text-secondary);
}

.colophon a:hover {
    color: var(--text);
}

/* ---------------------------------------------------------
   Reveal, driven by IntersectionObserver rather than a
   scroll listener.
   --------------------------------------------------------- */
.rise {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 600ms var(--ease-out), transform 600ms var(--ease-out);
}

.rise.seen {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .rise {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* iOS-style switch used to cut the network */
.ios-switch {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    margin-top: 20px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
}

.ios-track {
    width: 51px;
    height: 31px;
    border-radius: var(--radius-pill);
    background: #39393D;
    position: relative;
    flex-shrink: 0;
    transition: background 280ms var(--ease-out);
}

.ios-knob {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 27px;
    height: 27px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.35);
    transition: transform 300ms var(--ease-spring);
}

.ios-switch[aria-pressed="true"] .ios-track {
    background: var(--danger);
}

.ios-switch[aria-pressed="true"] .ios-knob {
    transform: translateX(20px);
}

.ios-label {
    font-size: 15px;
    font-weight: 600;
}

@media (prefers-reduced-motion: reduce) {

    .ios-track,
    .ios-knob {
        transition: none;
    }
}