/* =============================================================================
   PRISM MARKETING — the public site's design system

   Loaded by the landing page and by every page under app/marketing/. NOT loaded
   by layouts/base.html, and it must never be: the rules below are deliberately
   unscoped (`body`, `.btn`, `.wrap`, `.browser`) because they describe a page
   that has no app chrome on it. Linked into the authenticated app they would
   restyle every button in the product.

   WHY IT IS A FILE. This was 513 lines inside home.html's <style>, which was
   fine while there was one marketing page and impossible the moment there were
   twelve: `.btn`, `.wrap`, `.tier` and the fake-browser kit are the design
   language every new page has to reuse, and a second page could only reuse them
   by copying them. tests/test_page_local_css.py names that outcome exactly —
   "two pages declaring one selector ... was never page-specific" — and its
   ceiling of 115 redundant copies would have been blown by a single paste.

   WHAT LIVES WHERE. prism-common.css owns the LANDING PAGE — COMPOSITION &
   MOTION section: the scroll-reveal vocabulary, the parallax stack, the bento
   grid, the pinned scene, the mobile sheet, `.px-seam`. All of it is scoped
   `.px-landing`, because that sheet loads on every page in the app. This file
   owns the components those compositions arrange. A new *motion* layer still
   belongs in prism-common.css (tests/test_landing_motion.py enforces the
   reduced-motion and phone cutoffs there); a new *component* belongs here.

   THE EXEMPTION IT CARRIES. tests/test_light_mode_css.py excludes home.html
   from its contrast and hardcoded-colour contracts — "standalone with its own
   design system" — and that exemption travels with the system, not with the
   file, so this sheet inherits it. It is not a licence: colour here comes from
   the --px-* set below or from a --prism-* token, never from a literal typed at
   the point of use, and the sheet is held to the parse-integrity and
   token-exists contracts that do apply to it.

   The public site is dark-only by design — there is no .white-content branch
   here, and adding one would mean the marketing site had grown a second theme
   that nothing in the app can flip.
   ========================================================================== */

/* =====================================================================
   PRISM LANDING PAGE  —  self-contained marketing styles
   Aesthetic: dark editorial-tech with a "light through a prism" spectrum
   motif. Palette mirrors the in-app brand tokens so it stays on-brand.
   ===================================================================== */
:root {
    --px-bg:        #0a0b12;
    --px-bg-2:      #0e0f1b;
    --px-panel:     #14162552;
    --px-panel-s:   #171a2b;
    --px-panel-s2:  #1d2036;
    --px-border:    rgba(255,255,255,.09);
    --px-border-s:  rgba(255,255,255,.14);
    --px-text:      #edeef6;
    --px-muted:     #9aa1b8;
    --px-faint:     #6a7089;
    --px-accent:    #1d8cf8;
    --px-accent-2:  #8b5cf6;
    --px-accent-3:  #e14eca;
    --px-green:     #00e6ba;
    --px-green-d:   #00b894;
    --px-red:       #fd5d93;
    --px-amber:     #ffb15d;
    /* --px-brand is NOT here. It reads --prism-brand, which prism-common.css
       declares on `body` rather than :root, so it has to be declared on
       `body` too — see the body rule below. */
    --px-brand-soft:linear-gradient(135deg, rgba(29,140,248,.18) 0%, rgba(139,92,246,.16) 52%, rgba(225,78,202,.18) 100%);
    /* Single source of truth lives in prism-common.css (loaded above), so
       the landing page and the app's scroll bar cannot drift apart. */
    --px-spectrum:  var(--prism-spectrum);
    --px-radius:    18px;
    --px-shadow:    0 30px 80px -30px rgba(0,0,0,.75);
    --px-maxw:      1180px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
    /* The brand mark, shared with the app instead of written twice. On the
       default `prism` skin --prism-brand resolves to exactly what used to
       be hardcoded in :root above:
         linear-gradient(135deg,#1d8cf8 0%, #8b5cf6 52%, #e14eca 100%)
       Same arrangement as --px-spectrum, and for the same reason: two
       copies of the brand gradient are two things to keep in step.

       Declared on `body` and not on :root with the rest of the --px-*
       tokens, and that is load-bearing rather than tidiness. A var() inside
       a custom property is substituted at the element the property is
       DECLARED on. prism-common.css puts --prism-brand on `body` (it reads
       the accent triplet, which the skins set on body[data-skin]), so a
       :root declaration here would look up a property that does not exist
       at :root and resolve to nothing — every brand fill on the page would
       silently go unpainted. --px-spectrum gets away with :root only
       because --prism-spectrum happens to be declared there too. */
    --px-brand: var(--prism-brand);
    margin: 0;
    font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    background: var(--px-bg);
    color: var(--px-text);
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
    line-height: 1.6;
}

/* Ambient background: layered radial "prism light" mesh + fine grid.
   Fixed so it parallaxes subtly under the scrolling content. */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -2;
    background:
        radial-gradient(60% 55% at 18% 12%, rgba(29,140,248,.20) 0%, transparent 60%),
        radial-gradient(55% 50% at 82% 8%, rgba(225,78,202,.16) 0%, transparent 55%),
        radial-gradient(70% 60% at 50% 100%, rgba(139,92,246,.16) 0%, transparent 60%),
        var(--px-bg);
}
body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    background-image:
        linear-gradient(rgba(255,255,255,.028) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,.028) 1px, transparent 1px);
    background-size: 46px 46px;
    mask-image: radial-gradient(circle at 50% 30%, #000 0%, transparent 78%);
    -webkit-mask-image: radial-gradient(circle at 50% 30%, #000 0%, transparent 78%);
    pointer-events: none;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

.wrap { width: 100%; max-width: var(--px-maxw); margin: 0 auto; padding: 0 24px; }

/* ---- Scroll progress spectrum bar ----
   No rule here on purpose. .prism-scroll-progress in prism-common.css (
   loaded above) is the whole component, and this page uses it directly.
   The copy that used to live here re-declared the geometry, the z-index
   and a literal purple glow, which is how it stayed at 3px with no track
   when the app's bar gained both. Sharing the spectrum token was never
   enough — everything around the gradient could still drift. */

/* ---- Buttons ---- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 10px;
    font-family: inherit; font-weight: 700; font-size: .98rem;
    padding: 14px 26px; border-radius: 999px; border: 1px solid transparent;
    cursor: pointer; transition: transform .25s cubic-bezier(.2,.7,.3,1), box-shadow .25s, background .25s, border-color .25s;
    white-space: nowrap; letter-spacing: .2px;
}
.btn-primary {
    background: var(--px-brand); color: #fff;
    box-shadow: 0 10px 30px -8px rgba(139,92,246,.55);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 18px 42px -10px rgba(139,92,246,.7); color:#fff; }
.btn-ghost {
    background: rgba(255,255,255,.03); color: var(--px-text);
    border-color: var(--px-border-s);
}
.btn-ghost:hover { background: rgba(255,255,255,.08); transform: translateY(-2px); border-color: var(--px-border-s); }
.btn-sm { padding: 10px 20px; font-size: .9rem; }
.btn-lg { padding: 17px 34px; font-size: 1.05rem; }
.btn-block { width: 100%; }
/* The .btn display rule beats the UA's [hidden] { display: none }, so a
   hidden button (the tools' edit/clear controls) needs the guard restated at
   the same specificity — the same trap the category form documents. */
.btn[hidden] { display: none; }

/* ---- Navbar ---- */
.nav {
    position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
    display: flex; align-items: center; justify-content: space-between;
    /* Named because the dropdown panel has to clear the bar, and the distance
       from the link row to the bar's bottom edge IS this padding. Written
       twice, the two drift and the panel starts cutting the bar's hairline
       again — which is exactly how it shipped. */
    --px-nav-pad: 16px;
    padding: var(--px-nav-pad) 0; transition: background .3s, border-color .3s, backdrop-filter .3s;
    border-bottom: 1px solid transparent;
}
.nav.scrolled {
    background: rgba(10,11,18,.72);
    backdrop-filter: saturate(160%) blur(14px);
    -webkit-backdrop-filter: saturate(160%) blur(14px);
    border-bottom: 1px solid var(--px-border);
}
/* Three columns, not space-between. space-between distributes rather than
   centres, so the link group's position was a function of how wide the
   brand and the CTA group happened to be — and they differ, and the CTA's
   width changes with SIGNUP_OPEN, so the links sat visibly left of centre.
   Equal 1fr side tracks put the auto track in the true middle whatever
   flanks it. The 1180px column is unchanged: the brand still lines up with
   the hero headline and every section below. */
.nav-inner { width: 100%; max-width: var(--px-maxw); margin: 0 auto; padding: 0 24px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
/* justify-self: start, or the anchor stretches across the whole 1fr track
   and the click target runs to the middle of the page. */
.brand { display: flex; align-items: center; gap: 9px; font-weight: 800; justify-self: start; }
.brand-logo { height: 30px; width: auto; display: block; flex: none; }
/* The gradient fill and the open-sweep live in prism-common.css's LANDING
   PAGE section, scoped `.px-landing` — see the note there. */
.brand-text { font-family: 'Space Grotesk', sans-serif; font-size: 1.35rem; letter-spacing: .5px; }
/* Prominent hero logo (real Prism mark, transparent glow) */
.hero-logo { height: 76px; width: auto; margin: 0 auto 6px; display: block;
    filter: drop-shadow(0 10px 30px rgba(139,92,246,.4)); }
/* `align-self: stretch` on both this and .nav-drop below is what lets the
   dropdown panel hang off the BAR. Without it the <details> box is just its
   32px summary, centred in a 78px bar, so the panel's `top: 100%` resolved
   to y=69 and the bar's own bottom hairline drew straight through the top of
   the panel. The links stay centred — that is the summary's own
   `align-items: center`, not this. */
.nav-links { display: flex; align-items: center; gap: 30px; justify-self: center; align-self: stretch; }
.nav-links .lnk { color: var(--px-muted); font-weight: 600; font-size: .95rem; transition: color .2s; }
.nav-links .lnk:hover { color: var(--px-text); }
/* Hard right, including below 900px where this holds only the hamburger:
   .nav-links' children go display:none, so the middle track collapses to
   zero and the CTA track still ends at the column's right edge. */
.nav-cta { display: flex; align-items: center; gap: 12px; justify-self: end; }

/* ---- Section scaffolding ---- */
section { position: relative; }
.section-pad { padding: 96px 0; }
.eyebrow {
    display: inline-flex; align-items: center; gap: 9px;
    font-size: .78rem; font-weight: 700; letter-spacing: 2.4px; text-transform: uppercase;
    color: var(--px-muted); padding: 7px 15px; border-radius: 999px;
    border: 1px solid var(--px-border); background: rgba(255,255,255,.03);
}
.eyebrow .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--px-brand); }
h1,h2,h3,h4 { font-family: 'Space Grotesk', sans-serif; line-height: 1.08; margin: 0; font-weight: 700; text-wrap: balance; }
.h-section { font-size: clamp(2rem, 4vw, 2.9rem); letter-spacing: -.5px; }
.grad { background: var(--px-brand); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.lead { color: var(--px-muted); font-size: 1.12rem; max-width: 640px; }
.section-head { text-align: center; max-width: 720px; margin: 0 auto 58px; }
.section-head .lead { margin: 18px auto 0; }

/* =====================================================================
   HERO
   ===================================================================== */
.hero { padding: 152px 0 40px; text-align: center; }
.hero h1 {
    font-size: clamp(2.5rem, 6vw, 4.3rem); letter-spacing: -1.4px; margin: 26px auto 0;
    max-width: 900px;
}
.hero .lead { font-size: 1.22rem; margin: 24px auto 0; max-width: 660px; text-align: center; }
.hero-cta { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; margin-top: 36px; }
.hero-trust { display: flex; gap: 24px; justify-content: center; flex-wrap: wrap; margin-top: 26px; color: var(--px-faint); font-size: .9rem; font-weight: 500; }
.hero-trust span { display: inline-flex; align-items: center; gap: 8px; }
.hero-trust i { color: var(--px-green); }
/* What happens after the invite button — rendered by home.html only while the
   signup gate is closed (BETA SIGNUP GATE). One quiet line between the CTA row
   and the trust chips: brighter than the chips, smaller than the lead. */
.hero-beta-note { margin: 22px auto 0; max-width: 560px; text-align: center; color: var(--px-muted); font-size: .98rem; }

/* Hero product shot: browser-framed live dashboard mock with prism glow */
.hero-shot { position: relative; margin: 66px auto 0; max-width: 1060px; }
/* The glow bleeds vertically and NOT horizontally, and the 0 is load-bearing:
   at -4% it was 8% wider than .hero-shot, and once the shot stops being
   narrower than its 1060px max-width — i.e. below roughly 1100px — that spill
   lands past the viewport edge and gives the whole document a horizontal
   scrollbar. Pre-existing and easy to miss: no ELEMENT crosses the edge, so
   the usual hunt for a wide table or an unbroken string finds nothing, and the
   overflow scales with the viewport (4px at 740, 15px at 1024) rather than
   appearing at one breakpoint. The vertical bleed is what the glow is for and
   costs nothing, since a page scrolls that way anyway. */
.hero-shot::before {
    content: ''; position: absolute; inset: -8% 0 -12%; z-index: 0;
    background: radial-gradient(50% 50% at 50% 40%, rgba(139,92,246,.4) 0%, transparent 70%);
    filter: blur(30px); opacity: .8;
}
.hero-shot .browser { position: relative; z-index: 1; }
/* Spectrum "dispersion" beam under the hero shot.
   Centred with left/right rather than translateX(-50%), so the landing
   page's scroll parallax can own `transform` (translateY only) without
   fighting a centering trick — `transform: none` under reduced motion
   and on a phone then still leaves it centred. */
.hero-shot .beam {
    position: absolute; left: 11%; right: 11%; bottom: -30px;
    width: auto; height: 60px; z-index: 0; border-radius: 50%;
    background: var(--px-spectrum); filter: blur(38px); opacity: .45;
}

/* =====================================================================
   BROWSER-FRAME "SCREENSHOT" COMPONENT  (reused everywhere)
   Swap the .browser-body content for a real <img> to use a PNG instead.
   ===================================================================== */
.browser {
    border-radius: 16px; overflow: hidden;
    border: 1px solid var(--px-border-s);
    background: #0c0e18;
    box-shadow: var(--px-shadow);
}
.browser-bar {
    display: flex; align-items: center; gap: 8px;
    padding: 12px 16px; background: #10121e; border-bottom: 1px solid var(--px-border);
}
.browser-bar .dot { width: 11px; height: 11px; border-radius: 50%; background: #3a3f57; }
.browser-bar .dot.r { background: #fd5d93; } .browser-bar .dot.y { background: #ffb15d; } .browser-bar .dot.g { background: #00e6ba; }
.browser-bar .url {
    margin-left: 12px; flex: 1; max-width: 320px; font-size: .74rem; color: var(--px-faint);
    background: rgba(255,255,255,.04); border: 1px solid var(--px-border); border-radius: 7px;
    padding: 5px 12px; display: flex; align-items: center; gap: 7px;
}
.browser-bar .url i { font-size: .68rem; color: var(--px-green); }
.browser-body { background: linear-gradient(180deg,#0d0f1a,#0a0c15); padding: 20px; }
/* Real screenshot layer: injected by JS when a file exists in
   assets/img/screenshots/. Replaces the HTML mock in the same frame.
   See docs/LANDING_SCREENSHOTS.md. */
/* Reserving the image's box before the file loads is what stops swapping the
   mock out from shifting the page. The ratio comes from the frame's own
   data-shot-ar (set as --shot-ar by the loader at the bottom of this file),
   NOT from a literal: the page shots are 16:10 and the drawer shots are
   16:9, and object-fit defaults to `fill`, so one ratio for all of them
   stretches half of them. 16/10 is only the fallback for a frame that
   declares nothing. */
.shot-real { display: block; width: 100%; height: auto; aspect-ratio: var(--shot-ar, 16 / 10); }

/* ---- Dashboard mock internals ---- */
.mk-row { display: flex; gap: 14px; }
.kpis { display: grid; grid-template-columns: repeat(3,1fr); gap: 14px; }
.kpi {
    background: var(--px-panel-s); border: 1px solid var(--px-border); border-radius: 12px; padding: 15px 16px;
    text-align: left;
}
.kpi .lab { font-size: .68rem; text-transform: uppercase; letter-spacing: 1px; color: var(--px-faint); font-weight: 700; }
.kpi .val { font-family: 'Space Grotesk', sans-serif; font-size: 1.42rem; font-weight: 700; margin-top: 6px; }
.kpi .chg { font-size: .72rem; font-weight: 700; margin-top: 3px; display: inline-flex; align-items:center; gap:4px; }
.up { color: var(--px-green); } .down { color: var(--px-red); }

.panel {
    background: var(--px-panel-s); border: 1px solid var(--px-border); border-radius: 12px; padding: 16px;
    text-align: left;
}
.panel-title { font-size: .74rem; text-transform: uppercase; letter-spacing: 1px; color: var(--px-faint); font-weight: 700; margin-bottom: 14px; display:flex; justify-content:space-between; align-items:center; }
.panel-title .pill { font-size: .64rem; padding: 3px 9px; border-radius: 999px; background: rgba(29,140,248,.14); color: #7cc0ff; letter-spacing: .5px; }

/* CSS bar chart */
.chart { display: flex; align-items: flex-end; gap: 8px; height: 118px; padding-top: 6px; }
.chart .bar { flex: 1; border-radius: 5px 5px 2px 2px; position: relative; min-height: 6px;
    background: linear-gradient(180deg, rgba(29,140,248,.9), rgba(29,140,248,.25)); }
.chart .bar.alt { background: linear-gradient(180deg, rgba(225,78,202,.9), rgba(225,78,202,.22)); }
.chart .bar.pos { background: linear-gradient(180deg, rgba(0,230,186,.95), rgba(0,230,186,.2)); }

/* Transaction rows */
.txn { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid rgba(255,255,255,.05); }
.txn:first-child { border-top: none; }
.txn .ic { width: 30px; height: 30px; border-radius: 8px; flex: none; display: grid; place-items: center; font-size: .8rem; color:#fff; }
.txn .meta { flex: 1; min-width: 0; }
.txn .nm { font-size: .82rem; font-weight: 600; color: var(--px-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.txn .badge {
    font-size: .64rem; font-weight: 700; padding: 2px 8px; border-radius: 999px; margin-top: 3px; display: inline-flex; align-items:center; gap:5px;
    border: 1px solid var(--px-border);
}
.txn .amt { font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: .86rem; white-space: nowrap; }
.auto-tag { font-size: .58rem; color: var(--px-accent); border:1px solid rgba(29,140,248,.4); padding:1px 6px; border-radius:999px; margin-left:6px; vertical-align:middle; font-weight:700; letter-spacing:.4px;}

.bd-mortgage { background: linear-gradient(135deg,#fd5d93,#ec250d); }
.bd-utility  { background: linear-gradient(135deg,#1d8cf8,#0d6efd); }
.bd-rent     { background: linear-gradient(135deg,#00e6ba,#2dce89); }
.bd-maint    { background: linear-gradient(135deg,#ff8d72,#ff6b35); }
.bd-tax      { background: linear-gradient(135deg,#e14eca,#ba54f5); }
.bd-ins      { background: linear-gradient(135deg,#ffd15d,#ffa726); }

/* mini property table */
.ptable { width: 100%; border-collapse: collapse; font-size: .82rem; }
.ptable td, .ptable th { text-align: left; padding: 11px 8px; border-top: 1px solid rgba(255,255,255,.05); }
.ptable th { font-size: .64rem; text-transform: uppercase; letter-spacing: 1px; color: var(--px-faint); border-top:none; }
.ptable .prop { display: flex; align-items: center; gap: 10px; font-weight: 600; }
.ptable .thumb { width: 30px; height: 30px; border-radius: 8px; flex:none; background: var(--px-brand); display:grid; place-items:center; color:#fff; font-size:.72rem;}
.ptable .money { font-family:'Space Grotesk',sans-serif; font-weight:700;}
.mini-bar { height: 6px; border-radius: 999px; background: rgba(255,255,255,.08); overflow:hidden; width:70px;}
.mini-bar > span { display:block; height:100%; background: var(--px-brand); }

/* =====================================================================
   TRUST BAND
   ===================================================================== */
.trust-band { border-top: 1px solid var(--px-border); border-bottom: 1px solid var(--px-border); background: rgba(255,255,255,.015); }
.trust-band .wrap { display: flex; align-items: center; justify-content: space-between; gap: 30px; flex-wrap: wrap; padding-top: 30px; padding-bottom: 30px; }
.trust-item { display: flex; align-items: center; gap: 12px; color: var(--px-muted); font-weight: 600; font-size: .95rem; }
.trust-item i { font-size: 1.35rem; background: var(--px-brand); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color: transparent; }
.trust-item strong { color: var(--px-text); }

/* =====================================================================
   FEATURE ROWS (alternating)
   ===================================================================== */
.feature-row { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: center; }
.feature-row + .feature-row { margin-top: 110px; }
.feature-row.flip .feat-copy { order: 2; }
.feat-tag { display:inline-flex; align-items:center; gap:8px; font-size:.8rem; font-weight:700; letter-spacing:1px; text-transform:uppercase; color:#a9b2ff; }
.feat-tag i { font-size:.85rem; }
.feature-row h3 { font-size: clamp(1.6rem, 3vw, 2.15rem); letter-spacing: -.5px; margin: 16px 0 16px; }
.feature-row p.lead { font-size: 1.06rem; }
.feat-list { list-style: none; padding: 0; margin: 24px 0 0; display: grid; gap: 12px; }
.feat-list li { display: flex; gap: 12px; align-items: flex-start; color: var(--px-muted); font-size: .98rem; }
.feat-list li i { color: var(--px-green); margin-top: 4px; flex: none; }
.feat-list li b { color: var(--px-text); font-weight: 600; }

/* =====================================================================
   BENTO GRID
   The grid, the cell, its spotlight, the size modifiers and the icon/badge
   internals are NOT here — they moved to the LANDING PAGE — COMPOSITION &
   MOTION section of prism-common.css. The ASSET TYPE CARDS section of that
   sheet already built on `.bento .cell` while the cell itself lived here,
   so the component was split with its base half outside every contract.
   What stays below is the three badge colours, which are literals rather
   than tokens and would have arrived in the shared sheet as new hardcoded
   skin colours.
   ===================================================================== */
.badge-pro { background: rgba(139,92,246,.18); color:#c4b5ff; border:1px solid rgba(139,92,246,.4); }
.badge-ent { background: rgba(225,78,202,.16); color:#f3a9e6; border:1px solid rgba(225,78,202,.4); }
.badge-soon { background: rgba(255,177,93,.16); color:#ffcf9e; border:1px solid rgba(255,177,93,.42); }
/* "Coming soon" markers (amber) for features that aren't live yet */
.soon-pill { display:inline-block; font-size:.64rem; font-weight:800; letter-spacing:.4px; color:#ffcf9e; background: rgba(255,177,93,.13); border:1px solid rgba(255,177,93,.38); padding:3px 10px; border-radius:999px; white-space:nowrap; }
.soon-tag { font-size:.58rem; font-weight:800; letter-spacing:.4px; text-transform:uppercase; color:#ffcf9e; background: rgba(255,177,93,.13); border:1px solid rgba(255,177,93,.38); padding:1px 7px; border-radius:999px; margin-left:7px; vertical-align:middle; }
.tier.featured .soon-tag { color:#fff3e3; background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.35); }

/* NOTE: the asset-type card's own rules (.asset-type-eg / -chips / -note /
   -footer and .field-chip) are NOT here — they live in the ASSET TYPE CARDS
   section of prism-common.css, on --prism-* tokens, so they stay inside the
   light-mode and contrast contracts. See tests/test_page_local_css.py. */

/* =====================================================================
   CATEGORY CHIPS
   ---------------------------------------------------------------------
   The scrolling marquee these were written for is gone from the landing page
   (it restated /asset-types at 1,353px of scroll), and with it .cat-marquee,
   .cat-track and @keyframes cat-scroll.

   The CHIP is not landing-page furniture and must not be deleted with it:
   /asset-types/<slug> renders the same .cat-chip standing still, through
   blocks.category_chip_wall — see the chip-wall block further down this file,
   which styles .px-chip-wall .cat-chip and nothing else. Removing this rule
   with the marquee it used to sit under would have stripped the chips off all
   three asset-class pages, and nothing in the suite watches for it.
   ===================================================================== */
.cat-chip { display: inline-flex; align-items: center; gap: 11px; padding: 12px 20px; border-radius: 999px; border: 1px solid var(--px-border); background: rgba(255,255,255,.03); white-space: nowrap; font-weight: 600; }
/* The tile colour is the seeded category's own hex, arriving as --chip-bg so
   the `background` declaration stays in the sheet and only its value comes
   from the template; the fallback keeps a missing value neutral rather than
   transparent. No `color` — these are emoji now, which ignore it, and .82rem
   left a ~13px glyph floating in a 30px tile. */
.cat-chip .ci { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; font-size: 1rem; line-height: 1; background: var(--chip-bg, rgba(255,255,255,.08)); }

/* =====================================================================
   SCREENSHOT SHOWCASE
   The three-across grid is gone: at a third of the container each shot was
   about 360px, too small to read, so the section illustrated the product
   without ever showing it. #showcase is now a pinned scene (.scene-* in
   prism-common.css) that holds one full-width frame and cross-fades the
   three views. `.shot` stays because the scene still uses it per view.
   ===================================================================== */
.shot { position: relative; }

/* =====================================================================
   PRICING
   ===================================================================== */
.price-toggle { display: inline-flex; align-items: center; gap: 4px; padding: 5px; border-radius: 999px; border: 1px solid var(--px-border); background: rgba(255,255,255,.03); margin: 26px auto 0; }
.price-toggle button { border: none; background: transparent; color: var(--px-muted); font-family: inherit; font-weight: 700; font-size: .9rem; padding: 9px 20px; border-radius: 999px; cursor: pointer; transition: all .25s; }
.price-toggle button.active { background: var(--px-brand); color: #fff; box-shadow: 0 6px 18px -8px rgba(139,92,246,.7); }
.save-pill { margin-left: 8px; font-size: .68rem; font-weight: 800; color: var(--px-green); background: rgba(0,230,186,.12); border:1px solid rgba(0,230,186,.35); padding: 3px 9px; border-radius: 999px; letter-spacing:.4px; }

.pricing-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; align-items: stretch; }
.tier {
    display: flex; flex-direction: column;
    background: linear-gradient(165deg, rgba(255,255,255,.05), rgba(255,255,255,.015));
    border: 1px solid var(--px-border); border-radius: 20px; padding: 32px 28px; position: relative;
    transition: transform .3s, border-color .3s, box-shadow .3s;
}
.tier:hover { transform: translateY(-5px); border-color: var(--px-border-s); }
.tier.featured {
    border-color: transparent;
    background:
        linear-gradient(165deg, rgba(139,92,246,.14), rgba(225,78,202,.06)) padding-box,
        var(--px-brand) border-box;
    border: 1.5px solid transparent;
    box-shadow: 0 30px 70px -30px rgba(139,92,246,.6);
}
.tier-badge { position: absolute; top: -13px; left: 50%; transform: translateX(-50%); background: var(--px-brand); color: #fff; font-size: .72rem; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; padding: 6px 16px; border-radius: 999px; white-space: nowrap; }
.tier-name { display: flex; align-items: center; gap: 10px; font-family:'Space Grotesk',sans-serif; font-size: 1.3rem; font-weight: 700; }
.tier-name .ti { width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center; background: var(--px-brand-soft); border: 1px solid var(--px-border-s); font-size: .95rem; }
.tier-desc { color: var(--px-muted); font-size: .92rem; margin: 12px 0 22px; min-height: 40px; }
.tier-price { display: flex; align-items: baseline; gap: 6px; }
.tier-price .amt { font-family:'Space Grotesk',sans-serif; font-size: 3rem; font-weight: 700; letter-spacing: -1px; }
.tier-price .per { color: var(--px-faint); font-weight: 600; font-size: 1rem; }
.tier-note { color: var(--px-faint); font-size: .82rem; margin-top: 6px; min-height: 18px; }
.tier .btn { margin: 24px 0 26px; }
.tier-feats { list-style: none; padding: 0; margin: 0; display: grid; gap: 13px; }
.tier-feats li { display: flex; gap: 11px; align-items: flex-start; font-size: .92rem; color: var(--px-muted); }
.tier-feats li i { color: var(--px-green); margin-top: 3px; flex: none; font-size: .82rem; }
.tier-feats li b { color: var(--px-text); font-weight: 700; }
.tier-feats .head { font-size: .72rem; text-transform: uppercase; letter-spacing: 1px; color: var(--px-faint); font-weight: 800; margin-top: 4px; }
/* Featured (Pro) card sits on a bright gradient — lift text contrast so it stays legible */
.tier.featured .tier-desc { color: rgba(255,255,255,.9); }
.tier.featured .tier-feats li { color: rgba(255,255,255,.94); }
.tier.featured .tier-feats li b { color: #fff; }
.tier.featured .tier-feats li i { color: #eafff9; }
.tier.featured .tier-feats .head { color: rgba(255,255,255,.82); }
.tier.featured .tier-price .per,
.tier.featured .tier-note { color: rgba(255,255,255,.88); }
.tier.featured .ti { background: rgba(255,255,255,.2); border-color: rgba(255,255,255,.4); }

/* comparison table */
.compare-wrap { margin-top: 70px; overflow-x: auto; }
.compare { width: 100%; min-width: 640px; border-collapse: collapse; }
.compare th, .compare td { padding: 15px 18px; text-align: center; border-bottom: 1px solid var(--px-border); }
.compare th:first-child, .compare td:first-child { text-align: left; color: var(--px-text); font-weight: 600; font-size: .95rem; }
.compare thead th { font-family:'Space Grotesk',sans-serif; font-size: 1.05rem; color: var(--px-text); border-bottom: 1px solid var(--px-border-s); }
.compare thead th .sub { display:block; font-family:'Plus Jakarta Sans',sans-serif; font-size:.76rem; color: var(--px-faint); font-weight:600; margin-top:2px; }
.compare thead th.hi { background: linear-gradient(180deg, rgba(139,92,246,.14), transparent); border-radius: 12px 12px 0 0; }
.compare td.hi { background: rgba(139,92,246,.05); }
.compare tbody td { color: var(--px-muted); font-size: .92rem; }
.compare .yes { color: var(--px-green); font-size: 1rem; }
.compare .no { color: var(--px-faint); }
.compare .val { color: var(--px-text); font-weight: 700; font-family:'Space Grotesk',sans-serif; }

/* =====================================================================
   FAQ
   ===================================================================== */
.faq { max-width: 780px; margin: 0 auto; display: grid; gap: 14px; }
.faq-item { border: 1px solid var(--px-border); border-radius: 14px; background: rgba(255,255,255,.02); overflow: hidden; transition: border-color .25s; }
.faq-item[open] { border-color: var(--px-border-s); }
.faq-item summary { list-style: none; cursor: pointer; padding: 20px 24px; font-family:'Space Grotesk',sans-serif; font-weight: 600; font-size: 1.05rem; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary .chev { transition: transform .3s; color: var(--px-accent); flex: none; }
.faq-item[open] summary .chev { transform: rotate(180deg); }
.faq-item .ans { padding: 0 24px 22px; color: var(--px-muted); font-size: .98rem; }

/* =====================================================================
   FINAL CTA + FOOTER
   ===================================================================== */
.final-cta { text-align: center; }
.final-card {
    position: relative; overflow: hidden; border-radius: 28px; padding: 72px 32px;
    border: 1px solid var(--px-border-s);
    background: linear-gradient(160deg, rgba(29,140,248,.12), rgba(225,78,202,.1));
}
.final-card::before { content:''; position:absolute; left:50%; top:-40%; transform:translateX(-50%); width:120%; height:140%; background: radial-gradient(50% 50% at 50% 50%, rgba(139,92,246,.35), transparent 65%); filter: blur(30px); }
.final-card > * { position: relative; z-index: 1; }
.final-card h2 { font-size: clamp(2rem, 4.5vw, 3.2rem); letter-spacing: -1px; }
.spectrum-line { height: 4px; width: 120px; margin: 0 auto 30px; border-radius: 999px; background: var(--px-spectrum); }

footer { border-top: 1px solid var(--px-border); padding: 62px 0 34px; margin-top: 100px; }
/* Six tracks since the footer became the site's internal-linking surface:
   brand, Product, Asset types, Resources, Company, Legal. Resources arrived
   with the first content family (/tools) and is where guides, compare and
   blog land. The gap narrowed with the sixth track so the link columns keep
   a workable measure at 1180px; long labels wrapping to two lines is the
   accepted cost, and already happens below 900px. */
.foot-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr .9fr .9fr; gap: 34px; }
.foot-brand p { color: var(--px-muted); font-size: .92rem; max-width: 280px; margin: 16px 0 0; }
.foot-col h5 { font-size: .78rem; text-transform: uppercase; letter-spacing: 1.4px; color: var(--px-faint); margin: 0 0 16px; font-family:'Plus Jakarta Sans',sans-serif; font-weight: 800; }
.foot-col a { display: block; color: var(--px-muted); font-size: .92rem; margin-bottom: 11px; transition: color .2s; }
.foot-col a:hover { color: var(--px-text); }
.foot-bottom { display: flex; justify-content: space-between; align-items: center; gap: 20px; flex-wrap: wrap; margin-top: 48px; padding-top: 26px; border-top: 1px solid var(--px-border); color: var(--px-faint); font-size: .86rem; }

/* =====================================================================
   REVEAL ANIMATION
   Not here either. The single `.reveal` that used to live at this spot —
   one 28px fade applied identically to 44 elements — is now a four-member
   vocabulary (.reveal / .reveal-shot / .reveal-line / .reveal-set) in
   prism-common.css, driven by assets/js/prism-landing.js. The progressive
   enhancement is unchanged: content is visible until the inline <head>
   script confirms JS by adding `js` to <html>, so the page never depends
   on JS to show. Reduced motion is handled there too; what remains below
   is the two page-local animations this file still owns.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; scroll-behavior: auto !important; }
}

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
@media (max-width: 900px) {
    .nav-links .lnk, .nav-cta .btn-ghost { display: none; }
    /* The dropdowns go with the links they sit beside: <summary> carries .lnk
       and is hidden by the rule above, but the <details> around it is not, and
       an empty 0-width box in a flex row is still a gap. */
    .nav-drop { display: none; }
    /* The hamburger, gated on the script that implements it rather than on the
       motion engine. prism-common.css shows it for `.px-motion` — from when
       setMenu lived in prism-landing.js — which is a page the marketing site
       does not load. Same specificity, later sheet, so this widens it to every
       page whose nav script is actually running. Without it a phone gets no
       navigation at all on eleven of the twelve pages. */
    .px-nav .nav-menu-btn { display: inline-flex; }
    .feature-row.flip .feat-copy { order: 0; }
    .pricing-grid { grid-template-columns: 1fr; max-width: 460px; margin: 0 auto; }
    .tier.featured { transform: none; }
    .foot-grid { grid-template-columns: 1fr 1fr; gap: 30px; }
    .kpis { grid-template-columns: repeat(3,1fr); }
}
@media (max-width: 560px) {
    .section-pad { padding: 68px 0; }
    .hero { padding: 128px 0 20px; }
    .kpis { grid-template-columns: 1fr; }
    .mk-row { flex-direction: column; }
    .foot-grid { grid-template-columns: 1fr 1fr; }
    .trust-band .wrap { justify-content: center; text-align: center; }
}

/* =============================================================================
   THE DEEPER PAGES
   Everything above describes the landing page's components, which the pages
   under app/marketing/ reuse verbatim. What follows is what only they need: a
   nav that points at real pages rather than anchors, a compact page header
   where the landing page has a full hero, and the four content shapes those
   pages repeat — a field table, a metric grid, a card grid and a prose column.

   Scoped `.px-marketing` where a rule is theirs alone, unscoped where it
   upgrades shared chrome (the dropdowns, the wider footer) — the landing page
   carries the same nav and must get the same behaviour.
   ========================================================================== */

/* ---- Nav dropdowns -------------------------------------------------------
   <details>/<summary>, so the panel opens with no JavaScript at all;
   prism-marketing-nav.js only adds the manners. The marker is removed rather
   than hidden: `display: none` on ::-webkit-details-marker leaves Firefox's
   list-item triangle, and `list-style: none` alone leaves Safari's. */
.nav-drop { position: relative; }

/* Only where the dropdowns exist. Below 901px the bar is a hamburger and the
   `max-width: 900px` block above sets `.nav-drop { display: none }` — which
   this would OUTRANK if it were written unscoped, because a media query adds
   no specificity and this rule comes later in the file. The dropdowns would
   then be `display: flex` at zero width on a phone, and three zero-width flex
   items in a `gap: 30px` row is 60px of nav that is not there today.
   `align-self` alone is harmless at any width; `display` is not.

   What the two declarations buy: the <details> box fills the link row, so the
   panel's `top: 100%` reaches the bottom of that row rather than the bottom of
   a 32px summary floating in a 78px bar — which is why the panel used to open
   at y=69 with the bar's own hairline drawn across it. The summary keeps its
   natural height and is centred, because stretching the SUMMARY instead also
   clears the bar and silently drags the hover underline down with it
   (`.lnk::after` is `bottom: -2px` on the summary, so a 45px summary paints it
   6px below where every plain link in the bar does). The panel is
   `position: absolute` and so is not a flex item here. */
@media (min-width: 901px) {
    .nav-drop { align-self: stretch; display: flex; align-items: center; }
}
.nav-drop > summary {
    display: inline-flex; align-items: center; gap: 7px;
    cursor: pointer; list-style: none; user-select: none;
}
.nav-drop > summary::-webkit-details-marker { display: none; }
.nav-drop > summary i { font-size: .62rem; transition: transform .2s; opacity: .7; }
.nav-drop[open] > summary i { transform: rotate(180deg); }
.nav-drop[open] > summary { color: var(--px-text); }
.nav-links .lnk.is-active,
.nav-drop.is-active > summary { color: var(--px-text); }

.nav-panel {
    position: absolute; top: calc(100% + var(--px-nav-pad) + 10px); left: 50%; transform: translateX(-50%);
    min-width: 250px; padding: 10px;
    display: flex; flex-direction: column;
    /* Opaque, deliberately. This floats over arbitrary page content, and the
       design system's rule for that kind of chrome is that it stays readable
       whatever is behind it — at 96% the hero headline was still legible
       through the panel. A backdrop-filter cannot rescue that: it blurs what
       shows through rather than hiding it. */
    background: var(--px-panel-s);
    border: 1px solid var(--px-border-s); border-radius: 14px;
    box-shadow: var(--px-shadow);
}
/* The bar is `overflow: visible` but the panel still has to clear the fixed
   header's own stacking context, which sits at z-index 1000. */
.nav-panel { z-index: 1001; }
/* A hit area spanning the gap between the bar and the panel. Closing is
   click-outside (`!e.target.closest('.nav-drop')` in prism-marketing-nav.js),
   so without this a click in that band lands on the page and dismisses the menu
   the pointer was travelling toward.

   On `.nav-drop`, not on the summary, and the height is the panel's own offset
   expression — so the band starts exactly where the <details> box ends and
   finishes exactly where the panel begins, whatever the offset becomes. Hung
   off the summary it stopped 6px short of the panel, because the summary's
   bottom edge is not the box the panel is measured from. */
.nav-drop[open]::after {
    content: ''; position: absolute; left: 0; right: 0; top: 100%;
    height: calc(var(--px-nav-pad) + 10px);
}
.nav-panel a {
    display: block; padding: 9px 13px; border-radius: 9px;
    color: var(--px-muted); font-size: .92rem; font-weight: 600;
    transition: background .15s, color .15s; white-space: nowrap;
}
.nav-panel a:hover, .nav-panel a:focus-visible {
    background: rgba(255,255,255,.05); color: var(--px-text);
}

/* Group headings in the phone sheet. Flat rather than nested there: a
   dropdown inside a full-screen menu is two taps to reach a link that fits on
   the screen anyway. */
.px-nav-menu .menu-head {
    display: block; margin: 22px 0 6px;
    font-size: .72rem; letter-spacing: 2px; text-transform: uppercase;
    color: var(--px-faint); font-weight: 800;
}
.px-nav-menu .menu-head:first-child { margin-top: 0; }

/* ---- Breadcrumbs --------------------------------------------------------- */
.px-crumbs { padding: 128px 0 0; }
.px-crumbs ol {
    max-width: var(--px-maxw); margin: 0 auto; padding: 0 24px;
    list-style: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
    font-size: .84rem; color: var(--px-faint);
}
.px-crumbs li { display: inline-flex; align-items: center; gap: 8px; }
.px-crumbs a { color: var(--px-muted); }
.px-crumbs a:hover { color: var(--px-text); }
.px-crumbs i { font-size: .52rem; opacity: .5; transform: rotate(-90deg); }
.px-crumbs [aria-current="page"] { color: var(--px-text); font-weight: 600; }

/* ---- Page header ---------------------------------------------------------
   Where the landing page has a 152px hero with a product shot, a deeper page
   has this: the same type ramp, a third of the height. Left-aligned rather
   than centred, because these pages are read rather than scanned. */
/* 128px, not 40: .nav is position:fixed and ~78px tall, so a page header
   without the breadcrumb rail above it starts underneath the bar. The rail
   carries the same clearance, which is why the pages that have one then take
   the smaller value below. */
.px-page-head { padding: 128px 0 56px; }
.px-marketing .px-page-head h1 {
    font-size: clamp(2.1rem, 4.4vw, 3.2rem); letter-spacing: -1px; margin: 20px 0 0;
    max-width: 15ch;
}
.px-page-head .lead { margin: 22px 0 0; font-size: 1.16rem; max-width: 660px; }
.px-page-head .hero-cta { justify-content: flex-start; margin-top: 34px; }
.px-crumbs + .px-page-head { padding-top: 26px; }
@media (max-width: 900px) { .px-page-head { padding-top: 104px; } }

/* ---- Prose ---------------------------------------------------------------
   A measure, not a page width. 68ch is the readable band; the surrounding
   .wrap stays 1180px so a table or a frame inside the column can still break
   out of it. */
.px-prose { max-width: 68ch; }
.px-prose p { color: var(--px-muted); font-size: 1.03rem; line-height: 1.72; margin: 0 0 20px; }
.px-prose h3 { font-size: 1.35rem; margin: 40px 0 14px; }
.px-prose h3:first-child { margin-top: 0; }
.px-prose ul { margin: 0 0 22px; padding-left: 20px; color: var(--px-muted); line-height: 1.7; }
.px-prose li { margin-bottom: 9px; }
.px-prose strong, .px-prose b { color: var(--px-text); }
.px-prose a { color: var(--px-accent); text-decoration: underline; text-underline-offset: 3px; }

/* ---- The kinds row -------------------------------------------------------
   The sub-types an asset class covers. Reuses .field-chip's shape from
   prism-common.css at a larger size, because these are the words a visitor
   arrived searching for and they should be the first thing on the page. */
.px-kinds { display: flex; flex-wrap: wrap; gap: 9px; margin: 26px 0 0; }
.px-kinds span {
    padding: 7px 14px; border-radius: 999px; font-size: .86rem; font-weight: 600;
    color: var(--px-text); border: 1px solid var(--px-border-s);
    background: rgba(255,255,255,.04);
}

/* ---- Field table ---------------------------------------------------------
   Label and note, read straight off ASSET_TYPE_SCHEMAS. A definition list
   rather than a <table>: there is one value per term, and a table would
   promise columns that do not exist. */
.px-spec { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 44px; margin: 0; }
.px-spec > div {
    display: grid; grid-template-columns: minmax(140px, 34%) 1fr; gap: 18px;
    padding: 15px 0; border-top: 1px solid var(--px-border);
}
.px-spec dt { color: var(--px-text); font-weight: 700; font-size: .94rem; }
.px-spec dd { margin: 0; color: var(--px-muted); font-size: .94rem; line-height: 1.6; }

/* ---- Metric grid --------------------------------------------------------- */
.px-metrics { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.px-metric {
    padding: 22px; border-radius: 14px;
    border: 1px solid var(--px-border); background: var(--px-panel-s);
}
.px-metric h4 { font-size: 1.05rem; margin: 0 0 8px; }
.px-metric p { margin: 0; color: var(--px-muted); font-size: .92rem; line-height: 1.6; }

/* ---- Numbered steps ------------------------------------------------------
   The counter is CSS rather than markup, so inserting a step renumbers for
   free and a screen reader is not read a number twice. */
.px-steps { counter-reset: px-step; display: grid; gap: 18px; }
.px-step { counter-increment: px-step; display: grid; grid-template-columns: 42px 1fr; gap: 18px; align-items: start; }
.px-step::before {
    content: counter(px-step); grid-row: span 2;
    width: 42px; height: 42px; border-radius: 12px;
    display: grid; place-items: center;
    font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: 1.05rem;
    color: var(--px-text); background: var(--px-brand-soft);
    border: 1px solid var(--px-border-s);
}
.px-step h4 { font-size: 1.05rem; margin: 9px 0 6px; }
.px-step p { margin: 0 0 4px; color: var(--px-muted); font-size: .95rem; line-height: 1.62; }

/* ---- Card grid -----------------------------------------------------------
   The hub pages. Reuses .cell's material from prism-common.css but as a link,
   so the whole card is the target rather than the four words inside it. */
.px-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 18px; }
.px-card {
    display: block; padding: 26px; border-radius: var(--px-radius);
    border: 1px solid var(--px-border); background: var(--px-panel-s);
    transition: border-color .2s, transform .2s;
}
.px-card:hover { border-color: var(--px-border-s); transform: translateY(-3px); }
.px-card .b-ic {
    width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
    background: var(--px-brand-soft); border: 1px solid var(--px-border-s);
    margin-bottom: 16px; color: var(--px-text);
}
.px-card h3 { font-size: 1.18rem; margin: 0 0 9px; }
.px-card p { margin: 0; color: var(--px-muted); font-size: .95rem; line-height: 1.62; }
.px-card .px-card-go { display: inline-flex; align-items: center; gap: 8px; margin-top: 16px; color: var(--px-accent); font-size: .9rem; font-weight: 700; }

/* ---- Static chip wall ----------------------------------------------------
   The chips for one asset class, laid out as a wall. The `animation: none` is
   a leftover guard from when the landing page scrolled these same chips past
   in a marquee; that marquee is gone, so it now cancels nothing and is kept
   only because the rule is what gives this file a chip-wall selector to hang
   future layout on. A page about one asset class wants its categories
   readable, not moving past. */
.px-chip-wall { display: flex; flex-wrap: wrap; gap: 10px; }
.px-chip-wall .cat-chip { animation: none; }

/* ---- Related pages ------------------------------------------------------- */
.px-siblings { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin-top: 18px; }
.px-sibling {
    display: flex; align-items: center; gap: 13px; padding: 17px 20px;
    border-radius: 14px; border: 1px solid var(--px-border); background: var(--px-panel-s);
    color: var(--px-text); font-weight: 600; transition: border-color .2s;
}
.px-sibling:hover { border-color: var(--px-border-s); }
.px-sibling i { color: var(--px-muted); }

/* ---- Comparison pages (/compare) -----------------------------------------
   The matrix itself is `.compare` from the PRICING section — one table
   component, `.hi` on OUR column here instead of Pro's. Additions only. */
.compare td .cell-note { display: block; font-size: .74rem; color: var(--px-faint); font-weight: 500; margin-top: 4px; white-space: normal; }
.compare .vs-text { font-size: .88rem; font-weight: 600; font-family: 'Plus Jakarta Sans', sans-serif; }
.compare.wide { min-width: 880px; }
.compare-vs { margin-top: 34px; }
.compare-vs .compare td:first-child { font-size: .92rem; }

.vs-verdict, .vs-choose { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.vs-verdict-card {
    padding: 26px; border-radius: 16px;
    border: 1px solid var(--px-border); background: var(--px-panel-s);
}
.vs-verdict-card.is-us { border-color: var(--px-border-s); background: linear-gradient(180deg, rgba(139,92,246,.07), transparent), var(--px-panel-s); }
.vs-verdict-card h3, .vs-choose-col h3 { font-size: 1.08rem; margin: 0 0 10px; }
.vs-verdict-card p { margin: 0; color: var(--px-muted); font-size: .97rem; line-height: 1.66; }

/* Contender cards on the roundups: a .px-card with pros, cons and a price
   line. Cons take the faint minus deliberately — not red: a con on an honest
   card is information, not an alarm. Declared after .feat-list so the color
   wins on equal specificity. */
.vs-contender .vs-bestfor {
    display: inline-block; margin: 4px 0 12px;
    font-size: .72rem; font-weight: 800; letter-spacing: .8px;
    text-transform: uppercase; color: var(--px-accent);
}
.vs-contender.is-us { border-color: var(--px-border-s); background: linear-gradient(180deg, rgba(139,92,246,.07), transparent), var(--px-panel); }
.vs-contender .feat-list { margin-top: 14px; gap: 8px; }
.vs-contender .feat-list li { font-size: .9rem; }
.vs-cons li i { color: var(--px-faint); }
.vs-price {
    margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--px-border);
    color: var(--px-text); font-weight: 700; font-size: .95rem;
    font-family: 'Space Grotesk', sans-serif;
}
.vs-facts { margin-top: 22px; }
.vs-facts a { color: var(--px-accent); text-decoration: underline; text-underline-offset: 3px; }

/* Micro-headings inside the Resources dropdown panel — the nav carries two
   curated clusters there now (free tools, compare). */
.nav-panel .panel-head {
    display: block; padding: 9px 13px 3px;
    font-size: .66rem; letter-spacing: 1.8px; text-transform: uppercase;
    color: var(--px-faint); font-weight: 800; white-space: nowrap;
}
.nav-panel a + .panel-head { margin-top: 7px; padding-top: 12px; border-top: 1px solid var(--px-border); }

/* ---- FAQ topic grouping -------------------------------------------------- */
.px-faq-group + .px-faq-group { margin-top: 42px; }
.px-faq-group > h3 {
    font-size: .8rem; letter-spacing: 2.2px; text-transform: uppercase;
    color: var(--px-faint); font-family: 'Plus Jakarta Sans', sans-serif;
    font-weight: 800; margin: 0 0 16px;
}

/* ---- Narrow ------------------------------------------------------------- */
@media (max-width: 900px) {
    /* The dropdown panels go with .nav-links' children; the phone sheet lists
       everything flat instead. */
    .px-crumbs { padding-top: 104px; }
    .px-spec { grid-template-columns: 1fr; }
    .px-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* padding-bottom only. The shorthand here reset padding-top to 26px and
       put the page's eyebrow underneath the fixed bar — the clearance is set
       once, above, and the pages with a breadcrumb rail take the smaller value
       from the adjacent-sibling rule. */
    .px-page-head { padding-bottom: 40px; }
    .vs-verdict, .vs-choose { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
    .px-metrics { grid-template-columns: 1fr; }
    .px-spec > div { grid-template-columns: 1fr; gap: 4px; }
    .px-kinds span { font-size: .8rem; padding: 6px 12px; }
}

/* ---- The phone sheet has to scroll --------------------------------------
   prism-common.css lays the sheet out as a fixed, full-viewport flex column
   with no overflow rule, which was fine while it held five links: the content
   was shorter than the screen, so there was nothing to reach. Grouped
   navigation made it 1150px in a 667px viewport, and `overflow-y: visible` on
   a fixed box does not scroll — it clips. Everything past the fold became
   unreachable, including the two buttons at the bottom, and the body is
   scroll-locked while the sheet is open so the page behind could not move
   either. A phone got the top third of the menu and no way to the rest.

   `min-height: 0` is the load-bearing half. A flex item defaults to
   `min-height: auto`, which refuses to shrink below its content — so adding
   `overflow-y: auto` to the link list alone changes nothing at all, because
   the list never gets smaller than the links inside it.

   The list scrolls and the actions stay pinned, rather than scrolling the
   whole sheet: the CTA is the reason the sheet exists, and it should not be
   something you have to scroll a menu to find. `overflow-y: auto` on the sheet
   as well is the backstop for a future sheet whose pinned rows alone overflow.

   Scoped `.px-landing` and not `.px-marketing`, because the landing page has
   the same sheet and the same bug. */
.px-landing .px-nav-menu {
    overflow-y: auto;
    /* A flick at the end of the list must not rubber-band the locked body. */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}

.px-landing .px-nav-menu .menu-links {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}

/* A rule between the scrolling list and the pinned buttons, so a part-scrolled
   list reads as cut off by the actions rather than running into them. */
.px-landing .px-nav-menu .menu-actions {
    border-top: 1px solid var(--px-border);
    padding-top: 22px;
}

/* ---- Collapsible sheet groups ---------------------------------------------
   The families are <details>, collapsed by default, so the sheet fits one
   phone screen again — the flat list had reached 1150px in a 667px viewport
   and only worked because it scrolls. Marker removal needs both lines for
   the same reason .nav-drop's does. The TOP LEVEL IS ONE RANK: the flat links
   (Pricing, FAQ) take the same small-caps row treatment as the group
   summaries — they briefly kept the sheet's original 1.6rem sizing, which
   put the two single pages in display type over three quiet labels and read
   as an inverted hierarchy, not emphasis. A chevron is now the only thing
   that says "this row opens". Links inside an open group are the step-down
   1.22rem, so destination links and row labels still read apart. */
.px-nav-menu .menu-group { border-bottom: 1px solid var(--px-border); }
.px-nav-menu .menu-group > summary {
    display: flex; align-items: center; justify-content: space-between;
    padding: 18px 0; cursor: pointer; list-style: none; user-select: none;
}
.px-nav-menu .menu-group > summary::-webkit-details-marker { display: none; }
.px-nav-menu .menu-group > summary .menu-head { margin: 0; }
.px-nav-menu .menu-group > summary i {
    font-size: .68rem; color: var(--px-faint); transition: transform .2s;
}
.px-nav-menu .menu-group[open] > summary i { transform: rotate(180deg); }
.px-nav-menu .menu-group .menu-group-links {
    display: flex; flex-direction: column; padding: 0 0 10px 16px;
}
.px-nav-menu .menu-group .menu-group-links a { font-size: 1.22rem; padding: 11px 0; }
.px-nav-menu .menu-group .menu-group-links a:last-child { border-bottom: none; }
/* The flat top-level links, matched to .menu-head and the summary rows above.
   Only Pricing and FAQ sit directly in .menu-links, so the child combinator
   targets exactly them. Scoped .px-landing to out-rank the sheet's base link
   rule in prism-common.css (.px-landing .px-nav-menu .menu-links a), which
   sets the 1.6rem display type this row must not have — same scoping the
   .px-nav-menu rules at the top of this section already use. font-family
   resets the display face that rule sets; .menu-head never opts into it. */
.px-landing .px-nav-menu .menu-links > a {
    font-family: inherit;
    font-size: .72rem; letter-spacing: 2px; text-transform: uppercase;
    font-weight: 800; color: var(--px-faint);
    padding: 18px 0; border-bottom: 1px solid var(--px-border);
}

/* =============================================================================
   FORM KIT
   The marketing site's first inputs (built for /tools/reo-schedule, inherited
   by every tool after it). prism-common.css's .form-control rules only
   recolour black-dashboard geometry these pages never load, so this is the
   whole system: field, input, affixed input, segmented control, checkbox.

   Two decisions carried over from the app's design notes rather than
   rediscovered: every field is label-THEN-control on one baseline (never a
   bottom-aligned grid — variable hint text under fields is what wrecked the
   exit planner's first assumptions panel, so hints here are `title` tooltips),
   and a control with a handful of options is a segmented button row, never a
   native <select>, because Safari draws the AppKit menu in the OS appearance
   whatever the page says. The one native popup surface left is the date
   input, which is why .px-input carries `color-scheme: dark` — the site is
   dark-only, so the literal keyword is the token flip.
   ========================================================================== */
.px-form-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 16px 16px;
}
.px-field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.px-field[hidden] { display: none; }
.px-field.span-2 { grid-column: span 2; }
.px-field > label {
    font-size: .7rem; font-weight: 800; letter-spacing: 1.2px;
    text-transform: uppercase; color: var(--px-faint); white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
}
.px-field > label .req { color: var(--px-accent); }

.px-input {
    width: 100%; min-width: 0; font-family: inherit; font-size: .95rem;
    font-weight: 600; color: var(--px-text);
    background: rgba(255,255,255,.04);
    border: 1px solid var(--px-border-s); border-radius: 11px;
    padding: 11px 13px;
    transition: border-color .2s, box-shadow .2s, background .2s;
    color-scheme: dark;
}
.px-input::placeholder { color: var(--px-faint); font-weight: 500; }
.px-input:focus {
    outline: none; border-color: var(--px-accent);
    box-shadow: 0 0 0 3px rgba(29,140,248,.22);
    background: rgba(255,255,255,.06);
}
/* Money and rate fields: the affix says the unit, so spinners are noise. */
.px-input::-webkit-outer-spin-button,
.px-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.px-input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

.px-input-wrap { position: relative; display: flex; align-items: center; }
.px-input-wrap .affix {
    position: absolute; font-size: .8rem; font-weight: 700;
    color: var(--px-faint); pointer-events: none;
}
.px-input-wrap .affix.pre { left: 13px; }
.px-input-wrap .affix.post { right: 13px; }
.px-input.with-pre { padding-left: 30px; }
.px-input.with-post { padding-right: 46px; }

/* Segmented control — radios drawn as the pricing page's toggle, because it
   IS that control's look: same pill, same active fill, keyboard-reachable
   through the real inputs underneath. */
.px-seg {
    display: inline-flex; gap: 4px; padding: 4px; border-radius: 999px;
    border: 1px solid var(--px-border); background: rgba(255,255,255,.03);
}
.px-seg label { position: relative; }
.px-seg input { position: absolute; inset: 0; opacity: 0; pointer-events: none; }
.px-seg span {
    display: inline-flex; align-items: center; gap: 7px; padding: 8px 16px;
    border-radius: 999px; font-size: .86rem; font-weight: 700;
    color: var(--px-muted); cursor: pointer; transition: all .2s;
    white-space: nowrap;
}
.px-seg span:hover { color: var(--px-text); }
.px-seg input:checked + span {
    background: var(--px-brand); color: #fff;
    box-shadow: 0 6px 18px -8px rgba(139,92,246,.7);
}
.px-seg input:focus-visible + span { box-shadow: 0 0 0 3px rgba(29,140,248,.35); }

.px-check {
    display: inline-flex; align-items: center; gap: 9px; font-size: .92rem;
    font-weight: 600; color: var(--px-muted); cursor: pointer;
}
.px-check input { width: 17px; height: 17px; accent-color: var(--px-accent); margin: 0; }

/* =============================================================================
   FREE TOOL SURFACES (/tools/<slug>)
   The working panel, the results table and its totals, all on the panel
   material the rest of the site already uses.
   ========================================================================== */
.px-tool {
    border: 1px solid var(--px-border-s); border-radius: var(--px-radius);
    background: var(--px-panel-s); padding: 26px;
}
.px-tool h3 { font-size: 1.2rem; margin: 0 0 18px; }
.px-tool h3 i { color: var(--px-accent); margin-right: 8px; font-size: 1rem; }

/* The optional purchase-history fields fold away: the schedule is usable
   without them, and fourteen visible fields per property is the version of
   this tool nobody finishes. */
.px-tool details.px-more { margin-top: 18px; }
.px-tool details.px-more > summary {
    display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
    list-style: none; user-select: none;
    font-size: .84rem; font-weight: 700; color: var(--px-accent);
}
.px-tool details.px-more > summary::-webkit-details-marker { display: none; }
.px-tool details.px-more > summary i { font-size: .66rem; transition: transform .2s; }
.px-tool details.px-more[open] > summary i { transform: rotate(180deg); }
.px-tool details.px-more > .px-form-grid { margin-top: 16px; }

.px-tool-formrow {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin-bottom: 18px;
}
.px-tool-actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 22px; }

.px-tool-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin: 18px 0; }
/* display: grid beats the UA's [hidden] rule; the REO page hides this strip
   until there is a portfolio to summarize. */
.px-tool-kpis[hidden] { display: none; }
/* ---- Calculator answers (prism-calc-tools.js pages) ----------------------
   A three-figure strip for the calculators whose answer set is three, so a
   short answer never renders a dead fourth track; the hero cell is THE
   number the page is named after, drawn larger with the accent on its
   label; is-neg colours a genuinely negative result (a losing cash flow, an
   underwater LTV) without repainting the whole cell. The responsive
   collapse for .cols-3 lives in the media blocks at the bottom of this
   sheet — a media query adds no specificity, so the override has to
   restate the modifier there or phones would keep three columns. */
.px-tool-kpis.cols-3 { grid-template-columns: repeat(3, 1fr); }
.px-tool-kpis .kpi.is-hero { border-color: var(--px-border-s); }
.px-tool-kpis .kpi.is-hero .lab { color: var(--px-accent); }
.px-tool-kpis .kpi.is-hero .val { font-size: 1.9rem; }
.px-tool-kpis .kpi .val.is-neg { color: var(--px-red); }
/* The dynamic caveat under a calculator's answers (an underwater LTV, a
   break-even past 100%): .px-tool-note sets display, so the [hidden] the JS
   toggles needs the guard restated at author specificity. */
.px-tool-note[hidden] { display: none; }

.px-sched-wrap {
    overflow-x: auto; border: 1px solid var(--px-border); border-radius: 14px;
    background: rgba(255,255,255,.015);
}
.px-sched { width: 100%; min-width: 1150px; border-collapse: collapse; font-size: .85rem; }
.px-sched th {
    text-align: right; padding: 11px 12px; white-space: nowrap;
    font-size: .62rem; text-transform: uppercase; letter-spacing: .8px;
    color: var(--px-faint); font-weight: 800;
    background: rgba(255,255,255,.03); border-bottom: 1px solid var(--px-border-s);
}
.px-sched td {
    text-align: right; padding: 10px 12px; white-space: nowrap;
    border-top: 1px solid rgba(255,255,255,.05);
    font-family: 'Space Grotesk', sans-serif; font-weight: 600;
}
.px-sched th:first-child, .px-sched td:first-child { text-align: left; }
.px-sched td:first-child { font-family: 'Plus Jakarta Sans', sans-serif; }
.px-sched td .sub { display: block; font-family: 'Plus Jakarta Sans', sans-serif; font-size: .74rem; color: var(--px-faint); font-weight: 500; }
.px-sched .t-pos { color: var(--px-green); }
.px-sched .t-neg { color: var(--px-red); }
.px-sched tfoot td {
    border-top: 1px solid var(--px-border-s); background: rgba(255,255,255,.03);
    font-weight: 700;
}
.px-sched .row-actions { display: inline-flex; gap: 7px; }

.px-icon-btn {
    width: 30px; height: 30px; border-radius: 8px; cursor: pointer;
    border: 1px solid var(--px-border); background: rgba(255,255,255,.03);
    color: var(--px-muted); display: inline-grid; place-items: center;
    font-size: .72rem; transition: all .2s;
}
.px-icon-btn:hover { color: var(--px-text); border-color: var(--px-border-s); background: rgba(255,255,255,.07); }
.px-icon-btn.danger:hover { color: var(--px-red); border-color: rgba(253,93,147,.5); }

.px-tool-empty {
    padding: 34px 20px; text-align: center; color: var(--px-faint);
    font-size: .95rem;
}
.px-tool-empty[hidden] { display: none; }
.px-tool-empty i { display: block; font-size: 1.5rem; margin-bottom: 10px; color: var(--px-muted); }

.px-tool-note {
    display: flex; gap: 12px; align-items: flex-start; padding: 16px 18px;
    border: 1px solid var(--px-border); border-radius: 14px;
    background: rgba(255,255,255,.02); color: var(--px-muted); font-size: .92rem;
}
.px-tool-note i { color: var(--px-accent); margin-top: 3px; flex: none; }
.px-tool-note b { color: var(--px-text); }

/* ---- The mortgage calculator's own pieces --------------------------------
   The payment breakdown list and the year/month amortization rows. The
   principal-share bar reuses .mini-bar from the dashboard-mock kit above —
   the table itself is the chart, which is what lets the page carry no
   charting library at all. */
.mtg-rows { max-width: 460px; }
.mtg-row {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 18px; padding: 11px 0; border-top: 1px solid rgba(255,255,255,.05);
    color: var(--px-muted); font-size: .95rem;
}
.mtg-row:first-child { border-top: none; }
.mtg-row span:last-child {
    font-family: 'Space Grotesk', sans-serif; font-weight: 700;
    color: var(--px-text);
}
.mtg-row.is-total {
    border-top: 1px solid var(--px-border-s); margin-top: 4px; padding-top: 14px;
    color: var(--px-text); font-weight: 700;
}
.mtg-row.is-total span:last-child { color: var(--px-green); font-size: 1.08rem; }

.mtg-note { color: var(--px-faint); font-size: .88rem; margin: -6px 0 16px; }

.px-sched tr.is-year td { background: rgba(255,255,255,.025); }
.px-sched tr.is-year td:first-child { width: 44px; padding-right: 0; }
.px-sched tr.mtg-month td {
    font-size: .8rem; color: var(--px-muted); padding-top: 7px; padding-bottom: 7px;
}
.mtg-toggle i { transition: transform .2s; font-size: .62rem; }
.mtg-toggle.open i { transform: rotate(180deg); }
.px-sched .mtg-mix { display: inline-block; vertical-align: middle; background: rgba(253,93,147,.25); }
.px-sched .mtg-mix > span { background: var(--px-green); }

@media (max-width: 900px) {
    .px-tool-kpis, .px-tool-kpis.cols-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .px-tool { padding: 20px 16px; }
    .px-field.span-2 { grid-column: auto; }
    .px-tool-kpis, .px-tool-kpis.cols-3 { grid-template-columns: 1fr; }
}
