/*
 * Native-only screens: the settings sheet (.pxs) and the app home (.pxh).
 *
 * Both are injected by JavaScript and only mount inside the Android shell, but
 * the rules are still scoped to html.is-native-app so a stray element can never
 * change the website.
 *
 * No backdrop-filter anywhere. Android's WebView renders large blurred surfaces
 * as pale rectangles, which is what made the old header look broken. Depth here
 * is built the other way instead: a one-pixel highlight along the top edge of
 * each surface, as if a light above it were catching the lip. That is what
 * separates a card from its background on a dark screen, and it costs nothing
 * to composite.
 */

html.is-native-app {
    --pxs-bg: #0a0a0a;
    --pxs-card: #131315;
    --pxs-card-hi: #17171a;
    --pxs-line: rgba(255, 255, 255, 0.08);
    --pxs-text: #f4f4f5;
    --pxs-dim: rgba(244, 244, 245, 0.55);
    --pxs-faint: rgba(244, 244, 245, 0.38);
    --pxs-accent: #9ed4b5;
    --pxs-danger: #ff8080;
    --pxs-up: #6ee7a8;
    --pxs-down: #ff8f8f;
}

/* The motion and depth tokens used below (--px-ease-*, --px-edge, --px-lift)
   are defined in native-app.css, which loads on every page. */

/*
 * Press feedback, applied once to everything tappable.
 *
 * A touch screen has no hover, so the press is the only chance the interface
 * gets to say it heard you. Scale is the cheapest way to say it: it composites
 * on the GPU, it scales the element's contents with it, and at these amounts it
 * is felt more than seen. The transition is on transform alone — `all` would
 * drag colour and shadow changes into the same timing and muddy both.
 */
html.is-native-app .pxs-btn,
html.is-native-app .pxs__icon,
html.is-native-app .pxs-gear,
html.is-native-app .pxs-max,
html.is-native-app .pxs-id__addr {
    transition: transform 140ms var(--px-ease-out);
}

html.is-native-app .pxs-btn:active,
html.is-native-app .pxs-max:active {
    transform: scale(0.965);
}

/* Round targets take a slightly deeper press; there is no edge to give it away. */
html.is-native-app .pxs__icon:active,
html.is-native-app .pxs-gear:active {
    transform: scale(0.9);
}

html.is-native-app .pxs-id__addr:active {
    transform: scale(0.96);
}

/*
 * Full-width rows are the exception. Scaling one pulls its edges away from the
 * surface it sits on, which looks like a rendering fault rather than a press,
 * so these get a wash of light instead.
 */
html.is-native-app .pxs-row {
    transition: background-color 140ms var(--px-ease-out);
}

@media (prefers-reduced-motion: reduce) {
    html.is-native-app .pxs-btn,
    html.is-native-app .pxs__icon,
    html.is-native-app .pxs-gear,
    html.is-native-app .pxs-max,
    html.is-native-app .pxs-id__addr {
        transition: none;
    }

    /* The press response itself stays: it is feedback, not decoration. */
}

/* ═══════════════════════ Settings sheet ═══════════════════════ */

.pxs {
    display: none;
}

html.is-native-app .pxs {
    position: fixed;
    inset: 0;
    z-index: 4000;
    display: block;
    /* Contains the sheet while it sits below the fold, before and after. */
    overflow: hidden;
}

/*
 * The scrim is its own layer rather than a background on the overlay, so that
 * fading it does not also fade the sheet. Animating the overlay as a whole
 * would make the sheet itself translucent on the way in, and you would read the
 * profile page through it — which looks like a rendering fault rather than a
 * sheet arriving. The sheet stays fully opaque and simply travels; only the
 * darkness behind it changes.
 *
 * Once the sheet has settled it covers the scrim completely, so this is only
 * ever seen in passing.
 */
html.is-native-app .pxs::before {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    animation: pxs-scrim 340ms var(--px-ease-out);
}

html.is-native-app .pxs[hidden] {
    display: none;
}

html.is-native-app.pxs-locked,
html.is-native-app.pxs-locked body {
    overflow: hidden;
}

.pxs__sheet {
    /* Positioned so it paints above the absolutely-positioned scrim. */
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--pxs-bg);
    animation: pxs-rise 340ms var(--px-ease-drawer);
}

/*
 * It leaves the way it arrived. A sheet that rises from the bottom and then
 * simply blinks out breaks the spatial story — you can no longer tell where it
 * went, or where it will be next time.
 *
 * The exit is quicker than the entrance. Arriving is the system presenting
 * something and can afford to be gracious; leaving is a response to the user,
 * and anything they asked for should feel immediate.
 */
html.is-native-app .pxs.is-closing {
    pointer-events: none;
}

html.is-native-app .pxs.is-closing::before {
    animation: pxs-scrim 240ms var(--px-ease-out) reverse forwards;
}

html.is-native-app .pxs.is-closing .pxs__sheet {
    animation: pxs-rise 240ms var(--px-ease-drawer) reverse forwards;
}

@keyframes pxs-rise {
    from { transform: translateY(100%); }
    to { transform: translateY(0); }
}

@keyframes pxs-scrim {
    from { opacity: 0; }
    to { opacity: 1; }
}

/*
 * Reduced motion keeps a cross-fade rather than dropping to nothing: the sheet
 * covers the whole screen, and swapping the entire view with no transition at
 * all is its own kind of disorienting.
 */
@media (prefers-reduced-motion: reduce) {
    html.is-native-app .pxs::before {
        animation: pxs-scrim 160ms linear;
    }

    html.is-native-app .pxs.is-closing::before {
        animation: pxs-scrim 160ms linear reverse forwards;
    }

    /* No travel, but the sheet still cross-fades: it covers the whole screen,
       and swapping the entire view with nothing at all is its own kind of
       disorienting. */
    .pxs__sheet {
        animation: pxs-scrim 160ms linear;
    }

    html.is-native-app .pxs.is-closing .pxs__sheet {
        animation: pxs-scrim 160ms linear reverse forwards;
    }
}

.pxs__bar {
    display: grid;
    grid-template-columns: 44px 1fr 44px;
    align-items: center;
    flex: 0 0 auto;
    /* Paints up through the status bar so the sheet reads as one surface. */
    padding-top: var(--praxis-safe-top, 0px);
    height: calc(56px + var(--praxis-safe-top, 0px));
    background: var(--pxs-bg);
    border-bottom: 1px solid var(--pxs-line);
}

.pxs__title {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    text-align: center;
    color: var(--pxs-text);
    letter-spacing: 0.01em;
}

.pxs__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--pxs-text);
    -webkit-tap-highlight-color: transparent;
}

.pxs__icon svg {
    width: 21px;
    height: 21px;
}

.pxs__icon[hidden] {
    visibility: hidden;
    display: flex;
}

.pxs__body {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 18px 16px calc(28px + var(--praxis-safe-bottom, 0px));
}

/* ── Identity ── */

.pxs-id {
    display: flex;
    align-items: center;
    gap: 13px;
    margin-bottom: 20px;
}

.pxs-id__avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    flex: 0 0 auto;
    border-radius: 50%;
    font-size: 21px;
    font-weight: 700;
    color: #fff;
}

.pxs-id__text {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.pxs-id__text strong {
    font-size: 18px;
    font-weight: 650;
    color: var(--pxs-text);
}

.pxs-id__addr {
    align-self: flex-start;
    padding: 0;
    border: 0;
    background: none;
    color: var(--pxs-dim);
    font-family: inherit;
    font-size: 13px;
    letter-spacing: 0.02em;
}

/* ── Cards ── */

.pxs-card {
    padding: 16px;
    margin-bottom: 14px;
    background: var(--pxs-card);
    border: 1px solid var(--pxs-line);
    border-radius: 16px;
    box-shadow: var(--px-edge), var(--px-lift);
}

.pxs-card--rows {
    padding: 4px 16px;
}

.pxs-card--danger {
    margin-top: 22px;
}

.pxs-card--secret {
    margin-top: 12px;
    background: var(--pxs-card-hi);
}

.pxs-card__label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--pxs-faint);
}

/*
 * Tabular figures on every number that can change.
 *
 * By default the digits in most faces have their own widths, so a balance
 * ticking from 1.1111 to 1.9999 makes the whole line breathe in and out. Fixing
 * the advance width holds it still. This is the sort of thing nobody points at,
 * but a price display without it never quite looks like a real trading app.
 */
.pxs-balance {
    display: block;
    margin-top: 6px;
    font-size: 30px;
    font-weight: 680;
    letter-spacing: -0.022em;
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
    color: var(--pxs-text);
}

.pxs-balance.is-error {
    font-size: 15px;
    font-weight: 500;
    color: var(--pxs-danger);
}

.pxs-heading {
    margin: 22px 0 9px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--pxs-faint);
}

.pxs-note {
    margin: 10px 0 0;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--pxs-dim);
}

.pxs-warn {
    margin: 0 0 12px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--pxs-danger);
}

.pxs-foot {
    margin: 26px 0 0;
    text-align: center;
    font-size: 11.5px;
    color: var(--pxs-faint);
}

/* ── Rows ── */

.pxs-row {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 56px;
    padding: 12px 0;
    border: 0;
    border-bottom: 1px solid var(--pxs-line);
    background: none;
    color: var(--pxs-text);
    font-family: inherit;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}

.pxs-row:last-child {
    border-bottom: 0;
}

.pxs-row__text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1 1 auto;
    min-width: 0;
}

.pxs-row__title {
    font-size: 15px;
    font-weight: 500;
}

.pxs-row__sub {
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--pxs-dim);
}

.pxs-row__value {
    flex: 0 0 auto;
    font-size: 13.5px;
    font-variant-numeric: tabular-nums;
    color: var(--pxs-dim);
}

.pxs-row__chev {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
    color: var(--pxs-faint);
}

.pxs-row.is-danger .pxs-row__title {
    color: var(--pxs-danger);
}

.pxs-row:active {
    background: rgba(255, 255, 255, 0.03);
}

/* ── Buttons ── */

.pxs-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 16px;
}

.pxs-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 46px;
    padding: 0 18px;
    border: 1px solid var(--pxs-line);
    border-radius: 12px;
    background: var(--pxs-card-hi);
    color: var(--pxs-text);
    font-family: inherit;
    font-size: 14.5px;
    font-weight: 600;
    box-shadow: var(--px-edge), var(--px-lift);
    -webkit-tap-highlight-color: transparent;
}

/*
 * A very slight vertical gradient rather than a flat fill. A solid block of
 * colour reads as a coloured rectangle; the same colour lit from above reads as
 * an object, and that is the whole difference between a button that looks
 * drawn and one that looks pressable.
 */
.pxs-btn--primary {
    border-color: transparent;
    background: linear-gradient(180deg, #aadcc1 0%, var(--pxs-accent) 100%);
    color: #06130d;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.3),
        0 1px 2px rgba(0, 0, 0, 0.4);
}

.pxs-btn--block {
    width: 100%;
    margin-top: 16px;
}

.pxs-btn:disabled {
    opacity: 0.55;
}

/* ── Receive ── */

.pxs-qr {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 216px;
    height: 216px;
    margin: 8px auto 18px;
    padding: 12px;
    background: #fff;
    border-radius: 16px;
}

.pxs-qr svg {
    width: 100%;
    height: 100%;
    display: block;
}

.pxs-qr__wait {
    font-size: 13px;
    color: #555;
}

.pxs-receive__hint {
    margin: 0 0 12px;
    text-align: center;
    font-size: 13px;
    color: var(--pxs-dim);
}

.pxs-addrbox {
    padding: 13px 14px;
    background: var(--pxs-card);
    border: 1px solid var(--pxs-line);
    border-radius: 12px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 13px;
    line-height: 1.6;
    word-break: break-all;
    color: var(--pxs-text);
}

.pxs-addrbox--key {
    color: var(--pxs-accent);
}

/* ── Forms ── */

.pxs-field {
    display: block;
    margin-bottom: 16px;
}

.pxs-field__label {
    display: block;
    margin-bottom: 7px;
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--pxs-dim);
}

.pxs-field input {
    width: 100%;
    min-height: 50px;
    padding: 0 14px;
    background: var(--pxs-card);
    border: 1px solid var(--pxs-line);
    border-radius: 12px;
    color: var(--pxs-text);
    font-family: inherit;
    font-size: 16px; /* Anything smaller and Android zooms the page on focus. */
}

.pxs-field input:focus {
    outline: none;
    border-color: rgba(158, 212, 181, 0.5);
}

.pxs-field__amount {
    position: relative;
    display: block;
}

.pxs-field__amount input {
    padding-right: 74px;
}

.pxs-max {
    position: absolute;
    top: 50%;
    right: 8px;
    transform: translateY(-50%);
    padding: 7px 12px;
    border: 0;
    border-radius: 8px;
    background: rgba(158, 212, 181, 0.14);
    color: var(--pxs-accent);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 700;
}

.pxs-summary {
    display: flex;
    flex-direction: column;
    gap: 9px;
    margin: 0 0 4px;
    padding: 14px;
    background: var(--pxs-card);
    border: 1px solid var(--pxs-line);
    border-radius: 12px;
}

.pxs-summary div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.pxs-summary dt {
    font-size: 13px;
    color: var(--pxs-dim);
}

.pxs-summary dd {
    margin: 0;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--pxs-text);
}

/* ── Messages ── */

.pxs-msg {
    margin: 14px 0 0;
    padding: 11px 13px;
    border-radius: 10px;
    font-size: 13px;
    line-height: 1.5;
}

.pxs-msg--err {
    background: rgba(255, 128, 128, 0.1);
    color: var(--pxs-danger);
}

.pxs-msg--ok {
    background: rgba(110, 231, 168, 0.1);
    color: var(--pxs-up);
}

.pxs-msg--info {
    background: rgba(255, 255, 255, 0.05);
    color: var(--pxs-dim);
}

/* ── Recovery phrase ── */

.pxs-words {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 7px;
}

.pxs-word {
    display: flex;
    align-items: baseline;
    gap: 5px;
    padding: 8px 6px;
    background: rgba(255, 255, 255, 0.04);
    border-radius: 8px;
    font-size: 13px;
    color: var(--pxs-text);
}

.pxs-word i {
    font-style: normal;
    font-size: 10px;
    color: var(--pxs-faint);
}

/* ── Gear trigger in the profile header ── */

.pxs-gear {
    display: none;
}

html.is-native-app .pxs-gear {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    border: 1px solid var(--pxs-line);
    border-radius: 50%;
    background: var(--pxs-card);
    color: var(--pxs-text);
    -webkit-tap-highlight-color: transparent;
}

html.is-native-app .pxs-gear svg {
    width: 19px;
    height: 19px;
    overflow: visible;
}

/* itshover's gear motion: the whole thing turns, the hub pops, the body
   breathes. Origins are in viewBox units for the same WebView reason as the
   tab icons. */
@keyframes px-gear-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

@keyframes px-gear-hub {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.1); }
}

@keyframes px-gear-body {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.02); }
}

.pxs-gear.is-playing .px-i-gear {
    transform-origin: 16px 16px;
    animation: px-gear-spin 0.9s ease-in-out;
}

.pxs-gear.is-playing .px-i-gear-hub {
    transform-origin: 16px 16px;
    animation: px-gear-hub 0.3s ease-out;
}

.pxs-gear.is-playing .px-i-gear-body {
    transform-origin: 16px 16px;
    animation: px-gear-body 0.6s ease-in-out;
}

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

/* Hosted alerts card, moved in from the profile page. */
html.is-native-app #pxs-alerts-slot .native-alerts {
    display: block;
}
/* ═══════════════════════ App home ═══════════════════════ */

/*
 * Two things: a statement with one action, then the board.
 *
 * The previous version was six bordered cards stacked down the screen, each too
 * small to hold anything and each surrounded by its own padding. That reads as
 * empty and unfinished at the same time — the space between the boxes is doing
 * nothing, and no single box is worth looking at.
 *
 * So the boxes are gone. Hierarchy here comes from type size and from space,
 * not from drawing a container around every group, and the launch list runs the
 * full width of the screen with hairline rules instead of sitting inside a
 * rounded card. A long list of real rows is what actually fills a screen.
 */

.pxh {
    display: none;
}

html.is-native-app .pxh {
    display: block;
    /* No side padding: the rows below are meant to reach the screen edges. */
    padding: calc(var(--landing-header-clearance, 56px) + 4px) 0 20px;
}

/* ── The statement ── */

.pxh-lede {
    padding: 14px 20px 26px;
}

/*
 * The greeting, deliberately set as a sentence rather than as a label. Small
 * uppercase text with wide tracking reads as a category heading; this is meant
 * to read as the app saying hello, so it keeps sentence case and normal
 * spacing.
 */
.pxh-lede__greet {
    display: block;
    font-size: 15px;
    font-weight: 500;
    letter-spacing: -0.005em;
    color: var(--pxs-dim);
}

/*
 * One oversized typographic moment per screen. At this size the letterforms'
 * own sidebearings read as gaps, so the tracking is pulled well in — the larger
 * the type, the more negative it has to go to still read as words.
 */
.pxh-lede__head {
    margin: 14px 0 0;
    font-size: 40px;
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -0.042em;
    color: var(--pxs-text);
}

.pxh-lede__value {
    display: block;
    margin: 12px 0 0;
    font-size: 52px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.045em;
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
    color: var(--pxs-text);
}

/* The unit rides small and dim next to the figure, so the number itself is the
   thing being read and the denomination is just available. */
.pxh-lede__value em {
    margin-left: 8px;
    font-size: 17px;
    font-style: normal;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--pxs-faint);
}

.pxh-lede__sub {
    margin: 14px 0 0;
    font-size: 14.5px;
    line-height: 1.5;
    font-variant-numeric: tabular-nums;
    color: var(--pxs-dim);
}

/* ── Actions ── */

.pxh-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 22px;
}

.pxh-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 52px;
    padding: 0 12px;
    border: 1px solid transparent;
    border-radius: 14px;
    background: linear-gradient(180deg, #aadcc1 0%, var(--pxs-accent) 100%);
    color: #06130d;
    font-size: 15.5px;
    font-weight: 650;
    letter-spacing: -0.005em;
    text-decoration: none;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.3),
        0 1px 2px rgba(0, 0, 0, 0.4);
    -webkit-tap-highlight-color: transparent;
    transition: transform 140ms var(--px-ease-out);
}

/*
 * The leaderboard is the secondary of the two, so it is the same shape and
 * weight but sits back a level: no fill of its own, just a lit edge. Giving
 * both buttons the accent would make neither of them the answer to "what do I
 * do here".
 */
.pxh-cta--ghost {
    border-color: var(--pxs-line);
    background: rgba(255, 255, 255, 0.05);
    color: var(--pxs-text);
    box-shadow: var(--px-edge);
}

.pxh-cta:active {
    transform: scale(0.975);
}

/* ── The board ── */

.pxh-feed__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 0 20px 12px;
}

/* Tracking is kept modest here: "Trending on Robinhood" plus the live badge has
   to fit on one line on a 360px screen. */
.pxh-feed__head h2 {
    margin: 0;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--pxs-faint);
}

.pxh-live {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--pxs-up);
}

.pxh-live__dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--pxs-up);
}

/*
 * A slow ambient pulse, the one piece of motion on this screen that nothing
 * triggered. It earns its place by saying the list is live rather than a
 * snapshot. Half a hertz, well clear of the roughly 0.2Hz range that reads as
 * a distracting throb, and it stops entirely under reduced motion.
 */
@media (prefers-reduced-motion: no-preference) {
    .pxh-live__dot {
        animation: pxh-pulse 2s var(--px-ease-in-out) infinite;
    }
}

@keyframes pxh-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.3; transform: scale(0.8); }
}

/*
 * Rows run edge to edge and are separated by a rule rather than boxed. A list
 * that touches both edges reads as part of the screen; the same list inset
 * inside a rounded card reads as a widget dropped onto it.
 */
.pxh-row {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 13px 20px;
    border-top: 1px solid rgba(255, 255, 255, 0.055);
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: background-color 140ms var(--px-ease-out);
}

.pxh-row:active {
    background: rgba(255, 255, 255, 0.04);
}

.pxh-row__logo {
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    border-radius: 50%;
    object-fit: cover;
    background: #202024;
}

/* Stands in for a missing image with the ticker's initial, so the row reads as
   intentional rather than as artwork that failed to arrive. */
.pxh-row__logo--none {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    font-weight: 700;
    color: var(--pxs-faint);
}

.pxh-row__main {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex: 1 1 auto;
    min-width: 0;
}

.pxh-row__sym {
    font-size: 15.5px;
    font-weight: 650;
    letter-spacing: -0.01em;
    color: var(--pxs-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pxh-row__name {
    font-size: 12.5px;
    color: var(--pxs-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pxh-row__side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 3px;
    flex: 0 0 auto;
}

.pxh-row__mc {
    font-size: 15px;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
    color: var(--pxs-text);
}

.pxh-row__vol {
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--pxs-faint);
}

.pxh-none {
    margin: 0;
    padding: 22px 20px;
    border-top: 1px solid rgba(255, 255, 255, 0.055);
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--pxs-dim);
}

/* ── Skeletons ── */

.pxh-skel {
    border-radius: 8px;
    background: linear-gradient(90deg, #141417 25%, #1b1b1f 37%, #141417 63%);
    background-size: 400% 100%;
    animation: pxh-shimmer 1.3s ease-in-out infinite;
}

/* The placeholder logo has to stay a circle at the row's logo size. */
.pxh-skel.pxh-row__logo {
    border-radius: 50%;
}

@keyframes pxh-shimmer {
    from { background-position: 100% 50%; }
    to { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .pxh-skel { animation: none; }
}

/* ── Entrance ── */

/*
 * The statement settles, then the board. Only two elements now, so this is a
 * single beat rather than a cascade — short enough to be felt and not waited
 * on, and nothing is blocked from being tapped while it runs.
 *
 * Guarded on no-preference rather than switched off under reduce, so the
 * opacity: 0 start state is never applied unless the animation that clears it
 * is certain to run. A stagger that fails leaves a blank screen.
 */
@media (prefers-reduced-motion: no-preference) {
    html.is-native-app .pxh > * {
        opacity: 0;
        transform: translateY(8px);
        animation: pxh-enter 320ms var(--px-ease-out) forwards;
    }

    html.is-native-app .pxh > :nth-child(2) {
        animation-delay: 60ms;
    }
}

@keyframes pxh-enter {
    to {
        opacity: 1;
        transform: translateY(0);
    }
}
