/*
 * Native app chrome.
 *
 * Everything here is scoped to html.is-native-app, so the web experience is
 * untouched. The goal is that the Android build reads as a real app rather than
 * a site in a webview: a flat top bar that melts into the status bar, a bottom
 * tab bar for primary navigation, and none of the floating glass surfaces that
 * only make sense with a mouse.
 *
 * Backdrop filters are removed throughout. Android's WebView renders large
 * blurred surfaces as pale rectangular artifacts, which is what made the header
 * look like a white band sitting under the status bar.
 */

/*
 * Cross-document view transitions.
 *
 * This is the one rule here that is not scoped to html.is-native-app, because
 * @view-transition is document-wide and cannot be put behind a selector. The
 * website therefore also gets a soft cross-fade between pages; the named
 * elements below stay app-only, so on the web this is just the root fade.
 *
 * It has to be static CSS. It was previously injected by a script in <head>,
 * which looked equivalent but was not: measured against a real navigation, the
 * incoming document reported no active transition at `pagereveal` even though
 * the outgoing one had started it, and the navigation fell back to a hard page
 * swap. Declaring it in a stylesheet removes that race.
 *
 * Browsers without support ignore the rule and navigate exactly as before.
 */
@view-transition {
    navigation: auto;
}

html.is-native-app {
    /* Capacitor writes --safe-area-inset-* onto <html> from the real window
       insets. It reports 0 when it insets the webview natively instead of
       letting it draw edge to edge, which is the correct value in that case:
       the webview already starts below the bars. env() covers the gap before
       the first injection lands. */
    --praxis-safe-top: var(--safe-area-inset-top, env(safe-area-inset-top, 0px));
    --praxis-safe-bottom: var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px));

    --praxis-appbar-h: 56px;

    /* The dock floats clear of the bottom edge, so the space it reserves is its
       own height plus the gap underneath it plus the gesture inset. Everything
       that needs to clear the dock reads --praxis-tabbar-total, including the
       terminal's viewport arithmetic. */
    --praxis-dock-h: 58px;
    --praxis-dock-inset: 10px;
    --praxis-tabbar-h: var(--praxis-dock-h);
    --praxis-tabbar-total: calc(
        var(--praxis-dock-h) + var(--praxis-dock-inset) * 2 + var(--praxis-safe-bottom)
    );
    --praxis-app-bg: #0a0a0a;
    --praxis-app-line: rgba(255, 255, 255, 0.07);

    /*
     * Motion and depth tokens. They live here rather than in native-screens.css
     * because this file is on every page and that one is only on two, so
     * anything defined there would resolve to nothing on the terminal and the
     * leaderboard.
     *
     * The stock CSS easings are too soft to read as deliberate. These are the
     * strong variants: --px-ease-out for anything entering or answering a
     * touch, --px-ease-in-out for movement across the screen, and the iOS
     * drawer curve for sheets.
     *
     * There is deliberately no ease-in. It holds still at the very moment the
     * user is watching hardest, which reads as lag however short it is.
     */
    --px-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
    --px-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
    --px-ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

    /*
     * Depth without backdrop-filter, which this WebView renders as a pale
     * rectangle. A one-pixel highlight along the top edge reads as light
     * catching the lip of a surface, and a shadow underneath lifts it off the
     * page. Together they separate a card from its background on a dark screen
     * for the cost of a composited shadow.
     */
    --px-edge: inset 0 1px 0 rgba(255, 255, 255, 0.045);
    --px-lift: 0 1px 2px rgba(0, 0, 0, 0.45);
    --px-lift-lg: 0 8px 24px rgba(0, 0, 0, 0.45), 0 2px 6px rgba(0, 0, 0, 0.35);

    /* Page content reads this through var() fallbacks rather than inheritance,
       because the site declares it on .landing-header, which main content is not
       descended from. Declaring it at the root makes every page's top spacing
       track the shorter app bar without touching each stylesheet. */
    --landing-header-clearance: calc(var(--praxis-appbar-h) + var(--praxis-safe-top));
}

html.is-native-app,
html.is-native-app body {
    background: var(--praxis-app-bg);
    /* A rubber-band overscroll reveals the page behind the fixed bars, which
       looks broken on a tab layout. */
    overscroll-behavior-y: none;
}

/* Marketing motion is expensive on mid-range phones and reads as web, not app. */
html.is-native-app .lp-beams,
html.is-native-app .lp-aurora,
html.is-native-app .lp-orb,
html.is-native-app .lp-lamp {
    display: none !important;
}

/* ───────────────────────── Top app bar ───────────────────────── */

/* The status bar sits inside the bar's own padding box, so the background paints
   continuously from the top of the screen down past the clock, and the logo row
   starts below it. That is what makes the bar read as one surface with the
   status bar instead of a strip butted against it. */
html.is-native-app .landing-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 900;
    padding: var(--praxis-safe-top) 0 0 !important;
    background: var(--praxis-app-bg);
    border-bottom: 1px solid var(--praxis-app-line);
    pointer-events: auto;
}

/* The terminal re-declares the clearance on the body and again inside media
   queries; both need beating so its header matches every other page. */
html.is-native-app body.page-demo-terminal,
html.is-native-app body.page-demo-terminal .landing-header {
    --landing-header-clearance: calc(var(--praxis-appbar-h) + var(--praxis-safe-top));
}

html.is-native-app body.page-demo-terminal .landing-header {
    padding: var(--praxis-safe-top) 0 0 !important;
}

html.is-native-app .landing-nav--terminal {
    min-height: var(--praxis-appbar-h) !important;
    padding: 0 12px !important;
    border-radius: 0 !important;
    border: 0 !important;
    background: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    box-shadow: none !important;
}

html.is-native-app .landing-nav {
    width: 100%;
    max-width: none;
    margin: 0;
    min-height: var(--praxis-appbar-h);
    padding: 0 14px !important;
    gap: 10px;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    box-shadow: none !important;
}

html.is-native-app .landing-header.is-scrolled .landing-nav {
    border: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
}

html.is-native-app .landing-nav__logo {
    height: 22px;
    width: auto;
}

/*
 * The tab bar carries navigation now, so the top bar keeps only the wordmark.
 *
 * The connect pill goes with it: a phone app should not ask for a wallet in the
 * chrome of every screen. Profile prompts on arrival when nobody is connected,
 * and the trade flow asks at the point it actually needs a signature.
 */
html.is-native-app .landing-nav__actions .landing-nav__icon-btn,
html.is-native-app .landing-nav__links,
html.is-native-app .landing-nav__connect,
html.is-native-app .nav-connect-btn,
html.is-native-app .landing-nav__back {
    display: none !important;
}

/* The one exception: on the terminal the arrow is how you leave an open trade. */
html.is-native-app body.term-trade-open .landing-nav__back {
    display: inline-flex !important;
}

/* ───────────────────────── Content clearance ───────────────────────── */

html.is-native-app body {
    padding-bottom: var(--praxis-tabbar-total);
}

/* The terminal manages its own viewport math off these two variables, so
   feeding the tab bar in here keeps its internal dvh calculations correct
   instead of overriding each one. */
html.is-native-app body.page-demo-terminal {
    padding-bottom: 0;
    --term-bottom-space: calc(16px + var(--praxis-tabbar-total));
}

html.is-native-app .term-board-shell {
    padding-bottom: var(--praxis-tabbar-total) !important;
}

/* Full-screen chart hides the tabs, so nothing needs reserving. */
html.is-native-app body.page-demo-terminal.term-chart-only {
    --term-bottom-space: 16px;
}

html.is-native-app body.page-demo-terminal.term-chart-only .praxis-tabbar {
    display: none;
}

/* ───────────────────────── Terminal: open trade ───────────────────────── */

/*
 * The trade view could not be scrolled.
 *
 * body.page-demo-terminal is overflow:hidden, which propagates to the viewport,
 * and on phones the trade shell is laid out height:auto/overflow:visible with no
 * scroll container of its own. Anything below the fold — including the buy and
 * sell panel — was simply clipped and unreachable.
 *
 * Giving the view its own scroller fixes that and lets it sit exactly between
 * the header and the tab bar, rather than guessing at a bottom inset.
 */
html.is-native-app body.page-demo-terminal.term-trade-open .term-trade-view {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: var(--praxis-tabbar-total);
    overflow-y: auto;
    overscroll-behavior-y: contain;
    -webkit-overflow-scrolling: touch;
}

/*
 * Edge to edge. The stacked !important paddings left the content in a narrow
 * column with a wide dead margin either side, which on a phone is the one
 * resource there is none of.
 */
html.is-native-app body.page-demo-terminal.term-trade-open .term-trade-view .term-shell {
    height: auto !important;
    min-height: 0 !important;
    max-width: none !important;
    width: 100% !important;
    margin-top: calc(var(--landing-header-clearance) + 6px) !important;
    padding: 0 0 26px !important;
    gap: 8px !important;
}

html.is-native-app body.page-demo-terminal.term-trade-open .term-main,
html.is-native-app body.page-demo-terminal.term-trade-open .term-col.term-center,
html.is-native-app body.page-demo-terminal.term-trade-open .term-col.term-right {
    width: 100% !important;
    max-width: none !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
    gap: 8px !important;
}

/* Square edges read as an app surface; an inset rounded panel reads as a page. */
html.is-native-app body.page-demo-terminal.term-trade-open .term-main,
html.is-native-app body.page-demo-terminal.term-trade-open .term-hero,
html.is-native-app body.page-demo-terminal.term-trade-open .term-col.term-center,
html.is-native-app body.page-demo-terminal.term-trade-open .term-col.term-right > .term-card {
    border-radius: 0 !important;
    border-left: 0 !important;
    border-right: 0 !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    /* Android's WebView paints large blurred surfaces as pale rectangles. */
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    box-shadow: none !important;
}

html.is-native-app body.page-demo-terminal.term-trade-open .term-hero,
html.is-native-app body.page-demo-terminal.term-trade-open .term-col.term-center,
html.is-native-app body.page-demo-terminal.term-trade-open .term-col.term-right > .term-card {
    background: #121215 !important;
}

/* A chart tall enough to read but short enough that the buy panel is one
   thumb-flick away rather than a full screen down. */
html.is-native-app body.page-demo-terminal.term-trade-open .term-chart-row {
    min-height: 0 !important;
}

html.is-native-app body.page-demo-terminal.term-trade-open .term-chart-wrap--gt {
    flex: 0 0 auto !important;
    height: 42dvh !important;
    min-height: 260px !important;
}

/* The live-trades list scrolls internally, which steals the gesture from the
   page and traps the buy panel below it again. */
html.is-native-app body.page-demo-terminal.term-trade-open .term-trade-view #term-tx-card {
    flex: 0 0 auto !important;
    min-height: 0 !important;
}

html.is-native-app body.page-demo-terminal.term-trade-open .term-trade-view #term-tx-card .tx-list {
    max-height: 46vh !important;
    overscroll-behavior-y: contain;
}

/* Expanded chart takes the whole window back, tab bar included. */
html.is-native-app body.page-demo-terminal.term-chart-only .term-trade-view {
    bottom: 0;
    overflow: hidden;
}

html.is-native-app body.page-demo-terminal.term-chart-only .term-trade-view .term-shell {
    margin-top: 0 !important;
    padding-bottom: 0 !important;
    height: 100dvh !important;
}

html.is-native-app body.page-demo-terminal.term-chart-only .term-chart-wrap--gt {
    flex: 1 1 auto !important;
    height: auto !important;
}

/* ───────────────────────── Bottom tab bar ───────────────────────── */

.praxis-tabbar {
    display: none;
}

/*
 * A floating dock rather than a bar welded to the bottom edge. The page runs
 * underneath it, which is what makes an app feel like it has depth instead of
 * being a document with a footer.
 *
 * No backdrop-filter: Android's WebView turns large blurred surfaces into pale
 * rectangles, so the fill is solid and simply lighter than the page.
 */
html.is-native-app .praxis-tabbar {
    position: fixed;
    left: 10px;
    right: 10px;
    bottom: calc(var(--praxis-safe-bottom) + var(--praxis-dock-inset));
    z-index: 3000;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    align-items: center;
    height: var(--praxis-dock-h);
    padding: 0 6px;
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: 999px;
    /* Lit from above, like every other surface in the app, so the pill reads as
       an object floating over the page rather than a hole cut out of it. */
    background: linear-gradient(180deg, #1c1d22 0%, #17181c 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.07),
        0 10px 30px rgba(0, 0, 0, 0.55),
        0 2px 8px rgba(0, 0, 0, 0.4);
}

.praxis-tabbar__item {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    justify-self: center;
    width: 100%;
    max-width: 64px;
    height: 46px;
    border: 0;
    border-radius: 999px;
    background: none;
    color: rgba(255, 255, 255, 0.46);
    font-family: inherit;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition:
        color 180ms var(--px-ease-out),
        background-color 180ms var(--px-ease-out),
        transform 140ms var(--px-ease-out);
}

/* The label still carries the accessible name; the dock just does not draw it. */
.praxis-tabbar__item > span {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    white-space: nowrap;
    clip-path: inset(50%);
}

.praxis-tabbar__item svg {
    width: 23px;
    height: 23px;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
    /* The trophy throws confetti past the icon box. */
    overflow: visible;
}

/*
 * The press is the only feedback a touch screen can give before the navigation
 * starts, and here it matters more than usual: the page underneath is being
 * replaced, so without it there is a beat where nothing at all has acknowledged
 * the tap. It fires on pointer-down, ahead of the navigation.
 */
.praxis-tabbar__item:active {
    color: rgba(255, 255, 255, 0.8);
    transform: scale(0.88);
}

@media (prefers-reduced-motion: reduce) {
    .praxis-tabbar__item {
        transition: color 180ms linear, background-color 180ms linear;
    }

    /* The scale stays. It is feedback, not decoration. */
}

.praxis-tabbar__item.is-active {
    color: var(--accent-light, #9ed4b5);
    background: rgba(158, 212, 181, 0.13);
}

/* ─────────────── Navigating without the shell blinking ───────────────
 *
 * Naming these two pulls them out of the page cross-fade: the browser matches
 * them across documents and holds them in place, so a dock tap looks like the
 * content swapping under a stationary dock rather than the window reloading.
 *
 * The dock's own snapshot still cross-fades, which is what slides the active
 * highlight from the old item to the new one.
 */
html.is-native-app .praxis-tabbar {
    view-transition-name: praxis-dock;
}

html.is-native-app .landing-header {
    view-transition-name: praxis-topbar;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: 190ms;
}

::view-transition-old(praxis-dock),
::view-transition-new(praxis-dock),
::view-transition-old(praxis-topbar),
::view-transition-new(praxis-topbar) {
    animation-duration: 190ms;
}

@media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation: none !important;
    }
}

/* ─────────────────── Tab icon animation ───────────────────
 *
 * Ported from the itshover animated icon set. Transform origins are written in
 * viewBox units rather than percentages with transform-box: fill-box, because
 * fill-box on <g> is the shakier of the two in Android's WebView.
 *
 * Nothing animates until scripts/native-shell-ui.js adds .is-playing, so the
 * bar is static at rest and costs no compositing while the user reads a page.
 */

/* Home */
@keyframes px-home-roof {
    from { transform: translateY(-2px); opacity: 0.55; }
    to { transform: translateY(0); opacity: 1; }
}

@keyframes px-home-house {
    from { transform: scale(0.94); }
    to { transform: scale(1); }
}

@keyframes px-home-door {
    from { transform: scaleY(0); }
    to { transform: scaleY(1); }
}

.praxis-tabbar__item.is-playing .px-i-roof {
    animation: px-home-roof 0.4s ease-out;
}

.praxis-tabbar__item.is-playing .px-i-house {
    transform-origin: 12px 16.5px;
    animation: px-home-house 0.3s ease-out;
}

.praxis-tabbar__item.is-playing .px-i-door {
    transform-origin: 12px 21px;
    animation: px-home-door 0.3s ease-out 0.3s both;
}

/* Trade */
@keyframes px-bar-rise {
    from { transform: scaleY(0); }
    to { transform: scaleY(1); }
}

@keyframes px-bar-base {
    0%, 100% { transform: scaleX(1); }
    50% { transform: scaleX(1.06); }
}

.praxis-tabbar__item.is-playing .px-i-bar1,
.praxis-tabbar__item.is-playing .px-i-bar2,
.praxis-tabbar__item.is-playing .px-i-bar3 {
    animation: px-bar-rise 0.3s ease-out both;
}

.praxis-tabbar__item.is-playing .px-i-bar1 { transform-origin: 6px 20px; }
.praxis-tabbar__item.is-playing .px-i-bar2 { transform-origin: 12px 20px; animation-delay: 0.1s; }
.praxis-tabbar__item.is-playing .px-i-bar3 { transform-origin: 18px 20px; animation-delay: 0.2s; }

.praxis-tabbar__item.is-playing .px-i-baseline {
    transform-origin: 11px 20px;
    animation: px-bar-base 0.4s ease-in-out;
}

/* Board */
@keyframes px-trophy-lift {
    0% { transform: translateY(0) rotate(0deg); }
    40% { transform: translateY(-3px) rotate(-10deg); }
    70% { transform: translateY(-3px) rotate(10deg); }
    100% { transform: translateY(0) rotate(0deg); }
}

/*
 * Confetti travel is roughly half the source's, which was tuned for an icon
 * with room around it. In a tab bar the burst would otherwise clear the bar
 * entirely and scatter over the page above it.
 */
@keyframes px-confetti-1 {
    0% { opacity: 0; transform: translate(0, 0) rotate(0deg) scale(0); }
    30% { opacity: 1; transform: translate(-3px, -4px) rotate(60deg) scale(1); }
    100% { opacity: 0; transform: translate(-6px, -8px) rotate(140deg) scale(0.5); }
}

@keyframes px-confetti-2 {
    0% { opacity: 0; transform: translate(0, 0) rotate(0deg) scale(0); }
    30% { opacity: 1; transform: translate(-1px, -4px) rotate(-45deg) scale(1); }
    100% { opacity: 0; transform: translate(-3px, -9px) rotate(-100deg) scale(0.5); }
}

@keyframes px-confetti-3 {
    0% { opacity: 0; transform: translate(0, 0) rotate(0deg) scale(0); }
    30% { opacity: 1; transform: translate(1px, -4px) rotate(55deg) scale(1); }
    100% { opacity: 0; transform: translate(3px, -9px) rotate(120deg) scale(0.5); }
}

@keyframes px-confetti-4 {
    0% { opacity: 0; transform: translate(0, 0) rotate(0deg) scale(0); }
    30% { opacity: 1; transform: translate(3px, -4px) rotate(-60deg) scale(1); }
    100% { opacity: 0; transform: translate(6px, -8px) rotate(-140deg) scale(0.5); }
}

.px-i-cf1,
.px-i-cf2,
.px-i-cf3,
.px-i-cf4 {
    opacity: 0;
}

.praxis-tabbar__item.is-playing .px-i-trophy {
    transform-origin: 12px 20px;
    animation: px-trophy-lift 0.8s ease-out;
}

.praxis-tabbar__item.is-playing .px-i-cf1 {
    transform-origin: 12px 7px;
    animation: px-confetti-1 0.8s ease-out 0.1s;
}

.praxis-tabbar__item.is-playing .px-i-cf2 {
    transform-origin: 13px 6px;
    animation: px-confetti-2 0.8s ease-out 0.1s;
}

.praxis-tabbar__item.is-playing .px-i-cf3 {
    transform-origin: 14px 7px;
    animation: px-confetti-3 0.8s ease-out 0.1s;
}

.praxis-tabbar__item.is-playing .px-i-cf4 {
    transform-origin: 13px 8px;
    animation: px-confetti-4 0.8s ease-out 0.1s;
}

/* Profile */
@keyframes px-user-pop {
    0% { transform: translateY(0) scale(1); }
    45% { transform: translateY(-1px) scale(1.08); }
    100% { transform: translateY(0) scale(1); }
}

.praxis-tabbar__item.is-playing .px-i-avatar {
    transform-origin: 12px 12px;
    animation: px-user-pop 0.45s ease-out;
}

@media (prefers-reduced-motion: reduce) {
    .praxis-tabbar__item.is-playing * {
        animation: none !important;
    }
}

/* ───────────────────────── Page-level trims ───────────────────────── */

/*
 * Home is a dashboard in the app, not a pitch.
 *
 * Someone who has installed the app has already been sold; what they want on
 * open is their balance, something to trade and where they stand. The marketing
 * sections stay in the markup for the website and are simply not rendered here,
 * with scripts/native-home.js inserting the dashboard ahead of them.
 */
html.is-native-app body.page-home main.lp > section {
    display: none !important;
}

html.is-native-app body.page-home #lp-bg,
html.is-native-app .lp-coin-field {
    display: none !important;
}

/* ───────────────────────── Profile ───────────────────────── */

/*
 * Managing the wallet, signing out and resetting the paper account all live in
 * the settings sheet now. Leaving duplicates on the portfolio screen made it
 * read as a settings page that happened to show a balance.
 */
html.is-native-app .page-profile .profile-head__actions,
html.is-native-app .page-profile .profile-account-menu {
    display: none !important;
}

html.is-native-app .page-profile .profile-shell {
    padding: calc(var(--landing-header-clearance, 56px) + 14px) 14px 8px;
}

html.is-native-app .page-profile .profile-head {
    display: block;
    margin-bottom: 14px;
}

html.is-native-app .page-profile .profile-head h1 {
    font-size: 22px;
    letter-spacing: -0.02em;
}

html.is-native-app .page-profile .profile-columns {
    grid-template-columns: 1fr;
    gap: 14px;
}

/* Edge-to-edge panels read as app surfaces; inset rounded cards read as web. */
html.is-native-app .page-profile .profile-board,
html.is-native-app .page-profile .profile-balance-card {
    border-radius: 16px;
}

html.is-native-app .page-profile .profile-table-scroll {
    max-height: none;
}

/* Docs sidebar is a desktop affordance; the content reads fine linearly. */
html.is-native-app .page-docs .docs-shell {
    display: block;
    padding-top: calc(var(--landing-header-clearance, 56px) + 16px);
}

html.is-native-app .page-docs .docs-board--nav {
    display: none;
}

/* Edge-to-edge cards read as app surfaces; inset rounded panels read as web. */
html.is-native-app .page-docs .docs-board {
    border-radius: 0;
    border-left: 0;
    border-right: 0;
}

html.is-native-app .page-leaderboard .dashboard-main {
    padding-top: calc(var(--landing-header-clearance, 56px) + 16px);
}

/* Hover states stick on touch after a tap, so drop them. */
@media (hover: none) {
    html.is-native-app .lp-card:hover,
    html.is-native-app .fund-eco-card:hover {
        transform: none;
        box-shadow: none;
    }
}
