/*
    Daman product feed — the "two free pages, then ask" affordances.

    Plain CSS, loaded from the views that use the feed: the Flex base theme excludes page-level
    stylesheets from its SCSS compile, so this cannot live in _custom.scss without either being
    dropped or taking theme.css down with it.

    RTL: logical properties only. This is read right-to-left by most of its audience.
*/

.dfeed-ui {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .6rem;
    padding-block: 1.5rem 2rem;
    text-align: center;
}

/* "Showing 72 of 480" — the honest replacement for the page numbers this feed removes. Hidden when
   the total is unknown rather than guessed at. */
.dfeed-status {
    font-size: .82rem;
    color: var(--body-secondary-color, #6c757d);
    font-variant-numeric: tabular-nums;
}

.dfeed-more {
    min-inline-size: 12rem;
    border-radius: 999px;
    font-weight: 600;
    padding-block: .6rem;
    /* 44px tall: this is the primary control at the bottom of a long phone scroll, and it is the only
       way forward once auto-loading stops. */
    min-block-size: 44px;
}

.dfeed-more:disabled {
    opacity: .55;
}

/* ---------- End of feed ----------
   A feed that simply stops leaves people scrolling a dead page wondering if it broke. */

.dfeed-end {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .25rem;
    font-size: .85rem;
    color: var(--body-secondary-color, #6c757d);
}

.dfeed-top {
    font-weight: 600;
    text-decoration: none;
}

/* ---------- Pull up to load more ----------
   The floating pill that rises from the bottom edge while a thumb drags past the end of the list.
   It is decoration over the "Show more" button, which stays exactly as it is and remains the
   accessible route (WCAG 2.5.7 wants a single-pointer alternative to any drag).

   It lives on <body>, NOT in the grid — see the note in daman-feed.js. Everything that moves is
   transform and opacity, so the whole gesture stays on the compositor.

   The bottom offset mirrors .pd-sticky-cart (product-detail.css): the mobile bottom nav is 58px
   plus the safe-area inset, and nothing may sit under it. */
.dfeed-pull {
    position: fixed;
    inset-inline: 0;
    inset-block-end: 1.25rem;
    /* Above .pd-sticky-cart (1030) and .daman-bottomnav (1025); far below Smartstore's own
       offcanvas, which is 99999. */
    z-index: 1035;
    display: flex;
    justify-content: center;
    pointer-events: none;
    visibility: hidden;
    opacity: 0;
    /* Parked below the edge. JS drives an inline transform during the drag; this is where it
       springs back to. */
    transform: translateY(140%);
    transition: opacity .18s ease, transform .34s cubic-bezier(.22, 1, .36, 1), visibility 0s linear .34s;
}

.dfeed-pull.is-on {
    visibility: visible;
    opacity: 1;
    transition: opacity .12s ease, transform .34s cubic-bezier(.22, 1, .36, 1), visibility 0s;
}

/* While the finger is down JS owns the position outright — a transition here would lag the drag
   by a third of a second and the pill would stop feeling attached to the thumb. */
.dfeed-pull.is-dragging {
    transition: none;
}

.dfeed-pull-card {
    display: flex;
    align-items: center;
    gap: .6rem;
    max-inline-size: calc(100% - 2rem);
    padding-block: .5rem;
    padding-inline: .6rem 1rem;
    border-radius: 999px;
    background: var(--card-bg, #fff);
    box-shadow: 0 8px 28px rgba(0, 0, 0, .18), 0 0 0 1px rgba(0, 0, 0, .04);
    font-size: .85rem;
    font-weight: 600;
    color: var(--body-color, #212529);
}

/* The ring: a conic sweep clipped to a ring by an inner disc. --dfeed-p is a plain number (0–100)
   set from JS on each frame. No SVG, nothing to lay out. */
.dfeed-pull-ring {
    position: relative;
    flex: 0 0 auto;
    inline-size: 30px;
    block-size: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        conic-gradient(var(--mp-accent, #4f46e5) calc(var(--dfeed-p, 0) * 1%), rgba(128, 128, 128, .18) 0);
}

.dfeed-pull-ring::before {
    content: "";
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    background: var(--card-bg, #fff);
}

.dfeed-pull-chev {
    position: relative;   /* over the inner disc */
    font-size: 11px;
    color: var(--mp-accent, #4f46e5);
    transition: transform .2s cubic-bezier(.22, 1, .36, 1);
}

/* Threshold reached: the chevron turns over, which is the same "let go now" language as every
   pull-to-refresh, and the label says so in words. */
.dfeed-pull.is-ready .dfeed-pull-chev {
    transform: rotate(180deg);
}

.dfeed-pull.is-loading .dfeed-pull-chev {
    opacity: 0;
}

/* Loading: the ring stops reporting a position it no longer knows and simply spins. */
.dfeed-pull.is-loading .dfeed-pull-ring {
    background: conic-gradient(var(--mp-accent, #4f46e5) 25%, rgba(128, 128, 128, .18) 0);
    animation: dfeed-pull-spin .8s linear infinite;
}

@keyframes dfeed-pull-spin {
    to { transform: rotate(360deg); }
}

.dfeed-pull-label {
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Clear of the mobile bottom nav (58px + the safe-area inset, as .pd-sticky-cart already assumes)
   and of the product page's sticky add-to-cart bar, which sits on top of it. */
@media (max-width: 991.98px) {
    .dfeed-pull {
        inset-block-end: calc(var(--daman-bottomnav-h, 58px) + env(safe-area-inset-bottom, 0px) + 12px);
    }
}

/* A user who asked the OS to stop moving things still gets the pill and the ring — they carry the
   meaning — but not the spring or the spin. */
@media (prefers-reduced-motion: reduce) {
    .dfeed-pull,
    .dfeed-pull.is-on {
        transition: opacity .1s linear, visibility 0s;
    }

    .dfeed-pull.is-loading .dfeed-pull-ring {
        animation: none;
    }

    .dfeed-pull-chev {
        transition: none;
    }
}

/* ---------- Skeletons ----------
   Placeholders rather than a spinner: the grid keeps its shape while a page is in flight, so the
   page does not jump under a thumb that is already reaching for something.

   These are appended INTO the grid, so they must sit in the same track as a real card. The card
   dimensions come from the grid itself — a fixed height here would fight every breakpoint. */

/* Shaped like the card that is coming — image block, a short meta line, two title lines and a
   price — rather than one flat rectangle. The parts carry the grey; the container is the card
   frame, and each card sweeps ON ITS OWN so a page in flight reads as N products arriving rather
   than one grey slab.

   In a product grid the placeholder also carries `art` (set in daman-feed.js). That is load-bearing:
   .artlist-grid is a flex-wrap container whose column widths are declared against `> .art` at each
   breakpoint, so without it the placeholder had no width rule and stretched across the entire row. */
.dfeed-skel {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: .4rem;
    padding: var(--art-padding, .5rem);
    border-radius: 12px;
    background: transparent;
}


.dfeed-skel-img {
    aspect-ratio: 1 / 1;
    border-radius: 10px;
    background: rgba(128, 128, 128, .13);
}

.dfeed-skel-line {
    block-size: 10px;
    border-radius: 999px;
    background: rgba(128, 128, 128, .13);
}

/* Widths, not content: a run of identical bars reads as a table. These are the proportions of a
   real card — a small meta line, a title that wraps, and a price that is short and heavier. */
.dfeed-skel-line--sm { inline-size: 38%; }
.dfeed-skel-line--md { inline-size: 72%; }

.dfeed-skel-line--price {
    inline-size: 46%;
    block-size: 14px;
    margin-block-start: .15rem;
}

/* One sweep per card. It crosses THIS placeholder only, which is what makes a page in flight read
   as several products arriving instead of one grey slab breathing. */
.dfeed-skel::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .55), transparent);
    animation: dfeed-shimmer 1.2s infinite;
}

/* …and offset, so they do not pulse in unison — which reads as one object again. Must come after
   the shorthand above: `animation` resets animation-delay to 0. */
.dfeed-skel:nth-child(2n)::after { animation-delay: .18s; }
.dfeed-skel:nth-child(3n)::after { animation-delay: .36s; }

/* A feed of ROWS, not cards — the console's order and product lists. A card-shaped placeholder
   there would promise the wrong thing while the page is in flight, so the parts are dropped and
   the frame itself becomes the bar. */
.dfeed-skel--row {
    display: block;
    block-size: 64px;
    margin-block-end: .5rem;
    border-radius: 10px;
    background: rgba(128, 128, 128, .13);
}

.dfeed-skel--row > * { display: none; }

/* The sweep follows the reading direction: rightward in LTR, leftward in RTL. transform is physical
   and has no logical equivalent, so each direction needs its own keyframes — and BOTH ends must be
   declared in them. (Setting only the end state and leaving the start on the rule above is how you
   get an RTL shimmer that starts off-element and travels further away, never crossing it at all.) */
@keyframes dfeed-shimmer {
    from { transform: translateX(-100%); }
    to   { transform: translateX(100%); }
}

@keyframes dfeed-shimmer-rtl {
    from { transform: translateX(100%); }
    to   { transform: translateX(-100%); }
}

[dir="rtl"] .dfeed-skel::after {
    animation-name: dfeed-shimmer-rtl;
}

/* Respect a user who has asked the OS to stop moving things. The skeleton still communicates
   "loading" by existing; it does not need to shimmer to do that. */
@media (prefers-reduced-motion: reduce) {
    .dfeed-skel::after {
        animation: none;
    }
}
