/* Odette landing page — layout.
   ─────────────────────────────────────────────────────────────────────────
   Colour, type and buttons live in design-system.css. Nothing here should
   introduce a raw hex that the themes need to move; if a value has to change
   between ink and light, it belongs in a token, not in this file.

   The @import is what makes this stylesheet self-sufficient, and it is not
   redundant with index.html's <link>. privacy.html and tos.html load THIS
   file and nothing else, so without the import every var() they inherit
   resolves to nothing: those pages fall back to a white ground and Times.
   index.html links design-system.css directly as well, so it still gets the
   parallel fetch and the import costs it only a cache hit.

   Those two pages also read five legacy token names plus .footer-bottom —
   see the compatibility block at the bottom, and do not prune it by grepping
   this file alone. */
@import url('design-system.css?v=1');

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

html { scroll-behavior: smooth; }

/* The fixed header must never cover the opening line of an anchor target. */
#how-it-works, #markets, #compare, #faq { scroll-margin-top: 6rem; }

body {
    font-family: var(--sans);
    background: var(--background);
    color: var(--t2);
    font-size: 15px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* height:auto is load-bearing, not tidiness: the width/height ATTRIBUTES on
   the shots are there to reserve layout space, and without this the attribute
   height wins over the scaled width and the image renders at natural size. */
img { max-width: 100%; height: auto; }

a { color: var(--t1); text-decoration: none; }
a:hover { color: var(--primary); }

.dim { color: var(--t3); }

/* One content width. The banner, the screenshot and every section align on
   the same two edges — the nav is the single deliberate exception. */
.inner { max-width: 1140px; margin: 0 auto; padding-inline: 40px; }

.wordmark {
    font-weight: 600;
    letter-spacing: 0.14em;
    font-size: 15px;
    color: var(--t1);
}

/* ── Nav ──────────────────────────────────────────────────────────────────
   Sticky, in two states: transparent while it is over the hero, a raised
   surface once the page has moved under it. The transparent state is what
   lets it sit over the dissolving screenshot without fighting it, and JS
   writes data-solid past the first few pixels of scroll.

   Below the menu overlay's z-index on purpose: the sheet is the whole
   navigation at that width and nothing may float over it. */
.nav-shell {
    position: sticky;
    top: 0;
    z-index: 50;
    background: transparent;
    border-bottom: 1px solid transparent;
    transition: background-color .26s var(--ease-house),
                border-color .26s var(--ease-house);
}
.nav-shell[data-solid="true"] {
    background: var(--background);   /* fallback where color-mix is missing */
    background: color-mix(in srgb, var(--background) 86%, transparent);
    border-bottom-color: var(--hair);
    -webkit-backdrop-filter: blur(20px);
            backdrop-filter: blur(20px);   /* the ONE blur on the page */
}

.nav {
    max-width: 1140px;
    margin: 0 auto;
    padding: 1.5rem 40px;
    display: flex;
    align-items: center;
    gap: 0.45rem;
}
.nav-actions { display: flex; align-items: center; gap: 0.45rem; margin-left: auto; }

.theme-toggle { padding: 0; width: 36px; height: 33px; }
.theme-toggle svg { stroke: var(--chip-text); }
.theme-toggle:hover svg { stroke: var(--t1); }

/* Shape defined once; the nav's copy is hidden on desktop by the media query
   below, while the one inside the menu is always shown because the menu only
   ever appears at mobile widths anyway. */
.burger {
    display: none;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 4.5px;
    width: 42px;
    height: 42px;
    flex: none;
    border: 0;
    border-radius: 9px;
    background: var(--chip-fill);
    cursor: pointer;
}
.burger:hover { background: var(--chip-hover); }
.burger span {
    display: block;
    width: 16px;
    height: 1.6px;
    border-radius: 2px;
    background: var(--t1);
}
.burger svg { width: 15px; height: 15px; stroke: var(--t1); }
.menu .burger { display: inline-flex; }
/* The same finger-floor design-system.css gives the buttons: the burger is
   the first thing a phone thumb aims at and was the one control left at 42. */
@media (pointer: coarse) {
    .burger { width: 44px; height: 44px; }
}

/* ── Mobile menu ──────────────────────────────────────────────────────────
   A full-screen sheet rather than a dropdown: at this width it is the whole
   navigation, and a small panel hanging off the header makes the competition
   banner inside it look like an advert. */
.menu {
    position: fixed;
    inset: 0;
    z-index: 100;
    background: var(--background);
    display: flex;
    flex-direction: column;
    padding: 1rem 20px 2rem;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.menu[hidden] { display: none; }   /* [hidden] loses to display:flex */

.menu-bar { display: flex; align-items: center; gap: 0.5rem; }
.menu-bar .wordmark { margin-right: auto; }

.menu-items { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 1.5rem; }

/* The rows ARE buttons. Everything else tappable on this site is one, and a
   bare text list reads as copy rather than navigation. */
.mitem {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 52px;
    padding: 0 1.25rem;
    border-radius: 9px;
    background: var(--chip-fill);
    color: var(--t1);
    font-size: 12px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.mitem:hover { background: var(--chip-hover); color: var(--t1); }
.mitem svg { width: 14px; height: 14px; stroke: var(--t3); flex: none; }

/* Pushed to the bottom so the competition and the CTA sit under the thumb. */
/* The banner stacks here: at 350px of usable width its desktop row would put
   the pool figure and the button on top of each other. */
.menu-competition { flex-direction: column; align-items: stretch; gap: 1rem; padding: 1.3rem 1.25rem; }
.menu-competition .competition-title { font-size: 1.25rem; white-space: normal; }
.menu-competition .competition-sub { white-space: normal; }
.menu-competition .competition-data { margin-left: 0; gap: 0.7rem; }
.menu-competition .pool-figure { font-size: 2.1rem; }
.menu-competition .competition-cta { margin-left: auto; }

.menu-foot { margin-top: auto; padding-top: 2rem; }
.menu-cta { width: 100%; margin-top: 0.75rem; }
.menu-links {
    display: flex;
    justify-content: center;
    gap: 1.5rem;
    margin-top: 1.4rem;
    font-size: 13px;
    flex-wrap: wrap;
}
.menu-links a, .menu-theme { color: var(--t3); }
.menu-links a:hover, .menu-theme:hover { color: var(--primary); }
.menu-theme {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

/* ── Hero ─────────────────────────────────────────────────────────────── */
.hero {
    position: relative;
    max-width: 1140px;
    margin: 0 auto;
    padding: 6.5rem 40px 0;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* The one atmospheric effect on the page. Everything else is flat.
   The width is capped at the hero's own: a fixed 960px is wider than the
   viewport between the mobile breakpoint and 960px, and an absolutely
   positioned box that wide scrolls the whole page sideways. */
.glow {
    position: absolute;
    top: -140px;
    left: 50%;
    transform: translateX(-50%);
    width: min(960px, 100%);
    height: 580px;
    background: radial-gradient(50% 50% at 50% 42%, var(--glow), transparent 70%);
    pointer-events: none;
}

/* No max-width: the <br> in the markup owns the break. A measure clamp here
   would rewrap the first sentence and land the fold mid-thought. */
.hero-title { position: relative; font-size: 5.6rem; line-height: 1.01; }
.hero-title em { font-style: italic; color: var(--t2); }

/* One step brighter than body copy: this line is the pitch, and it was the
   first thing to disappear when it sat at --t2. */
.hero-sub {
    position: relative;
    font-size: 16.5px;
    margin-top: 1.8rem;
    max-width: 52ch;
    color: var(--hero-sub);
}

.hero-actions {
    position: relative;
    display: flex;
    gap: 0.7rem;
    align-items: center;
    margin-top: 2.6rem;
    flex-wrap: wrap;
    justify-content: center;
}

/* ── The live line ────────────────────────────────────────────────────────
   Two prices and the settlement time, in the mono. It is the hero's proof
   that the thing behind this page is running: the prices come from the same
   fetch the markets strip uses, and the expiry is a protocol constant, not a
   number invented to fill the row. */
.hero-live {
    position: relative;
    display: flex;
    gap: 2.2rem;
    align-items: baseline;
    justify-content: center;
    margin-top: 3.2rem;
    flex-wrap: wrap;
    font-size: 13px;
    color: var(--t3);
}
.hero-live b { font-weight: 500; color: var(--t1); }

/* ── Weekly competition ───────────────────────────────────────────────────
   Paper on both themes. The trophy is a cover background rather than an <img>
   so the card can grow with its content without the art detaching. */
.competition-wrap { padding-top: 4.5rem; }

.competition {
    /* The source art is a paper card sitting ON a dark ground, so `cover` on a
       short wide box fits it by WIDTH and leaves its dark frame showing at both
       ends. Oversizing the width crops that frame off; --paper backs whatever
       the art does not reach, so a taller box (mobile) still reads as paper. */
    background: var(--paper) url('img/competition-trophy.webp') center / 120% auto no-repeat;
    border-radius: 12px;
    padding: 1.1rem 1.75rem;
    color: var(--ink);
    display: flex;
    align-items: center;
    gap: 2.5rem;
}
/* On light, paper-on-paper needs an edge to read as an object. */
[data-theme="light"] .competition { border: 1px solid var(--ink-line); }

.competition-title { font-size: 1.35rem; color: var(--ink); white-space: nowrap; }
.competition-sub {
    font-size: 12.5px;
    color: var(--ink2);
    margin-top: 0.25rem;
    white-space: nowrap;
}
.competition-data { display: flex; align-items: center; gap: 2.25rem; margin-left: auto; }

.pool { display: flex; align-items: center; gap: 0.7rem; }
.pool-figure {
    font-size: 2.5rem;
    color: var(--ink);
    letter-spacing: -0.01em;
    line-height: 1;
}
.pool-label { font-size: 12.5px; color: var(--ink2); line-height: 1.35; }

.competition-cta { padding: 0.7rem 1.2rem; font-size: 13px; }

/* ── The product shot, fading off the fold ────────────────────────────────
   Two halves of one effect: the mask dissolves the image, and the negative
   margin pulls the next section up UNDER it. Change one and you get either a
   hard edge or a band of empty ground — the bug this replaced. */
.shot-wrap { padding-top: 4rem; }

.shot-fade {
    -webkit-mask-image: linear-gradient(to bottom, #000 40%, transparent 96%);
            mask-image: linear-gradient(to bottom, #000 40%, transparent 96%);
    margin-bottom: -130px;
    /* Leaves a little faster than the page it sits on, so the dissolve reads
       as departure rather than as a static gradient. JS writes --drift; the
       clamp lives there too, or a long page would sail it into the nav. */
    transform: translateY(calc(var(--drift, 0) * -0.1px));
}

.window {
    border: 1px solid var(--hair2);
    border-bottom: 0;
    border-radius: 12px 12px 0 0;
    overflow: hidden;
    box-shadow: var(--shadow-win);
}
.window-bar {
    display: flex;
    align-items: center;
    padding: 0.55rem 1rem;
    background: #0A0E17;          /* invariant: window chrome reads as an app
                                     window on either ground */
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.window-brand { font-weight: 600; font-size: 11px; letter-spacing: 0.14em; color: #C6D0DE; }
.window-url { font-size: 12px; color: #7E8A9C; margin-left: auto; }
.window img { display: block; width: 100%; height: auto; }

/* ── Section rhythm ───────────────────────────────────────────────────────
   One spacing value for every section, so the page has a beat. The first one
   after the hero shot carries extra top padding because the shot is pulled
   into it by the fade's negative margin. */
.section { padding-top: 7.5rem; }
#how-it-works { padding-top: 8.5rem; }
#features { padding-top: 8rem; }
.section-head, .section-center { text-align: center; }

/* ── How it works ─────────────────────────────────────────────────────────
   Text and screen alternate sides. The screen column is slightly wider: a
   50/50 split makes the shots too small to read what is in them. */
.steps { display: flex; flex-direction: column; gap: 4.5rem; margin-top: 3.5rem; }
.step {
    --t: 0;                        /* scroll progress, written by landing.js */
    display: grid;
    grid-template-columns: 1fr 1.15fr;
    gap: 3.5rem;
    align-items: center;
}
.step-flip .step-copy { order: 2; }
.step-flip .step-shot { order: 1; }
.step-num { font-size: 1.6rem; color: var(--t3); }
/* The heading takes the display serif: these are the page's mid-level titles,
   and the walkthrough is where the voice of the headlines meets the product.
   Weight and tracking come from the .display role's register, sized a tier
   below the section heads. */
.step-copy h3 {
    font-family: var(--display);
    font-weight: 400;
    font-size: 1.7rem;
    letter-spacing: -0.02em;
    line-height: 1.15;
    color: var(--t1);
    margin-top: 0.5rem;
}
.step-copy p { font-size: 15px; color: var(--t3); margin-top: 0.6rem; max-width: 38ch; }

/* Grey pre-echo to ink, driven by scroll. The next heading is always already
   on screen at ~15% ink and fills left to right as you arrive. A gradient
   clipped to the text gets most of what per-word splitting would, for free.
   Guarded, because without the clip the fill colour would hide the words.

   Every selector in here is .js-scoped: landing.js adds that class when it
   actually runs, so a page whose script never arrives shows plain solid
   headings instead of a pre-echo nothing will ever fill. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
    .js .step-copy h3 {
        background-image: linear-gradient(to right,
                          var(--t1) 50%,
                          color-mix(in srgb, var(--t1) 15%, transparent) 50%);
        background-size: 200% 100%;
        background-position-x: calc(100% - var(--t) * 100%);
        -webkit-background-clip: text;
                background-clip: text;
        -webkit-text-fill-color: transparent;
        color: transparent;
        transition: background-position-x 1s var(--ease-settle);
    }
    .js .step-copy p { opacity: calc(0.35 + var(--t) * 0.65); }
}
/* Every screenshot on the page dissolves, not just the hero one — a framed
   shot next to three fading ones looks like the odd one out. Gentler than the
   hero's 40%: these carry dashboards you are meant to read. The mask takes the
   border and the shadow down with the image, which is the point: the frame
   should not outlive what it frames. */
.step-shot {
    border: 1px solid var(--hair2);
    border-radius: 10px;
    overflow: hidden;
    box-shadow: var(--shadow-step);
    -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
}
.step-shot img { display: block; width: 100%; height: auto; }

/* ── Markets — the asset strip ────────────────────────────────────────────
   Mark, then symbol over its live line. The strip is the only place on the
   page carrying third-party artwork, which is exactly why the marks are held
   in a chip: one shape and one ground for six logos drawn to six different
   conventions. */
.markets {
    display: flex;
    justify-content: center;
    gap: 2.9rem;
    margin-top: 2.75rem;
    flex-wrap: wrap;
}
.asset { display: flex; align-items: center; gap: 0.7rem; }

/* Theme-INVARIANT, like the trophy paper and the window chrome: the two
   monochrome marks are inverted to white below, and white needs a dark ground
   on BOTH themes. Do not token this. */
.asset-chip {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: #10182B;
    border: 1px solid var(--hair);
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}
.asset-mark { width: 18px; height: 18px; }
/* ETH and XRP ship as single-colour marks that would otherwise be black on
   the chip. The full-colour logos are left alone — inverting a brand's own
   palette is not ours to do. */
.asset-mark-mono { filter: brightness(0) invert(1); }

.asset-lines { text-align: left; }
.asset-sym { display: block; font-weight: 600; color: var(--t1); font-size: 13.5px; line-height: 1.3; }
.asset-live { display: flex; gap: 0.5rem; align-items: baseline; }
.asset-live .price { font-size: 13px; color: var(--t3); }
/* The label is set by JS as a word; the caps are the stylesheet's, so the
   script keeps writing "Calm" and this decides how it is spoken. */
.vol { font-size: 12px; font-weight: 500; }
/* Volatility, not price direction — see the note in index.html. Calm is the
   ABSENCE of weather, so it sits in the label grey: colour appears only when
   conditions change, which is what makes a Heated day actually read as one —
   and it stops borrowing --positive from the job that token's own comment
   reserves for real gains. */
.vol-calm    { color: var(--t3); }
.vol-active  { color: var(--primary); }
.vol-heated  { color: var(--caution); }
.vol-extreme { color: var(--negative); }

/* ── Comparison ───────────────────────────────────────────────────────────
   Still no vertical dividers: what marks the subject is a raised band behind
   its whole column, the way a pricing table marks the plan it wants you to
   pick. Every cell is a direct child of one grid, so the rows align without
   any row wrapper to keep in sync. */
.cmp {
    display: grid;
    grid-template-columns: 1.2fr 1fr 1fr;
    column-gap: 1.5rem;
    row-gap: 0;                     /* the band must be continuous */
    align-items: stretch;
    max-width: 1000px;
    margin: 3rem auto 0;
}
.cmp > * { padding-block: 1rem; font-size: 14.5px; }

/* The two outer columns carry the rules; the band carries the middle. */
.cmp-label, .cmp-rival { border-bottom: 1px solid var(--hair); }
.cmp-label { color: var(--t2); font-weight: 500; }

/* The band gains an EDGE. A tint alone reads as a wash across the middle of
   a table; the hairline is what makes it one raised object you could pick up.
   Every subject cell carries the two side edges, and the first and last close
   the top and bottom — so the outline is continuous down the column. */
.cmp-subject {
    background: var(--subject-band);
    padding-inline: 1.25rem;
    border-left: 1px solid var(--subject-edge);
    border-right: 1px solid var(--subject-edge);
}

/* Counting from the edges rather than naming the cells means a new row needs
   no CSS: the second child is always the head cell, the second-from-last
   always the final one. */
.cmp > :nth-child(2) {
    border-top: 1px solid var(--subject-edge);
    border-radius: 10px 10px 0 0;
}
/* The last row closes the comparison; a rule under it would float. This has to
   come BEFORE the band's closing edge below, or it would strip it: the two
   selectors have equal specificity and both match the final subject cell. */
.cmp > :nth-last-child(-n+3) { border-bottom: 0; }
.cmp > :nth-last-child(2) {
    border-bottom: 1px solid var(--subject-edge);
    border-radius: 0 0 10px 10px;
}

/* Child selector, because `.cmp > *` sets the cell size and outranks a bare
   class. */
.cmp > .cmp-hcell { font-size: 12.5px; color: var(--t3); }
.cmp-subject.cmp-hcell { color: var(--primary); }
.val-good   { color: var(--positive); font-weight: 600; }
.val-bad    { color: var(--negative); opacity: 0.85; }
/* The ink red survives its softening (5.3:1); the light one does not — the
   .85 dragged a passing red to 4.3:1. On light the token is deep enough to
   carry the row at full strength. */
[data-theme="light"] .val-bad { opacity: 1; }
.val-strong { color: var(--t1); }
.val-dim    { color: var(--t3); }

/* ── Real trades — the fills ledger ───────────────────────────────────────
   Hairline rows, three columns: what it was, what happened, what it returned.
   The result column is right-aligned so the four figures form a column of
   their own, which is the part of a trade history the eye goes to. */
.ledger { max-width: 1000px; margin: 2.5rem auto 0; text-align: left; }
.led-row {
    display: grid;
    grid-template-columns: 150px 1fr auto;
    gap: 2rem;
    align-items: center;
    padding: 1.3rem 0;
    border-bottom: 1px solid var(--hair);
}
/* The ledger opens with a rule as well as closing on one, or the first row
   looks like it is hanging off the subhead. */
.led-row:first-child { border-top: 1px solid var(--hair); }
.led-tag { font-size: 13px; font-weight: 600; color: var(--t2); }
.led-story { font-size: 14.5px; color: var(--t3); max-width: 56ch; }
.led-result { text-align: right; }
.led-value {
    font-size: 1.6rem;
    font-weight: 600;
    color: var(--positive);
    letter-spacing: -0.01em;
}
.led-value-words { font-size: 1.3rem; color: var(--t1); }
.led-caption { display: block; font-size: 12.5px; color: var(--t3); margin-top: 0.1rem; }

/* ── Features — the chapter panel ─────────────────────────────────────────
   Every colour inside this panel is a LITERAL, and that is deliberate: the
   panel is dark on both themes, the way the trophy banner is paper on both.
   Tokening these would make the panel invisible on ink and unreadable on
   light. It is the same rule as --paper / --ink, applied to a dark object. */
.chapter {
    position: relative;
    overflow: hidden;
    background: linear-gradient(180deg, #141B2E 0%, #0A0F1D 100%);
    border-radius: 16px;
    padding: 5rem 4rem;
}
/* The panel's own weather. It is the second and last atmospheric effect on
   the page, and it belongs to the panel rather than the ground. */
.chapter-glow {
    position: absolute;
    top: -140px;
    left: 50%;
    transform: translateX(-50%);
    width: 720px;
    height: 380px;
    background: radial-gradient(50% 50% at 50% 50%, rgba(125, 211, 252, 0.12), transparent 70%);
    pointer-events: none;
}
.chapter-head { position: relative; text-align: center; }
.chapter-title { color: #F5F7FA; }
.chapter-sub   { color: #96A1B2; }

.chapter-cards {
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1rem;
    margin-top: 3rem;
}
/* Hairline, no fill. A translucent fill inside a panel that is itself a fill
   makes four grey boxes; the outline gives the same grouping for nothing. */
.chapter-card {
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 10px;
    padding: 1.6rem 1.5rem;
}
/* The eyebrow names the subject, so four unrelated features scan as a set. */
.chapter-eyebrow { font-size: 12.5px; font-weight: 600; color: #7DD3FC; }
.chapter-card h3 {
    font-family: var(--display);
    font-weight: 400;
    font-size: 1.35rem;
    letter-spacing: -0.02em;
    line-height: 1.15;
    color: #F5F7FA;
    margin-top: 0.55rem;
}
.chapter-card p  { font-size: 14px; color: #96A1B2; margin-top: 0.4rem; }

/* ── Powered by Thetanuts ─────────────────────────────────────────────────
   One statement at display scale with the partner's name washed in its own
   green, and one line of evidence under it. The wash is invariant: the same
   mint reads as a highlighter on either ground. */
.statement {
    font-size: 2.9rem;
    line-height: 1.18;
    max-width: 26ch;
    margin: 0 auto;
}
/* Painted as a background IMAGE rather than a colour so it can be swept on:
   the wash draws itself across the word once, when the statement arrives. */
.wash {
    background-image: linear-gradient(rgba(68, 244, 171, 0.22), rgba(68, 244, 171, 0.22));
    background-repeat: no-repeat;
    background-size: 100% 100%;   /* full at rest: the sweep is JS's to arm */
    border-radius: 8px;
    padding: 0.02em 0.16em;
    transition: background-size .6s var(--ease-settle) .15s;
}
.js .wash { background-size: 0% 100%; }
.js .reveal.in .wash { background-size: 100% 100%; }
.statement-evidence { font-size: 15px; color: var(--t3); margin: 1.4rem auto 0; max-width: 62ch; }

/* ── FAQ ──────────────────────────────────────────────────────────────── */
.faq { max-width: 760px; margin: 2.75rem auto 0; }
.faq details { border-top: 1px solid var(--hair); }
.faq details:last-of-type { border-bottom: 1px solid var(--hair); }
.faq summary {
    padding: 1.15rem 0;
    cursor: pointer;
    font-size: 15px;
    font-weight: 500;
    color: var(--t1);
    list-style: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    transition: color .2s var(--ease-house);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--primary); }
/* ONE glyph rotated, not '+' swapped for '−': a content swap snaps, and the
   rotation is the only part of the marker that can carry the motion. */
.faq summary::after {
    content: '+';
    color: var(--t3);
    font-size: 1.15rem;
    line-height: 1;
    flex: none;
    transition: transform .3s var(--ease-house), color .2s var(--ease-house);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details p {
    padding-bottom: 1.3rem;
    font-size: 14.5px;
    color: var(--t3);
    max-width: 62ch;
}
/* Smooth open where the browser can interpolate to a keyword height. Where it
   cannot (Firefox, older Safari), landing.js drives the same motion. */
.faq details::details-content {
    block-size: 0;
    overflow-y: clip;
    transition: block-size .3s var(--ease-house), content-visibility .3s allow-discrete;
}
.faq details[open]::details-content { block-size: auto; transition-duration: .42s; }
.faq details[data-anim] { overflow: hidden; }

/* ── Closing CTA ──────────────────────────────────────────────────────────
   Sunken, never lighter: the primary button must stay the brightest thing on
   the page at the moment of the ask. */
.cta {
    margin-top: 7.5rem;
    padding: 6.5rem 40px;
    text-align: center;
    background: var(--sunken);
    border-top: 1px solid var(--hair);
}
.cta-title { font-size: 3.4rem; line-height: 1.05; max-width: 16ch; margin: 0 auto; }
.cta-sub { font-size: 16px; color: var(--t3); margin: 1.3rem auto 0; max-width: 46ch; }
.cta-btn { margin-top: 2.25rem; padding: 1.05rem 2.2rem; }

/* ── Footer ───────────────────────────────────────────────────────────── */
/* No top margin: the CTA band above supplies the separation, and the footer
   continues its sunken step rather than floating away from it — literally, by
   carrying the same ground, so the two read as one closing block. */
.site-footer {
    border-top: 1px solid var(--hair);
    padding: 3.5rem 0 2rem;
    background: var(--sunken);
}
.frow { display: flex; justify-content: space-between; gap: 3rem; flex-wrap: wrap; }
.fbrand .dim { font-size: 13.5px; margin-top: 0.35rem; }
.fcols { display: flex; gap: 5rem; }
.fcol { display: flex; flex-direction: column; gap: 0.55rem; }
.fcol b { font-weight: 600; color: var(--t1); font-size: 14px; margin-bottom: 0.3rem; }
.fcol a { color: var(--t3); font-size: 14px; }
.fcol a:hover { color: var(--primary); }

/* .footer-bottom is also used by privacy.html and tos.html — keep it. */
.footer-bottom {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 3rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--hair);
    color: var(--t3);
    font-size: 13px;
    flex-wrap: wrap;
}
.footer-bottom a { color: var(--t3); }
.footer-bottom a:hover { color: var(--primary); }
.footer-legal { display: flex; gap: 1.5rem; }

/* ── Reveal — fires once, then unobserves ─────────────────────────────────
   Three variants on one observer. The direction ones are for the walkthrough
   screens, which arrive from the side they sit on; the scale one is the
   chapter panel settling into place.

   .js-scoped, and the class is added by landing.js ITSELF, not by the head
   script: the file that reveals is the only file allowed to hide. Blocked
   scripts, a failed fetch, an early error - in every one of those worlds
   these sections simply exist, which is what this stylesheet used to promise
   and quietly did not keep. */
.js .reveal {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity .6s var(--ease-house), transform .6s var(--ease-house);
}
.js .reveal-left  { transform: translate(-24px, 12px); }
.js .reveal-right { transform: translate(24px, 12px); }
.js .reveal-scale { transform: scale(0.98); }
.js .reveal.in { opacity: 1; transform: none; }

/* Everything arrives in its final state: nothing waits on a scroll position,
   a transition or an observer. --t is !important because landing.js writes it
   inline, and an inline property would otherwise outrank this. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .js .reveal, .js .reveal-left, .js .reveal-right, .js .reveal-scale {
        opacity: 1;
        transform: none;
        transition: none;
    }
    .step { --t: 1 !important; }
    .step-copy h3 { transition: none; }
    .shot-fade { transform: none; }
    .wash { background-size: 100% 100%; transition: none; }
    .nav-shell { transition: none; }
}

/* ── Scrollbar ────────────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--hair2); border-radius: 999px; }

/* ══ Mobile ═══════════════════════════════════════════════════════════════
   One breakpoint. The layout is either the wide, two-column reading of the
   page or the stacked one; there is no in-between arrangement worth the
   third set of rules. */
@media (max-width: 899px) {
    .inner { padding-inline: 20px; }

    /* Nav: the links move into the sheet, so only the wordmark, the CTA and
       the burger stay. The theme toggle goes with them — it lives in the
       menu's link row, where there is space for a word. */
    .nav { padding: 1rem 20px; }
    .nav-link, .theme-toggle { display: none; }
    .burger { display: inline-flex; order: 3; }
    .nav-actions { gap: 0.5rem; }
    /* BOTH copies of the CTA — the nav's and the menu sheet's — or the pair
       visibly resizes the moment the sheet opens over the bar. */
    .nav-actions .nbtn-accent,
    .menu-bar .nbtn-accent { padding: 0.7rem 1rem; font-size: 12px; }

    /* Hero */
    .hero { padding: 3.25rem 20px 0; }
    .glow { top: -80px; width: min(420px, 100%); height: 340px; }
    .hero-title { font-size: 2.75rem; line-height: 1.08; }
    .hero-sub { font-size: 15px; margin-top: 1.1rem; max-width: 36ch; }
    /* Full width and stacked: bigger targets, and two half-width buttons at
       this size leave neither of them room for its label. */
    .hero-actions { flex-direction: column; width: 100%; gap: 0.6rem; margin-top: 1.75rem; }
    .hero-actions .btn { width: 100%; }
    /* The line wraps rather than shrinking past legibility; the expiry lands
       on its own row, which is the reading order anyway. */
    .hero-live { gap: 0.5rem 1.1rem; margin-top: 2rem; font-size: 12px; }

    /* Competition — the desktop row would put the figure and the button on
       top of each other at this width. */
    .competition-wrap { padding-top: 2.25rem; }
    .competition { flex-direction: column; align-items: stretch; gap: 1rem; padding: 1.3rem 1.25rem; }
    .competition-title { font-size: 1.25rem; white-space: normal; }
    .competition-sub { white-space: normal; font-size: 12px; }
    .competition-data { margin-left: 0; gap: 0.7rem; }
    .pool-figure { font-size: 2.1rem; }
    .pool-label { font-size: 11.5px; }
    .competition-cta { margin-left: auto; padding: 0.7rem 1rem; font-size: 11px; }

    /* The shot is CROPPED before it fades. Whole, it is ~170px tall here and
       the dissolve has no room to read as one — it just looks like a low
       image. Cropping to a fixed height keeps the top of the app legible and
       gives the mask something to work across. */
    .shot-wrap { padding-top: 2.25rem; }
    .shot-fade {
        -webkit-mask-image: linear-gradient(to bottom, #000 30%, transparent 95%);
                mask-image: linear-gradient(to bottom, #000 30%, transparent 95%);
        margin-bottom: -140px;
    }
    .window img { height: 400px; object-fit: cover; object-position: top; }

    /* Sections */
    .section { padding-top: 4.5rem; }
    #how-it-works { padding-top: 5rem; }
    .shead { font-size: 1.9rem; }
    .ssub { font-size: 14.5px; }

    /* Walkthrough: text, then the screen it describes. The flip is dropped —
       alternating sides means nothing once everything is one column, and
       leaving it in puts one image above its own heading.

       The shots take the hero's own crop treatment: whole, each is ~166px of
       dark-on-dark and the fade mask erases half of that — a smudge where the
       proof should be. Cropped, the top of each dashboard stays legible and
       the fade has room to mean something. Slightly shorter than the hero's
       400px: three of these stack, and the middle of the page must not sag. */
    .steps { gap: 3rem; margin-top: 2.25rem; }
    .step { grid-template-columns: 1fr; gap: 1.1rem; }
    .step-flip .step-copy, .step-flip .step-shot { order: 0; }
    .step-num { font-size: 1.35rem; }
    .step-copy h3 { font-size: 1.45rem; margin-top: 0.4rem; }
    .step-copy p { font-size: 14px; max-width: none; }
    .step-shot img { height: 300px; object-fit: cover; object-position: top; }

    .markets { gap: 0.9rem 1.6rem; margin-top: 1.75rem; }
    .asset { gap: 0.6rem; }
    .asset-chip { width: 28px; height: 28px; }
    .asset-mark { width: 15px; height: 15px; }
    .asset-sym { font-size: 12.5px; }
    .asset-live { gap: 0.4rem; }
    .asset-live .price { font-size: 12px; }

    /* The comparison keeps three columns: rows scan better than a stack, and
       the values are short enough to fit at 12.5px. */
    .cmp { grid-template-columns: 1.05fr .95fr .9fr; column-gap: 0.75rem; margin-top: 1.9rem; }
    .cmp > * { padding-block: 0.75rem; font-size: 12.5px; }
    .cmp .num { font-size: 12.5px; }
    .cmp-subject { padding-inline: 0.6rem; }
    .cmp > .cmp-hcell { padding-block: 0.7rem; font-size: 12px; }
    .cmp > :nth-child(2)      { border-radius: 8px 8px 0 0; }
    .cmp > :nth-last-child(2) { border-radius: 0 0 8px 8px; }

    /* The three columns stack, but the row keeps its rules: they are what
       still says "ledger" once the grid is gone. */
    .ledger { margin-top: 1.75rem; }
    .led-row { display: block; padding: 1.05rem 0; }
    .led-tag { display: block; font-size: 12.5px; }
    .led-story { font-size: 13.5px; margin-top: 0.35rem; max-width: none; }
    .led-result {
        display: flex;
        align-items: baseline;
        gap: 0.5rem;
        margin-top: 0.55rem;
        text-align: left;
    }
    .led-value { font-size: 1.3rem; }
    .led-value-words { font-size: 1.15rem; }
    .led-caption { display: inline; font-size: 12px; margin-top: 0; }

    /* The panel keeps its inset but loses most of it: at 390px a 3.5rem pad
       leaves the cards narrower than their own copy. */
    .chapter { border-radius: 14px; padding: 1.75rem 1.4rem; }
    .chapter-glow { top: -90px; width: 420px; height: 240px; }
    .chapter-title { font-size: 1.9rem; line-height: 1.12; }
    .chapter-sub { font-size: 14.5px; margin-top: 0.55rem; }
    .chapter-cards { grid-template-columns: 1fr; gap: 0.6rem; margin-top: 1.5rem; }
    .chapter-card { border-radius: 10px; padding: 1.1rem 1.2rem; }
    .chapter-card h3 { font-size: 1.25rem; }

    .statement { font-size: 1.8rem; line-height: 1.28; max-width: none; }
    .wash { border-radius: 6px; padding: 0.02em 0.14em; }
    .statement-evidence { font-size: 14px; margin-top: 0.9rem; }

    .faq { margin-top: 1.75rem; }
    .faq summary { font-size: 14.5px; padding: 1rem 0; }
    .faq details p { font-size: 13.5px; }

    .cta { margin-top: 4.5rem; padding: 4rem 20px; }
    .cta-title { font-size: 2.2rem; line-height: 1.12; max-width: 14ch; }
    .cta-sub { font-size: 14.5px; max-width: 32ch; }
    .cta-btn { width: 100%; margin-top: 1.75rem; }

    .site-footer { padding: 2.5rem 0 1.5rem; }
    .frow { flex-direction: column; gap: 1.75rem; }
    .fcols { gap: 4rem; }
    .footer-bottom { flex-direction: column; gap: 0.4rem; margin-top: 2rem; font-size: 12px; }
    .footer-legal { gap: 1.25rem; }
}

/* ══ Compatibility — privacy.html and tos.html ════════════════════════════
   Those two pages load THIS stylesheet and read the old token names from
   their own <style> blocks. They are not part of this redesign and were not
   edited, so the names are aliased onto the new scale rather than removed.
   --accent has no counterpart in the new system and keeps its literal value;
   it is the only place that colour still appears. */
:root {
    --text-primary:   var(--t1);
    --text-secondary: var(--t2);
    --text-muted:     var(--t3);
    --accent:         #FDE047;
}

/* ── Targeted fixes (2026-09-29) ──────────────────────────────────────────
   Five changes from the landing audit, desktop only (the ≤899px layout is
   untouched): the scenario numbers carry their rows; two section heads break
   the centred rhythm; the smallest captions come up a step; the feature cards
   become a ruled 2×2 list. The closing line is copy (index.html). */
@media (min-width: 900px) {
    /* 1 · the four results are the anchor of the ledger */
    .led-row { padding: 1.9rem 0; }
    .led-value {
        font-family: var(--display);
        font-weight: 400;
        font-size: 3.5rem;
        line-height: 1;
        letter-spacing: -0.02em;
    }
    .led-value-words { font-family: var(--display); font-style: italic; font-size: 2.1rem; line-height: 1.05; }
    .led-caption { margin-top: 0.4rem; }

    /* 2 · How it works and the comparison: heads set left, not centred */
    #how-it-works .section-head {
        display: flex;
        justify-content: space-between;
        align-items: flex-end;
        gap: 2rem;
        text-align: left;
    }
    #how-it-works .section-head .ssub { margin-top: 0; }
    #compare {
        display: grid;
        grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
        column-gap: 4rem;
        align-items: start;
    }
    #compare .section-head { text-align: left; }
    #compare .cmp { margin: 0; max-width: none; }

    /* 3 · the smallest captions come up a step */
    .led-caption   { font-size: 14px; color: var(--t2); }
    .led-tag       { font-size: 14px; }
    .cmp > .cmp-hcell { font-size: 13.5px; }
    .chapter-eyebrow  { font-size: 13.5px; }
    .asset-live .price { font-size: 14px; color: var(--t2); }

    /* 5 · the four features: a ruled 2×2 list, not four equal boxes */
    .chapter-cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: 3rem;
        row-gap: 0;
        max-width: 860px;
        margin-inline: auto;
    }
    .chapter-card {
        border: 0;
        border-top: 1px solid rgba(255, 255, 255, 0.08);
        border-radius: 0;
        padding: 1.5rem 0;
        text-align: left;
    }
    .chapter-card p { font-size: 15px; }
}
