/*
    Wahaj (falak-theme-onyx) — theme stylesheet.

    Shares its base with Falak Theme 2026 and Falak Nova, deliberately: the f-*
    rules skin the SDK components, and themes disagreeing about what
    <falak-slider> looks like structurally is how a shared component library
    rots. Onyx re-skins the token block and appends its own chrome at the end of
    the file; the middle is the common base and should stay diffable against it.

    Onyx is the deep-navy-on-cream storefront: ink #101631 carries every action,
    cream #F2E3D0 is the contrast on it, and the page alternates white and
    #f5f5f5 bands. The measurements below were read off the reference
    storefront's computed styles rather than estimated — where a comment gives a
    pixel value, that is what the reference actually renders.

    RTL-first: every directional rule uses logical properties, so Arabic and
    English render natively from the same CSS. The platform injects the brand
    tokens (--color-primary, --color-primary-dark, --color-primary-light,
    --color-text, --font-main) in master.twig; everything below derives from
    them so a merchant's color choice restyles the whole theme.
*/

/* ---------------------------------------------------------------- tokens */

:root {
    /* fallbacks — overridden by the platform-injected block in master.twig.
       Names match the 2026 template exactly: everything below this block reads
       them, including every f-* component skin. */

    /*
     * Ink IS the brand colour here. In a warm theme --color-primary is an
     * accent laid over near-black text; in Onyx the navy is both, so a
     * merchant who rebrands moves buttons, links, header and footer together
     * and the theme stays coherent instead of growing a second accent.
     */
    --color-primary: #101631;
    --color-primary-dark: #080d20;
    --color-primary-light: #2a3358;
    --color-primary-tint: #e8eaf0;
    --color-text: #101631;
    --font-main: 'IBM Plex Sans Arabic', sans-serif;

    /*
     * Cream, not white, is the contrast on primary — it is what the reference
     * puts inside every navy button and on every footer heading, and it is the
     * single detail that keeps the navy from reading as generic corporate blue.
     */
    --color-on-primary: #f2e3d0;
    --color-cream: #f2e3d0;

    /* derived neutrals — cool-biased so they sit under the navy without going
       muddy, and still holding if a merchant picks a warm primary */
    --color-bg: #ffffff;
    --color-surface: #f5f5f5;
    --color-border: rgba(16, 22, 49, 0.12);
    /* The reference sets body copy to 75% ink rather than solid — the page
       reads softer for it, and headings gain their weight by contrast. */
    --color-text-soft: rgba(16, 22, 49, 0.75);
    --color-text-faint: rgba(16, 22, 49, 0.5);
    --color-hairline: rgba(16, 22, 49, 0.08);
    --color-danger: #c62828;

    /*
     * Sale red is a SEPARATE token from danger. The reference prices sale items
     * in pure red and reports errors in a darker one; folding them together
     * makes every discounted price look like a validation failure.
     */
    --color-sale: #ff0000;
    --color-announce: #ef3f38;
    --color-success: #09692d;

    /*
     * Ink for a surface that is a FIXED white in both themes — the round card
     * controls sitting on a product photo, a CTA that inverts on hover. Those
     * pills stay white on purpose (white-on-photo is legible over any image),
     * so their ink must NOT follow --color-text: in dark mode that flips to a
     * near-white and paints a near-white glyph on a white disc. Deliberately
     * not redefined in the dark block below.
     */
    --color-on-white: #101631;

    /* chrome grounds — set by the customizer's Colors group when the merchant
       fills them, otherwise these */
    --color-header-bg: var(--color-bg);
    /* Tint layered under the pinned header's blur, so the glyphs keep
       contrast over whatever section is behind it. */
    --color-header-veil: rgba(255, 255, 255, 0.55);
    --color-footer-bg: #101631;

    /* The cream category strip under the header's top row. Its own token so a
       merchant can recolour it without touching the header. */
    --color-navstrip-bg: var(--color-cream);
    /* Header icon discs: a flat off-white plate, so the brand-coloured glyph
       sitting in it is what carries the colour on the bar. Started at #f8f8f8
       and walked down in steps: 3%, 6% and 8% off white all still read as
       white beside the bar. A disc on a white header needs about 11% before
       the eye calls it grey rather than a trick of the screen.

       Opaque, unlike the translucent grey this replaced, and the SAME in every
       header state - over the hero the discs stay this plate rather than
       frosting into the photograph. The transparent-state rules at the end of
       the file undo that state's white ink to suit. */
    --color-icon-disc: #e4e4e4;
    /* Text on that plate (the language and currency pills). The plate does not
       change in dark mode, so its ink must not either: --color-text flips to
       near-white there and the globe vanished on the light pill. */
    --color-icon-disc-ink: #101631;
    /* The lift under those discs: a tight 3px blur, barely there. A wide soft
       shadow at this size does not read as depth, it reads as the control
       floating - which is what the earlier 0 4px 14px attempt looked like. A
       short offset and a small blur give the plate an edge and nothing more.
       The hover value is the same shadow opened one step, so the disc looks
       like it rises rather than like it swapped for a different control. */
    --shadow-icon-disc: 0 1px 3px rgba(0, 0, 0, 0.10);
    --shadow-icon-disc-hover: 0 2px 6px rgba(0, 0, 0, 0.14);
    /* The hero carries the same pair. They are small enough not to lift the
       controls off the bar over a photograph, which is what the heavier
       version did. Stated as their own tokens so this state can go back to
       none without touching a rule. */
    --shadow-icon-disc-hero: var(--shadow-icon-disc);
    --shadow-icon-disc-hero-hover: var(--shadow-icon-disc-hover);

    /*
     * rhythm — three radii, each with one job, taken from the reference:
     * controls 12px, cards and media 14px, full-bleed slideshows 18px.
     */
    --radius-sm: 0.75rem;
    --radius: 0.875rem;
    --radius-lg: 1.125rem;
    --shadow-sm: 0 1px 2px rgba(16, 22, 49, 0.05);
    --shadow: 0 4px 16px rgba(16, 22, 49, 0.08);
    --container: 1400px;

    /* The header is two stacked rows: a control row and a category strip.
       --header-h is the whole thing, because that is what sticky offsets and
       scroll-margin need. The strip collapses to 0 on phones, where the
       categories move into the drawer. */
    --header-row-h: 4rem;
    --navstrip-h: 3.3125rem;
    --header-h: calc(var(--header-row-h) + var(--navstrip-h));

    /* control heights — every button, input and select lands on 45px, so rows
       of mixed controls align without per-component nudging */
    --control-h: 2.8125rem;
    --icon-btn: 2.75rem;

    --transition: 180ms ease;

    /*
     * Type ladder. The reference runs a 1.3 heading scale over a 16px body, so
     * the heading steps are not round numbers — they are that scale's output,
     * kept exact rather than rounded to a tidier-looking ramp.
     */
    --fs-caption: 0.75rem;      /* 12px   — labels, meta chips           */
    --fs-meta: 0.8125rem;       /* 13px   — struck-through was-price     */
    --fs-nav: 0.875rem;         /* 14px   — nav links, footer links      */
    --fs-control: 0.9375rem;    /* 15px   — button labels                */
    --fs-body: 1rem;            /* 16px   — body copy, sale price        */
    --fs-lead: 1.125rem;        /* 18px   — intro paragraphs             */
    --fs-card: 1.4625rem;       /* 23.4px — card + footer headings       */
    --fs-sub: 1.5rem;
    --fs-block: 1.75rem;
    --fs-section: 1.95rem;      /* 31.2px — section titles               */
    --fs-hero: 3rem;

    /* The reference gutters at 50px on desktop — wide, and a large part of why
       the grid reads as premium rather than cramped. */
    --gutter: 3.125rem;
    --block-space: 2.25rem;
    --grid-gap: 1.25rem;

    /* body copy runs loose: 28.8px on 16px */
    --leading: 1.8;
}

@media (max-width: 1023px) {
    :root {
        --gutter: 1.5rem;
    }
}

@media (max-width: 767px) {
    :root {
        --gutter: 1rem;
        --block-space: 1.75rem;
        --grid-gap: 0.75rem;
        --fs-section: 1.5rem;
        --fs-card: 1.125rem;
        --fs-hero: 2rem;
        --header-row-h: 3.5rem;
        --navstrip-h: 0rem;
    }
}

/* ------------------------------------------------------------------ base */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--font-main);
    color: var(--color-text-soft);
    background: var(--color-bg);
    line-height: var(--leading);
    font-size: var(--fs-body);
    /* Nothing may widen the page: stray overflow clips instead of adding a
       horizontal scrollbar on small screens. `clip` (unlike `hidden`) creates
       no scroll container, so the sticky header keeps working. */
    overflow-x: clip;
}

/*
 * The same rule again, on the wrapper — and it is the one that actually works.
 *
 * `overflow` on <body> does not clip the body's own content while <html> is
 * `visible`: it PROPAGATES to the viewport, and the body itself then computes
 * to `visible`. So the declaration above quietly clips nothing, and the page
 * measures wider than the viewport inside a phone at every breakpoint — a real
 * horizontal overflow, visible as a gutter down the RTL start edge.
 *
 * What overflows is the reveal system below (`[data-reveal]`), by design: an
 * un-revealed card sits translated off its resting place, and a translation
 * counts toward scrollable overflow until the element scrolls into view and
 * settles. Every below-the-fold section therefore widened the document until
 * it had been reached — which is also why the overflow was the same 26-32px on
 * a 1280px display as on a 360px phone.
 *
 * .app-inner is a plain element, so the value applies to it rather than
 * propagating anywhere. `clip` rather than `hidden` for the reason above: it
 * creates no scroll container, so `position: sticky` still resolves against the
 * viewport. Nothing here establishes a containing block for fixed descendants
 * either, so the off-canvas drawer and the bottom bar still escape it.
 */
.app-inner { overflow-x: clip; }

img { max-width: 100%; height: auto; }

/* Content imagery shows a quiet surface, not a white flash, while loading.
   (Product cards already get this from their media box.) */
.hero-slider__img,
.photo-tile img,
.article-card > img {
    background: var(--color-surface);
}

/*
 * Headings carry the ink at full strength while body copy sits at 75%. That
 * one-step contrast is what separates a heading from its paragraph here —
 * at this scale no size jump is large enough to do it alone.
 */
h1, h2, h3, h4 {
    line-height: 1.23;
    margin-block: 0 0.6em;
    font-weight: 700;
    color: var(--color-text);
    text-wrap: balance;
}

h1 { font-size: clamp(1.6rem, 1.25rem + 1.4vw, 2.25rem); }
h2 { font-size: clamp(1.35rem, 1.1rem + 1vw, var(--fs-section)); }
h3 { font-size: var(--fs-card); }
h4 { font-size: var(--fs-lead); }

a { color: var(--color-primary); }

:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
    border-radius: 2px;
}

::selection {
    background: color-mix(in srgb, var(--color-primary) 18%, var(--color-bg));
}

.container {
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.skip-link {
    position: absolute;
    inset-inline-start: 0;
    top: -100%;
    background: var(--color-primary);
    color: var(--color-on-primary);
    padding: 0.5rem 1rem;
    z-index: 100;
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.skip-link:focus { top: 0; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* --------------------------------------------------------------- buttons */

/*
 * One control height (45px) and one control radius (12px) across the theme.
 * Buttons are NOT uppercased and NOT bold in the reference — they sit at 15px
 * regular weight. The restraint is deliberate: against a navy this dark, a
 * bold caps label reads as shouting.
 */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: var(--control-h);
    padding: 0.5rem 1.875rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-decoration: none;
    font: inherit;
    font-size: var(--fs-control);
    font-weight: 500;
    line-height: 1.2;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.btn--primary {
    background: var(--color-primary);
    color: var(--color-on-primary);
}
/* Lightening rather than darkening on hover: #101631 is close enough to black
   that --color-primary-dark is indistinguishable from it in motion. */
.btn--primary:hover { background: var(--color-primary-light); }

/*
 * Secondary is a filled tile, not an outline. Its fill is `transparent`, so it
 * picks up whichever band it sits on: on a white section it reads as an
 * outlined button, on the grey band as a recessed one — one rule, both looks.
 */
.btn--outline,
.btn--secondary {
    background: transparent;
    border-color: var(--color-border);
    color: var(--color-text);
}
.btn--outline:hover,
.btn--secondary:hover {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-on-primary);
}

/* The inverse pair — cream on navy grounds, where a navy button would vanish. */
.btn--cream {
    background: var(--color-cream);
    color: var(--color-primary);
}
.btn--cream:hover { background: #e8d5bb; }

.btn--block { width: 100%; }

/* Press feedback: a 1px settle while the button is held. */
.btn:active:not([disabled]) { transform: translateY(1px); }

.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

.btn.is-added { background: var(--color-primary-light); }

/* ==== SDK COMPONENT CLASSES — generated, do not edit (see sync-theme-css.mjs) ==== */
/*
    Every class the SDK components render, copied from the SDK source so it is
    searchable here. The SDK ships the same rules inside @layer falak; this
    unlayered copy takes precedence but is identical, so nothing changes until
    you override a rule in the "platform components" section that follows.
    Because this copy is unlayered, an override must match the copied rule's
    specificity (e.g. two classes beat one) — unlike the SDK's layered sheet.
    Regenerate after an SDK update:
      node packages/falak-components/scripts/sync-theme-css.mjs <this file>
*/

/* ---- from packages/falak-components/src/components.css ---- */

/*
    FalakCart storefront components — default stylesheet.

    Linked at head:start for every storefront render — before the theme's own
    stylesheet and inside `@layer falak` (see styles.css) — so components are
    styled in any theme without the theme author doing anything, and any rule
    the theme writes wins over these.

    Everything here derives from the brand tokens master.twig already emits
    (--color-primary, --color-text, --font-main, ...), with fallbacks for each,
    so a merchant's colour choice restyles the components exactly as it
    restyles the theme's own markup. Themes override any rule by writing a
    plain selector in their own app.css — these are light-DOM elements with no
    shadow root, so nothing needs piercing and nothing needs !important.

    Tailwind-based themes need nothing extra: every value here derives from
    CSS custom properties, so a merchant palette reaches these components the
    same way it reaches the theme own markup.

    RTL-first, like the reference theme: logical properties throughout.
*/

/* ------------------------------------------------------------------ tokens */

:root {
    --f-radius: var(--radius-sm, 0.5rem);
    --f-border: var(--color-border, #e8eaef);
    --f-surface: var(--color-surface, #ffffff);
    --f-text: var(--color-text, #1f2430);
    --f-text-soft: var(--color-text-soft, #6b7280);
    --f-text-faint: var(--color-text-faint, #9aa1ad);
    --f-danger: var(--color-danger, #c0392b);
    --f-star: #facc15;
    --f-star-empty: #e2e5ea;
}

/*
    Components stay invisible until the SDK upgrades them (base.js sets
    data-falak on connect), so a slow bundle shows nothing rather than a flash
    of raw content and unstyled attributes.

    The list is deliberate rather than every falak-* element. It names only the
    components whose pre-upgrade DOM is *wrong*:

      - the first four render their own markup, so before upgrade they are
        either empty or showing unformatted attributes;
      - an accordion body holds author content that has no collapsed state yet,
        so it would appear expanded and then snap shut;
      - a modal holds author content with no dialog around it yet, so it would
        render inline at the foot of the page.

    Anything not listed is correct before upgrade and must stay visible —
    <falak-menu> in particular wraps server-rendered navigation, and hiding it
    would undo the very reason that markup is server-rendered.
*/
falak-quantity-input:not([data-falak]),
falak-rating-stars:not([data-falak]),
falak-product-card:not([data-falak]),
falak-products-list:not([data-falak]),
falak-accordion-body:not([data-falak]),
falak-modal:not([data-falak]) {
    visibility: hidden;
}

/* A modal must not occupy layout before it becomes a dialog. */
falak-modal:not([data-falak]) { display: none; }

falak-accordion,
falak-accordion-head,
falak-accordion-body,
falak-product-card,
falak-products-list {
    display: block;
}

/* --------------------------------------------------------- quantity input */

.f-qty {
    display: inline-flex;
    align-items: center;
    background: var(--f-surface);
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    overflow: hidden;
}

.f-qty__step {
    inline-size: 2.25rem;
    block-size: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: none;
    font: inherit;
    font-size: 1.05rem;
    line-height: 1;
    color: var(--f-text-soft);
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.f-qty__step:hover:not(:disabled) { background: rgba(0, 0, 0, 0.04); }
.f-qty__step:disabled { opacity: 0.35; cursor: default; }

.f-qty__input {
    inline-size: 3rem;
    block-size: 2.25rem;
    padding: 0;
    text-align: center;
    font: inherit;
    font-size: 0.85rem;
    color: var(--f-text);
    background: transparent;
    border: 0;
    border-inline: 1px solid var(--f-border);
}

.f-qty__input:focus { outline: none; }

/* --------------------------------------------------------------- accordion */

.f-accordion {
    display: flex;
    flex-direction: column;
    inline-size: 100%;
    background: var(--f-surface);
    border-radius: var(--f-radius);
}

.f-accordion--bordered { border: 1px solid var(--f-border); }

.f-accordion__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    font-weight: 600;
    color: var(--f-text);
    cursor: pointer;
    user-select: none;
}

.f-accordion--sm .f-accordion__head { padding: 0.5rem 0.75rem; font-size: 0.85rem; }
.f-accordion--lg .f-accordion__head { padding: 1.25rem 1.5rem; font-size: 1.05rem; }

.f-accordion__head[role='button']:focus-visible {
    outline: 2px solid var(--color-primary, #1d9e75);
    outline-offset: -2px;
    border-radius: var(--f-radius);
}

.f-accordion__icon {
    flex: none;
    inline-size: 1.5rem;
    block-size: 1.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: var(--f-text-soft);
    font-size: 1rem;
    line-height: 1;
}

.f-accordion__body {
    padding: 0 1rem 1rem;
    font-size: 0.875rem;
    line-height: 1.7;
    color: var(--f-text-soft);
}

/* The one rule that makes the accordion an accordion. */
.f-accordion__body[data-collapsed='true'] { display: none; }

/* ------------------------------------------------------------------- stars */

.f-stars {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.f-stars__set {
    display: inline-flex;
    align-items: center;
    gap: 0.0625rem;
}

/*
    Two stacked glyphs with the top one clipped to a width percentage, so a 4.2
    rating renders a genuinely 20%-filled fifth star instead of being rounded
    to the nearest half-star image.
*/
.f-stars__star {
    position: relative;
    display: inline-block;
    inline-size: 1rem;
    block-size: 1rem;
    line-height: 1;
    cursor: default;
}

.f-stars__star::before {
    content: '\2605';
    position: absolute;
    inset: 0;
    color: var(--f-star-empty);
}

.f-stars__fill {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    inline-size: var(--f-star-fill, 0%);
    overflow: hidden;
    color: var(--f-star);
    font-style: normal;
    line-height: 1;
}

.f-stars__fill::before { content: '\2605'; }

.f-stars[role='radiogroup'] .f-stars__star { cursor: pointer; }
.f-stars[role='radiogroup'] .f-stars__star:focus-visible {
    outline: 2px solid var(--color-primary, #1d9e75);
    outline-offset: 2px;
}

.f-stars__value { font-size: 0.85rem; font-weight: 700; color: var(--f-text); }
.f-stars__count { font-size: 0.75rem; color: var(--f-text-faint); }

falak-rating-stars[data-busy] { opacity: 0.5; }

/* -------------------------------------------------------------- product card */

.f-card { block-size: 100%; }

.f-card__inner {
    display: flex;
    flex-direction: column;
    block-size: 100%;
    background: var(--f-surface);
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    overflow: hidden;
    transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.f-card__inner:hover {
    box-shadow: 0 6px 20px rgba(15, 23, 42, 0.08);
    transform: translateY(-2px);
}

.f-card__media {
    position: relative;
    display: block;
    aspect-ratio: 1;
    background: rgba(0, 0, 0, 0.03);
    overflow: hidden;
}

.f-card__media img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

.f-card__placeholder { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.05); }

/*
 * Video commerce. Every rule here is keyed on .f-card__video, an element that
 * only exists when a card was explicitly asked for a clip (its own `video`
 * attribute, or a [data-video-commerce] ancestor) AND the product has one. A
 * card that is not showing video matches none of this, so adding it changes
 * nothing about how any existing card in any theme renders.
 */
/* The still sits UNDER the clip and fills the same box, so the swap from one to
   the other is invisible. Absolute, because the clip must be able to lie over
   it rather than push it out of the way. */
.f-card__still {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

.f-card__video {
    position: relative;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
    /* Transparent on purpose: a background here would paint over the still
       while the clip is still arriving, which is the whole point of having
       one. */
    background: transparent;
}

.f-card__video-badge {
    position: absolute;
    inset-block-end: 0.5rem;
    inset-inline-start: 0.5rem;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    background: rgb(0 0 0 / 55%);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.6;
    pointer-events: none;
}

.f-card__badge {
    position: absolute;
    inset-block-start: 0.5rem;
    inset-inline-start: 0.5rem;
    padding: 0.125rem 0.5rem;
    border-radius: 0.25rem;
    background: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
    font-size: 0.7rem;
    font-weight: 700;
}

/* The percentage inside the sale badge, and the two marks the legacy card
   also carries: "hot" under the sale badge from 30% off, and the
   merchant's free-shipping promise in the bottom corner. Each has its own
   corner or offset so a product carrying all of them stacks nothing. */
.f-card__badge-pct { font-size: 0.85rem; font-weight: 800; margin-inline-end: 0.15rem; }
/* Sale and hot stack in one column at the start corner, so a theme that
   draws the sale badge larger (Onyx's hexagon) pushes hot down with it
   instead of under it. The badge stays a positioned box for Onyx's
   ::after, which fills it to centre the percentage. */
.f-card__marks { position: absolute; inset-block-start: 0.5rem; inset-inline-start: 0.5rem; display: flex; flex-direction: column; align-items: flex-start; gap: 0.3rem; }
.f-card__marks .f-card__badge { position: relative; inset: auto; }
.f-card__hot {
    position: relative;
    inset: auto;    padding: 0.125rem 0.5rem;
    border-radius: 0.25rem;
    background: linear-gradient(135deg, #f97316, #ea580c);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1.5;
}
.f-card__ship {
    position: absolute;
    inset-block-end: 0.5rem;
    inset-inline-end: 0.5rem;
    padding: 0.125rem 0.5rem;
    border-radius: 0.25rem;
    background: var(--f-success, #059669);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    line-height: 1.5;
}

/*
 * The special-offer ribbon. Opposite corner to .f-card__badge, because a
 * discounted product that is ALSO in an offer carries both and they must not
 * stack on top of each other.
 *
 * It names the offer; it never carries its value. See loadOffer() in
 * product-card.js for why.
 */
.f-card__offer {
    position: absolute;
    inset-block-start: 0.5rem;
    inset-inline-end: 0.5rem;
    max-inline-size: 65%;
    padding: 0.125rem 0.5rem;
    border-radius: 0.25rem;
    background: var(--f-danger, #c0392b);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1.5;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.f-card__body {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    padding: 0.75rem;
    flex-grow: 1;
}

.f-card__title {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.f-card__link {
    color: var(--f-text);
    text-decoration: none;
    transition: color 0.15s ease;
}

.f-card__link:hover { color: var(--color-primary, #1d9e75); }

.f-card__price {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin: auto 0 0;
    padding-block-start: 0.25rem;
}

.f-card__price-now { font-size: 1rem; font-weight: 700; color: var(--f-text); }
.f-card__price-was { font-size: 0.75rem; color: var(--f-text-faint); }
.f-card__stock { margin: 0; font-size: 0.75rem; font-weight: 600; color: var(--f-danger); }

.f-card__actions { display: flex; align-items: stretch; gap: 0.5rem; padding: 0 0.75rem 0.75rem; }
.f-card__actions:empty { display: none; }

/*
    The card's buy button. An outline that fills on hover, so a grid of
    cards reads as products first and buttons second; the theme restyles it
    through .f-card__add. The host is display:contents (see .f-add-product),
    so the button itself is the flex item and takes the remaining width.
*/
.f-card__add {
    flex: 1 1 auto;
    min-inline-size: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    min-block-size: 2.4rem;
    padding: 0.45rem 0.75rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: transparent;
    color: var(--f-text);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.16s ease, border-color 0.16s ease, color 0.16s ease;
}
.f-card__add > span { overflow: hidden; text-overflow: ellipsis; }
.f-card__add > svg { flex: none; }
.f-card__add:hover:not(:disabled) {
    background: var(--color-primary, #1d9e75);
    border-color: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
}
.f-card__add:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }
.f-card__add:disabled { opacity: 0.55; cursor: not-allowed; }

.f-card__wishlist {
    flex: none;
    inline-size: 2.4rem;
    min-block-size: 2.4rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: transparent;
    color: var(--f-text-soft);
    cursor: pointer;
    transition: border-color 0.16s ease, color 0.16s ease;
}
.f-card__wishlist:hover { border-color: var(--color-primary, #1d9e75); color: var(--color-primary, #1d9e75); }
.f-card__wishlist.is-active { color: var(--f-danger); border-color: var(--f-danger); }

.f-card--out-of-stock .f-card__media { opacity: 0.6; }
.f-card--empty { display: none; }

.f-card--skeleton {
    border-radius: var(--f-radius);
    background: rgba(0, 0, 0, 0.05);
    aspect-ratio: 3 / 4;
    animation: f-pulse 1.4s ease-in-out infinite;
}

@keyframes f-pulse { 50% { opacity: 0.45; } }

/* ------------------------------------------------------------- products list */

.f-list { display: block; inline-size: 100%; }

.f-list__grid {
    display: grid;
    gap: 1rem;
    /* Column count is an element attribute, so density is a theme decision. */
    grid-template-columns: repeat(var(--f-list-columns, 4), minmax(0, 1fr));
}

@media (max-width: 1023px) {
    .f-list__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 639px) {
    .f-list__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.f-list__count { margin: 0 0 0.75rem; font-size: 0.8rem; color: var(--f-text-faint); }

.f-list__message {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 2.5rem 1rem;
    text-align: center;
    font-size: 0.875rem;
    color: var(--f-text-soft);
}

.f-list__retry {
    padding: 0.5rem 1rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--f-text);
    cursor: pointer;
}

.f-list__retry:hover { background: rgba(0, 0, 0, 0.04); }

.f-list[data-busy] .f-list__grid { opacity: 0.7; }

@media (prefers-reduced-motion: reduce) {
    .f-card__inner,
    .f-qty__step { transition: none; }
    .f-card__inner:hover { transform: none; }
    .f-card--skeleton { animation: none; }
}

/* ------------------------------------------------- product card variants */
/*
    Theme-raed's custom-salla-product-card vocabulary, as attributes:
    minimal · full-image · special · horizontal. Same data, four treatments.
*/

/* minimal: dense grids — image, title, price, nothing else */
.f-card--minimal .f-card__body { padding: 0.5rem 0.25rem 0.25rem; gap: 0.2rem; }
.f-card--minimal .f-card__inner { border: 0; background: transparent; }
.f-card--minimal .f-card__inner:hover { box-shadow: none; transform: none; }
.f-card--minimal .f-card__media { border-radius: var(--f-radius); }

/* full-image: the image is the card; title and price sit over its foot */
.f-card--full-image .f-card__inner { position: relative; border: 0; }
.f-card--full-image .f-card__media { aspect-ratio: 3 / 4; }

.f-card--full-image .f-card__body {
    position: absolute;
    inset-block-end: 0;
    inset-inline: 0;
    padding: 2rem 0.9rem 0.9rem;
    gap: 0.15rem;
    background: linear-gradient(to top, rgba(10, 14, 12, 0.78), transparent);
}

.f-card--full-image .f-card__link,
.f-card--full-image .f-card__price-now { color: #fff; }
.f-card--full-image .f-card__price-was { color: rgba(255, 255, 255, 0.72); }

/* special: the featured slot — stronger frame + remaining-stock urgency */
.f-card--special .f-card__inner {
    border: 2px solid var(--color-primary, #1d9e75);
}

.f-card__remaining {
    margin: 0;
    align-self: flex-start;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--color-primary, #1d9e75) 12%, transparent);
    color: var(--color-primary, #1d9e75);
    font-size: 0.7rem;
    font-weight: 700;
}

/* horizontal: image beside content — search results, compact lists */
.f-card--horizontal .f-card__inner { flex-direction: row; align-items: stretch; }
.f-card--horizontal .f-card__media { flex: none; inline-size: 7.5rem; aspect-ratio: 1; }
.f-card--horizontal .f-card__body { justify-content: center; }

/* ========================================================================
   Add-product button
   The host is display:contents so the inner <button> takes the host's place
   in whatever flex/grid row the theme laid out (a card's action row, the
   product page's CTA row); the theme skins the button via `button-class`.
   ======================================================================== */

.f-add-product { display: contents; }
.f-add-product[hidden] { display: none; }
.f-add-product[aria-busy="true"] .f-add-product__button { opacity: 0.7; cursor: progress; }
.f-add-product__button:disabled { cursor: not-allowed; }

/* ========================================================================
   Cart summary — the header's cart entry: icon, count, total
   ======================================================================== */

.f-cart-summary { display: inline-block; }
.f-cart-summary[hidden] { display: none; }

.f-cart-summary__link {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    color: inherit;
    text-decoration: none;
}

.f-cart-summary__icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.4rem;
    block-size: 2.4rem;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: inherit;
}

.f-cart-summary__icon.is-bumped { animation: f-cart-bump 0.5s ease; }

.f-cart-summary__count {
    position: absolute;
    inset-block-start: -0.25rem;
    inset-inline-end: -0.25rem;
    min-inline-size: 1.2rem;
    block-size: 1.2rem;
    padding-inline: 0.3rem;
    border-radius: 999px;
    background: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1.2rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.f-cart-summary__count[hidden] { display: none; }

.f-cart-summary__content { display: flex; flex-direction: column; line-height: 1.15; }
.f-cart-summary__label { font-size: 0.7rem; color: var(--f-text-soft); }
.f-cart-summary__total { font-size: 0.85rem; font-weight: 700; color: var(--f-text); font-variant-numeric: tabular-nums; }

/* The product picture in flight (see animateToCart). */
.f-cart-thumb { position: fixed; pointer-events: none; z-index: 99999; }

@keyframes f-cart-bump {
    0% { transform: scale(1); }
    30% { transform: scale(1.25, 0.8); }
    50% { transform: scale(0.85, 1.15); }
    70% { transform: scale(1.1, 0.95); }
    100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .f-cart-summary__icon.is-bumped { animation: none; }
}

/* ========================================================================
   Cart coupons — input + apply/remove, applied chip, coupon cards
   ======================================================================== */

.f-cart-coupons { display: block; }

/* <falak-cart-offers>: the cart page's offer tracker. One card per offer the
   cart is measured against — unlocked ones tinted and ticked, locked ones
   neutral with a progress bar. */
.f-cart-offers { display: block; margin-block-end: 1rem; }
.f-offer-track { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.f-offer-track__card { border: 1.5px solid var(--f-border); border-radius: calc(var(--f-radius) * 1.4); background: var(--f-surface); padding: 0.8rem 0.9rem; transition: border-color 0.3s ease, background-color 0.3s ease; }
.f-offer-track__card.is-unlocked { border-color: color-mix(in srgb, var(--f-success, #16a34a) 35%, transparent); background: color-mix(in srgb, var(--f-success, #16a34a) 7%, var(--f-surface)); }
.f-offer-track__top { display: flex; align-items: center; gap: 0.65rem; }
.f-offer-track__icon { flex: none; display: inline-flex; align-items: center; justify-content: center; inline-size: 2.25rem; block-size: 2.25rem; border-radius: 0.65rem; background: color-mix(in srgb, var(--color-primary, #1d9e75) 12%, transparent); color: var(--color-primary, #1d9e75); }
.f-offer-track__card.is-unlocked .f-offer-track__icon { background: color-mix(in srgb, var(--f-success, #16a34a) 14%, transparent); color: var(--f-success, #16a34a); }
.f-offer-track__text { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.f-offer-track__title { font-size: 0.9rem; font-weight: 700; color: var(--f-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f-offer-track__sub { font-size: 0.8rem; color: var(--f-text-soft); }
.f-offer-track__card.is-unlocked .f-offer-track__sub { color: var(--f-success, #16a34a); font-weight: 600; }
.f-offer-track__state { flex: none; display: inline-flex; color: var(--f-text-faint); }
.f-offer-track__card.is-unlocked .f-offer-track__state { color: var(--f-success, #16a34a); }
.f-offer-track__bar { margin-block-start: 0.6rem; block-size: 6px; border-radius: 999px; background: color-mix(in srgb, var(--f-text) 8%, transparent); overflow: hidden; }
.f-offer-track__fill { display: block; block-size: 100%; border-radius: inherit; background: var(--color-primary, #1d9e75); transition: inline-size 0.4s ease; }
.f-cart-coupons[hidden] { display: none; }
.f-cart-coupons__label { display: block; margin-block-end: 0.4rem; font-size: 0.85rem; font-weight: 600; color: var(--f-text); }
.f-cart-coupons__row { display: flex; gap: 0.5rem; }

.f-cart-coupons__input {
    flex: 1 1 auto;
    min-inline-size: 0;
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    letter-spacing: 0.03em;
}
.f-cart-coupons__input:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 1px; }
.f-cart-coupons__input:disabled { opacity: 0.75; }
.f-cart-coupons__input.is-invalid { border-color: var(--f-danger); }
.f-cart-coupons__button { flex: none; min-inline-size: 5.5rem; }
.f-cart-coupons__button[data-coupon-remove] { min-inline-size: 2.75rem; padding-inline: 0.75rem; }

.f-cart-coupons__error { margin: 0.45rem 0 0; font-size: 0.82rem; color: var(--f-danger); }
.f-cart-coupons__error[hidden] { display: none; }

.f-cart-coupons__applied {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-block-start: 0.6rem;
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--f-border);
    border-inline-start: 3px solid var(--color-primary, #1d9e75);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    font-size: 0.85rem;
}
.f-cart-coupons__code { font-weight: 700; letter-spacing: 0.04em; color: var(--f-text); }
.f-cart-coupons__code::before {
    content: "";
    display: inline-block;
    inline-size: 0.45rem;
    block-size: 0.45rem;
    margin-inline-end: 0.4rem;
    border-radius: 50%;
    background: var(--color-primary, #1d9e75);
    vertical-align: middle;
}
.f-cart-coupons__applied-note { color: var(--f-text-soft); }

.f-cart-coupons__slider { display: block; margin-block-start: 1rem; }

/* Ticket-style card; the notches are the card background on purpose. */
.f-coupon-card {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--f-border);
    border-radius: calc(var(--f-radius) * 1.2);
    background: var(--f-surface);
    cursor: pointer;
    transition: border-color 0.16s ease, transform 0.16s ease;
}
.f-coupon-card:hover { border-color: var(--color-primary, #1d9e75); transform: translateY(-1px); }
.f-coupon-card:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }
.f-coupon-card--disabled { cursor: not-allowed; opacity: 0.55; }
.f-coupon-card--disabled:hover { border-color: var(--f-border); transform: none; }
.f-coupon-card--current { border-color: var(--color-primary, #1d9e75); }

.f-coupon-card__top { padding: 0.85rem 0.9rem 0.6rem; }
.f-coupon-card__amount { font-size: 1.2rem; font-weight: 800; color: var(--color-primary, #1d9e75); line-height: 1.1; }
.f-coupon-card__secondary { font-size: 0.75rem; color: var(--f-text-soft); margin-block-start: 0.15rem; }
.f-coupon-card__code {
    display: inline-block;
    margin-block-start: 0.5rem;
    padding: 0.2rem 0.5rem;
    border: 1px dashed var(--color-primary, #1d9e75);
    border-radius: 4px;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--f-text);
}
.f-coupon-card__divider {
    position: relative;
    block-size: 0;
    border-block-start: 1px dashed var(--f-border);
    margin-inline: 0.6rem;
}
.f-coupon-card__divider::before,
.f-coupon-card__divider::after {
    content: "";
    position: absolute;
    inset-block-start: -0.5rem;
    inline-size: 1rem;
    block-size: 1rem;
    border-radius: 50%;
    background: var(--color-bg, #f0f0f0);
    border: 1px solid var(--f-border);
}
.f-coupon-card__divider::before { inset-inline-start: -1.1rem; }
.f-coupon-card__divider::after { inset-inline-end: -1.1rem; }

.f-coupon-card__bottom { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 0.35rem 0.5rem; padding: 0.6rem 0.9rem 0.8rem; }
.f-coupon-card__terms { font-size: 0.72rem; color: var(--f-text-soft); line-height: 1.4; }
.f-coupon-card__expiry.is-soon { color: var(--f-danger); font-weight: 600; }
.f-coupon-card__action { flex: none; margin-inline-start: auto; font-size: 0.78rem; font-weight: 700; white-space: nowrap; color: var(--color-primary, #1d9e75); }
.f-coupon-card--disabled .f-coupon-card__action { color: var(--f-text-soft); }

@media (prefers-reduced-motion: reduce) {
    .f-coupon-card:hover { transform: none; }
}

/* ========================================================================
   Product options — variant pills
   ======================================================================== */

.f-options { display: flex; flex-direction: column; gap: 0.9rem; }
.f-options[hidden] { display: none; }
.f-options__group { display: flex; flex-direction: column; gap: 0.45rem; }
.f-options__label { display: flex; align-items: baseline; gap: 0.4rem; font-size: 0.85rem; color: var(--f-text-soft); }
.f-options__name { font-weight: 600; color: var(--f-text); }
.f-options__name::after { content: ":"; }
.f-options__chosen { color: var(--f-text); }
.f-options__hint { font-size: 0.8rem; }
.f-options__group--invalid .f-options__hint { color: var(--f-danger); font-weight: 600; }
.f-options__pills { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.f-options__pill {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 2.75rem;
    min-block-size: 2.25rem;
    padding: 0.35rem 0.85rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}
.f-options__pill:hover:not(:disabled) { border-color: var(--color-primary, #1d9e75); }
.f-options__pill:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }
.f-options__pill.is-selected {
    border-color: var(--color-primary, #1d9e75);
    background: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
}
.f-options__pill:disabled { cursor: not-allowed; color: var(--f-text-faint); background: transparent; }
.f-options__pill--out_of_stock::after,
.f-options__pill--impossible::after {
    content: "";
    position: absolute;
    inset-inline: 0.4rem;
    inset-block-start: 50%;
    border-block-start: 1px solid currentColor;
    transform: rotate(-12deg);
    opacity: 0.7;
}
.f-options__group--invalid .f-options__pill:not(.is-selected) { border-color: var(--f-danger); }
.f-options__error { margin: 0; font-size: 0.82rem; color: var(--f-danger); }
.f-options__error[hidden] { display: none; }

/*
 * A `color` or `image` option's pill: the swatch IS the label, so the pill
 * shrinks to it and the selected state becomes a ring rather than the solid
 * primary fill the text pills use — that fill would paint over the very
 * colour the shopper is choosing.
 */
.f-options__pill--swatch {
    min-inline-size: 0;
    min-block-size: 0;
    padding: 0.2rem;
    border-radius: 50%;
}
.f-options__pill--swatch.is-selected {
    background: var(--f-surface);
    color: var(--f-text);
    box-shadow: 0 0 0 2px var(--color-primary, #1d9e75) inset;
}
.f-options__pill--image { border-radius: var(--f-radius); }

/*
 * The swatch carries its OWN shape rather than inheriting the pill's. Themes
 * reshape `.f-options__pill` freely — every one of them squares it off on the
 * product page — and an inherited radius would turn each colour circle into a
 * rounded rectangle wherever they did.
 */
.f-options__swatch {
    display: block;
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border-radius: 50%;
    /* A white or near-white swatch would otherwise vanish into the pill. */
    box-shadow: 0 0 0 1px rgb(0 0 0 / 12%) inset;
}
.f-options__pill--image .f-options__swatch {
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border-radius: var(--f-radius);
}
.f-options__swatch--image { object-fit: cover; }

/* The strike-through marking an unbuyable value has to sit ABOVE the swatch. */
.f-options__pill--swatch.f-options__pill--out_of_stock::after,
.f-options__pill--swatch.f-options__pill--impossible::after {
    inset-inline: 0;
    z-index: 1;
    border-block-start-color: var(--f-danger);
    border-block-start-width: 2px;
    opacity: 0.9;
}
.f-options__pill--swatch:disabled { opacity: 0.45; }

/* A group with more values than pills can carry. */
.f-options__select {
    inline-size: 100%;
    max-inline-size: 22rem;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.9rem;
    cursor: pointer;
}
.f-options__select:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }
.f-options__select option:disabled { color: var(--f-text-faint); }
.f-options__group--invalid .f-options__select { border-color: var(--f-danger); }

/* ========================================================================
   Quick add — variant chooser dialog for cards
   ======================================================================== */

.f-quick-add__product { display: flex; align-items: center; gap: 0.9rem; margin-block-end: 1rem; }
.f-quick-add__image {
    flex: none;
    inline-size: 4.5rem;
    block-size: 4.5rem;
    border-radius: var(--f-radius);
    object-fit: cover;
    background: rgba(0, 0, 0, 0.05);
}
.f-quick-add__meta { display: flex; flex-direction: column; gap: 0.25rem; min-inline-size: 0; }
.f-quick-add__eyebrow { font-size: 0.78rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--f-text-soft); }
.f-quick-add__name { font-weight: 600; color: var(--f-text); text-decoration: none; }
.f-quick-add__name:hover { color: var(--color-primary, #1d9e75); }
.f-quick-add__prices { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.5rem; }
.f-quick-add__price { font-size: 1rem; color: var(--f-text); }
.f-quick-add__compare { font-size: 0.9rem; color: var(--f-text-faint); }
.f-quick-add__save {
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: rgba(192, 57, 43, 0.1);
    color: var(--f-danger);
    font-size: 0.75rem;
    font-weight: 700;
}
/* Every optional row is rendered hidden until it has something to say, so
   the dialog never reserves space for a line the product has no data for. */
.f-quick-add__compare[hidden],
.f-quick-add__save[hidden],
.f-quick-add__stock[hidden] { display: none; }
.f-quick-add__form { display: flex; flex-direction: column; gap: 1rem; }
.f-quick-add__stock { margin: 0; font-size: 0.85rem; color: var(--f-text-soft); }
.f-quick-add__stock--out { color: var(--f-danger); }
.f-quick-add__actions { display: flex; align-items: stretch; gap: 0.75rem; }
.f-quick-add__actions .f-add-product__button { flex: 1 1 auto; }
.f-quick-add__footnote {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    font-size: 0.8rem;
    color: var(--f-text-soft);
}
.f-quick-add__details { color: inherit; }

/* ========================================================================
   Wishlist button — the heart
   ======================================================================== */

.f-wishlist { display: contents; }
.f-wishlist[hidden] { display: none; }

.f-wishlist__button { color: var(--f-text-soft); }
.f-wishlist__button:hover:not(:disabled) { color: var(--f-danger); border-color: var(--f-danger); }
.f-wishlist__button.is-added { color: var(--f-danger); border-color: var(--f-danger); }
.f-wishlist__button.is-added .f-wishlist__icon { fill: currentColor; }
.f-wishlist__button.is-pulsing .f-wishlist__icon { animation: f-heart 0.45s ease; }
.f-wishlist__label { margin-inline-start: 0.4rem; font-size: 0.85rem; font-weight: 600; }

/* The card's square, matching .f-card__add's height. */
.f-card__wishlist.is-added { color: var(--f-danger); border-color: var(--f-danger); }
.f-card__wishlist.is-added .f-wishlist__icon { fill: currentColor; }

@keyframes f-heart {
    0% { transform: scale(1); }
    35% { transform: scale(1.35); }
    70% { transform: scale(0.9); }
    100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .f-wishlist__button.is-pulsing .f-wishlist__icon { animation: none; }
}

/* ========================================================================
   Drawer — the off-canvas panel (wishlist drawer uses it)
   ======================================================================== */

.f-wishlist-drawer { display: inline-block; }
.f-wishlist-drawer[hidden] { display: none; }
body.f-drawer-open { overflow: hidden; }

.f-wishlist-drawer__trigger {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.4rem;
    block-size: 2.4rem;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: inherit;
    cursor: pointer;
}
.f-wishlist-drawer__trigger:hover { color: var(--f-danger); }
.f-wishlist-drawer__trigger:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }

.f-search { display: inline-flex; }

.f-search__trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.4rem;
    block-size: 2.4rem;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: inherit;
    cursor: pointer;
}
.f-search__trigger:hover { color: var(--color-primary, #1d9e75); }
.f-search__trigger:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }

.f-wishlist-drawer__count {
    position: absolute;
    inset-block-start: -0.25rem;
    inset-inline-end: -0.25rem;
    min-inline-size: 1.2rem;
    block-size: 1.2rem;
    padding-inline: 0.3rem;
    border-radius: 999px;
    background: var(--f-danger);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1.2rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.f-wishlist-drawer__count[hidden] { display: none; }

.f-drawer__backdrop {
    position: fixed;
    inset: 0;
    z-index: 1090;
    background: rgba(8, 14, 12, 0.5);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, visibility 0.2s ease;
}

.f-drawer {
    position: fixed;
    inset-block: 0;
    inset-inline-end: 0;
    z-index: 1100;
    inline-size: min(26rem, 100vw);
    display: flex;
    flex-direction: column;
    background: var(--f-surface);
    color: var(--f-text);
    box-shadow: -12px 0 40px rgba(8, 14, 12, 0.18);
    transform: translateX(100%);
    visibility: hidden;
    transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1), visibility 0.28s;
}
[dir="rtl"] .f-drawer { transform: translateX(-100%); }
.f-wishlist-drawer--start .f-drawer { inset-inline-end: auto; inset-inline-start: 0; transform: translateX(-100%); }
[dir="rtl"] .f-wishlist-drawer--start .f-drawer { transform: translateX(100%); }

.f-wishlist-drawer[open] .f-drawer { transform: translateX(0); visibility: visible; }
.f-wishlist-drawer[open] .f-drawer__backdrop { opacity: 1; visibility: visible; }

.f-drawer__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1rem 1.25rem;
    border-block-end: 1px solid var(--f-border);
}
.f-drawer__title { margin: 0; font-size: 1.05rem; font-weight: 700; display: flex; align-items: center; gap: 0.5rem; }
.f-drawer__badge {
    min-inline-size: 1.4rem;
    padding: 0 0.4rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.06);
    font-size: 0.75rem;
    text-align: center;
    line-height: 1.4rem;
}
.f-drawer__close {
    inline-size: 2rem;
    block-size: 2rem;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: var(--f-text-soft);
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
}
.f-drawer__close:hover { background: rgba(0, 0, 0, 0.1); }
.f-drawer__body { flex: 1 1 auto; overflow-y: auto; padding: 0.5rem 1.25rem; }
.f-drawer__foot { padding: 1rem 1.25rem; border-block-start: 1px solid var(--f-border); }
.f-drawer__loading { display: flex; justify-content: center; padding: 2rem; }
.f-drawer__empty { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 3rem 1rem; color: var(--f-text-soft); text-align: center; }
.f-drawer__empty-icon { color: var(--f-text-faint); }
.f-drawer__empty-icon svg { inline-size: 2.5rem; block-size: 2.5rem; }

.f-wishlist-drawer__list { list-style: none; margin: 0; padding: 0; }
.f-wishlist-drawer__item {
    display: flex;
    gap: 0.9rem;
    padding: 0.9rem 0;
    border-block-end: 1px solid var(--f-border);
}
.f-wishlist-drawer__item:last-child { border-block-end: 0; }
.f-wishlist-drawer__media { flex: none; inline-size: 4.5rem; block-size: 4.5rem; border-radius: var(--f-radius); overflow: hidden; background: rgba(0, 0, 0, 0.05); }
.f-wishlist-drawer__media img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.f-wishlist-drawer__info { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.f-wishlist-drawer__name {
    font-weight: 600;
    color: var(--f-text);
    text-decoration: none;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.f-wishlist-drawer__name:hover { color: var(--color-primary, #1d9e75); }
.f-wishlist-drawer__price { margin: 0; font-size: 0.9rem; font-weight: 700; }
.f-wishlist-drawer__price del { margin-inline-start: 0.35rem; font-weight: 400; color: var(--f-text-faint); }
.f-wishlist-drawer__actions { display: flex; align-items: center; gap: 0.5rem; margin-block-start: 0.2rem; }
.f-wishlist-drawer__actions .f-add-product__button { flex: 1 1 auto; }

@media (prefers-reduced-motion: reduce) {
    .f-drawer, .f-drawer__backdrop { transition: none; }
}

/* ========================================================================
   Checkout — steps + summary column; payment status
   ======================================================================== */

.f-checkout { display: block; }
.f-checkout__layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(18rem, 24rem); gap: 2rem; align-items: start; }
@media (max-width: 899px) { .f-checkout__layout { grid-template-columns: minmax(0, 1fr); } .f-checkout__aside { order: -1; } }

.f-checkout__step { padding: 1.1rem 0; border-block-end: 1px solid var(--f-border); }
.f-checkout__step-head { display: flex; align-items: center; gap: 0.85rem; }
.f-checkout__step-icon {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.5rem;
    block-size: 2.5rem;
    border-radius: 50%;
    border: 1px solid var(--f-border);
    color: var(--f-text-soft);
    background: var(--f-surface);
}
.f-checkout__step-icon.is-active { color: var(--color-on-primary, #fff); background: var(--color-primary, #1d9e75); border-color: transparent; }
.f-checkout__step--done .f-checkout__step-icon { color: var(--color-primary, #1d9e75); border-color: var(--color-primary, #1d9e75); }
.f-checkout__step--todo { opacity: 0.55; }
.f-checkout__step-text { flex: 1 1 auto; min-inline-size: 0; }
.f-checkout__step-title { margin: 0; font-size: 1.05rem; font-weight: 700; }
.f-checkout__step-sub { color: var(--f-text-soft); }
.f-checkout__edit { flex: none; }
.f-checkout__done-line { margin: 0.5rem 0 0 3.35rem; font-size: 0.9rem; color: var(--f-text-soft); }
.f-checkout__body { display: flex; flex-direction: column; gap: 1rem; margin-block-start: 1rem; }
.f-checkout__hint { margin: 0; font-size: 0.85rem; color: var(--f-text-soft); }
/* The contact step of a digital order: phone + send-code side by side, the
   code row beneath, and the "we found your details" note. */
.f-checkout__phone-row { display: flex; gap: 0.5rem; align-items: stretch; }
.f-checkout__phone-row .f-input { flex: 1 1 auto; min-inline-size: 0; }
.f-checkout__phone-row .f-btn { flex: none; white-space: nowrap; }
.f-checkout__recognized { margin: 0; padding: 0.6rem 0.8rem; border-radius: var(--f-radius); background: color-mix(in srgb, var(--color-primary, #1d9e75) 10%, transparent); color: var(--f-text); font-size: 0.88rem; }
.f-checkout__otp { gap: 0.5rem; }
.f-checkout__otp-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.f-checkout [hidden] { display: none !important; }
.f-checkout__error { margin: 0; padding: 0.6rem 0.8rem; border-radius: var(--f-radius); background: color-mix(in srgb, var(--f-danger) 10%, transparent); color: var(--f-danger); font-size: 0.88rem; }
.f-checkout__loading { display: flex; justify-content: center; padding: 2rem; }

.f-checkout__methods { display: grid; gap: 0.6rem; }
.f-checkout__method {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.8rem 0.9rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.f-checkout__method:hover { border-color: var(--color-primary, #1d9e75); }
.f-checkout__method.is-selected { border-color: var(--color-primary, #1d9e75); box-shadow: 0 0 0 1px var(--color-primary, #1d9e75) inset; }
.f-checkout__method input { accent-color: var(--color-primary, #1d9e75); }
.f-checkout__method-logo { flex: none; inline-size: 3rem; block-size: 2rem; object-fit: contain; }
.f-checkout__method-logo--empty { display: inline-flex; align-items: center; justify-content: center; color: var(--f-text-faint); }
.f-checkout__method-text { display: flex; flex-direction: column; gap: 0.1rem; min-inline-size: 0; }
.f-checkout__method-text small { color: var(--f-text-soft); }
/* "You'll be charged 12.50 USD" — only under a method that settles in another currency. */
.f-checkout__charge-note { font-size: 0.78rem; color: var(--f-text-faint); font-variant-numeric: tabular-nums; }
.f-checkout__tag { color: var(--color-primary, #1d9e75) !important; font-weight: 600; }

.f-checkout__form { display: flex; flex-direction: column; gap: 0.9rem; }
.f-checkout__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.9rem; }
@media (max-width: 599px) { .f-checkout__grid { grid-template-columns: minmax(0, 1fr); } }
.f-field { display: flex; flex-direction: column; gap: 0.35rem; min-inline-size: 0; }
.f-field--wide { grid-column: 1 / -1; }
.f-field__label { font-size: 0.85rem; font-weight: 600; color: var(--f-text); }
.f-input {
    inline-size: 100%;
    padding: 0.6rem 0.8rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
}
.f-input:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 1px; }
.f-input:disabled { opacity: 0.6; }

.f-checkout__review { display: grid; gap: 0.6rem; margin: 0; }
.f-checkout__review div { display: grid; grid-template-columns: 9rem minmax(0, 1fr); gap: 0.5rem; font-size: 0.9rem; }
.f-checkout__review dt { color: var(--f-text-soft); }
.f-checkout__review dd { margin: 0; }
.f-checkout__total-line { margin: 0; font-size: 1rem; display: flex; justify-content: space-between; }

.f-checkout__signin { display: flex; flex-direction: column; align-items: flex-start; gap: 0.75rem; padding: 1.5rem; border: 1px solid var(--f-border); border-radius: var(--f-radius); background: var(--f-surface); }
.f-checkout__title { margin: 0; font-size: 1.2rem; }
.f-checkout__back { font-size: 0.85rem; color: var(--f-text-soft); }

.f-checkout__summary { position: sticky; inset-block-start: 1rem; padding: 1.1rem; border: 1px solid var(--f-border); border-radius: calc(var(--f-radius) * 1.4); background: var(--f-surface); display: flex; flex-direction: column; gap: 1rem; }
.f-checkout__summary-title { margin: 0; font-size: 1rem; display: flex; align-items: center; gap: 0.5rem; }
.f-checkout__count { min-inline-size: 1.4rem; padding: 0 0.4rem; border-radius: 999px; background: rgba(0, 0, 0, 0.06); font-size: 0.75rem; text-align: center; line-height: 1.4rem; }
.f-checkout__lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.7rem; max-block-size: 18rem; overflow-y: auto; }
.f-checkout__line { display: flex; align-items: center; gap: 0.7rem; }
.f-checkout__line-media { position: relative; flex: none; inline-size: 3.25rem; block-size: 3.25rem; border-radius: var(--f-radius); overflow: visible; background: rgba(0, 0, 0, 0.05); }
/* display: block — an inline img sits on the text baseline and adds descender
   space below itself, so the list overflowed its box by ~8px and grew a
   scrollbar even when every line fit. */
.f-checkout__line-media img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; border-radius: var(--f-radius); }
.f-checkout__line-qty { position: absolute; inset-block-start: -0.35rem; inset-inline-end: -0.35rem; min-inline-size: 1.2rem; block-size: 1.2rem; padding-inline: 0.3rem; border-radius: 999px; background: var(--f-text); color: var(--f-surface); font-size: 0.68rem; line-height: 1.2rem; text-align: center; }
.f-checkout__line-text { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; font-size: 0.85rem; }
.f-checkout__line-name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.f-checkout__line-text small { color: var(--f-text-soft); }
.f-checkout__line-total { flex: none; font-weight: 700; font-size: 0.85rem; }
.f-checkout__totals { display: flex; flex-direction: column; gap: 0.45rem; padding-block-start: 0.75rem; border-block-start: 1px solid var(--f-border); }
.f-checkout__row { display: flex; justify-content: space-between; font-size: 0.9rem; color: var(--f-text-soft); }
.f-checkout__row--discount { color: var(--color-primary, #1d9e75); }
.f-checkout__row--total { margin-block-start: 0.35rem; padding-block-start: 0.6rem; border-block-start: 1px solid var(--f-border); color: var(--f-text); font-size: 1.05rem; font-weight: 700; }
.f-checkout__row > span:first-child { display: inline-flex; align-items: center; gap: 0.3rem; }

.f-checkout__info-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.05rem;
    block-size: 1.05rem;
    border: 0;
    border-radius: 50%;
    background: var(--f-border);
    color: var(--f-text-soft);
    cursor: pointer;
    flex: none;
}
.f-checkout__info-btn:hover { background: var(--color-primary, #1d9e75); color: var(--color-on-primary, #fff); }

.f-checkout__progress { display: block; margin-block-end: 1.25rem; }

/* ---- payment return page: verifying / success / pending / failed / error ---- */
.f-payment-status { display: block; inline-size: 100%; max-inline-size: 60rem; margin-inline: auto; text-align: start; }
.f-payment-status__shell { display: flex; flex-direction: column; gap: 1.25rem; }

/* The hero: one panel that says where the payment stands. Its tone (the
   accent, the tint behind the icon, the ink of the title) is set per state
   with custom properties, so every piece below reads the same three. */
.f-payment-status__hero {
    --fps-accent: var(--f-text);
    --fps-ink: var(--f-text);
    --fps-tint: rgba(0, 0, 0, 0.05);
    --fps-ring: rgba(0, 0, 0, 0.1);
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    padding: 2.75rem 1.5rem 2.25rem;
    border: 1px solid var(--f-border);
    border-radius: calc(var(--f-radius) * 2);
    background: var(--f-surface);
    text-align: center;
}
.f-payment-status__hero::before { content: ""; position: absolute; inset: 0 0 auto 0; block-size: 0.3rem; background: var(--fps-accent); }
.f-payment-status__hero::after {
    content: "";
    position: absolute;
    inset-inline: -20%;
    inset-block-start: -45%;
    block-size: 75%;
    background: radial-gradient(closest-side, var(--fps-tint), transparent);
    pointer-events: none;
}
.f-payment-status__hero > * { position: relative; z-index: 1; }
.f-payment-status__hero.is-success { --fps-accent: #16a34a; --fps-ink: #14532d; --fps-tint: rgba(22, 163, 74, 0.14); --fps-ring: rgba(22, 163, 74, 0.25); }
.f-payment-status__hero.is-pending { --fps-accent: #d97706; --fps-ink: #78350f; --fps-tint: rgba(217, 119, 6, 0.14); --fps-ring: rgba(217, 119, 6, 0.25); }
.f-payment-status__hero.is-failed { --fps-accent: #dc2626; --fps-ink: #7f1d1d; --fps-tint: rgba(220, 38, 38, 0.12); --fps-ring: rgba(220, 38, 38, 0.25); }

.f-payment-status__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 4.5rem;
    block-size: 4.5rem;
    margin-block-end: 0.4rem;
    border-radius: 50%;
    background: var(--f-surface);
    color: var(--fps-accent);
    box-shadow: 0 0 0 0.5rem var(--fps-tint), 0 0 0 1px var(--fps-ring);
}
.f-payment-status__icon .f-order__icon { inline-size: 2.1rem; block-size: 2.1rem; }
.f-payment-status__eyebrow { margin: 0; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--fps-accent); }
.f-payment-status__title { margin: 0; font-size: clamp(1.5rem, 3vw, 2rem); font-weight: 800; line-height: 1.2; color: var(--fps-ink); }
.f-payment-status__text { margin: 0; max-inline-size: 34rem; color: var(--f-text-soft); line-height: 1.6; }

/* Order placed → Payment → Confirmed. The connector between two dots takes
   the accent once the step before it is done. */
.f-payment-status__steps {
    display: flex;
    align-items: flex-start;
    inline-size: 100%;
    max-inline-size: 30rem;
    margin: 1.1rem 0 0.4rem;
    padding: 0;
    list-style: none;
}
.f-payment-status__step {
    position: relative;
    flex: 1 1 0;
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--f-text-faint);
}
.f-payment-status__step + .f-payment-status__step::before {
    content: "";
    position: absolute;
    inset-block-start: 0.8rem;
    inset-inline-end: 50%;
    inline-size: 100%;
    block-size: 2px;
    background: var(--f-border);
}
.f-payment-status__step.is-done + .f-payment-status__step::before { background: var(--fps-accent); }
.f-payment-status__step-dot {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.65rem;
    block-size: 1.65rem;
    border: 2px solid var(--f-border);
    border-radius: 50%;
    background: var(--f-surface);
    color: var(--f-text-faint);
    font-size: 0.72rem;
}
.f-payment-status__step-dot i { font-style: normal; }
.f-payment-status__step-dot .f-order__icon { inline-size: 0.9rem; block-size: 0.9rem; }
.f-payment-status__step.is-done,
.f-payment-status__step.is-current,
.f-payment-status__step.is-failed { color: var(--f-text); }
.f-payment-status__step.is-done .f-payment-status__step-dot,
.f-payment-status__step.is-failed .f-payment-status__step-dot { border-color: var(--fps-accent); background: var(--fps-accent); color: #fff; }
.f-payment-status__step.is-current .f-payment-status__step-dot { border-color: var(--fps-accent); color: var(--fps-accent); box-shadow: 0 0 0 0.3rem var(--fps-tint); }
.f-payment-status__step.is-current { color: var(--fps-ink); }
.f-payment-status__step-label { padding-inline: 0.25rem; }

/* The order number is a button: tap to copy. */
.f-payment-status__pill {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    margin-block-start: 0.5rem;
    padding: 0.4rem 0.5rem;
    padding-inline-start: 0.9rem;
    border: 1px solid var(--f-border);
    border-radius: 999px;
    background: var(--f-surface);
    font: inherit;
    font-size: 0.88rem;
    color: var(--f-text);
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.f-payment-status__pill:hover,
.f-payment-status__pill:focus-visible { border-color: var(--fps-accent); box-shadow: 0 0 0 0.2rem var(--fps-tint); outline: none; }
.f-payment-status__pill.is-copied { border-color: #16a34a; }
.f-payment-status__pill.is-copied .f-payment-status__pill-copy { background: #dcfce7; color: #16a34a; }
.f-payment-status__pill-label { font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--f-text-soft); }
.f-payment-status__pill b { font-weight: 700; font-variant-numeric: tabular-nums; }
.f-payment-status__pill-copy {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.6rem;
    block-size: 1.6rem;
    border-radius: 50%;
    background: var(--fps-tint);
    color: var(--fps-accent);
}
.f-payment-status__pill-copy .f-order__icon { inline-size: 0.85rem; block-size: 0.85rem; }

/* Total · method · date, under the pill. */
.f-payment-status__meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.6rem 0;
    inline-size: 100%;
    max-inline-size: 34rem;
    margin: 1rem 0 0;
    padding: 0.85rem 0 0;
    border-block-start: 1px dashed var(--f-border);
}
.f-payment-status__meta-item { flex: 1 1 9rem; display: flex; flex-direction: column; gap: 0.15rem; padding-inline: 0.75rem; }
.f-payment-status__meta-item + .f-payment-status__meta-item { border-inline-start: 1px solid var(--f-border); }
.f-payment-status__meta dt { font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--f-text-faint); }
.f-payment-status__meta dd { margin: 0; font-size: 0.95rem; font-weight: 700; color: var(--f-text); }

.f-payment-status__spinner {
    inline-size: 2.1rem;
    block-size: 2.1rem;
    border-radius: 50%;
    border: 3px solid var(--f-border);
    border-block-start-color: var(--fps-accent, var(--f-text));
    animation: f-payment-status-spin 0.7s linear infinite;
}
.f-payment-status__spinner--sm { inline-size: 0.9rem; block-size: 0.9rem; border-width: 2px; }
@keyframes f-payment-status-spin { to { transform: rotate(360deg); } }
.f-payment-status__polling,
.f-payment-status__redirect {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin: 0.9rem 0 0;
    font-size: 0.84rem;
    color: var(--f-text-soft);
}
.f-payment-status__polling-count { padding: 0.1rem 0.55rem; border-radius: 999px; background: var(--fps-tint); color: var(--fps-ink); font-size: 0.74rem; font-weight: 700; }
/* Fills over the moment before the thank-you page takes over. */
.f-payment-status__progress { display: block; inline-size: 12rem; block-size: 0.3rem; margin-block-start: 0.6rem; border-radius: 999px; background: var(--fps-tint); overflow: hidden; }
.f-payment-status__progress i { display: block; inline-size: 100%; block-size: 100%; background: var(--fps-accent); transform-origin: 0 50%; animation: f-payment-status-fill 1.8s linear forwards; }
[dir="rtl"] .f-payment-status__progress i { transform-origin: 100% 50%; }
@keyframes f-payment-status-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Items beside the payment, delivery and next-steps cards. */
.f-payment-status__grid { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(16rem, 1fr); gap: 1.25rem; align-items: start; }
.f-payment-status__side { display: flex; flex-direction: column; gap: 1.25rem; }
.f-payment-status__card {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    padding: 1.35rem 1.4rem;
    border: 1px solid var(--f-border);
    border-radius: calc(var(--f-radius) * 1.5);
    background: var(--f-surface);
    text-align: start;
}
.f-payment-status__card-title { display: flex; align-items: center; gap: 0.5rem; margin: 0; font-size: 1rem; font-weight: 700; color: var(--f-text); }
.f-payment-status__card-title .f-order__icon { inline-size: 1.1rem; block-size: 1.1rem; color: var(--f-text-soft); }
.f-payment-status__card-title small { margin-inline-start: auto; font-size: 0.75rem; font-weight: 600; color: var(--f-text-faint); }
.f-payment-status__items { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.f-payment-status__item { display: flex; align-items: center; gap: 0.85rem; padding-block: 0.7rem; border-block-start: 1px solid var(--f-border); }
.f-payment-status__item:first-child { padding-block-start: 0; border-block-start: 0; }
.f-payment-status__thumb {
    position: relative;
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 3.25rem;
    block-size: 3.25rem;
    border: 1px solid var(--f-border);
    border-radius: 0.65rem;
    background: rgba(0, 0, 0, 0.03);
    color: var(--f-text-faint);
}
.f-payment-status__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; border-radius: inherit; }
.f-payment-status__qty {
    position: absolute;
    inset-block-start: -0.45rem;
    inset-inline-end: -0.45rem;
    min-inline-size: 1.25rem;
    block-size: 1.25rem;
    padding-inline: 0.3rem;
    border-radius: 999px;
    background: var(--f-text);
    color: var(--f-surface);
    font-size: 0.7rem;
    line-height: 1.25rem;
    text-align: center;
}
.f-payment-status__item-body { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.f-payment-status__item-name { font-size: 0.92rem; font-weight: 600; color: var(--f-text); overflow-wrap: anywhere; }
.f-payment-status__item-each { font-size: 0.78rem; color: var(--f-text-faint); }
.f-payment-status__item-total { font-size: 0.92rem; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.f-payment-status__totals { display: flex; flex-direction: column; gap: 0.45rem; margin: 0; padding-block-start: 0.9rem; border-block-start: 1px solid var(--f-border); }
.f-payment-status__totals-row { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.9rem; color: var(--f-text-soft); }
.f-payment-status__totals-row dd { margin: 0; color: var(--f-text); font-variant-numeric: tabular-nums; }
.f-payment-status__totals-row--grand { margin-block-start: 0.35rem; padding-block-start: 0.7rem; border-block-start: 1px dashed var(--f-border); font-size: 1.05rem; font-weight: 800; color: var(--f-text); }
.f-payment-status__facts { display: flex; flex-direction: column; gap: 0.55rem; margin: 0; }
.f-payment-status__facts > div { display: flex; justify-content: space-between; align-items: center; gap: 1rem; font-size: 0.9rem; }
.f-payment-status__facts dt { color: var(--f-text-soft); }
.f-payment-status__facts dd { margin: 0; text-align: end; color: var(--f-text); }
.f-payment-status__badge { display: inline-flex; align-items: center; padding: 0.2rem 0.6rem; border-radius: 999px; background: rgba(0, 0, 0, 0.06); color: var(--f-text); font-size: 0.75rem; font-weight: 700; }
.f-payment-status__badge.is-paid,
.f-payment-status__badge.is-completed { background: #dcfce7; color: #166534; }
.f-payment-status__badge.is-pending,
.f-payment-status__badge.is-unpaid { background: #fef3c7; color: #92400e; }
.f-payment-status__badge.is-failed { background: #fee2e2; color: #991b1b; }
.f-payment-status__note { margin: 0; font-size: 0.82rem; color: var(--f-text-soft); }
.f-payment-status__address { display: flex; flex-direction: column; gap: 0.2rem; font-style: normal; font-size: 0.9rem; line-height: 1.5; color: var(--f-text-soft); }
.f-payment-status__address-name { font-weight: 700; color: var(--f-text); }
.f-payment-status__next { display: flex; flex-direction: column; gap: 0.7rem; margin: 0; padding: 0; list-style: none; counter-reset: fps-next; }
.f-payment-status__next li { position: relative; padding-inline-start: 2.1rem; font-size: 0.88rem; line-height: 1.5; color: var(--f-text-soft); counter-increment: fps-next; }
.f-payment-status__next li::before {
    content: counter(fps-next);
    position: absolute;
    inset-inline-start: 0;
    inset-block-start: 0.05rem;
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.5rem;
    block-size: 1.5rem;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: var(--f-text);
    font-size: 0.72rem;
    font-weight: 700;
}
.f-payment-status__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.65rem; }
.f-payment-status__actions .f-btn { justify-content: center; }

@media (max-width: 47.99rem) {
    .f-payment-status__grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 36rem) {
    .f-payment-status__hero { padding: 2.1rem 1rem 1.75rem; }
    .f-payment-status__meta-item + .f-payment-status__meta-item { border-inline-start: 0; }
    .f-payment-status__actions { flex-direction: column; align-items: stretch; }
}
@media (prefers-reduced-motion: reduce) {
    .f-payment-status__spinner,
    .f-payment-status__progress i { animation-duration: 0.01ms; animation-iteration-count: 1; }
}

/* ========================================================================
   Product availability ("notify me"), size guide, reviews summary
   ======================================================================== */

.f-availability { display: block; }
.f-availability[hidden] { display: none; }
.f-availability__button { display: inline-flex; align-items: center; gap: 0.45rem; }
.f-availability__done { display: inline-flex; align-items: center; gap: 0.45rem; margin: 0; color: var(--color-primary, #1d9e75); font-weight: 600; }
.f-availability__form { display: flex; flex-direction: column; gap: 0.9rem; }
.f-availability__error { margin: 0; font-size: 0.85rem; color: var(--f-danger); }
.f-availability__error[hidden] { display: none; }

.f-size-guide { display: inline-block; }
.f-size-guide[hidden] { display: none; }
.f-size-guide__link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0;
    border: 0;
    background: none;
    color: var(--color-primary, #1d9e75);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}
.f-size-guide__body { display: flex; flex-direction: column; gap: 1rem; }
/* A size guide is very often a phone screenshot — tall, and far bigger than
   the dialog meant to hold it. Width was capped and height was not, so the
   modal grew to whatever the merchant uploaded and pushed its own header off
   the screen. The ratio survives the cap because the width stays free to
   shrink with it. */
.f-size-guide__image { max-inline-size: 100%; block-size: auto; max-block-size: 70vh; align-self: center; border-radius: var(--f-radius); }
.f-size-guide__content table { inline-size: 100%; border-collapse: collapse; font-size: 0.9rem; }
.f-size-guide__content th, .f-size-guide__content td { padding: 0.5rem 0.6rem; border: 1px solid var(--f-border); text-align: start; }
.f-size-guide__content th { background: rgba(0, 0, 0, 0.04); font-weight: 700; }

.f-reviews-summary { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 1.5rem; align-items: center; }
.f-reviews-summary[hidden] { display: none; }
@media (max-width: 599px) { .f-reviews-summary { grid-template-columns: minmax(0, 1fr); } }
.f-reviews-summary__loading { display: flex; justify-content: center; padding: 1rem; }
.f-reviews-summary__empty { margin: 0; color: var(--f-text-soft); }
.f-reviews-summary__score { display: flex; flex-direction: column; align-items: center; gap: 0.25rem; min-inline-size: 8rem; }
.f-reviews-summary__average { font-size: 2.6rem; font-weight: 800; line-height: 1; color: var(--f-text); }
.f-reviews-summary__total { font-size: 0.85rem; color: var(--f-text-soft); }
.f-reviews-summary__bars { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.f-reviews-summary__row { display: grid; grid-template-columns: 2.6rem minmax(0, 1fr) 2.5rem; align-items: center; gap: 0.6rem; font-size: 0.85rem; }
.f-reviews-summary__row-label { color: var(--f-text-soft); white-space: nowrap; }
.f-reviews-summary__star { color: #f5a623; }
.f-reviews-summary__bar { display: block; block-size: 0.55rem; border-radius: 999px; background: rgba(0, 0, 0, 0.07); overflow: hidden; }
.f-reviews-summary__fill { display: block; block-size: 100%; border-radius: 999px; background: #f5a623; transition: inline-size 0.4s ease; }
.f-reviews-summary__count { text-align: end; color: var(--f-text-soft); font-variant-numeric: tabular-nums; }
.f-availability__note { margin: 0 0 0.5rem; font-size: 0.85rem; color: var(--f-text-soft); }

/* ========================================================================
   Add-product toast — the "added to your cart" card
   ======================================================================== */
.f-add-toast {
    position: fixed;
    z-index: 1100;
    inline-size: min(22rem, calc(100vw - 2rem));
    opacity: 0;
    transform: translateY(0.75rem);
    transition: opacity 0.25s ease, transform 0.25s ease;
    pointer-events: none;
}
.f-add-toast[hidden] { display: none; }
.f-add-toast.is-in { opacity: 1; transform: none; pointer-events: auto; }
.f-add-toast--bottom-end { inset-block-end: 1.25rem; inset-inline-end: 1.25rem; }
.f-add-toast--bottom-start { inset-block-end: 1.25rem; inset-inline-start: 1.25rem; }
.f-add-toast--bottom-center { inset-block-end: 1.25rem; inset-inline-start: 50%; transform: translate(-50%, 0.75rem); }
.f-add-toast--bottom-center.is-in { transform: translate(-50%, 0); }
.f-add-toast--top-end { inset-block-start: 1.25rem; inset-inline-end: 1.25rem; transform: translateY(-0.75rem); }
.f-add-toast--top-start { inset-block-start: 1.25rem; inset-inline-start: 1.25rem; transform: translateY(-0.75rem); }
.f-add-toast--top-center { inset-block-start: 1.25rem; inset-inline-start: 50%; transform: translate(-50%, -0.75rem); }
.f-add-toast--top-center.is-in { transform: translate(-50%, 0); }
.f-add-toast__card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1rem;
    border-radius: 0.75rem;
    background: var(--f-surface, #fff);
    color: var(--f-text, #1f2937);
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.22);
}
.f-add-toast__close {
    position: absolute;
    inset-block-start: 0.5rem;
    inset-inline-end: 0.5rem;
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
}
.f-add-toast__close:hover { background: rgba(0, 0, 0, 0.06); }
.f-add-toast__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding-inline-end: 2rem;
    font-weight: 700;
    color: var(--f-success, #15803d);
}
.f-add-toast__icon { flex: none; }
.f-add-toast__product { display: flex; align-items: center; gap: 0.75rem; }
.f-add-toast__image {
    flex: none;
    inline-size: 3.5rem;
    block-size: 3.5rem;
    object-fit: cover;
    border-radius: 0.5rem;
    background: rgba(0, 0, 0, 0.05);
}
.f-add-toast__info { display: flex; flex-direction: column; gap: 0.15rem; min-inline-size: 0; }
.f-add-toast__name {
    font-weight: 600;
    color: inherit;
    text-decoration: none;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.f-add-toast__variant, .f-add-toast__price { font-size: 0.85rem; opacity: 0.75; }
.f-add-toast__summary {
    margin: 0;
    padding-block-start: 0.75rem;
    border-block-start: 1px solid rgba(0, 0, 0, 0.08);
    font-size: 0.85rem;
    opacity: 0.85;
}
.f-add-toast__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.f-add-toast__actions .f-btn { justify-content: center; text-align: center; }
@media (prefers-reduced-motion: reduce) { .f-add-toast { transition: none; } }

/* ===== contact form ===== */
/* Every colour goes through the --f-* tokens, which fall back to the theme's
   --color-* names, so a theme restyles this form by setting the variables it
   already sets rather than by overriding selectors here. */

.f-contact {
    display: grid;
    gap: 1rem;
}

.f-contact__row {
    display: grid;
    /* Two up where there is room, stacked where there is not — the phone and
       email pair is the only row that shares a line. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: 1rem;
}

.f-contact__field { display: grid; gap: 0.5rem; min-inline-size: 0; }

.f-contact__label {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--f-text);
}
.f-contact__label-icon {
    display: inline-flex;
    color: var(--f-text-soft);
}
.f-contact__required { color: var(--f-danger); line-height: 1; }

.f-contact__input {
    inline-size: 100%;
    padding: 0.8rem 1rem;
    border: 1px solid transparent;
    border-radius: var(--f-radius);
    /* The field is the light plate in the reference, sitting on a tinted
       panel the theme paints — hence a background of its own rather than a
       border alone. */
    background: var(--f-input-bg, #ffffff);
    color: var(--f-text);
    font: inherit;
    font-size: 0.9375rem;
    line-height: 1.6;
}
.f-contact__input::placeholder { color: var(--f-text-faint); }
.f-contact__input:focus {
    outline: none;
    border-color: var(--color-primary, #b08658);
}

.f-contact__input--area {
    min-block-size: 8rem;
    resize: vertical;
}

/* File inputs cannot be styled through the input box itself in every engine,
   so the plate is kept and only the button part is toned down. */
.f-contact__input[type="file"] { padding: 0.6rem 0.75rem; cursor: pointer; }
.f-contact__input[type="file"]::file-selector-button {
    margin-inline-end: 0.75rem;
    padding: 0.4rem 0.9rem;
    border: 0;
    border-radius: calc(var(--f-radius) - 2px);
    background: var(--f-border);
    color: var(--f-text);
    font: inherit;
    font-size: 0.875rem;
    cursor: pointer;
}

.f-contact__error {
    margin: 0;
    color: var(--f-danger);
    font-size: 0.875rem;
}
.f-contact__error[hidden] { display: none; }

.f-contact falak-button { margin-block-start: 0.25rem; }

/* The confirmation sits WITH the form, under the button — a banner on the
   row, not a panel in the form's place. */
.f-contact__done {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-radius: var(--f-radius);
    background: var(--f-success-bg, rgba(22, 163, 74, 0.1));
    color: var(--f-text);
}
.f-contact__done[hidden] { display: none; }
.f-contact__done p { margin: 0; font-size: 0.9375rem; line-height: 1.6; }
.f-contact__done-icon {
    display: grid;
    place-items: center;
    flex: none;
    inline-size: 2rem;
    block-size: 2rem;
    border-radius: 50%;
    background: var(--f-success, #16a34a);
    color: #fff;
}

/* ===== contact links ===== */
/* The footer's "how to reach us" row: outlined chips, icon then label. Sits
   above <falak-social>, which is the same shop's profiles as bare icons. */

.f-contact-links { display: block; }
.f-contact-links[hidden] { display: none; }

.f-contact-links__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.6rem;
}

.f-contact-links__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.5rem 0.9rem;
    border: 1px solid currentColor;
    border-radius: var(--f-radius);
    color: inherit;
    font-size: 0.875rem;
    line-height: 1.4;
    text-decoration: none;
    /* The chip borrows the footer's ink at 65% so the outline reads as a
       hairline on a dark ground without needing a second colour token. */
    opacity: 0.65;
    transition: opacity 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.f-contact-links__chip:hover,
.f-contact-links__chip:focus-visible {
    opacity: 1;
    color: var(--color-primary, #b08658);
    text-decoration: none;
}

.f-contact-links__icon { display: inline-flex; flex: none; }
.f-contact-links__label { white-space: nowrap; }

/* ========================================================================
   NEWSLETTER — <falak-newsletter>
   ======================================================================== */
/* Structure only: the row, the growing field, the status line. Colours and
   shapes come from the theme, which is why every value here goes through the
   --f-* tokens with quiet fallbacks. */

.f-newsletter { display: block; }

.f-newsletter__form { margin: 0; }

.f-newsletter__label {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.f-newsletter__row {
    display: flex;
    gap: 0.5rem;
    align-items: stretch;
}

.f-newsletter__input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.6rem 0.9rem;
    border: 1px solid var(--f-border, rgba(0, 0, 0, 0.14));
    border-radius: var(--f-radius, 0.5rem);
    background: var(--f-bg, #fff);
    color: var(--f-text, inherit);
    font: inherit;
}

.f-newsletter__submit {
    flex: none;
    padding: 0.6rem 1.4rem;
    border: 1px solid transparent;
    border-radius: var(--f-radius, 0.5rem);
    background: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
    font: inherit;
    cursor: pointer;
}

.f-newsletter__submit:disabled { opacity: 0.6; cursor: wait; }

.f-newsletter__status {
    margin: 0.5rem 0 0;
    font-size: 0.875rem;
}

.f-newsletter__status.is-error { color: var(--f-danger, #c0392b); }

@media (max-width: 479px) {
    .f-newsletter__row { flex-wrap: wrap; }
    .f-newsletter__submit { flex: 1 1 100%; }
}

/* ------------------------------------------------------------------ counter */

/*
 * justify-content matters more than it looks. Dropped into a grid or flex
 * parent — a stats row, say — an inline-flex element is blockified and
 * stretched to the full cell, and `text-align: center` on that parent cannot
 * reach flex children: the figure ends up hard against the start edge while
 * the label under it stays centred. Centring here costs nothing in normal
 * flow, where the box shrink-wraps anyway, and a theme that wants the figure
 * aligned to the edge overrides one property.
 */
.f-counter { display: inline-flex; align-items: baseline; justify-content: center; gap: 0.1em; font-variant-numeric: tabular-nums; }
.f-counter[hidden] { display: none; }

/* ---------------------------------------------------------- image compare */

/*
 * Built around a native range input. Everything visible reads one custom
 * property, --f-compare-pos, so the block renders correctly at its 50% default
 * even if the script never runs.
 */
.f-compare {
    --f-compare-pos: 50%;
    --f-compare-knob: 2.75rem;
    position: relative;
    display: block;
    overflow: hidden;
    isolation: isolate;
    border-radius: var(--f-radius);
}

.f-compare[hidden] { display: none; }

/* A fixed ratio on both photos: a comparison whose halves are different shapes
   shows the crop rather than the difference. */
.f-compare__photo { display: block; inline-size: 100%; aspect-ratio: 3 / 2; object-fit: cover; background: var(--f-surface); }

.f-compare__before { position: absolute; inset: 0; clip-path: inset(0 calc(100% - var(--f-compare-pos)) 0 0); }
.f-compare__before .f-compare__photo { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; aspect-ratio: auto; }

/* RTL reads the handle from the right, and so does the range input's own
   travel — clip from the opposite edge or the two move in opposite directions. */
[dir="rtl"] .f-compare__before { clip-path: inset(0 0 0 calc(100% - var(--f-compare-pos))); }

.f-compare__label {
    position: absolute;
    inset-block-start: 1rem;
    padding: 0.3rem 0.85rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 600;
    pointer-events: none;
}

.f-compare__label--before { inset-inline-start: 1rem; }
.f-compare__label--after { inset-inline-end: 1rem; }

/*
 * The input covers the whole photo and draws nothing — its thumb is a
 * hairline, and the knob below is an ordinary element. A thumb styled as the
 * knob stops half a knob short of each edge while the divider runs the full
 * width, and Chrome paints it straight through the overflow clip above.
 */
.f-compare__range {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    appearance: none;
    -webkit-appearance: none;
    cursor: ew-resize;
    touch-action: pan-y;
}

.f-compare__range:focus { outline: none; }
.f-compare__range::-webkit-slider-runnable-track { background: transparent; border: 0; }
.f-compare__range::-moz-range-track { background: transparent; border: 0; }
.f-compare__range::-webkit-slider-thumb { -webkit-appearance: none; inline-size: 1px; block-size: 100%; border: 0; background: transparent; cursor: ew-resize; }
.f-compare__range::-moz-range-thumb { inline-size: 1px; block-size: 100%; border: 0; border-radius: 0; background: transparent; cursor: ew-resize; }

/* margin-inline-start rather than a translate, so both centre on the handle in
   either writing direction without a second rule. */
.f-compare__divider {
    position: absolute;
    inset-block: 0;
    inset-inline-start: var(--f-compare-pos);
    inline-size: 2px;
    margin-inline-start: -1px;
    background: #fff;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
    pointer-events: none;
}

.f-compare__knob {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: var(--f-compare-pos);
    inline-size: var(--f-compare-knob);
    block-size: var(--f-compare-knob);
    margin-block-start: calc(var(--f-compare-knob) / -2);
    margin-inline-start: calc(var(--f-compare-knob) / -2);
    border-radius: 50%;
    background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6 3 12l6 6M15 6l6 6-6 6'/%3E%3C/svg%3E") center / 1.15rem no-repeat;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
    pointer-events: none;
}

/* Keyboard focus has to land on something visible, and the input draws
   nothing — so the ring goes on the knob it moves. */
.f-compare__range:focus-visible ~ .f-compare__knob { box-shadow: 0 0 0 3px var(--color-primary, #1d9e75), 0 6px 18px rgba(0, 0, 0, 0.28); }

@media (max-width: 639px) {
    .f-compare { --f-compare-knob: 2.25rem; }
    .f-compare__photo { aspect-ratio: 4 / 5; }
    .f-compare__label { inset-block-start: 0.75rem; padding: 0.25rem 0.6rem; }
    .f-compare__label--before { inset-inline-start: 0.75rem; }
    .f-compare__label--after { inset-inline-end: 0.75rem; }
}

/* --------------------------------------------------------------- categories */

.f-categories { display: block; }
.f-categories[hidden] { display: none; }
.f-categories__note { margin: 0; padding-block: 2rem; text-align: center; color: var(--f-text-soft); font-size: 0.9rem; }

.f-categories__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 1.25rem;
}

.f-categories__link { display: grid; gap: 0.5rem; text-align: center; color: inherit; text-decoration: none; }

.f-categories__image {
    display: block;
    inline-size: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--f-radius);
    background: var(--f-surface);
}

.f-categories__image--empty { border: 1px dashed var(--f-border); }
.f-categories__name { font-weight: 600; font-size: 0.92rem; }
.f-categories__count { color: var(--f-text-soft); font-size: 0.78rem; }

/* Round tiles — the "shop by category" circles most storefronts open with. */
.f-categories--circles .f-categories__image { border-radius: 50%; }

.f-categories--list .f-categories__list { grid-template-columns: minmax(0, 1fr); gap: 0.5rem; }
.f-categories--list .f-categories__link { grid-template-columns: 3rem minmax(0, 1fr); align-items: center; text-align: start; gap: 0.75rem; }
.f-categories--list .f-categories__image { inline-size: 3rem; }

/* ---- from packages/falak-components/src/components.chrome.css ---- */

/*
    Storefront chrome — button, modal, slider, menu, breadcrumb and the footer
    trust row.

    Split from components.css only for file size; both are imported by the entry
    and Vite's library mode concatenates them into one extracted
    falak-components.css. Same rules apply: derive from the theme's brand
    tokens, logical properties throughout so RTL needs no second stylesheet.
*/

/* ========================================================================
   Button
   ======================================================================== */

.f-btn-wrap { display: inline-block; }
falak-button[width="wide"],
falak-button[width="wide"] .f-btn-wrap { display: block; inline-size: 100%; }
.f-btn__link { display: block; text-decoration: none; }

.f-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding-inline: 1.25rem;
    min-block-size: 2.75rem;
    border: 1px solid transparent;
    border-radius: var(--f-radius);
    font: inherit;
    font-weight: 600;
    font-size: 0.9rem;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease, opacity 0.16s ease;
}

.f-btn:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }
.f-btn:hover:not(:disabled) { opacity: 0.88; }
.f-btn:disabled,
.f-btn--disabled { opacity: 0.5; cursor: not-allowed; }

.f-btn--primary { background: var(--color-primary, #1d9e75); color: var(--color-on-primary, #fff); }
.f-btn--light { background: rgba(0, 0, 0, 0.05); color: var(--f-text); }
.f-btn--danger { background: var(--f-danger); color: #fff; }

.f-btn--primary-outline { background: transparent; border-color: var(--color-primary, #1d9e75); color: var(--color-primary, #1d9e75); }
.f-btn--light-outline { background: transparent; border-color: var(--f-border); color: var(--f-text); }
.f-btn--danger-outline { background: transparent; border-color: var(--f-danger); color: var(--f-danger); }
.f-btn--fill-none { background: transparent; color: var(--f-text); }

.f-btn--primary-link,
.f-btn--light-link {
    background: none;
    border: 0;
    padding-inline: 0;
    min-block-size: auto;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.f-btn--primary-link { color: var(--color-primary, #1d9e75); }

.f-btn--icon { inline-size: 2.5rem; min-block-size: 2.5rem; padding: 0; border-radius: 50%; }
.f-btn--small { min-block-size: 2.15rem; padding-inline: 0.85rem; font-size: 0.8rem; }
.f-btn--large { min-block-size: 3.15rem; padding-inline: 1.75rem; font-size: 1rem; }
.f-btn--wide { inline-size: 100%; }

.f-btn__text { display: inline-flex; align-items: center; gap: 0.4rem; }
.f-btn__text--hidden { visibility: hidden; }

.f-btn__loader {
    inline-size: 1rem;
    block-size: 1rem;
    border: 2px solid currentColor;
    border-block-start-color: transparent;
    border-radius: 50%;
    animation: f-spin 0.7s linear infinite;
}

.f-btn--loader-center .f-btn__loader {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    margin-block-start: -0.5rem;
    margin-inline-start: -0.5rem;
}

.f-btn--loader-before { flex-direction: row-reverse; }

@keyframes f-spin { to { transform: rotate(360deg); } }

/* ========================================================================
   Modal
   ======================================================================== */

.f-modal { position: fixed; inset: 0; z-index: 1000; display: none; }
.f-modal[data-visible="true"] { display: block; }
body.f-modal-open { overflow: hidden; }

.f-modal__overlay {
    position: absolute;
    inset: 0;
    background: rgba(8, 14, 12, 0.55);
    animation: f-fade 0.18s ease;
}

.f-modal__wrapper {
    position: relative;
    block-size: 100%;
    display: flex;
    justify-content: center;
    padding: 1rem;
    overflow-y: auto;
}

/* `align-items: center` on a scroll container clips what it cannot fit, and it
   clips at the TOP — where the title and the close button are. A modal taller
   than the viewport put its own header at a negative offset that no scrolling
   could reach, because a flex item centred past the start edge sits outside
   the scrollable area entirely.

   `margin-block: auto` centres identically while there is room to spare and
   collapses to zero when there is not, so an oversized dialog starts at the
   top and scrolls normally. Preferred over `align-items: safe center`, which
   does the same in one line but only on newer engines. */
.f-modal__wrapper--middle { align-items: flex-start; }
.f-modal__wrapper--middle > .f-modal__body { margin-block: auto; }
.f-modal__wrapper--top { align-items: flex-start; }
.f-modal__wrapper--bottom { align-items: flex-end; }

.f-modal__body {
    position: relative;
    inline-size: 100%;
    background: var(--f-surface);
    border-radius: calc(var(--f-radius) * 1.6);
    box-shadow: 0 20px 60px rgba(8, 14, 12, 0.28);
    animation: f-rise 0.2s ease;
}

.f-modal__body:not(.f-modal__body--flush) { padding: 1.5rem; }
.f-modal__body--flush { padding: 0; }
.f-modal__body--xs { max-inline-size: 20rem; }
.f-modal__body--sm { max-inline-size: 26rem; }
.f-modal__body--md { max-inline-size: 34rem; }
.f-modal__body--lg { max-inline-size: 46rem; }
.f-modal__body--xl { max-inline-size: 60rem; }

.f-modal__header { display: flex; align-items: flex-start; gap: 1rem; }
.f-modal__header--center { justify-content: center; text-align: center; }
.f-modal__heading { flex: 1; display: flex; flex-direction: column; gap: 0.25rem; }
.f-modal__heading--reverse { flex-direction: column-reverse; }
.f-modal__title { margin: 0; font-size: 1.05rem; font-weight: 700; color: var(--f-text); }
.f-modal__subtitle { margin: 0; font-size: 0.85rem; color: var(--f-text-soft); }

.f-modal__close {
    order: 2;
    flex: none;
    inline-size: 2rem;
    block-size: 2rem;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: var(--f-text-soft);
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
}

.f-modal__close:hover { background: rgba(0, 0, 0, 0.1); }
.f-modal__loading { display: flex; justify-content: center; padding: 2rem; }

.f-modal__spinner {
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border: 2px solid var(--f-border);
    border-block-start-color: var(--color-primary, #1d9e75);
    border-radius: 50%;
    animation: f-spin 0.7s linear infinite;
}

.f-hidden { display: none !important; }

@keyframes f-fade { from { opacity: 0; } }
@keyframes f-rise { from { opacity: 0; transform: translateY(12px); } }

/* ========================================================================
   Slider
   ======================================================================== */

.f-slider { position: relative; display: block; }
.f-slider--static .f-slider__controls,
.f-slider--static .f-slider__dots { display: none; }

.f-slider__head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    margin-block-end: 1.15rem;
}

.f-slider__title { margin: 0; font-size: 1.25rem; font-weight: 700; }
.f-slider__subtitle { margin: 0.2rem 0 0; font-size: 0.85rem; color: var(--f-text-soft); }
.f-slider__head-actions { flex: none; display: flex; align-items: center; gap: 0.75rem; }
.f-slider__all { font-size: 0.85rem; font-weight: 600; color: var(--color-primary, #1d9e75); text-decoration: none; }
.f-slider__all:hover { text-decoration: underline; }

.f-slider__viewport { position: relative; }

/*
    Native scroll-snap does the work. grid-auto-columns derives each slide's
    width from the requested slides-per-view, so a fractional value (peeking
    the next card) is a legitimate setting rather than a special case.
*/
.f-slider__track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - (var(--f-slider-per-view, 4) - 1) * 1rem) / var(--f-slider-per-view, 4));
    gap: 1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    padding-block-end: 0.25rem;
}

.f-slider__track::-webkit-scrollbar { display: none; }

.f-slider__track:focus-visible {
    outline: 2px solid var(--color-primary, #1d9e75);
    outline-offset: 3px;
    border-radius: var(--f-radius);
}

.f-slider__slide { scroll-snap-align: start; min-inline-size: 0; }

@media (max-width: 1023px) { .f-slider__track { grid-auto-columns: calc((100% - 2rem) / 3); } }
@media (max-width: 767px) { .f-slider__track { grid-auto-columns: calc((100% - 1rem) / 2); } }
@media (max-width: 479px) { .f-slider__track { grid-auto-columns: 78%; } }

.f-slider__controls { display: flex; gap: 0.5rem; }

.f-slider__arrow {
    inline-size: 2.25rem;
    block-size: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--f-border);
    border-radius: 50%;
    background: var(--f-surface);
    color: var(--f-text);
    cursor: pointer;
    transition: opacity 0.15s ease, background-color 0.15s ease;
}

.f-slider__arrow:hover:not(:disabled) { background: rgba(0, 0, 0, 0.04); }
.f-slider__arrow:disabled { opacity: 0.35; cursor: default; }

/* Chevron drawn from two borders — no icon asset, and it mirrors with the
   writing mode because the sides are logical. */
.f-slider__arrow::before {
    content: "";
    inline-size: 0.5rem;
    block-size: 0.5rem;
    border-inline-start: 2px solid currentColor;
    border-block-start: 2px solid currentColor;
}

.f-slider__arrow--prev::before { transform: rotate(-45deg); margin-inline-start: 0.2rem; }
.f-slider__arrow--next::before { transform: rotate(135deg); margin-inline-end: 0.2rem; }

/*
    The chevron's SIDES are logical (they follow the writing mode) but its
    ROTATION is not — in RTL the same -45° turned the glyph downwards. The
    angles flip with the direction so prev/next always point outwards.
*/
[dir='rtl'] .f-slider__arrow--prev::before,
.f-slider[dir='rtl'] .f-slider__arrow--prev::before { transform: rotate(45deg); }
[dir='rtl'] .f-slider__arrow--next::before,
.f-slider[dir='rtl'] .f-slider__arrow--next::before { transform: rotate(-135deg); }

.f-slider:not(.f-slider--controls-outer) .f-slider__controls {
    position: absolute;
    inset-block-start: 50%;
    inset-inline: 0;
    transform: translateY(-50%);
    justify-content: space-between;
    pointer-events: none;
}

.f-slider:not(.f-slider--controls-outer) .f-slider__arrow {
    pointer-events: auto;
    margin-inline: -0.75rem;
    box-shadow: 0 2px 10px rgba(8, 14, 12, 0.12);
}

.f-slider--arrows-centered .f-slider__controls { inset-block-start: 38%; }

.f-slider__dots { display: flex; justify-content: center; gap: 0.4rem; margin-block-start: 1rem; }

.f-slider__dot {
    inline-size: 0.5rem;
    block-size: 0.5rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--f-border);
    cursor: pointer;
    transition: inline-size 0.2s ease, background-color 0.2s ease;
}

.f-slider__dot.is-active {
    inline-size: 1.35rem;
    border-radius: 999px;
    background: var(--color-primary, #1d9e75);
}

/* ---- gap + auto widths (slides-per-view="auto") ---- */
.f-slider__track { gap: var(--f-slider-gap, 1rem); }
.f-slider--per-auto .f-slider__track { grid-auto-columns: max-content; }

/* ---- centered (blog / photos): active slide in the middle, edges peeking ---- */
.f-slider--centered .f-slider__slide { scroll-snap-align: center; }
.f-slider--centered .f-slider__track { scroll-padding-inline: 10%; padding-inline: 10%; }

/* ---- vertical & fullscreen: the same track, snapping on the other axis ---- */
@media (min-width: 768px) {
    .f-slider--vertical .f-slider__track {
        grid-auto-flow: row;
        grid-auto-columns: unset;
        grid-auto-rows: 100%;
        overflow-x: hidden;
        overflow-y: auto;
        scroll-snap-type: y mandatory;
        block-size: var(--f-slider-height, 480px);
    }
    .f-slider--vertical .f-slider__slide { scroll-snap-align: start; }
}
.f-slider--fullscreen { --f-slider-height: 100svh; }
.f-slider--fullscreen .f-slider__track { padding-block-end: 0; }

/* ---- type presets that are pure sizing ---- */
.f-slider--fullwidth .f-slider__track,
.f-slider--fullscreen .f-slider__track,
.f-slider--testimonials .f-slider__track,
.f-slider--blog .f-slider__track,
.f-slider--thumbs .f-slider__track {
    grid-auto-columns: 100%;
}
@media (min-width: 1024px) {
    .f-slider--testimonials .f-slider__track { grid-auto-columns: calc((100% - var(--f-slider-gap, 1rem)) / 2); }
}

/* ---- overlays: badges and buttons an author placed over the gallery ---- */
.f-slider__extra { position: absolute; z-index: 2; }

/* ---- thumbs gallery ---- */
.f-slider__body { display: flex; flex-direction: column; gap: 0.75rem; }
.f-slider__body .f-slider__viewport { min-inline-size: 0; flex: 1; }

.f-slider__thumbs { position: relative; }

.f-slider__thumbs-track {
    display: flex;
    gap: 0.5rem;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scroll-behavior: smooth;
    scrollbar-width: none;
}
.f-slider__thumbs-track::-webkit-scrollbar { display: none; }

.f-slider__thumb {
    flex: none;
    inline-size: 4.5rem;
    block-size: 4.5rem;
    padding: 0;
    border: 2px solid transparent;
    border-radius: var(--f-radius);
    overflow: hidden;
    background: none;
    cursor: pointer;
    scroll-snap-align: start;
    opacity: 0.7;
    transition: opacity 0.15s ease, border-color 0.15s ease;
}
.f-slider__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
.f-slider__thumb:hover { opacity: 1; }
.f-slider__thumb.is-active { opacity: 1; border-color: var(--color-primary, #1d9e75); }

.f-slider__thumbs-nav {
    position: absolute;
    inset-block-start: 50%;
    inset-inline: -0.5rem;
    display: flex;
    justify-content: space-between;
    transform: translateY(-50%);
    pointer-events: none;
}
.f-slider__thumbs-nav .f-slider__arrow { pointer-events: auto; inline-size: 1.75rem; block-size: 1.75rem; }

/* Thumbs beside the gallery on desktop. */
@media (min-width: 768px) {
    .f-slider--vertical-thumbs .f-slider__body { flex-direction: row-reverse; }
    .f-slider--vertical-thumbs .f-slider__thumbs-track {
        flex-direction: column;
        overflow-x: hidden;
        overflow-y: auto;
        max-block-size: var(--f-slider-height, 480px);
        scroll-snap-type: y proximity;
    }
    .f-slider--vertical-thumbs .f-slider__thumbs-nav { display: none; }
}

/* Thumbs as a wrapping grid — no strip, no arrows. */
.f-slider--grid-thumbs .f-slider__thumbs-track { flex-wrap: wrap; overflow: visible; }
.f-slider--grid-thumbs .f-slider__thumbs-nav { display: none; }

.f-products-slider { display: block; }
.f-products-slider[hidden] { display: none; }

.f-products-slider__skeleton {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - 3rem) / 4);
    gap: 1rem;
    overflow: hidden;
}

/* ========================================================================
   Menu
   ======================================================================== */

/*
    The host is transparent to layout.

    In its default mode this component wraps markup the theme already rendered,
    and the theme's own rules position that markup — a header's flex row expects
    the <nav> as its child, not a wrapper around it. `display: contents` lets the
    element carry behaviour and state without introducing a box that would break
    whatever layout it was dropped into.
*/
.f-menu { display: contents; }
.f-menu[hidden] { display: none; }

/* Rendered mode supplies its own box, since there is no theme markup to defer to. */
.f-menu__nav { display: block; }
.f-menu__list { list-style: none; margin: 0; padding: 0; }
.f-menu__list--root { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; }
.f-menu__item { position: relative; }

.f-menu__link {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.55rem 0.7rem;
    border-radius: var(--f-radius);
    color: var(--f-text);
    font-size: 0.9rem;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}

.f-menu__link:hover { color: var(--color-primary, #1d9e75); }
.f-menu__link:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: -2px; }
.f-menu__image { inline-size: 1.5rem; block-size: 1.5rem; border-radius: 4px; object-fit: cover; }

.f-menu__caret {
    inline-size: 0.4rem;
    block-size: 0.4rem;
    border-inline-end: 1.5px solid currentColor;
    border-block-end: 1.5px solid currentColor;
    transform: rotate(45deg);
    margin-block-start: -0.2rem;
    transition: transform 0.18s ease;
}

.f-menu__item.is-open > .f-menu__link .f-menu__caret {
    transform: rotate(-135deg);
    margin-block-start: 0.15rem;
}

.f-menu__list--sub {
    position: absolute;
    inset-block-start: 100%;
    inset-inline-start: 0;
    z-index: 60;
    min-inline-size: 12rem;
    padding: 0.4rem;
    background: var(--f-surface);
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    box-shadow: 0 12px 32px rgba(8, 14, 12, 0.14);
    display: none;
}

/*
    State rules carry an extra class on purpose.

    A theme may put its own class on the host — the reference theme uses
    class="main-menu" so the component inherits its drawer transform and
    colours — and a descendant rule like `.main-menu ul { display: flex }`
    (0,0,1,1) outranks a single-class `.f-menu__list--sub` (0,0,1,0). That
    would leave every submenu permanently open. Two classes (0,0,2,0) win
    without reaching for !important.
*/
.f-menu .f-menu__list--sub { display: none; }
.f-menu .f-menu__item.is-open > .f-menu__list--sub { display: block; }

.f-menu__list--sub .f-menu__list--sub { inset-block-start: -0.4rem; inset-inline-start: 100%; }
.f-menu__list--flip { inset-inline-start: auto; inset-inline-end: 0; }
.f-menu__list--sub .f-menu__list--flip { inset-inline-end: 100%; }

/* The drawer is the same markup laid out as a stack that expands in place. */
.f-menu--mobile .f-menu__list--root { flex-direction: column; align-items: stretch; gap: 0; }
.f-menu--mobile .f-menu__link { padding: 0.85rem 0.25rem; border-block-end: 1px solid var(--f-border); }
.f-menu--mobile .f-menu__caret { margin-inline-start: auto; }

.f-menu--mobile .f-menu__list--sub {
    position: static;
    display: none;
    min-inline-size: 0;
    padding: 0;
    padding-inline-start: 1rem;
    background: transparent;
    border: 0;
    box-shadow: none;
}

.f-menu--mobile .f-menu__item.is-open > .f-menu__list--sub { display: block; }

/* ========================================================================
   Breadcrumb
   ======================================================================== */

.f-breadcrumb { display: block; }
.f-breadcrumb[hidden] { display: none; }

.f-breadcrumb__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8rem;
    color: var(--f-text-soft);
}

.f-breadcrumb__item { display: flex; align-items: center; gap: 0.4rem; }
.f-breadcrumb__item + .f-breadcrumb__item::before { content: "/"; color: var(--f-text-faint); }
.f-breadcrumb__item a { color: inherit; text-decoration: none; }
.f-breadcrumb__item a:hover { color: var(--color-primary, #1d9e75); }
.f-breadcrumb__item.is-current { color: var(--f-text); font-weight: 600; }

/* ========================================================================
   Footer: social, payments, apps, trust badges
   ======================================================================== */

.f-social[hidden],
.f-payments[hidden],
.f-apps[hidden],
.f-trust[hidden] { display: none; }

.f-social__title,
.f-payments__title,
.f-apps__title {
    margin: 0 0 0.75rem;
    font-size: 0.9rem;
    font-weight: 700;
    color: inherit;
}

.f-social__list,
.f-payments__list,
.f-trust__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.f-social__link {
    inline-size: 2.25rem;
    block-size: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--f-border);
    border-radius: 50%;
    color: inherit;
    transition: background-color 0.16s ease, border-color 0.16s ease, transform 0.16s ease;
}

.f-social__link:hover {
    background: var(--color-primary, #1d9e75);
    border-color: transparent;
    color: var(--color-on-primary, #fff);
    transform: translateY(-1px);
}

.f-social__link:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }
.f-social--share .f-social__list { gap: 0.4rem; }

.f-payments__item {
    inline-size: 2.9rem;
    block-size: 1.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border: 1px solid var(--f-border);
    border-radius: 5px;
    background: var(--f-surface);
    color: var(--f-text-soft);
}

.f-payments__logo {
    inline-size: 100%;
    block-size: 100%;
    object-fit: contain;
    padding: 0.15rem 0.3rem;
}

.f-payments__label {
    font-size: 0.55rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.f-apps__list { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.f-apps--vertical .f-apps__list { flex-direction: column; align-items: flex-start; }

.f-apps__item {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.45rem 0.9rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    color: inherit;
    text-decoration: none;
    transition: border-color 0.16s ease, transform 0.16s ease;
}

.f-apps__item:hover { border-color: var(--color-primary, #1d9e75); transform: translateY(-1px); }
.f-apps__text { display: flex; flex-direction: column; line-height: 1.15; }
.f-apps__sub { font-size: 0.6rem; opacity: 0.72; }
.f-apps__store { font-size: 0.85rem; font-weight: 700; }

.f-trust__list { gap: 0.75rem; }

.f-trust__item {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.75rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    font-size: 0.75rem;
}

.f-trust__text { display: flex; flex-direction: column; line-height: 1.25; }
.f-trust__label { font-size: 0.68rem; opacity: 0.7; }
.f-trust__value { font-weight: 700; font-variant-numeric: tabular-nums; }
.f-trust__glyph { flex: none; color: var(--color-primary, #1d9e75); }

/* The certificate logos ship as 300–600px PNGs; without a cap they rendered
   at full size and the footer card grew to hold them. A badge is a chip:
   the logo is the height of two text lines, nothing more. */
.f-trust__logo {
    flex: none;
    block-size: 2.25rem;
    inline-size: auto;
    max-inline-size: 4.5rem;
    object-fit: contain;
    border-radius: 0.35rem;
}

.f-trust--dark .f-trust__item { border-color: rgba(255, 255, 255, 0.22); }
.f-trust--dark .f-trust__glyph { color: currentColor; }
/* On a dark footer the logos keep their white plate so colour marks stay legible. */
.f-trust--dark .f-trust__logo { background: #fff; padding: 0.15rem; }

@media (prefers-reduced-motion: reduce) {
    .f-slider__track { scroll-behavior: auto; }
    .f-btn__loader,
    .f-modal__spinner,
    .f-modal__overlay,
    .f-modal__body { animation: none; }
    .f-social__link:hover,
    .f-apps__item:hover { transform: none; }
}

/*
    `mobile` has to mean mobile. Without this the drawer variant renders as a
    plain vertical list in the desktop flow, on top of whatever the theme put
    in its header — which is exactly what it did.

    A theme that wants an always-visible menu omits the attribute.
*/
@media (min-width: 1024px) {
    .f-menu--mobile { display: none; }
}

/*
    Share row: a labelled strip, not a continuation of the buy box and not a
    bare cluster of circles. Laid out inline so the label and the icons read as
    one control, and aligned to the content start so it lines up with the
    buy box above it in either direction.
*/
.f-social--share {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-block-start: 1rem;
    padding-block-start: 1rem;
    border-block-start: 1px solid var(--f-border);
}

.f-social--share .f-social__list { justify-content: flex-start; }

.f-social__label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--f-text-soft);
}

/* Slightly smaller than the footer set — this is a secondary action. */
.f-social--share .f-social__link { inline-size: 2rem; block-size: 2rem; }

/* ========================================================================
   Announcement bar
   A full-width strip above the header. Short text sits centred; text
   wider than the viewport becomes a marquee that follows the page
   direction and pauses on hover. Colours default to the primary but are
   plain custom properties for a theme to override.
   ======================================================================== */

.f-announce {
    display: block;
    background: var(--f-announce-bg, var(--color-primary, #1d9e75));
    color: var(--f-announce-fg, var(--color-on-primary, #fff));
    font-size: 0.85rem;
    font-weight: 600;
}
.f-announce[hidden] { display: none; }

.f-announce__inner {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 2.4rem;
    padding: 0.35rem 2.5rem;
    overflow: hidden;
    text-align: center;
}

.f-announce__text,
.f-announce__link {
    color: inherit;
    text-decoration: none;
    white-space: nowrap;
}
.f-announce__link:hover { text-decoration: underline; }

/* Marquee: the track holds the message twice so the loop is seamless. */
.f-announce--scroll .f-announce__inner { justify-content: flex-start; padding-inline: 0; }
.f-announce__track {
    display: inline-flex;
    white-space: nowrap;
    will-change: transform;
    animation: f-announce-ltr var(--f-announce-duration, 18s) linear infinite;
}
.f-announce__track > * { padding-inline-end: 4rem; }
.f-announce[dir="rtl"] .f-announce__track,
[dir="rtl"] .f-announce__track { animation-name: f-announce-rtl; }
.f-announce__track:hover { animation-play-state: paused; }

@keyframes f-announce-ltr { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes f-announce-rtl { from { transform: translateX(0); } to { transform: translateX(50%); } }

.f-announce__close {
    position: absolute;
    inset-inline-end: 1rem;
    top: 50%;
    translate: 0 -50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.75;
}
.f-announce__close:hover { opacity: 1; background: rgba(255, 255, 255, 0.15); }
.f-announce--scroll .f-announce__close { inset-inline-end: 0.5rem; }

@media (prefers-reduced-motion: reduce) {
    .f-announce__track { animation: none; }
    .f-announce--scroll .f-announce__inner { justify-content: center; overflow-x: auto; }
}

/* ========================================================================
   Loading — the shared spinner, standalone / overlay / full page
   ======================================================================== */

.f-loading {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--f-text-soft, currentColor);
}

.f-loading__spinner {
    flex: none;
    inline-size: 1.35rem;
    block-size: 1.35rem;
    border: 2px solid var(--f-border);
    border-block-start-color: var(--color-primary, #1d9e75);
    border-radius: 50%;
    animation: f-spin 0.7s linear infinite;
}

.f-loading--sm .f-loading__spinner { inline-size: 1rem; block-size: 1rem; border-width: 2px; }
.f-loading--lg .f-loading__spinner { inline-size: 2.25rem; block-size: 2.25rem; border-width: 3px; }

/* A caption only makes sense on the full-page overlay; elsewhere it is
   screen-reader text so the spinner alone stays the visible affordance. */
.f-loading:not(.f-loading--page) .f-loading__label {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.f-loading--overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    justify-content: center;
    background: color-mix(in srgb, var(--f-surface, #fff) 80%, transparent);
}

.f-loading--page {
    position: fixed;
    inset: 0;
    z-index: 1300;
    flex-direction: column;
    justify-content: center;
    gap: 0.85rem;
    background: rgba(0, 0, 0, 0.45);
    color: #fff;
}

.f-loading--page .f-loading__spinner {
    inline-size: 2.25rem;
    block-size: 2.25rem;
    border-width: 3px;
    border-color: rgba(255, 255, 255, 0.3);
    border-block-start-color: #fff;
}

.f-loading--page .f-loading__label { font-size: 0.95rem; font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
    .f-loading__spinner { animation-duration: 1.4s; }
}

/* ========================================================================
   Notifications — the global toast stack
   ======================================================================== */

.f-notifications {
    position: fixed;
    z-index: 1150;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    inline-size: min(22rem, calc(100vw - 2rem));
    pointer-events: none;
}

.f-notifications--top-end { inset-block-start: 1.25rem; inset-inline-end: 1.25rem; }
.f-notifications--top-start { inset-block-start: 1.25rem; inset-inline-start: 1.25rem; }
.f-notifications--top-center { inset-block-start: 1.25rem; inset-inline-start: 50%; transform: translateX(-50%); }
.f-notifications--bottom-end { inset-block-end: 1.25rem; inset-inline-end: 1.25rem; }
.f-notifications--bottom-start { inset-block-end: 1.25rem; inset-inline-start: 1.25rem; }
.f-notifications--bottom-center { inset-block-end: 1.25rem; inset-inline-start: 50%; transform: translateX(-50%); }

.f-toast {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.75rem 0.9rem;
    border-radius: 0.65rem;
    background: var(--f-surface, #fff);
    color: var(--f-text, #1f2937);
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.18);
    pointer-events: auto;
    opacity: 0;
    transform: translateY(-0.5rem);
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.f-notifications--bottom-end .f-toast,
.f-notifications--bottom-start .f-toast,
.f-notifications--bottom-center .f-toast { transform: translateY(0.5rem); }

.f-toast.is-in { opacity: 1; transform: none; }
.f-toast.is-out { opacity: 0; }

.f-toast__icon { flex: none; margin-block-start: 0.1rem; }
.f-toast--success .f-toast__icon { color: var(--f-success, #15803d); }
.f-toast--error .f-toast__icon { color: var(--f-danger, #b91c1c); }
.f-toast--warning .f-toast__icon { color: #b45309; }
.f-toast--info .f-toast__icon { color: var(--color-primary, #1d9e75); }

.f-toast__message { flex: 1; margin: 0; font-size: 0.88rem; line-height: 1.4; }

.f-toast__close {
    flex: none;
    inline-size: 1.4rem;
    block-size: 1.4rem;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    opacity: 0.6;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}
.f-toast__close:hover { opacity: 1; background: rgba(0, 0, 0, 0.06); }

@media (prefers-reduced-motion: reduce) {
    .f-toast { transition: none; }
}

/* ========================================================================
   Progress bar — a filled bar for a value against a whole
   ======================================================================== */

.f-progress { display: block; }

.f-progress__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    margin-block-end: 0.4rem;
    font-size: 0.85rem;
}

.f-progress__label { color: var(--f-text, currentColor); }
.f-progress__value { color: var(--f-text-soft, currentColor); font-variant-numeric: tabular-nums; }

.f-progress__track {
    inline-size: 100%;
    block-size: 0.5rem;
    border-radius: 999px;
    background: var(--f-border, rgba(0, 0, 0, 0.08));
    overflow: hidden;
}

.f-progress__fill {
    block-size: 100%;
    border-radius: inherit;
    background: var(--color-primary, #1d9e75);
    transition: inline-size 0.3s ease;
}

.f-progress--success .f-progress__fill { background: var(--f-success, #15803d); }
.f-progress--warning .f-progress__fill { background: #b45309; }
.f-progress--danger .f-progress__fill { background: var(--f-danger, #b91c1c); }

.f-progress--sm .f-progress__track { block-size: 0.3rem; }
.f-progress--lg .f-progress__track { block-size: 0.75rem; }

@media (prefers-reduced-motion: reduce) {
    .f-progress__fill { transition: none; }
}

/* ========================================================================
   Tooltip — a small hover/focus hint
   ======================================================================== */

.f-tooltip {
    position: relative;
    display: inline-block;
}

.f-tooltip__trigger { display: inline-flex; }

.f-tooltip__bubble {
    position: absolute;
    z-index: 50;
    inline-size: max-content;
    max-inline-size: 16rem;
    padding: 0.4rem 0.65rem;
    border-radius: 0.4rem;
    background: var(--f-text, #1f2430);
    color: var(--f-surface, #fff);
    font-size: 0.78rem;
    line-height: 1.4;
    text-align: center;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(2px);
    transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
}

.f-tooltip.is-open .f-tooltip__bubble { opacity: 1; visibility: visible; transform: none; }

.f-tooltip[data-tooltip-position="top"] .f-tooltip__bubble {
    inset-block-end: calc(100% + 0.4rem);
    inset-inline-start: 50%;
    translate: -50% 0;
}
.f-tooltip[data-tooltip-position="top"].is-open .f-tooltip__bubble { transform: translate(-50%, 0); }
.f-tooltip[data-tooltip-position="top"]:not(.is-open) .f-tooltip__bubble { transform: translate(-50%, 2px); }

.f-tooltip[data-tooltip-position="bottom"] .f-tooltip__bubble {
    inset-block-start: calc(100% + 0.4rem);
    inset-inline-start: 50%;
}
.f-tooltip[data-tooltip-position="bottom"].is-open .f-tooltip__bubble { transform: translate(-50%, 0); }
.f-tooltip[data-tooltip-position="bottom"]:not(.is-open) .f-tooltip__bubble { transform: translate(-50%, -2px); }

.f-tooltip[data-tooltip-position="start"] .f-tooltip__bubble {
    inset-inline-end: calc(100% + 0.4rem);
    inset-block-start: 50%;
    transform: translateY(-50%);
}
.f-tooltip[data-tooltip-position="end"] .f-tooltip__bubble {
    inset-inline-start: calc(100% + 0.4rem);
    inset-block-start: 50%;
    transform: translateY(-50%);
}

@media (prefers-reduced-motion: reduce) {
    .f-tooltip__bubble { transition: none; }
}

/* ========================================================================
   Skeleton — a content-shaped loading placeholder
   ======================================================================== */

.f-skeleton {
    display: block;
    border-radius: var(--f-radius, 0.5rem);
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--f-text, #1f2430) 8%, transparent) 25%,
        color-mix(in srgb, var(--f-text, #1f2430) 14%, transparent) 37%,
        color-mix(in srgb, var(--f-text, #1f2430) 8%, transparent) 63%);
    background-size: 400% 100%;
    animation: f-shimmer 1.4s ease infinite;
}

.f-skeleton--circle { border-radius: 50%; }

.f-skeleton--text {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    background: none;
    animation: none;
}

.f-skeleton__line {
    display: block;
    block-size: 0.85rem;
    border-radius: 999px;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--f-text, #1f2430) 8%, transparent) 25%,
        color-mix(in srgb, var(--f-text, #1f2430) 14%, transparent) 37%,
        color-mix(in srgb, var(--f-text, #1f2430) 8%, transparent) 63%);
    background-size: 400% 100%;
    animation: f-shimmer 1.4s ease infinite;
}

@keyframes f-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .f-skeleton, .f-skeleton__line { animation: none; }
}

/* ========================================================================
   Placeholder — the "nothing here" block
   ======================================================================== */

.f-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    padding: 3rem 1rem;
    text-align: center;
}

.f-placeholder__icon { font-size: 2.5rem; line-height: 1; }
.f-placeholder__text { margin: 0 0 0.4rem; color: var(--f-text-soft); }
.f-placeholder__action { margin-block-start: 0.25rem; }

/* ========================================================================
   Maintenance alert — a prominent, store-wide notice
   ======================================================================== */

.f-maintenance {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.85rem 1.25rem;
    background: #fef3c7;
    color: #92400e;
    font-size: 0.9rem;
}

.f-maintenance[hidden] { display: none; }
.f-maintenance__icon { flex: none; margin-block-start: 0.1rem; }
.f-maintenance__text { flex: 1; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem; }
.f-maintenance__title { font-weight: 700; }

.f-maintenance__close {
    flex: none;
    inline-size: 1.6rem;
    block-size: 1.6rem;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.7;
}
.f-maintenance__close:hover { opacity: 1; background: rgba(0, 0, 0, 0.08); }

/* ========================================================================
   File upload — a drag-and-drop picker with previews
   ======================================================================== */

.f-upload__zone {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 1.75rem 1rem;
    border: 1.5px dashed var(--f-border);
    border-radius: var(--f-radius);
    color: var(--f-text-soft);
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.f-upload__zone:hover,
.f-upload__zone:focus-visible { border-color: var(--color-primary, #1d9e75); }
.f-upload__zone.is-dragover { border-color: var(--color-primary, #1d9e75); background: color-mix(in srgb, var(--color-primary, #1d9e75) 6%, transparent); }
.f-upload__icon { color: var(--color-primary, #1d9e75); }
.f-upload__label { font-size: 0.88rem; text-align: center; }

.f-upload__error { margin: 0.5rem 0 0; font-size: 0.82rem; color: var(--f-danger, #b91c1c); }

.f-upload__list { list-style: none; margin: 0.75rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.f-upload__item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
}
.f-upload__thumb { flex: none; inline-size: 2.5rem; block-size: 2.5rem; border-radius: calc(var(--f-radius) * 0.6); object-fit: cover; background: rgba(0, 0, 0, 0.04); }
.f-upload__thumb--file { display: flex; align-items: center; justify-content: center; color: var(--f-text-soft); }
.f-upload__name { flex: 1; font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f-upload__size { flex: none; font-size: 0.78rem; color: var(--f-text-soft); }
.f-upload__remove {
    flex: none;
    inline-size: 1.4rem;
    block-size: 1.4rem;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--f-text-soft);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}
.f-upload__remove:hover { background: rgba(0, 0, 0, 0.06); color: var(--f-danger, #b91c1c); }

/* ========================================================================
   Tabs — a horizontal switcher between panels
   ======================================================================== */

.f-tabs__header {
    display: flex;
    gap: 0.25rem;
    overflow-x: auto;
    border-block-end: 1px solid var(--f-border);
    margin-block-end: 1.25rem;
}

.f-tabs__tab {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.75rem 1rem;
    border: 0;
    border-block-end: 2px solid transparent;
    background: none;
    color: var(--f-text-soft);
    font: inherit;
    font-weight: 600;
    font-size: 0.9rem;
    white-space: nowrap;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.f-tabs__tab:hover { color: var(--f-text); }
.f-tabs__tab.is-active { color: var(--color-primary, #1d9e75); border-block-end-color: var(--color-primary, #1d9e75); }

.f-tabs__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 1.3rem;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: var(--f-border);
    color: var(--f-text-soft);
    font-size: 0.72rem;
    font-weight: 700;
}
.f-tabs__tab.is-active .f-tabs__badge { background: var(--color-primary, #1d9e75); color: var(--color-on-primary, #fff); }

/* ========================================================================
   Price range — a min/max filter, two handles over one track
   ======================================================================== */

.f-price-range { display: block; }

.f-price-range__numbers {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-block-end: 1rem;
}

.f-price-range__number { inline-size: 100%; min-inline-size: 0; text-align: center; font-variant-numeric: tabular-nums; }
.f-price-range__sep { flex: none; color: var(--f-text-soft); }

.f-price-range__track {
    position: relative;
    block-size: 4px;
    margin-block: 1.35rem;
    border-radius: 999px;
    background: var(--f-border);
}

.f-price-range__fill {
    position: absolute;
    inset-block: 0;
    border-radius: inherit;
    background: var(--color-primary, #1d9e75);
}

.f-price-range__slider {
    position: absolute;
    inset-inline: 0;
    inset-block-start: 50%;
    transform: translateY(-50%);
    inline-size: 100%;
    block-size: 4px;
    margin: 0;
    background: transparent;
    pointer-events: none;
    appearance: none;
    -webkit-appearance: none;
}

.f-price-range__slider::-webkit-slider-runnable-track { background: transparent; }
.f-price-range__slider::-moz-range-track { background: transparent; }

.f-price-range__slider::-webkit-slider-thumb {
    appearance: none;
    -webkit-appearance: none;
    pointer-events: auto;
    inline-size: 1.05rem;
    block-size: 1.05rem;
    border-radius: 50%;
    background: var(--color-primary, #1d9e75);
    border: 2px solid var(--f-surface, #fff);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
    cursor: pointer;
}

.f-price-range__slider::-moz-range-thumb {
    pointer-events: auto;
    inline-size: 1.05rem;
    block-size: 1.05rem;
    border-radius: 50%;
    background: var(--color-primary, #1d9e75);
    border: 2px solid var(--f-surface, #fff);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
    cursor: pointer;
}

/* ========================================================================
   Datetime picker — a date, and (given slots) a time to go with it
   ======================================================================== */

.f-datetime { display: flex; flex-direction: column; gap: 0.85rem; }
.f-datetime__date { inline-size: 100%; }

.f-datetime__slots {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.f-datetime__slot {
    padding: 0.5rem 0.9rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface, #fff);
    color: var(--f-text);
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.f-datetime__slot:hover { border-color: var(--color-primary, #1d9e75); }
.f-datetime__slot.is-selected { border-color: var(--color-primary, #1d9e75); background: var(--color-primary, #1d9e75); color: var(--color-on-primary, #fff); }

/* ========================================================================
   Search — a header trigger opening a live product-result dropdown, hosted
   in the shared <falak-modal> (position="top") rather than its own overlay
   ======================================================================== */

#falak-search .f-modal__body { max-inline-size: 640px; }

.f-search__panel {
    display: flex;
    flex-direction: column;
    padding: 1rem;
}

.f-search__form {
    position: relative;
    display: flex;
    align-items: center;
}

.f-search__form .f-search__icon {
    position: absolute;
    inset-inline-start: 0.9rem;
    display: inline-flex;
    color: var(--f-muted, #8a8f98);
    pointer-events: none;
}

.f-search__input {
    inline-size: 100%;
    padding-block: 0.75rem;
    padding-inline: 2.6rem 0.9rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface, #fff);
    color: var(--f-text);
    font: inherit;
    font-size: 1rem;
}
.f-search__input:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 1px; }

.f-search__results {
    margin-block-start: 0.75rem;
    max-block-size: min(60vh, 28rem);
    overflow-y: auto;
}

.f-search[data-busy="true"] .f-search__results { opacity: 0.6; }

.f-search__list { display: flex; flex-direction: column; gap: 0.25rem; }

.f-search__link {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.6rem;
    border-radius: var(--f-radius);
    text-decoration: none;
    color: inherit;
    transition: background-color 0.15s ease;
}
.f-search__link:hover,
.f-search__link:focus-visible { background: rgba(0, 0, 0, 0.04); }

.f-search__thumb {
    flex-shrink: 0;
    display: block;
    inline-size: 3rem;
    block-size: 3rem;
    border-radius: var(--f-radius);
    overflow: hidden;
    background: var(--f-surface-alt, #f2f3f5);
}
.f-search__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.f-search__thumb-placeholder { display: block; inline-size: 100%; block-size: 100%; }

.f-search__info {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-inline-size: 0;
}

.f-search__name {
    font-size: 0.92rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.f-search__price { display: flex; align-items: baseline; gap: 0.5rem; font-size: 0.88rem; }
.f-search__price-now { font-weight: 600; color: var(--color-primary, #1d9e75); }
.f-search__price-was { color: var(--f-muted, #8a8f98); font-size: 0.8rem; }

.f-search__view-all {
    display: block;
    margin-block-start: 0.5rem;
    padding-block: 0.7rem;
    text-align: center;
    border-block-start: 1px solid var(--f-border);
    color: var(--color-primary, #1d9e75);
    font-weight: 600;
    font-size: 0.9rem;
    text-decoration: none;
}
.f-search__view-all:hover { text-decoration: underline; }

.f-search__empty {
    padding-block: 1.5rem;
    text-align: center;
    color: var(--f-muted, #8a8f98);
    font-size: 0.9rem;
}

@media (max-width: 639px) {
    #falak-search .f-modal__wrapper--top { padding-block-start: 0; }
    #falak-search .f-modal__body { max-inline-size: 100%; border-radius: 0; min-block-size: 100dvh; }
}

/* ========================================================================
   Mini checkout — "buy now" for one product, hosted in the shared
   <falak-modal>. Its steps, methods, form and totals all reuse the
   .f-checkout__* classes above; only the product summary and footer are new.
   ======================================================================== */

.f-mini-checkout__item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding-block-end: 1rem;
    margin-block-end: 1rem;
    border-block-end: 1px solid var(--f-border);
}

.f-mini-checkout__image {
    flex: none;
    inline-size: 3.25rem;
    block-size: 3.25rem;
    border-radius: var(--f-radius);
    object-fit: cover;
    background: var(--f-surface-alt, #f2f3f5);
}
.f-mini-checkout__image--empty { display: block; }

.f-mini-checkout__item-text { display: flex; flex-direction: column; gap: 0.15rem; min-inline-size: 0; }
.f-mini-checkout__item-name { font-weight: 700; color: var(--f-text); }
.f-mini-checkout__item-meta { font-size: 0.85rem; color: var(--f-text-soft); }

.f-mini-checkout__footer {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding-block-start: 1rem;
    margin-block-start: 0.5rem;
}
.f-datetime__slot.is-selected { border-color: var(--color-primary, #1d9e75); background: var(--color-primary, #1d9e75); color: var(--color-on-primary, #fff); }

/* ========================================================================
   Countdown — offer timers, pre-order clocks, and the offer band
   ======================================================================== */

.f-countdown { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; }
.f-countdown[hidden] { display: none; }
.f-countdown--horizontal { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 1rem 1.25rem; }
.f-countdown__prefix { font-weight: 600; color: var(--f-text); }
.f-countdown__hint { margin: 0 0 0.5rem; font-size: 0.85rem; color: var(--f-text-soft); }

/* Days → seconds reads the same way in both directions: it is a number, not a sentence. */
.f-countdown__list {
    display: flex;
    direction: ltr;
    gap: 0.35rem;
    margin: 0;
    padding: 0;
    list-style: none;
    align-items: stretch;
}

.f-countdown__item {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-inline-size: 2.6rem;
    padding: 0.3rem 0.4rem;
    color: var(--f-text);
}

.f-countdown__item[hidden] { display: none; }

/* A colon before every visible unit but the first — `~` rather than `+`
   so a unit auto-segments hid does not leave a stray colon on the next one. */
.f-countdown:not(.f-countdown--boxed) .f-countdown__item:not([hidden]) ~ .f-countdown__item:not([hidden])::before {
    content: ":";
    position: absolute;
    left: -0.35rem;
    top: 0.25rem;
    font-weight: 700;
    color: var(--f-text-faint);
}

.f-countdown__value {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

.f-countdown__label { font-size: 0.7rem; color: var(--f-text-soft); margin-block-start: 0.15rem; }

.f-countdown--boxed .f-countdown__list { gap: 0.5rem; }
.f-countdown--boxed .f-countdown__item {
    min-inline-size: 3.25rem;
    padding: 0.45rem 0.5rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
}

.f-countdown[data-size="sm"] .f-countdown__value { font-size: 0.95rem; }
.f-countdown[data-size="sm"] .f-countdown__item { min-inline-size: 2.1rem; padding: 0.2rem 0.3rem; }
.f-countdown[data-size="sm"] .f-countdown__label { font-size: 0.6rem; }
.f-countdown[data-size="lg"] .f-countdown__value { font-size: 2rem; }
.f-countdown[data-size="lg"] .f-countdown__item { min-inline-size: 4.25rem; padding: 0.6rem 0.75rem; }
.f-countdown[data-size="lg"] .f-countdown__label { font-size: 0.8rem; }

.f-countdown[data-color="light"] .f-countdown__value,
.f-countdown[data-color="light"] .f-countdown__prefix,
.f-countdown[data-color="light"] .f-countdown__ended { color: #fff; }
.f-countdown[data-color="light"] .f-countdown__label { color: rgba(255, 255, 255, 0.75); }
.f-countdown[data-color="light"].f-countdown--boxed .f-countdown__item { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.25); }
.f-countdown[data-color="primary"].f-countdown--boxed .f-countdown__item { background: var(--color-primary, #1d9e75); border-color: transparent; }
.f-countdown[data-color="primary"] .f-countdown__value { color: var(--color-on-primary, #fff); }
.f-countdown[data-color="primary"] .f-countdown__label { color: var(--color-on-primary, #fff); opacity: 0.8; }

.f-countdown__ended { margin: 0; font-weight: 600; color: var(--f-danger); }
.f-countdown__ended[hidden] { display: none; }
.f-countdown[data-ended="true"] .f-countdown__list { opacity: 0.45; }
.f-countdown__invalid { margin: 0; font-size: 0.85rem; color: var(--f-danger); }

.f-countdown__info { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0; font-size: 0.9rem; color: var(--f-text-soft); }
.f-countdown__info b { color: var(--f-text); }
.f-countdown__pre-order { display: flex; flex-direction: column; align-items: center; }
.f-countdown__button { display: inline-flex; align-items: center; gap: 0.45rem; }

/* The band: headline, copy and button around the clock, on a coloured
   (or pictured) panel. The element itself is the panel so the customizer's
   background binding and the `image` attribute paint the same surface. */
.f-countdown--band {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-lg, 1rem);
    padding: clamp(2rem, 5vw, 3.5rem) clamp(1.25rem, 4vw, 3rem);
    text-align: center;
    background-size: cover;
    background-position: center;
}
.f-countdown--band[data-theme="dark"] { background-color: #1f2430; color: #fff; }
.f-countdown--band[data-theme="light"] { background-color: var(--color-surface-alt, #f4f5f7); color: var(--f-text); }
.f-countdown--band[data-theme="primary"] { background-color: var(--color-primary, #1d9e75); color: var(--color-on-primary, #fff); }
.f-countdown--image::before { content: ""; position: absolute; inset: 0; background: rgba(0, 0, 0, 0.45); }
.f-countdown--image[data-theme="light"]::before { background: rgba(255, 255, 255, 0.7); }

.f-countdown__content { position: relative; display: flex; flex-direction: column; align-items: center; gap: 1rem; max-inline-size: 60ch; margin-inline: auto; }
.f-countdown__title { margin: 0; font-size: clamp(1.4rem, 3vw, 2rem); color: inherit; }
.f-countdown__description { margin: 0; opacity: 0.9; color: inherit; }
.f-countdown--band .f-countdown__list { margin-block: 0.5rem; }
.f-countdown--band[data-theme="primary"] .f-countdown__item { background: rgba(255, 255, 255, 0.15); border-color: rgba(255, 255, 255, 0.3); }
.f-countdown--band[data-theme="primary"] .f-countdown__button { border-color: currentColor; color: inherit; }

/* ========================================================================
   Filters — the listing sidebar
   ======================================================================== */

.f-filters { display: block; }
.f-filters[hidden] { display: none; }
.f-filters[aria-busy="true"] { opacity: 0.6; pointer-events: none; }

.f-filters__widget { border-block-end: 1px solid var(--f-border); padding-block: 0.25rem 1rem; margin-block-end: 0.75rem; }
.f-filters__widget:last-child { border-block-end: 0; }

.f-filters__title { margin: 0; font-size: 0.95rem; font-weight: 700; color: var(--f-text); }
.f-filters__title > span { display: block; padding-block: 0.6rem; }

.f-filters__toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    inline-size: 100%;
    padding: 0.6rem 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    font-weight: 700;
    text-align: start;
    cursor: pointer;
}

/* The +/- glyph: a horizontal bar always, a vertical one until open. */
.f-filters__plusminus { position: relative; inline-size: 0.75rem; block-size: 0.75rem; flex: none; }
.f-filters__plusminus::before,
.f-filters__plusminus::after {
    content: "";
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 0;
    inline-size: 100%;
    block-size: 2px;
    margin-block-start: -1px;
    background: currentColor;
    transition: transform 0.2s ease;
}
.f-filters__plusminus::after { transform: rotate(90deg); }
.f-filters__widget[data-open="true"] .f-filters__plusminus::after { transform: rotate(0deg); }

.f-filters__body { padding-block-start: 0.25rem; }
.f-filters__body[hidden] { display: none; }

.f-filters__search { inline-size: 100%; margin-block-end: 0.6rem; font-size: 0.85rem; }

.f-filters__values { display: flex; flex-direction: column; gap: 0.55rem; }

.f-filters__option {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    font-size: 0.9rem;
    color: var(--f-text);
    cursor: pointer;
}
.f-filters__option.is-selected { font-weight: 600; }
.f-filters__checkbox,
.f-filters__radio { flex: none; inline-size: 1rem; block-size: 1rem; margin: 0; accent-color: var(--color-primary, #1d9e75); cursor: pointer; }
.f-filters__option-name { flex: 1; min-inline-size: 0; }
.f-filters__count { font-size: 0.8rem; color: var(--f-text-faint); font-variant-numeric: tabular-nums; }
.f-filters__option falak-rating-stars + .f-filters__option-name { flex: none; font-size: 0.8rem; color: var(--f-text-soft); }
/* The rating row shows stars only; the "& up" qualifier stays for screen
   readers so "4 stars" is still announced as a minimum, not an exact match. */
.f-filters__option-name--sr {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.f-filters__empty { margin: 0; font-size: 0.85rem; color: var(--f-text-soft); }

.f-filters__more {
    margin-block-start: 0.6rem;
    padding: 0;
    border: 0;
    background: none;
    color: var(--color-primary, #1d9e75);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.f-filters__chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0 0 0.75rem; padding: 0; list-style: none; }
.f-filters__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.6rem;
    border-radius: 999px;
    background: rgba(29, 158, 117, 0.12);
    color: var(--f-text);
    font-size: 0.8rem;
}
.f-filters__chip-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.1rem;
    block-size: 1.1rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--f-text-soft);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}
.f-filters__chip-remove:hover { background: rgba(0, 0, 0, 0.08); color: var(--f-text); }

.f-filters__reset,
.f-filters__footer .f-btn { inline-size: 100%; justify-content: center; }
.f-filters__footer { padding-block-start: 0.5rem; }

/* ---- from packages/falak-components/src/components.account.css ---- */

/*
    Account surface — login sheet, user menu, localization sheet, offer modal
    and the review list.

    Third of the three stylesheets the entry imports; Vite's library mode
    concatenates them into one falak-components.css. Same rules as the others:
    brand tokens only, logical properties throughout.
*/

/* ========================================================================
   Login sheet
   ======================================================================== */

.f-login { display: block; }

.f-login__form { display: flex; flex-direction: column; gap: 0.65rem; margin-block-start: 0.5rem; }
.f-login__label { font-size: 0.8rem; font-weight: 600; color: var(--f-text-soft); }

.f-login__input {
    inline-size: 100%;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.95rem;
}

.f-login__input:focus {
    outline: none;
    border-color: var(--color-primary, #1d9e75);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary, #1d9e75) 18%, transparent);
}

/* Country picker beside the number. The row follows the page direction so
   the picker sits at the start edge; the code and number themselves are LTR. */
.f-login__phone-row { display: flex; gap: 0.5rem; }
.f-login__phone-row .f-login__input { flex: 1 1 auto; min-inline-size: 0; }

.f-login__dial { position: relative; flex: 0 0 auto; }

.f-login__dial-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    block-size: 100%;
    padding: 0.7rem 0.7rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.95rem;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
}

.f-login__dial-toggle:focus-visible,
.f-login__dial-toggle[aria-expanded="true"] {
    outline: none;
    border-color: var(--color-primary, #1d9e75);
}

.f-login__dial-flag {
    flex: none;
    inline-size: 1.5rem;
    block-size: 1.125rem;
    object-fit: cover;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06);
}

/* A chevron drawn from two borders; it flips while the list is open. */
.f-login__dial-chevron {
    inline-size: 0.45em;
    block-size: 0.45em;
    margin-block-start: -0.25em;
    border-inline-end: 1.5px solid currentColor;
    border-block-end: 1.5px solid currentColor;
    transform: rotate(45deg);
    transition: transform 0.15s ease;
    opacity: 0.6;
}
.f-login__dial-toggle[aria-expanded="true"] .f-login__dial-chevron {
    margin-block-start: 0.25em;
    transform: rotate(-135deg);
}

.f-login__dial-menu {
    position: absolute;
    inset-inline-start: 0;
    inset-block-start: calc(100% + 0.4rem);
    z-index: 5;
    inline-size: 16rem;
    max-inline-size: calc(100vw - 3rem);
    padding: 0.5rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    box-shadow: 0 12px 32px rgba(8, 14, 12, 0.16);
}

.f-login__dial-search { padding-block-end: 0.5rem; }
.f-login__dial-search-input {
    inline-size: 100%;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.9rem;
}
.f-login__dial-search-input:focus {
    outline: none;
    border-color: var(--color-primary, #1d9e75);
}

.f-login__dial-list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-block-size: 15rem;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.f-login__dial-option {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.45rem 0.5rem;
    border-radius: calc(var(--f-radius) * 0.75);
    font-size: 0.9rem;
    cursor: pointer;
}
.f-login__dial-option[hidden] { display: none; }
.f-login__dial-option:hover,
.f-login__dial-option[data-active] { background: rgba(0, 0, 0, 0.05); }
.f-login__dial-option[aria-selected="true"] {
    background: color-mix(in srgb, var(--color-primary, #1d9e75) 12%, transparent);
    font-weight: 600;
}
.f-login__dial-option-code { flex: none; direction: ltr; font-variant-numeric: tabular-nums; }
.f-login__dial-option-name {
    flex: 1 1 auto;
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    opacity: 0.75;
}

/* The code field is read back digit by digit, so it gets room to breathe. */
.f-login__input--code {
    text-align: center;
    font-size: 1.4rem;
    font-weight: 700;
    letter-spacing: 0.5em;
    text-indent: 0.5em;
    font-variant-numeric: tabular-nums;
}

.f-login__error {
    margin: 0;
    font-size: 0.8rem;
    color: var(--f-danger);
}

.f-login__hint {
    margin: 0;
    padding: 0.45rem 0.6rem;
    border-radius: var(--f-radius);
    background: color-mix(in srgb, var(--color-primary, #1d9e75) 10%, transparent);
    font-size: 0.78rem;
    color: var(--f-text-soft);
}

.f-login__actions {
    display: flex;
    justify-content: space-between;
    gap: 0.75rem;
    margin-block-start: 0.15rem;
}

.f-login__link {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 0.78rem;
    color: var(--color-primary, #1d9e75);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.f-login__link:disabled { color: var(--f-text-faint); cursor: default; text-decoration: none; }

/* ========================================================================
   User menu
   ======================================================================== */

.f-user { display: inline-block; position: relative; }
.f-user__wrap { position: relative; }

.f-user__trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem;
    border: 0;
    border-radius: 999px;
    background: none;
    color: inherit;
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
}

.f-user__trigger:hover { background: rgba(0, 0, 0, 0.05); }
.f-user__trigger:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }

.f-user__avatar {
    flex: none;
    inline-size: 2rem;
    block-size: 2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.f-user__avatar--lg { inline-size: 2.6rem; block-size: 2.6rem; font-size: 0.9rem; }
.f-user__name { max-inline-size: 9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.f-user__panel {
    position: absolute;
    inset-block-start: calc(100% + 0.4rem);
    inset-inline-end: 0;
    z-index: 70;
    min-inline-size: 14rem;
    padding: 0.4rem;
    background: var(--f-surface);
    border: 1px solid var(--f-border);
    border-radius: calc(var(--f-radius) * 1.2);
    box-shadow: 0 14px 36px rgba(8, 14, 12, 0.16);
}

.f-user__panel[hidden] { display: none; }

.f-user__header {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.6rem 0.65rem 0.75rem;
    border-block-end: 1px solid var(--f-border);
    margin-block-end: 0.3rem;
}

.f-user__greeting { display: flex; flex-direction: column; line-height: 1.25; min-inline-size: 0; }
.f-user__greeting small { font-size: 0.68rem; color: var(--f-text-faint); }
.f-user__greeting strong { font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.f-user__list { list-style: none; margin: 0; padding: 0; }

.f-user__link {
    inline-size: 100%;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.55rem 0.65rem;
    border: 0;
    border-radius: var(--f-radius);
    background: none;
    color: var(--f-text);
    font: inherit;
    font-size: 0.85rem;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
}

.f-user__link:hover { background: rgba(0, 0, 0, 0.05); }
.f-user__icon { flex: none; display: inline-flex; color: var(--f-text-soft); }
.f-user__item--logout { margin-block-start: 0.25rem; padding-block-start: 0.25rem; border-block-start: 1px solid var(--f-border); }
.f-user__item--logout .f-user__link { color: var(--f-danger); }
.f-user__item--logout .f-user__icon { color: currentColor; }

/* Inline is a sidebar list, not a dropdown. */
.f-user--inline { display: block; inline-size: 100%; }
.f-user--inline .f-user__link { border-radius: 0; padding-inline: 0; }

/* ========================================================================
   Localization sheet
   ======================================================================== */

.f-locale { position: relative; display: inline-block; }
.f-locale[hidden] { display: none; }
.f-locale__chevron { display: inline-flex; opacity: 0.6; transition: transform 0.18s ease; }

.f-locale__trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.6rem;
    border: 0;
    border-radius: 999px;
    background: none;
    color: inherit;
    font: inherit;
    font-size: 0.82rem;
    cursor: pointer;
}

.f-locale__trigger:hover { background: rgba(0, 0, 0, 0.05); }
.f-locale__trigger:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }
.f-locale__globe { display: inline-flex; opacity: 0.75; }
.f-locale__sep { opacity: 0.45; }

/* ---- the preferences sheet -------------------------------------------
   Two groups (language, currency) of option cards. Each card leads with a
   small code chip (AR / EN, ر.س / $), then the name, and the chosen one
   carries a check at its end. Cards sit two abreast: the sheet holds ten
   currencies without becoming a scroll, and still reads as a list on a
   phone because the names are short. */

#falak-localization .f-modal__body { max-inline-size: 30rem; }

.f-locale__group + .f-locale__group {
    margin-block-start: 1.4rem;
    padding-block-start: 1.25rem;
    border-block-start: 1px solid var(--f-border);
}

.f-locale__heading {
    margin: 0 0 0.7rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--f-text-faint);
}

.f-locale__options,
.f-currency__options {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
}

.f-locale__option,
.f-currency__option {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.65rem;
    min-inline-size: 0;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.88rem;
    line-height: 1.25;
    text-align: start;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.f-locale__option:hover,
.f-currency__option:hover {
    border-color: color-mix(in srgb, var(--color-primary, #1d9e75) 55%, var(--f-border));
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

.f-locale__option:active,
.f-currency__option:active { transform: scale(0.985); }

.f-locale__option:focus-visible,
.f-currency__option:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }

.f-locale__option-label,
.f-currency__option-label { display: flex; flex-direction: column; gap: 0.1rem; min-inline-size: 0; line-height: 1.25; }
.f-locale__option-name,
.f-currency__option-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f-locale__option-sub { font-size: 0.74rem; font-weight: 400; color: var(--f-text-faint); }

/* ---- currency as a select, and the Ok that applies both ------------- */

.f-locale__select-wrap { position: relative; display: block; }

.f-locale__select {
    inline-size: 100%;
    appearance: none;
    -webkit-appearance: none;
    padding: 0.8rem 2.6rem 0.8rem 1rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.92rem;
    cursor: pointer;
}

[dir="rtl"] .f-locale__select { padding: 0.8rem 1rem 0.8rem 2.6rem; }

.f-locale__select:hover { border-color: color-mix(in srgb, var(--color-primary, #1d9e75) 55%, var(--f-border)); }
.f-locale__select:focus-visible {
    outline: none;
    border-color: var(--color-primary, #1d9e75);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary, #1d9e75) 18%, transparent);
}

.f-locale__select-chevron {
    position: absolute;
    inset-block: 0;
    inset-inline-end: 0.9rem;
    display: inline-flex;
    align-items: center;
    pointer-events: none;
    color: var(--f-text-soft);
}

.f-locale__actions { margin-block-start: 1.5rem; }

/* The code chip leads the card; it is what the eye scans down. */
.f-locale__code,
.f-currency__code {
    order: -1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    min-inline-size: 2.5rem;
    block-size: 1.7rem;
    padding-inline: 0.45rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--f-text) 6%, transparent);
    color: var(--f-text-soft);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    font-variant-numeric: tabular-nums;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.f-locale__option.is-current,
.f-currency__option.is-current {
    border-color: var(--color-primary, #1d9e75);
    background: color-mix(in srgb, var(--color-primary, #1d9e75) 8%, var(--f-surface));
    font-weight: 600;
}

.f-locale__option.is-current .f-locale__code,
.f-currency__option.is-current .f-currency__code {
    background: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
}

/* Check mark at the end of the chosen card. */
.f-locale__option.is-current::after,
.f-currency__option.is-current::after {
    content: "";
    flex: none;
    margin-inline-start: auto;
    inline-size: 1rem;
    block-size: 1rem;
    background: var(--color-primary, #1d9e75);
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12l5 5L20 7'/></svg>") center / contain no-repeat;
    mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12l5 5L20 7'/></svg>") center / contain no-repeat;
}

@media (max-width: 380px) {
    .f-locale__options,
    .f-currency__options { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------------------
   Currency switcher — hidden entirely on a one-currency store
   ------------------------------------------------------------------------ */

.f-currency { position: relative; display: inline-block; }
.f-currency[hidden] { display: none; }

/* The trigger pill: code + chevron (+ a coin a theme may hide). */
.f-currency__field {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.6rem;
    border: 0;
    border-radius: 999px;
    background: none;
    font: inherit;
    font-size: 0.85rem;
    color: inherit;
    cursor: pointer;
    white-space: nowrap;
}

.f-currency__field:hover { background: rgba(0, 0, 0, 0.05); }
.f-currency__field:focus-visible { outline: 2px solid var(--color-primary, #1d9e75); outline-offset: 2px; }
.f-currency__icon { display: inline-flex; opacity: 0.75; }
.f-currency__current { font-weight: 600; letter-spacing: 0.02em; font-variant-numeric: tabular-nums; }
.f-currency__chevron { display: inline-flex; opacity: 0.6; transition: transform 0.18s ease; }
.f-currency.is-open .f-currency__chevron,
.f-locale.is-open .f-locale__chevron { transform: rotate(180deg); }

/* The panel hangs from the trigger's inline-end edge and opens towards the
   page; where that would leave the viewport the component sets
   --f-switch-shift to slide it back in (a `translate`, so the open
   animation's `transform` is untouched). */
.f-switch__panel {
    position: absolute;
    inset-block-start: calc(100% + 0.5rem);
    inset-inline-end: 0;
    translate: var(--f-switch-shift, 0px) 0;
    z-index: 900;
    min-inline-size: 16.5rem;
    max-inline-size: min(20rem, calc(100vw - 2rem));
    padding: 0.5rem;
    border: 1px solid var(--f-border);
    border-radius: 1rem;
    background: var(--f-surface, #fff);
    color: var(--f-text);
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.14), 0 2px 8px rgba(0, 0, 0, 0.06);
    text-align: start;
    animation: f-switch-in 0.16s ease;
}

.f-switch__panel[hidden] { display: none; }

@keyframes f-switch-in {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: none; }
}

.f-switch__title {
    margin: 0;
    padding: 0.55rem 0.75rem 0.4rem;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--f-text-faint);
}

.f-switch__list {
    display: grid;
    gap: 0.15rem;
    max-block-size: min(60vh, 24rem);
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* One row: chip, name + symbol, check. */
.f-switch__item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    inline-size: 100%;
    padding: 0.5rem 0.6rem;
    border: 0;
    border-radius: 0.75rem;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
    transition: background-color 0.12s ease;
}

.f-switch__item:hover,
.f-switch__item:focus-visible { background: color-mix(in srgb, var(--f-text) 5%, transparent); outline: none; }
.f-switch__item.is-current { background: color-mix(in srgb, var(--color-primary, #1d9e75) 10%, transparent); }
.f-switch__item.is-current:hover,
.f-switch__item.is-current:focus-visible { background: color-mix(in srgb, var(--color-primary, #1d9e75) 15%, transparent); }

.f-switch__code {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    min-inline-size: 2.75rem;
    block-size: 2.25rem;
    padding-inline: 0.4rem;
    border-radius: 0.65rem;
    background: color-mix(in srgb, var(--f-text) 6%, transparent);
    color: var(--f-text-soft);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    font-variant-numeric: tabular-nums;
}

.f-switch__item.is-current .f-switch__code {
    background: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
}

.f-switch__text { display: flex; flex-direction: column; min-inline-size: 0; gap: 0.1rem; }
.f-switch__name { font-weight: 600; font-size: 0.9rem; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f-switch__sub { font-size: 0.74rem; line-height: 1.2; color: var(--f-text-faint); }
.f-switch__item.is-current .f-switch__name { font-weight: 700; }

.f-switch__item.is-current::after {
    content: "";
    flex: none;
    margin-inline-start: auto;
    inline-size: 1rem;
    block-size: 1rem;
    background: var(--color-primary, #1d9e75);
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12l5 5L20 7'/></svg>") center / contain no-repeat;
    mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12l5 5L20 7'/></svg>") center / contain no-repeat;
}

@media (prefers-reduced-motion: reduce) {
    .f-switch__panel { animation: none; }
    .f-currency__chevron,
    .f-locale__chevron { transition: none; }
}

/* Inside the preferences sheet the host must fill the row, or the option
   grid shrink-wraps to one narrow column. The option cards themselves share
   the language cards' rules above. */
.f-locale__group > falak-currency,
.f-currency[inline] { display: block; }

/* ========================================================================
   Comments / reviews
   ======================================================================== */

.f-comments { display: block; }
.f-comments[hidden] { display: none; }

.f-comments__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-block-end: 1rem;
}

.f-comments__title { margin: 0; font-size: 1.1rem; font-weight: 700; }
.f-comments__empty { margin: 0; padding: 1.5rem 0; color: var(--f-text-soft); font-size: 0.88rem; }

.f-comments__gate {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.9rem 1.1rem;
    border: 1px dashed var(--f-border);
    border-radius: var(--f-radius);
    margin-block-end: 1.25rem;
}

.f-comments__gate p { margin: 0; font-size: 0.85rem; color: var(--f-text-soft); }

.f-comments__form {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    align-items: flex-start;
    padding: 1.1rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    margin-block-end: 1.5rem;
}

.f-comments__rating { display: flex; align-items: center; gap: 0.6rem; }
.f-comments__label { font-size: 0.82rem; font-weight: 600; color: var(--f-text-soft); }

.f-comments__textarea {
    inline-size: 100%;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.9rem;
    resize: vertical;
}

.f-comments__textarea:focus {
    outline: none;
    border-color: var(--color-primary, #1d9e75);
}

.f-comments__error { margin: 0; font-size: 0.8rem; color: var(--f-danger); }

.f-comments__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.1rem; }
.f-comments__item { padding-block-end: 1.1rem; border-block-end: 1px solid var(--f-border); }
.f-comments__item:last-child { border-block-end: 0; padding-block-end: 0; }

.f-comments__meta { display: flex; align-items: center; gap: 0.65rem; margin-block-end: 0.4rem; }

.f-comments__avatar {
    flex: none;
    inline-size: 2rem;
    block-size: 2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.06);
    color: var(--f-text-soft);
    font-size: 0.75rem;
    font-weight: 700;
}

/*
    The name block must NOT stretch (`flex: 1` pushed the stars to the far
    edge of the row, a screen-width away from the name they belong to).
    Avatar, name and stars sit together as one group at the reading start.
*/
.f-comments__meta > div { display: flex; flex-direction: column; line-height: 1.3; min-inline-size: 0; }
.f-comments__author { font-size: 0.85rem; }
.f-comments__date { font-size: 0.72rem; color: var(--f-text-faint); }
.f-comments__text { margin: 0; font-size: 0.88rem; line-height: 1.65; color: var(--f-text-soft); }
.f-comments__more { display: flex; justify-content: center; margin-block-start: 1.25rem; }

@media (prefers-reduced-motion: reduce) {
    .f-locale__option { transition: none; }
}

/* Signed in but nothing to review against — a statement, not a call to action. */
.f-comments__gate--quiet {
    justify-content: flex-start;
    border-style: solid;
    background: rgba(0, 0, 0, 0.02);
}

/* A submitted review acknowledged while it waits for moderation. */
.f-comments__pending {
    margin: 0 0 1rem;
    padding: 0.7rem 1rem;
    border-radius: var(--f-radius);
    border: 1px solid color-mix(in srgb, var(--color-primary, #1d9e75) 35%, transparent);
    background: color-mix(in srgb, var(--color-primary, #1d9e75) 8%, transparent);
    font-size: 0.85rem;
    color: var(--f-text);
}


/* ========================================================================
   Offers list — the React SpecialOffersModal, laid inline as a section
   ======================================================================== */

.f-offers { display: block; }
.f-offers[hidden] { display: none; }

.f-offers__title { margin: 0 0 1rem; font-size: 1.25rem; font-weight: 700; }

.f-offers__grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 1rem;
}

.f-offers__card {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 1.1rem 1.2rem;
    border: 1px dashed color-mix(in srgb, var(--color-primary, #1d9e75) 45%, transparent);
    border-radius: calc(var(--f-radius) * 1.4);
    background: color-mix(in srgb, var(--color-primary, #1d9e75) 6%, var(--f-surface));
}

.f-offers__benefit {
    font-size: 1.15rem;
    font-weight: 800;
    color: var(--color-primary, #1d9e75);
}

.f-offers__name { margin: 0; font-size: 0.95rem; font-weight: 700; color: var(--f-text); }
.f-offers__text { margin: 0; font-size: 0.82rem; color: var(--f-text-soft); line-height: 1.55; }

.f-offers__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem 0.9rem;
    margin-block-start: 0.3rem;
    font-size: 0.72rem;
    color: var(--f-text-faint);
}

/* ========================================================================
   Offers banner — the legacy OffersBanner strip + its list modal trigger
   ======================================================================== */

.f-offer-banner { display: block; }
.f-offer-banner[hidden] { display: none; }

.f-offer-banner__strip {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    padding: 0.5rem 1rem;
    background: color-mix(in srgb, var(--color-primary, #1d9e75) 10%, var(--f-surface));
    border-block-end: 1px solid color-mix(in srgb, var(--color-primary, #1d9e75) 25%, transparent);
    font-size: 0.85rem;
}

.f-offer-banner__text { font-weight: 600; color: var(--f-text); }

.f-offer-banner__more {
    padding: 0.25rem 0.9rem;
    border: 1px solid var(--color-primary, #1d9e75);
    border-radius: 999px;
    background: transparent;
    color: var(--color-primary, #1d9e75);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.f-offer-banner__more:hover {
    background: var(--color-primary, #1d9e75);
    color: var(--color-on-primary, #fff);
}

/* ========================================================================
   Product questions & answers
   ======================================================================== */

.f-questions { display: block; }
.f-questions[hidden] { display: none; }
.f-questions[aria-busy="true"] { opacity: 0.6; pointer-events: none; }

.f-questions__header { margin-block-end: 1rem; }
.f-questions__header-row { display: flex; align-items: center; gap: 0.75rem; }

.f-questions__badge {
    flex: none;
    inline-size: 2.6rem;
    block-size: 2.6rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--f-radius);
    background: rgba(0, 0, 0, 0.06);
}

.f-questions__title { margin: 0; font-size: 1.15rem; font-weight: 700; }
.f-questions__subtitle { margin: 0.4rem 0 0; font-size: 0.85rem; color: var(--f-text-soft); }

.f-questions__gate {
    display: block;
    inline-size: 100%;
    padding: 0.9rem 1.1rem;
    border: 1px dashed var(--f-border);
    border-radius: var(--f-radius);
    background: none;
    color: var(--f-text-soft);
    font: inherit;
    font-size: 0.87rem;
    text-align: center;
    cursor: pointer;
    margin-block-end: 1.25rem;
}

.f-questions__form {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    padding: 1.1rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    margin-block-end: 1.5rem;
}

.f-questions__form-title {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.95rem;
    font-weight: 600;
}

.f-questions__textarea {
    inline-size: 100%;
    min-block-size: 5.5rem;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: var(--f-text);
    font: inherit;
    font-size: 0.9rem;
    resize: vertical;
}

.f-questions__textarea:focus { outline: none; border-color: var(--color-primary, #1d9e75); }

.f-questions__form-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.f-questions__anonymous {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.85rem;
    color: var(--f-text-soft);
    cursor: pointer;
    user-select: none;
}

.f-questions__error { margin: 0; font-size: 0.8rem; color: var(--f-danger); }

.f-questions__list-title { margin: 0 0 1rem; font-size: 1rem; font-weight: 600; }
.f-questions__list { display: grid; gap: 1rem; }

.f-questions__item {
    padding: 1.1rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
}

.f-questions__meta { display: flex; align-items: center; gap: 0.65rem; margin-block-end: 0.5rem; }

.f-questions__avatar {
    flex: none;
    inline-size: 2.25rem;
    block-size: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.06);
    color: var(--f-text-soft);
    font-size: 0.8rem;
    font-weight: 700;
}

.f-questions__who { display: flex; flex-direction: column; gap: 0.1rem; }
.f-questions__name { font-size: 0.87rem; }
.f-questions__time { font-size: 0.72rem; color: var(--f-text-soft); }

.f-questions__text { margin: 0 0 0.75rem; font-size: 0.92rem; line-height: 1.6; }

.f-questions__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding-block-start: 0.75rem;
    border-block-start: 1px solid var(--f-border);
}

.f-questions__count {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    color: var(--f-text-soft);
}

.f-questions__toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.35rem 0.7rem;
    border: none;
    border-radius: var(--f-radius);
    background: none;
    color: var(--color-primary, #1d9e75);
    font: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

.f-questions__toggle:hover { background: rgba(0, 0, 0, 0.05); }

.f-questions__replies {
    margin-block-start: 0.9rem;
    padding-block-start: 0.9rem;
    border-block-start: 1px solid var(--f-border);
    display: grid;
    gap: 0.7rem;
}

.f-questions__reply { padding: 0.85rem; border-radius: var(--f-radius); background: rgba(0, 0, 0, 0.03); }

.f-questions__reply-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-block-end: 0.4rem;
}

.f-questions__replier {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border-radius: 0.4rem;
    font-size: 0.78rem;
    font-weight: 600;
}

.f-questions__replier--admin { color: var(--f-success, #28a745); background: rgba(40, 167, 69, 0.1); }
.f-questions__replier--customer { color: var(--color-primary, #1d9e75); background: rgba(0, 0, 0, 0.05); }

.f-questions__reply-text { margin: 0; font-size: 0.85rem; line-height: 1.55; color: var(--f-text-soft); }

.f-questions__empty { text-align: center; padding: 2.5rem 1rem; }

.f-questions__empty-icon {
    inline-size: 4.5rem;
    block-size: 4.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: var(--color-primary, #1d9e75);
    margin-block-end: 1rem;
}

.f-questions__empty-title { margin: 0 0 0.4rem; font-size: 1.05rem; font-weight: 600; }
.f-questions__empty-text { margin: 0; font-size: 0.88rem; color: var(--f-text-soft); }

/* ========================================================================
   User profile — the customer's editable details
   ======================================================================== */
.f-profile { display: block; }
.f-profile__guest {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 2rem 1rem;
    text-align: center;
    opacity: 0.9;
}
.f-profile__icon { opacity: 0.5; }
.f-profile__stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
    gap: 0.75rem;
    margin: 0 0 1.5rem;
    padding: 0;
    list-style: none;
}
.f-profile__stat {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.85rem 1rem;
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 0.75rem;
    background: rgba(0, 0, 0, 0.02);
}
.f-profile__stat-value { font-size: 1.35rem; font-weight: 700; line-height: 1.1; }
.f-profile__stat-label { font-size: 0.8rem; opacity: 0.7; }
.f-profile__form { display: flex; flex-direction: column; gap: 1rem; }
.f-profile__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 1rem; }
.f-profile__field--address { grid-column: 1 / -1; }
.f-profile__input { inline-size: 100%; }
.f-profile__custom-fields { display: flex; flex-direction: column; gap: 0.4rem; padding-block-start: 0.25rem; border-block-start: 1px solid var(--f-border); }
.f-field__error { font-size: 0.8rem; color: var(--f-danger, #b91c1c); }
.f-profile__error { margin: 0; font-size: 0.9rem; color: var(--f-danger, #b91c1c); }
.f-profile__actions { display: flex; justify-content: flex-end; }
.f-profile[aria-busy="true"] .f-profile__save { opacity: 0.6; pointer-events: none; }

/* ========================================================================
   Order — one order: banner, header, progress, products, downloads, payment,
   address, tracking, actions, info. Compact mode keeps items + totals only.
   ======================================================================== */
.f-order { display: flex; flex-direction: column; gap: 1.25rem; }
.f-order__guest, .f-order__empty, .f-order__loading { text-align: center; padding: 1.5rem 1rem; opacity: 0.85; }
.f-order__skeleton { display: flex; flex-direction: column; gap: 1rem; }
.f-order__guest { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; }
.f-order__icon { inline-size: 1em; block-size: 1em; vertical-align: -0.15em; flex: none; }

.f-order__card {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.25rem;
    border: 1px solid var(--f-border);
    border-radius: calc(var(--f-radius) * 1.5);
    background: var(--f-surface);
}
.f-order__card-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.f-order__card-title { display: flex; align-items: center; gap: 0.5rem; margin: 0; font-size: 1.05rem; font-weight: 700; }
.f-order__card-title .f-order__icon { inline-size: 1.15em; block-size: 1.15em; }

/* Two columns: the order on the start side, the cards about it on the end side. */
.f-order__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.25rem; align-items: start; }
.f-order__main, .f-order__side { display: flex; flex-direction: column; gap: 1.25rem; min-inline-size: 0; }
@media (min-width: 900px) {
    .f-order__grid { grid-template-columns: minmax(0, 1fr) 19rem; }
}

/* ---- banner: payment required / failed / cancelled ---- */
.f-order__banner {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.9rem 1.1rem;
    border: 1px solid;
    border-radius: var(--f-radius);
    font-size: 0.92rem;
}
.f-order__banner-icon { flex: none; display: inline-flex; }
.f-order__banner-icon .f-order__icon { inline-size: 1.25rem; block-size: 1.25rem; }
.f-order__banner-text { flex: 1; margin: 0; display: flex; flex-wrap: wrap; gap: 0.25rem 0.5rem; }
.f-order__banner-cta { flex: none; }
.f-order__banner--warn { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.f-order__banner--danger { background: #fef2f2; border-color: #fecaca; color: #991b1b; }
.f-order__banner--muted { background: rgba(0, 0, 0, 0.03); border-color: var(--f-border); color: var(--f-text-soft); }

/* ---- header ---- */
.f-order__head { flex-direction: row; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.f-order__head-main { display: flex; flex-direction: column; gap: 0.6rem; min-inline-size: 0; }
.f-order__title { margin: 0; font-size: 1.35rem; font-weight: 800; overflow-wrap: anywhere; }
.f-order__pills { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.f-order__meta { margin: 0; display: flex; flex-wrap: wrap; gap: 0.35rem; font-size: 0.85rem; color: var(--f-text-soft); }
.f-order__meta-sep { opacity: 0.6; }
.f-order__invoice { flex: none; }
.f-order__status, .f-order__pay-status {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3rem 0.75rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.06);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: capitalize;
    white-space: nowrap;
}
.f-order__status--pending, .f-order__status--awaiting_payment { background: #fef3c7; color: #92400e; }
.f-order__status--processing, .f-order__status--in_processing { background: #dbeafe; color: #1e40af; }
.f-order__status--shipped, .f-order__status--out_for_delivery { background: #ede9fe; color: #5b21b6; }
.f-order__status--delivered, .f-order__status--completed, .f-order__status--waiting_for_review { background: #dcfce7; color: #166534; }
.f-order__status--cancelled, .f-order__status--returned { background: #fee2e2; color: #991b1b; }
.f-order__status--refunded { background: #ccfbf1; color: #115e59; }
.f-order__status--locked { background: rgba(0, 0, 0, 0.06); color: var(--f-text-soft); }
.f-order__status--return-pending { background: #fef3c7; color: #92400e; }
.f-order__status--return-approved, .f-order__status--return-return_received, .f-order__status--return-refunded { background: #dcfce7; color: #166534; }
.f-order__status--return-rejected { background: #fee2e2; color: #991b1b; }
.f-order__pay-status--paid, .f-order__pay-status--completed { background: #dcfce7; color: #166534; }
.f-order__pay-status--pending, .f-order__pay-status--unpaid { background: #fef3c7; color: #92400e; }
.f-order__pay-status--failed { background: #fee2e2; color: #991b1b; }
.f-order__pay-status--refunded, .f-order__pay-status--partially_refunded { background: #ccfbf1; color: #115e59; }

.f-order__tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.25rem 0.6rem;
    border: 1px solid var(--f-border);
    border-radius: 999px;
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--f-text-soft);
    white-space: nowrap;
}
.f-order__tag--sm { padding: 0.1rem 0.5rem; font-size: 0.7rem; }
.f-order__tag--success { background: #ecfdf5; border-color: #a7f3d0; color: #047857; }
.f-order__tag--warn { background: #fffbeb; border-color: #fde68a; color: #b45309; }
.f-order__badge {
    display: inline-block;
    padding: 0.2rem 0.55rem;
    border-radius: 0.4rem;
    background: rgba(0, 0, 0, 0.05);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.72rem;
    color: var(--f-text-soft);
    white-space: nowrap;
}

/* ---- locked box: progress / tracking before payment ---- */
.f-order__locked {
    align-items: center;
    text-align: center;
    border-style: dashed;
    padding-block: 1.75rem;
    color: var(--f-text-soft);
}
.f-order__locked--inline { padding: 1.25rem 1rem; border: 1px dashed var(--f-border); border-radius: var(--f-radius); background: rgba(0, 0, 0, 0.02); gap: 0.5rem; display: flex; flex-direction: column; }
.f-order__locked-icon { display: inline-flex; opacity: 0.6; }
.f-order__locked-icon .f-order__icon { inline-size: 1.4rem; block-size: 1.4rem; }
.f-order__locked-text { margin: 0; font-size: 0.9rem; }

/* ---- progress stepper: a row on wide screens, a list on narrow ---- */
.f-order__steps { position: relative; margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 1rem; }
.f-order__step { position: relative; display: flex; gap: 0.85rem; padding-inline-start: 0.25rem; }
.f-order__step-line { position: absolute; inset-inline-start: 0.85rem; inset-block-start: 1.35rem; inset-block-end: -1.1rem; border-inline-start: 2px solid var(--f-border); }
.f-order__step-line.is-done { border-color: #16a34a; }
.f-order__step-dot {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.35rem;
    block-size: 1.35rem;
    border-radius: 50%;
    border: 2px solid var(--f-border);
    background: var(--f-surface);
    color: #fff;
    z-index: 1;
}
.f-order__step-dot .f-order__icon { inline-size: 0.8rem; block-size: 0.8rem; }
.f-order__step.is-done .f-order__step-dot { border-color: #16a34a; background: #16a34a; }
.f-order__step.is-current .f-order__step-dot { border-color: var(--f-text); background: var(--f-surface); box-shadow: inset 0 0 0 3px var(--f-surface), inset 0 0 0 8px var(--f-text); }
.f-order__step:not(.is-done):not(.is-current) .f-order__step-body { opacity: 0.5; }
.f-order__step-body { display: flex; flex-direction: column; gap: 0.1rem; min-inline-size: 0; }
.f-order__step-title { font-size: 0.85rem; }
.f-order__step-text, .f-order__step-date { font-size: 0.75rem; color: var(--f-text-soft); }
@media (min-width: 720px) {
    .f-order__steps { flex-direction: row; align-items: flex-start; gap: 0; padding-block-start: 0.25rem; }
    .f-order__step { flex: 1; flex-direction: column; align-items: center; text-align: center; padding: 0; gap: 0.5rem; }
    .f-order__step-line { inset-inline-start: 50%; inset-inline-end: -50%; inset-block-start: 0.6rem; inset-block-end: auto; border-inline-start: 0; border-block-start: 2px solid var(--f-border); }
    .f-order__step-line.is-done { border-color: #16a34a; }
    .f-order__step-body { align-items: center; padding-inline: 0.25rem; }
    .f-order__step-text { display: none; }
    .f-order__step[title]:hover .f-order__step-text {
        display: block;
        position: absolute;
        inset-block-end: calc(100% + 0.35rem);
        inset-inline-start: 50%;
        transform: translateX(-50%);
        padding: 0.35rem 0.6rem;
        border-radius: 0.4rem;
        background: var(--f-text);
        color: var(--f-surface);
        font-size: 0.72rem;
        white-space: nowrap;
        z-index: 2;
    }
    [dir="rtl"] .f-order__step[title]:hover .f-order__step-text { transform: translateX(50%); }
}

/* ---- products ---- */
.f-order__items { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.75rem; }
.f-order__item { display: flex; align-items: flex-start; gap: 0.85rem; padding: 0.85rem; border-radius: var(--f-radius); background: rgba(0, 0, 0, 0.025); }
.f-order--compact .f-order__item, .f-order[compact] .f-order__item { padding: 0; background: none; align-items: center; }
.f-order__item-image { flex: none; inline-size: 3.25rem; block-size: 3.25rem; object-fit: cover; border-radius: 0.5rem; background: rgba(0, 0, 0, 0.05); }
.f-order__item-image--empty { display: inline-flex; align-items: center; justify-content: center; color: var(--f-text-faint); }
.f-order__item-info { flex: 1; display: flex; flex-direction: column; gap: 0.3rem; min-inline-size: 0; }
.f-order__item-name { font-weight: 600; color: inherit; text-decoration: none; overflow-wrap: anywhere; }
.f-order__item-meta { font-size: 0.82rem; color: var(--f-text-soft); }
.f-order__item-tags { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.f-order__item-tags:empty { display: none; }
.f-order__item-total { font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
.f-order__item-rate { align-self: flex-start; margin-block-start: 0.25rem; }
.f-order__item-reviewed { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: var(--f-text-soft); }

/* ---- digital downloads ---- */
.f-order__files { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.6rem; }
.f-order__file { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 0.85rem; border-radius: var(--f-radius); background: rgba(0, 0, 0, 0.025); }
.f-order__file-icon { flex: none; display: inline-flex; color: var(--f-text-soft); }
.f-order__file-info { flex: 1; display: flex; flex-direction: column; gap: 0.15rem; min-inline-size: 0; }
.f-order__file-name { font-weight: 600; overflow-wrap: anywhere; }
.f-order__file-meta { font-size: 0.78rem; color: var(--f-text-soft); }
.f-order__file-meta--warn { color: #b45309; }

/* ---- the customer's review ---- */
.f-order__review-text { margin: 0; font-size: 0.92rem; line-height: 1.55; }
.f-order__review-reply { display: flex; flex-direction: column; gap: 0.25rem; padding: 0.85rem; border-inline-start: 3px solid var(--f-border); background: rgba(0, 0, 0, 0.025); border-radius: 0 var(--f-radius) var(--f-radius) 0; font-size: 0.88rem; }
.f-order__review-reply time { font-size: 0.75rem; color: var(--f-text-soft); }
.f-order__review-reply p { margin: 0; }

/* ---- payment details + totals ---- */
.f-order__pay-rows { display: flex; flex-direction: column; gap: 0.5rem; }
.f-order__pay-row { display: flex; align-items: center; gap: 0.75rem; padding: 0.7rem 0.85rem; border-radius: var(--f-radius); background: rgba(0, 0, 0, 0.025); }
.f-order__pay-row-icon { flex: none; display: inline-flex; color: var(--f-text-soft); }
.f-order__pay-row-body { flex: 1; display: flex; flex-direction: column; gap: 0.1rem; min-inline-size: 0; }
.f-order__pay-row-label { font-size: 0.75rem; color: var(--f-text-soft); }
.f-order__pay-row-value { font-weight: 600; font-size: 0.92rem; }
.f-order__pay-failed { display: flex; align-items: center; gap: 0.6rem; padding: 0.7rem 0.85rem; border-radius: var(--f-radius); background: #fef2f2; color: #991b1b; font-size: 0.85rem; }
.f-order__pay-failed span:nth-child(2) { flex: 1; }
.f-order__section { display: flex; flex-direction: column; gap: 0.75rem; }
.f-order__section-title { margin: 0; font-size: 0.95rem; font-weight: 700; opacity: 0.85; }
.f-order__totals { gap: 0.45rem; padding: 0.25rem 0 0; }
.f-order[compact] .f-order__totals { padding: 1rem; border-radius: 0.75rem; background: rgba(0, 0, 0, 0.03); }
.f-order__row { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.92rem; color: var(--f-text-soft); }
.f-order__row > span:first-child { display: flex; flex-direction: column; gap: 0.05rem; }
.f-order__row > span:last-child { color: var(--f-text); font-variant-numeric: tabular-nums; }
.f-order__row-note { font-size: 0.72rem; color: var(--f-text-faint); }
.f-order__row--discount > span:last-child { color: #15803d; }
.f-order__row--total { margin-block-start: 0.35rem; padding-block-start: 0.7rem; border-block-start: 1px solid var(--f-border); font-weight: 700; font-size: 1.05rem; color: var(--f-text); }
/* The gateway's own currency, when it differs from what the shopper reads. */
.f-order__charged { margin: 0.4rem 0 0; font-size: 0.8rem; color: var(--f-text-faint); font-variant-numeric: tabular-nums; }

/* ---- sidebar cards ---- */
.f-order__detail-text { margin: 0; font-size: 0.9rem; line-height: 1.55; }
.f-order__contact { display: flex; flex-direction: column; gap: 0.35rem; padding-block-start: 0.75rem; border-block-start: 1px solid var(--f-border); color: var(--f-text-soft); font-size: 0.85rem; }
.f-order__contact > span { display: inline-flex; align-items: center; gap: 0.4rem; }
.f-order__kvs { display: flex; flex-direction: column; gap: 0.35rem; }
.f-order__kv { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.55rem 0.75rem; border-radius: var(--f-radius); background: rgba(0, 0, 0, 0.025); font-size: 0.85rem; }
.f-order__kv-label { color: var(--f-text-soft); }
.f-order__kv-value { font-weight: 600; text-align: end; overflow-wrap: anywhere; }
.f-order__kv-value.is-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.8rem; }
.f-order__kv-value.is-positive { color: #15803d; }
.f-order__kv-value.is-negative { color: #b91c1c; }
.f-order__tracking-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; }
.f-order__link { font-size: 0.85rem; font-weight: 600; color: var(--color-primary, #1d9e75); text-decoration: none; }
.f-order__link:hover { text-decoration: underline; }
.f-order__action-list { display: flex; flex-direction: column; gap: 0.6rem; }
.f-order__action-list .f-btn { justify-content: center; }
.f-order__return-status { margin: 0; display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; color: var(--f-text-soft); }
.f-order__cancel { color: #b91c1c; }

/* ---- dialogs: pay, invoice, return, rate, track ---- */
.f-order-dialog { display: flex; flex-direction: column; gap: 1rem; }
.f-order-dialog__hint { margin: 0; font-size: 0.9rem; color: var(--f-text-soft); line-height: 1.5; }
.f-order-dialog__subtitle { margin: 0.25rem 0 0; font-size: 0.9rem; font-weight: 700; }
.f-order-dialog__error { margin: 0; padding: 0.6rem 0.85rem; border-radius: var(--f-radius); background: #fef2f2; color: #991b1b; font-size: 0.85rem; }
.f-order-dialog__error[hidden] { display: none; }
.f-order-dialog__choices { display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); gap: 0.6rem; }
.f-order-dialog__choices .f-btn { justify-content: center; }
.f-order-dialog__summary { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.75rem 0.9rem; border-radius: var(--f-radius); background: rgba(0, 0, 0, 0.035); font-size: 0.9rem; }
.f-order-dialog__methods { display: flex; flex-direction: column; gap: 0.5rem; min-block-size: 3rem; justify-content: center; }
.f-order-dialog__method {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
    background: var(--f-surface);
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
}
.f-order-dialog__method img { inline-size: 2.25rem; block-size: 2.25rem; object-fit: contain; border-radius: 0.4rem; }
.f-order-dialog__method-icon { display: inline-flex; inline-size: 2.25rem; block-size: 2.25rem; align-items: center; justify-content: center; border-radius: 0.4rem; background: rgba(0, 0, 0, 0.05); color: var(--f-text-soft); }
.f-order-dialog__method:hover { border-color: var(--f-text-faint); }
.f-order-dialog__method.is-selected { border-color: var(--color-primary, #1d9e75); box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary, #1d9e75) 25%, transparent); }
.f-order-dialog__form { display: flex; flex-direction: column; gap: 0.9rem; }
.f-order-dialog__stars { display: flex; justify-content: center; padding-block: 0.25rem; font-size: 1.6rem; }
.f-order-dialog__footer { display: flex; justify-content: flex-end; gap: 0.6rem; flex-wrap: wrap; }
.f-order__events { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.6rem; max-block-size: 18rem; overflow-y: auto; }
.f-order__event { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.6rem 0.75rem; border-inline-start: 3px solid var(--f-border); background: rgba(0, 0, 0, 0.025); font-size: 0.85rem; }
.f-order__event:first-child { border-color: #16a34a; }
.f-order__event-meta { font-size: 0.75rem; color: var(--f-text-soft); }

/* ========================================================================
   Orders list — status filter, search, paged
   ======================================================================== */

.f-orders__guest { text-align: center; padding: 1.5rem 1rem; opacity: 0.85; display: flex; flex-direction: column; align-items: center; gap: 0.75rem; }
.f-orders__skeleton { padding: 0.5rem 0; }

.f-orders__toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-block-end: 1.25rem;
}
.f-orders__search { flex: 1; min-inline-size: 12rem; }
.f-orders__filter { flex: none; min-inline-size: 10rem; }

.f-orders__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }

.f-orders__row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.9rem 1rem;
    border: 1px solid var(--f-border);
    border-radius: var(--f-radius);
}

.f-orders__main { flex: 1; display: flex; flex-direction: column; gap: 0.15rem; min-inline-size: 0; text-decoration: none; color: inherit; }
.f-orders__number { font-weight: 700; }
.f-orders__date { font-size: 0.82rem; color: var(--f-text-soft); }

.f-orders__status {
    flex: none;
    padding: 0.25rem 0.7rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.06);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: capitalize;
}
.f-orders__status--pending, .f-orders__status--awaiting_payment { background: #fef3c7; color: #92400e; }
.f-orders__status--processing { background: #dbeafe; color: #1e40af; }
.f-orders__status--shipped, .f-orders__status--out_for_delivery { background: #e0e7ff; color: #3730a3; }
.f-orders__status--delivered, .f-orders__status--completed { background: #dcfce7; color: #166534; }
.f-orders__status--cancelled, .f-orders__status--refunded, .f-orders__status--returned { background: #fee2e2; color: #991b1b; }

.f-orders__total { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; }
.f-orders__more { display: flex; justify-content: center; margin-block-start: 1.25rem; }

/* ========================================================================
   Notification item — one row of a customer's notification history
   ======================================================================== */

.f-notification-item { display: block; }

.f-notification-item__link,
.f-notification-item {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    text-decoration: none;
    color: inherit;
}

.f-notification-item__icon {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.25rem;
    block-size: 2.25rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-primary, #1d9e75) 12%, transparent);
    color: var(--color-primary, #1d9e75);
}

.f-notification-item__text { flex: 1; display: flex; flex-direction: column; gap: 0.15rem; min-inline-size: 0; }
.f-notification-item__title { font-size: 0.92rem; }
.f-notification-item__body { font-size: 0.85rem; color: var(--f-text-soft); }
.f-notification-item__time { font-size: 0.78rem; color: var(--f-text-soft); }

.f-notification-item__dot {
    flex: none;
    inline-size: 0.5rem;
    block-size: 0.5rem;
    margin-block-start: 0.4rem;
    border-radius: 50%;
    background: var(--color-primary, #1d9e75);
}

.f-notification-item.is-unread { background: color-mix(in srgb, var(--color-primary, #1d9e75) 5%, transparent); }

/* ========================================================================
   Custom fields — merchant-defined form fields
   ======================================================================== */

.f-custom-fields { display: flex; flex-direction: column; gap: 1rem; }
.f-custom-fields__field falak-file-upload { margin-block-start: 0.35rem; }

.f-custom-fields__options { display: flex; flex-wrap: wrap; gap: 0.75rem 1.25rem; }

.f-custom-fields__option {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.9rem;
    cursor: pointer;
}

/* ==== END SDK COMPONENT CLASSES ==== */

/* ------------------------------------------------ platform components */
/*
    WHERE A DEVELOPER RESTYLES THE SDK COMPONENTS.

    The platform links /sdk/falak-components.css BEFORE this file and wraps
    it in `@layer falak`, and the full class list is copied into the block
    above. Rules here beat both: the SDK's layered sheet on layering, the
    copy on source order — match the copied rule's specificity and no
    !important is ever needed. There are three levels, cheapest first:

      1. Tokens.  The SDK reads --color-primary, --radius-sm, --color-border…
         from :root above, so the theme palette already reaches every
         component with no rule at all.
      2. Component variables.  Some components expose their own knobs
         (--f-announce-bg, --f-announce-fg, --f-slider-per-view).
      3. Selectors.  Target the SDK's class (.f-btn, .f-modal__body) or the
         element itself (falak-announcement, falak-quantity-input) and write
         normal CSS. Class names are a stable contract across SDK releases.
*/

/* 2. Announcement bar: the brand colour, with the theme's close
      affordance. --color-primary-dark is the hover shade for primary
      buttons, not a brand token. The class rules further down paint the
      strip at higher specificity; this keeps the variable chain in
      agreement so either route lands on the same colour. */
falak-announcement {
    --f-announce-bg: var(--color-primary);
    --f-announce-fg: var(--color-on-primary);
}
falak-announcement .f-announce__close:hover { background: rgba(255, 255, 255, 0.25); }

/* 3. Any SDK class can be overridden by name — the SDK sheet
      (/sdk/falak-components.css) is the reference for what exists. Here the
      bar gets the theme's taller rhythm; every other property stays the
      SDK's. */
.f-announce__inner { min-height: 2.75rem; }
/* Padding only for the centred bar: in marquee mode the copied rule
   `.f-announce--scroll .f-announce__inner` (two classes) zeroes it so the
   text can run edge to edge. Overrides must match the copied rule's
   specificity — the copy above is unlayered, unlike the SDK's own sheet. */
falak-announcement:not(.f-announce--scroll) .f-announce__inner { padding-inline: 3rem; }

/* Marquee: a seamless chain rather than the SDK's two-copy loop.

   The component scrolls merchant declarations whatever their length, over a
   track holding the message twice and travelling half its width. That only
   reads as continuous while one message is wider than the strip: a short
   message on a wide screen left most of the bar empty and snapped when the
   loop restarted. app.js repeats the message until the track covers the bar
   plus one spare copy and publishes one copy's width as --announce-step, so
   the loop travels exactly one copy and the frame it ends on is the frame it
   began on — unbroken text, no empty stretch, nothing to snap back to.

   The 50% fallback is the SDK's own distance over its two copies, so the bar
   still loops correctly if the script never runs.

   Direction follows the document, as the SDK's keyframes do: ltr drifts
   leftward so text enters at the right, rtl mirrors it. The SDK's
   timing-function, iteration count and :hover pause all still apply. */
falak-announcement.f-announce--scroll .f-announce__track {
    animation-name: announce-chain-ltr;
    animation-duration: var(--announce-chain-duration, 9s);
}
falak-announcement.f-announce--scroll[dir="rtl"] .f-announce__track { animation-name: announce-chain-rtl; }
@keyframes announce-chain-ltr {
    from { transform: translateX(0); }
    to   { transform: translateX(calc(-1 * var(--announce-step, 50%))); }
}
@keyframes announce-chain-rtl {
    from { transform: translateX(0); }
    to   { transform: translateX(var(--announce-step, 50%)); }
}
/* The SDK's own reduced-motion `animation: none` is (0,1,0) and the rules
   above out-rank it, so it must be restated at their specificity. */
@media (prefers-reduced-motion: reduce) {
    falak-announcement.f-announce--scroll .f-announce__track { animation: none; }
}


/* 3. SDK buttons rendered without `button-class` (user menu, modals, the
      default add button) take this theme's .btn shape, so every button on
      the page shares one silhouette. */
.f-btn {
    padding: 0.7rem 1.6rem;
    min-block-size: auto;
    border-radius: var(--radius-sm);
    line-height: 1.4;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.f-btn:hover:not(:disabled) { opacity: 1; }
.f-btn--primary:hover:not(:disabled) { background: var(--color-primary-dark); }
.f-btn:active:not(:disabled) { transform: translateY(1px); }

/* 3. Cards the SDK renders (home grid, sliders) carry the same buy button
      as the Twig card (.btn--card) so both card kinds look alike. */
.f-card__add {
    padding: 0.55rem 1rem;
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.f-card__add:active:not(:disabled) { transform: translateY(1px); }
.f-card__wishlist { border-radius: var(--radius-sm); }

/* 3. Header cart entry: the platform component wearing this theme's
      .cart-link outline. */
.cart-link .f-cart-summary__link { gap: 0.5rem; }
.cart-link .f-cart-summary__icon { width: auto; height: auto; background: transparent; }
.cart-link .f-cart-summary__count { position: static; margin-inline-start: 0.1rem; }
.cart-link .f-cart-summary__label { display: none; }
.cart-link .f-cart-summary__total { font-size: 0.9rem; }

/* 3. Modals and dropdowns follow the theme's radius and shadow rather than
      the SDK's derived ones. */
.f-modal__body { border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.f-menu__list--sub { border-radius: var(--radius); box-shadow: var(--shadow); }

/* ---------------------------------------------------------------- header */

/* Two-row header: brand bar on top, navigation bar below (Al-Mahud style). */
.site-header {
    /* --color-header-bg is only emitted when the merchant sets one, so an
       unset value falls through to the page background rather than pinning
       the header to a colour the theme never chose. */
    background: var(--color-header-bg, var(--color-bg));
}

.site-header--sticky {
    position: sticky;
    top: 0;
    z-index: 50;
    /* Soft edge so the header reads as its own surface over page content. */
    box-shadow: var(--shadow-sm);
}

.site-header__topbar-inner {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    min-height: var(--header-h);
}

/* categories bar — its own menu (handle: categories-menu), nothing else in it */
.site-header__navbar {
    border-top: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-border);
}

.cat-bar ul {
    display: flex;
    justify-content: center;
    gap: 0.25rem;
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-x: auto;
    scrollbar-width: none;
}

.cat-bar ul::-webkit-scrollbar { display: none; }

.cat-bar a {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.75rem 1rem;
    color: var(--color-text);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.95rem;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    transition: color var(--transition), border-color var(--transition);
}

.cat-bar a:hover {
    color: var(--color-primary);
    border-bottom-color: var(--color-primary);
}

.cat-bar img { border-radius: 4px; object-fit: cover; }

.site-header__logo {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-weight: 700;
    font-size: 1.15rem;
    color: inherit;
    text-decoration: none;
    flex-shrink: 0;
}

.site-header__logo img {
    width: 42px;
    height: 42px;
    object-fit: contain;
    border-radius: var(--radius-sm);
}

.site-header__actions {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-inline-start: auto;
}

/* cart pill */
.cart-link {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.45rem 0.9rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    color: inherit;
    text-decoration: none;
    font-weight: 600;
    font-size: 0.9rem;
    white-space: nowrap;
    transition: border-color var(--transition);
}
.cart-link:hover { border-color: var(--color-primary); }

/* dark top bar variant */
.topnav-is-dark .site-header {
    /* This selector outranks .site-header, so it has to honour the merchant's
       colour too — otherwise picking one does nothing while dark mode is on. */
    background: var(--color-header-bg, #171a21);
    color: #fff;
}
.topnav-is-dark .site-header__navbar { border-color: #2a2e38; }
.topnav-is-dark .site-header .cart-link { border-color: #3a3f4b; }
.topnav-is-dark .site-header .main-menu a { color: inherit; }
.topnav-is-dark .site-header .main-menu__submenu { background: #21252e; border-color: #3a3f4b; }

/* ------------------------------------------------------------- main menu */

.main-menu ul {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.main-menu a {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0.85rem;
    border-radius: var(--radius-sm);
    color: var(--color-text);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.95rem;
    transition: color var(--transition), background var(--transition);
}
.main-menu a:hover { color: var(--color-primary); }

.main-menu__item { position: relative; }

.main-menu__item.has-children > a::after {
    content: '';
    border: 4px solid transparent;
    border-top-color: currentColor;
    translate: 0 2px;
    transition: rotate var(--transition);
}

.main-menu__item.has-children.is-open > a::after {
    rotate: 180deg;
    translate: 0 -2px;
}

.main-menu__submenu {
    position: absolute;
    inset-inline-start: 0;
    top: 100%;
    min-width: 12rem;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 0.4rem;
    margin: 0;
    list-style: none;
    display: none;
    flex-direction: column;
    z-index: 60;
}

/* Opened by <falak-menu>, which toggles .is-open here; closed by outside
   click, Escape, or a second click on the parent. */
.main-menu__item.is-open > .main-menu__submenu { display: flex; }

.main-menu__submenu a {
    display: block;
    padding: 0.5rem 0.75rem;
    font-weight: 500;
}

/* ----------------------------------------------- nav overflow (priority+) */
/* Once wireNavOverflow() owns the bar (the attribute is its signature) the
   row must neither wrap — the cream strip's own rule stacks a crowded bar
   into extra rows — nor refuse to shrink: a flex item's min-width:auto means
   the <ul> would sooner overflow the nav than compress, so its scrollWidth
   never exceeded its clientWidth and there was nothing to measure. One row,
   shrinkable, overflow measurable; what does not fit folds into More.
   Without JS the attribute never appears and the bar wraps as before. */
@media (min-width: 861px) {
    .site-header__nav .main-menu > ul[data-nav-overflow] {
        flex-wrap: nowrap;
        min-width: 0;
    }
}

/* An item the bar could not fit, folded into the More dropdown by
   wireNavOverflow(). Desktop only — the drawer restores every row. */
.main-menu__item.is-collapsed { display: none; }

/* The More trigger reads as a control rather than a destination: an outlined
   pill, the count beside the label, and the has-children caret it inherits. */
.main-menu__more > a {
    border: 1px solid var(--color-border);
    border-radius: 999px;
    padding-inline: 0.9rem;
}

/* The count takes the trigger's own ink instead of naming a colour. The
   strip is white over the hero and dark ink once the header goes solid, and
   --color-text-soft is a fixed near-navy: beside a white "More" label it was
   a dark number on a dark photograph, the one unreadable thing on the row.
   Inheriting means it is white where the label is white and soft ink where
   the label is ink, with no second rule per state. */
.main-menu__more-count {
    font-weight: 700;
    color: inherit;
}

/* Pinned to the inline END — the More item is the bar's last, and a panel
   opening toward inline-start from there stays on screen. A long store's
   list scrolls inside the panel rather than running past the fold. */
.main-menu__more .main-menu__submenu {
    inset-inline-start: auto;
    inset-inline-end: 0;
    min-width: 14rem;
    max-height: min(26rem, 70vh);
    overflow-y: auto;
}

/* A collapsed parent's children, indented one step under it. */
.main-menu__submenu a.main-menu__more-child {
    padding-inline-start: 1.75rem;
    font-weight: 400;
}

/* mobile menu */
.menu-toggle {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 42px;
    height: 42px;
    padding: 10px;
    background: none;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.menu-toggle span {
    display: block;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
}

@media (max-width: 860px) {
    .menu-toggle { display: flex; }

    /* Tighter rhythm: at desktop gaps the toggle + brand + actions row is
       wider than a phone screen, which pushed the whole page into a
       horizontal scroll and shoved the menu button out of view. */
    .site-header__topbar-inner { gap: 0.75rem; }

    .site-header__actions { gap: 0.5rem; }

    /* A long store name must squeeze and ellipsize, never widen the page. */
    .site-header__logo {
        flex-shrink: 1;
        min-width: 0;
    }

    .site-header__logo span {
        min-width: 0;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        /* The name's own script sets its direction, so truncation always
           keeps the START of the name ("Tahseen U…"), never the tail
           ("…o Store") — e.g. a Latin store name on the RTL storefront. */
        unicode-bidi: plaintext;
        text-align: start;
    }

    /* Page menu moves to the drawer; the categories bar stays and scrolls. */
    .cat-bar ul { justify-content: flex-start; }

    /* Edge fade hints that the categories bar keeps scrolling. Symmetric, so
       it needs no RTL variant. */
    .cat-bar {
        -webkit-mask-image: linear-gradient(to right,
            transparent, #000 1.25rem, #000 calc(100% - 1.25rem), transparent);
        mask-image: linear-gradient(to right,
            transparent, #000 1.25rem, #000 calc(100% - 1.25rem), transparent);
    }

    .site-header .main-menu {
        position: fixed;
        inset-block: 0;
        inset-inline-start: 0;
        width: min(20rem, 85vw);
        background: var(--color-bg);
        color: var(--color-text);
        box-shadow: var(--shadow);
        padding: 1.25rem;
        /* Rounded trailing edge — the drawer reads as a card, not a cut. */
        border-start-end-radius: var(--radius-lg);
        border-end-end-radius: var(--radius-lg);
        transform: translateX(calc(var(--rtl-flip, -1) * 105%));
        transition: transform 220ms ease;
        z-index: 80;
        overflow-y: auto;
    }

    [dir="rtl"] .site-header .main-menu { --rtl-flip: 1; }

    body.menu-is-open .site-header .main-menu { transform: translateX(0); }

    .main-menu ul {
        flex-direction: column;
        align-items: stretch;
        gap: 0.15rem;
    }

    .main-menu a { padding: 0.7rem 0.75rem; }

    .main-menu__submenu {
        position: static;
        border: none;
        box-shadow: none;
        padding-inline-start: 1rem;
        background: transparent;
    }

    .menu-backdrop {
        position: fixed;
        inset: 0;
        background: rgba(15, 18, 24, 0.45);
        backdrop-filter: blur(2px);
        opacity: 0;
        pointer-events: none;
        transition: opacity 200ms ease;
        z-index: 70;
    }

    body.menu-is-open .menu-backdrop {
        opacity: 1;
        pointer-events: auto;
    }
}

/* ---------------------------------------------------------------- footer */

.site-footer {
    margin-top: 4rem;
    border-top: 1px solid var(--color-border);
    background: var(--color-footer-bg, var(--color-surface));
    padding-block: 2.5rem 1.5rem;
    font-size: 0.95rem;
}

.site-footer__inner {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem;
    justify-content: space-between;
    align-items: flex-start;
}

/* Stacked footer centers instead of ragged-wrapping. */
@media (max-width: 640px) {
    .site-footer__inner {
        flex-direction: column;
        align-items: center;
        text-align: center;
        gap: 1.5rem;
    }

    .site-footer__menu ul { justify-content: center; }
}

.site-footer__brand { max-width: 32ch; }

.site-footer__brand-name {
    font-weight: 700;
    font-size: 1.1rem;
    display: block;
    margin-bottom: 0.35rem;
}

.site-footer__about { color: var(--color-text-soft); margin: 0; }

.site-footer__menu ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.5rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.site-footer__menu a {
    color: var(--color-text-soft);
    text-decoration: none;
}
.site-footer__menu a:hover { color: var(--color-primary); }

.site-footer__contact {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.site-footer__contact a {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--color-text-soft);
    text-decoration: none;
    font-size: 0.92rem;
}

.site-footer__contact a:hover { color: var(--color-primary); }

.site-footer__contact svg {
    width: 1.05rem;
    height: 1.05rem;
    flex-shrink: 0;
}

.site-footer__copyright {
    margin: 2rem 0 0;
    padding-top: 1.25rem;
    border-top: 1px solid var(--color-border);
    color: var(--color-text-faint);
    font-size: 0.85rem;
    text-align: center;
    width: 100%;
}

.footer-is-dark .site-footer {
    background: var(--color-footer-bg, #171a21);
    border-top-color: #2a2e38;
    color: #d5d9e0;
}
.footer-is-dark .site-footer__about,
.footer-is-dark .site-footer__contact a,
.footer-is-dark .site-footer__menu a { color: #9aa1ad; }
.footer-is-dark .site-footer__contact a:hover { color: var(--color-primary-light); }
.footer-is-dark .site-footer__menu a:hover { color: var(--color-primary-light); }
.footer-is-dark .site-footer__copyright { border-top-color: #2a2e38; color: #6b7280; }

/* ------------------------------------------------------- blocks (areas) */

.block { margin-block: 3.5rem; }

.block__title {
    text-align: center;
    margin-bottom: 2rem;
}

/* Raed-style accent: a short primary bar anchors every section heading. */
.block__title::after {
    content: '';
    display: block;
    width: 2.5rem;
    height: 3px;
    border-radius: 999px;
    background: var(--color-primary);
    margin: 0.6rem auto 0;
}

/* hero slider — full-bleed photography with a directional scrim (Al-Mahud style) */
.block--hero-slider { margin-top: 0; }

.hero-slider {
    position: relative;
    overflow: hidden;
}

.hero-slider__slide {
    position: relative;
    min-height: clamp(340px, 44vw, 540px);
    display: none;
    align-items: center;
    color: #fff;
}

.hero-slider__slide.is-active { display: flex; }

.hero-slider__img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Scrim anchored to the reading side, so text stays legible on any photo. */
.hero-slider__slide::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(12, 14, 18, 0.66) 8%, rgba(12, 14, 18, 0.25) 55%, rgba(12, 14, 18, 0.05));
    /* Off unless the merchant sets Background dimming in the customizer. */
    opacity: var(--falak-overlay, 0%);
}

[dir="rtl"] .hero-slider__slide::after {
    background: linear-gradient(270deg, rgba(12, 14, 18, 0.66) 8%, rgba(12, 14, 18, 0.25) 55%, rgba(12, 14, 18, 0.05));
}

.hero-slider__content {
    position: relative;
    z-index: 1;
    width: 100%;
    padding-block: 3rem;
}

.hero-slider__content h2 {
    font-size: clamp(1.7rem, 1.1rem + 3vw, 3rem);
    font-weight: 800;
    letter-spacing: -0.01em;
    margin-bottom: 0.6rem;
    max-width: 22ch;
}

.hero-slider__content p {
    font-size: clamp(1rem, 0.9rem + 0.6vw, 1.25rem);
    max-width: 44ch;
    margin: 0 0 1.5rem;
    opacity: 0.92;
    line-height: 1.55;
}

.hero-slider__content .btn {
    padding: 0.85rem 2.2rem;
    font-size: 1.02rem;
}

.hero-slider__dots {
    position: absolute;
    inset-inline: 0;
    bottom: 1.1rem;
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    z-index: 2;
}

.hero-slider__dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 999px;
    border: none;
    padding: 0;
    background: rgba(255, 255, 255, 0.55);
    cursor: pointer;
    transition: background var(--transition), width var(--transition);
}

.hero-slider__dot.is-active {
    background: #fff;
    width: 1.5rem;
}

.hero-slider__arrow {
    position: absolute;
    top: 50%;
    translate: 0 -50%;
    z-index: 2;
    width: 2.75rem;
    height: 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.16);
    backdrop-filter: blur(4px);
    color: #fff;
    font-size: 1.3rem;
    cursor: pointer;
    transition: background var(--transition);
}

.hero-slider__arrow:hover { background: rgba(255, 255, 255, 0.34); }

.hero-slider__arrow--prev { inset-inline-start: 1rem; }
.hero-slider__arrow--next { inset-inline-end: 1rem; }

/* Arrow glyphs point along the reading direction; flip for RTL. */
[dir="rtl"] .hero-slider__arrow span { display: inline-block; scale: -1 1; }

@media (max-width: 640px) {
    .hero-slider__arrow { display: none; }

    /* No reading side on a narrow slide: an even scrim keeps the title
       legible wherever it lands on the photo. Also stated for RTL because
       the directional RTL scrim rule is more specific than this one. */
    .hero-slider__slide::after,
    [dir="rtl"] .hero-slider__slide::after {
        background: rgba(12, 14, 18, 0.5);
    }

    .hero-slider__content { padding-block: 2.5rem 3.25rem; }
}

/* testimonials */
.testimonials-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 1.5rem;
}

.testimonial-card {
    margin: 0;
    padding: 1.5rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-bg);
    box-shadow: var(--shadow-sm);
    transition: border-color var(--transition), box-shadow var(--transition), transform var(--transition);
}

.testimonial-card:hover {
    border-color: color-mix(in srgb, var(--color-primary) 35%, var(--color-border));
    box-shadow: var(--shadow);
    transform: translateY(-2px);
}

.testimonial-card__stars {
    color: #f5a623;
    letter-spacing: 2px;
    margin-bottom: 0.5rem;
}

.testimonial-card blockquote {
    margin: 0 0 0.75rem;
    color: var(--color-text-soft);
}

.testimonial-card figcaption { font-weight: 700; font-size: 0.9rem; }

/* banner */
.banner {
    position: relative;
    border-radius: var(--radius-lg);
    overflow: hidden;
    min-height: clamp(200px, 28vw, 340px);
    display: flex;
    align-items: center;
    background-size: cover;
    background-position: center;
    color: #fff;
}

.banner::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(10, 12, 16, 0.55), rgba(10, 12, 16, 0.1));
    /* Off unless the merchant sets Background dimming in the customizer. */
    opacity: var(--falak-overlay, 0%);
}

[dir="rtl"] .banner::before {
    background: linear-gradient(270deg, rgba(10, 12, 16, 0.55), rgba(10, 12, 16, 0.1));
}

.banner__content {
    position: relative;
    padding: 2rem clamp(1.25rem, 4vw, 3rem);
    max-width: 46ch;
}

.banner__content h2 { margin-bottom: 0.5rem; }
.banner__content p { margin: 0 0 1.25rem; opacity: 0.92; }

/* offer countdown block — the band itself is <falak-countdown theme="…">, SDK-styled */
.block--countdown falak-countdown { display: flex; }

/* features row — a focus carousel: three cards in view, the active one lifted
   and tilted, arrows on the sides and a dot row below. <custom-falak-features>
   in app.js moves .is-active; everything visual is decided here. */
.block--features { background: color-mix(in srgb, var(--color-primary) 8%, var(--color-bg)); }
.block--features .block-head { margin-block-end: 1rem; }

/* The inline padding is the arrows' own gutter, so they sit clear of the
   cards instead of over their edges. */
.features-carousel { position: relative; display: block; padding-inline: 3.5rem; }

.features-grid {
    --features-gap: 1.75rem;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - 2 * var(--features-gap)) / 3);
    gap: var(--features-gap);
    margin: 0;
    /* overflow-x clips vertically too, so the lifted card's shadow and tilted
       corners need room inside the scroller itself. */
    padding: 2.25rem 1.25rem 2.5rem;
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 1.25rem;
    scrollbar-width: none;
}

.features-grid::-webkit-scrollbar { display: none; }

.feature-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    min-inline-size: 0;
    padding: 2rem 1.75rem;
    text-align: center;
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--color-primary) 4%, var(--color-bg));
    overflow: hidden;
    scroll-snap-align: center;
    transition: transform 0.35s ease, box-shadow 0.35s ease, background-color 0.35s ease;
}

/* The two circles in the active card's corner. */
.feature-card::before,
.feature-card::after {
    content: "";
    position: absolute;
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-primary) 10%, transparent);
    opacity: 0;
    transition: opacity 0.35s ease;
    pointer-events: none;
}
.feature-card::before { inline-size: 9rem; block-size: 9rem; inset-block-end: -3.5rem; inset-inline-end: -2.5rem; }
.feature-card::after  { inline-size: 6rem; block-size: 6rem; inset-block-end: -1.25rem; inset-inline-end: -0.75rem; }
.feature-card > * { position: relative; z-index: 1; }

.feature-card.is-active {
    background: var(--color-bg);
    box-shadow: 0 14px 26px -6px color-mix(in srgb, var(--color-primary) 24%, transparent);
    transform: translateY(-0.75rem) rotate(-2deg) scale(1.03);
}
[dir="rtl"] .feature-card.is-active { transform: translateY(-0.75rem) rotate(2deg) scale(1.03); }
.feature-card.is-active::before,
.feature-card.is-active::after { opacity: 1; }

.feature-card__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 3rem;
    block-size: 3rem;
    color: color-mix(in srgb, var(--color-primary) 55%, transparent);
}
.feature-card__icon svg { inline-size: 100%; block-size: 100%; }
.feature-card__icon img { inline-size: 100%; block-size: 100%; object-fit: cover; border-radius: inherit; }

.feature-card h3 { margin: 0; color: var(--color-primary); font-size: 1.25rem; font-weight: 700; line-height: 1.35; }
.feature-card p { margin: 0; color: var(--color-text-soft); font-size: 0.92rem; line-height: 1.75; }

.feature-card__btn {
    margin-block-start: auto;
    box-shadow: 0 6px 14px color-mix(in srgb, var(--color-primary) 22%, transparent);
}
/* `auto` pins the button to the bottom; this keeps it off the text above. */
.feature-card p:has(+ .feature-card__btn) { margin-block-end: 0.75rem; }

.features-carousel__arrow {
    position: absolute;
    inset-block-start: calc(50% - 1rem);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--color-bg);
    color: var(--color-primary);
    box-shadow: 0 4px 14px color-mix(in srgb, var(--color-primary) 14%, transparent);
    cursor: pointer;
    transform: translateY(-50%);
    transition: box-shadow var(--transition), color var(--transition);
}
.features-carousel__arrow:hover { box-shadow: 0 6px 18px color-mix(in srgb, var(--color-primary) 24%, transparent); }
.features-carousel__arrow--prev { inset-inline-start: 0; }
.features-carousel__arrow--next { inset-inline-end: 0; }

/* Chevron from two logical borders; the rotation flips with the direction. */
.features-carousel__arrow::before {
    content: "";
    inline-size: 0.55rem;
    block-size: 0.55rem;
    border-inline-start: 2px solid currentColor;
    border-block-start: 2px solid currentColor;
}
.features-carousel__arrow--prev::before { transform: rotate(-45deg); margin-inline-start: 0.2rem; }
.features-carousel__arrow--next::before { transform: rotate(135deg); margin-inline-end: 0.2rem; }
[dir="rtl"] .features-carousel__arrow--prev::before { transform: rotate(45deg); }
[dir="rtl"] .features-carousel__arrow--next::before { transform: rotate(-135deg); }

.features-carousel__dots { display: flex; justify-content: center; align-items: center; gap: 0.4rem; }

.features-carousel__dot {
    inline-size: 0.45rem;
    block-size: 0.45rem;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: color-mix(in srgb, var(--color-primary) 30%, transparent);
    cursor: pointer;
    transition: inline-size 0.25s ease, background-color 0.25s ease;
}
.features-carousel__dot.is-active { inline-size: 1.4rem; background: var(--color-primary); }

.features-carousel.is-static .features-carousel__arrow,
.features-carousel.is-static .features-carousel__dots { display: none; }

@media (max-width: 1023px) {
    .features-grid { grid-auto-columns: calc((100% - var(--features-gap)) / 2); }
    .features-carousel { padding-inline: 3rem; }
}

@media (max-width: 767px) {
    .features-grid { --features-gap: 1rem; grid-auto-columns: 80%; padding-inline: 10%; scroll-padding-inline: 10%; }
    .features-carousel__arrow { inline-size: 2.25rem; block-size: 2.25rem; }
    /* No room for a gutter on a phone; the arrows overlay the peeking cards. */
    .features-carousel { padding-inline: 0; }
    .features-carousel__arrow--prev { inset-inline-start: -0.25rem; }
    .features-carousel__arrow--next { inset-inline-end: -0.25rem; }
}

@media (prefers-reduced-motion: reduce) {
    .feature-card, .feature-card::before, .feature-card::after, .features-carousel__dot { transition: none; }
}

/* image with text */
.image-text {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(1.5rem, 4vw, 3.5rem);
    align-items: center;
}

.image-text--flipped .image-text__media { order: 2; }

.image-text__media img {
    width: 100%;
    border-radius: var(--radius-lg);
    object-fit: cover;
    aspect-ratio: 4 / 3;
}

.image-text__body h2 { margin-bottom: 0.75rem; }
.image-text__body p { color: var(--color-text-soft); margin: 0 0 1.5rem; }

@media (max-width: 720px) {
    .image-text { grid-template-columns: 1fr; }
    .image-text--flipped .image-text__media { order: 0; }
}

/* -------------------------------------------------------------- listing */

.page-head {
    padding-block: 2rem 0.5rem;
}

.page-head h1 { margin-bottom: 0.25rem; }

.page-head__meta { color: var(--color-text-soft); font-size: 0.92rem; }

.product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 1.5rem;
    padding-block: 1.5rem 0;
}

@media (max-width: 560px) {
    .product-grid { grid-template-columns: repeat(2, 1fr); gap: 0.9rem; }
}

.product-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    color: inherit;
    text-decoration: none;
}

/* The name link stretches over the whole card; interactive children sit above. */
.product-card__link {
    color: inherit;
    text-decoration: none;
}

.product-card__link::after {
    content: '';
    position: absolute;
    inset: 0;
}

.product-card .btn--card { position: relative; z-index: 1; }

.btn--card {
    padding: 0.55rem 1rem;
    font-size: 0.9rem;
    background: transparent;
    border-color: var(--color-border);
    color: var(--color-text);
}

.btn--card:hover {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-on-primary);
}

.btn--card.is-added {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-on-primary);
}

.product-card__media {
    position: relative;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    transition: border-color var(--transition), box-shadow var(--transition);
}

/* The image zoom reads as elevation once the frame lifts with it. */
.product-card:hover .product-card__media {
    border-color: color-mix(in srgb, var(--color-primary) 25%, var(--color-border));
    box-shadow: var(--shadow);
}

.product-card__media img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    display: block;
    transition: transform 300ms ease;
}

.product-card:hover .product-card__media img { transform: scale(1.04); }

.product-card__placeholder {
    width: 100%;
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-faint);
    font-size: 2rem;
}

.product-card h3 {
    font-size: 0.98rem;
    font-weight: 600;
    margin: 0;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.product-card__price {
    margin: 0;
    font-weight: 700;
    color: var(--color-primary-dark);
}

/* ------------------------------------------------------- product single */

.product-single { padding-block: 1rem 2rem; }

.product-single__layout {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 3.5rem);
    align-items: start;
}

@media (max-width: 820px) {
    .product-single__layout { grid-template-columns: 1fr; }
}

/* gallery */
.gallery__main {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: var(--color-surface);
}

.gallery__main img {
    width: 100%;
    aspect-ratio: 1;
    display: block;
}

.gallery__thumbs {
    display: flex;
    gap: 0.6rem;
    margin-top: 0.75rem;
    overflow-x: auto;
    padding-bottom: 0.25rem;
}

.gallery__thumb {
    flex: 0 0 4.5rem;
    padding: 0;
    border: 2px solid var(--color-border);
    border-radius: var(--radius-sm);
    overflow: hidden;
    cursor: pointer;
    background: var(--color-surface);
}

.gallery__thumb img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    display: block;
}

.gallery__thumb.is-active { border-color: var(--color-primary); }

.product-image--contain { object-fit: contain; }
.product-image--cover { object-fit: cover; }

/* buy box */
.product-single__info h1 { margin-bottom: 0.5rem; }

.product-single__price {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--color-primary-dark);
    margin-block: 0 1rem;
}

.product-single__description {
    color: var(--color-text-soft);
    margin-bottom: 1.75rem;
}

.buy-box {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    align-items: center;
}

/* ------------------------------------------------------------------ cart */

.cart-page { padding-block: 1rem 2rem; }

.cart-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 20rem;
    gap: 2rem;
    align-items: start;
}

@media (max-width: 820px) {
    .cart-layout { grid-template-columns: 1fr; }
}

.cart-items {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.cart-item {
    display: flex;
    gap: 1rem;
    padding-block: 1.1rem;
    border-bottom: 1px solid var(--color-border);
    align-items: center;
}

.cart-item img {
    width: 76px;
    height: 76px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
    background: var(--color-surface);
    flex-shrink: 0;
}

.cart-item__info { flex: 1; min-width: 0; }

.cart-item__info a {
    color: inherit;
    text-decoration: none;
    font-weight: 600;
    display: block;
    margin-bottom: 0.2rem;
}
.cart-item__info a:hover { color: var(--color-primary); }

.cart-item__meta { color: var(--color-text-soft); font-size: 0.9rem; }

.cart-item__line-total { font-weight: 700; white-space: nowrap; }

.cart-summary {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    padding: 1.5rem;
    position: sticky;
    top: calc(var(--header-h) + 1rem);
}

.cart-summary h2 { font-size: 1.1rem; margin-bottom: 1rem; }

.cart-summary__row {
    display: flex;
    justify-content: space-between;
    margin-bottom: 0.6rem;
    color: var(--color-text-soft);
}

.cart-summary__row--total {
    color: var(--color-text);
    font-weight: 700;
    font-size: 1.1rem;
    border-top: 1px solid var(--color-border);
    padding-top: 0.75rem;
    margin-top: 0.75rem;
}

.cart-summary .btn { margin-top: 1rem; }

/* ---------------------------------------------------------- misc / pages */

.empty-state {
    text-align: center;
    padding-block: 4rem;
    color: var(--color-text-soft);
}

.empty-state__icon { font-size: 2.5rem; margin-bottom: 0.75rem; }
.empty-state p { margin-bottom: 1.5rem; }

/*
    The "other products" grid shown when a category turns up empty. Only the
    heading needs rules — the grid and cards inside it are <falak-products-list>,
    styled by the platform's falak-components.css.
*/
.product-listing__fallback {
    margin-block-start: 1rem;
    padding-block-start: 2.5rem;
    border-block-start: 1px solid var(--color-border);
}

.product-listing__fallback h2 {
    font-size: 1.125rem;
    margin-bottom: 1.25rem;
    text-align: center;
}

/*
    Listing layout: sidebar (<falak-filters>, SDK-styled) beside the grid on
    wide screens; on phones the sidebar is an off-canvas drawer opened by the
    toolbar button (app.js toggles .is-open).
*/
.product-listing__layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem; align-items: start; }
.product-listing--with-sidebar .product-listing__layout { grid-template-columns: 16.5rem minmax(0, 1fr); }

.product-listing__sidebar {
    position: sticky;
    top: 5.5rem;
    padding: 1rem 1.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface, #fff);
}

.product-listing__sidebar-head { display: flex; align-items: center; justify-content: space-between; margin-block-end: 0.25rem; }
.product-listing__sidebar-head h2 { font-size: 1rem; margin: 0; }
.product-listing__sidebar-close { display: none; border: 0; background: none; font-size: 1.5rem; line-height: 1; cursor: pointer; color: var(--color-text-soft); }

.product-listing__toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.product-listing__filters-trigger { display: none; position: relative; }
.product-listing__filters-dot { position: absolute; inset-inline-end: 0.35rem; inset-block-start: 0.35rem; inline-size: 0.5rem; block-size: 0.5rem; border-radius: 50%; background: var(--color-primary); }

.product-listing__sort { display: inline-flex; align-items: center; gap: 0.6rem; margin-inline-start: auto; font-size: 0.9rem; }
.product-listing__sort span { color: var(--color-text-soft); white-space: nowrap; }
.product-listing__sort select { min-inline-size: 11rem; }

.product-listing__backdrop { display: none; }

@media (max-width: 899px) {
    .product-listing--with-sidebar .product-listing__layout { grid-template-columns: minmax(0, 1fr); }
    .product-listing__filters-trigger { display: inline-flex; }
    .product-listing__sidebar-close { display: inline-block; }

    .product-listing__sidebar {
        position: fixed;
        inset-block: 0;
        inset-inline-start: 0;
        inline-size: min(20rem, 88vw);
        z-index: 60;
        overflow-y: auto;
        border-radius: 0;
        transform: translateX(-100%);
        transition: transform 0.25s ease;
    }
    [dir="rtl"] .product-listing__sidebar { transform: translateX(100%); }
    .product-listing__sidebar.is-open { transform: none; }

    .product-listing__backdrop { display: block; position: fixed; inset: 0; z-index: 59; background: rgba(0, 0, 0, 0.4); }
    .product-listing__backdrop[hidden] { display: none; }
    body.filters-are-open { overflow: hidden; }
}

.error-page { text-align: center; padding-block: 6rem 5rem; }

.error-page__code {
    font-size: clamp(4rem, 10vw, 7rem);
    font-weight: 800;
    line-height: 1;
    color: var(--color-border);
    margin-bottom: 0.5rem;
}

.error-page p { color: var(--color-text-soft); margin-bottom: 1.75rem; }

/* static content pages (page-single) */
.content-page { padding-block: 1.5rem 2rem; max-width: 760px; }
.content-page h1 { margin-bottom: 1.25rem; }
.content-page__body { color: var(--color-text-soft); }
.content-page__body img { border-radius: var(--radius); }

/* -------------------------------------------------------- customer area */

.account { padding-block: 1.5rem 2rem; }

.account__layout {
    display: grid;
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
}

@media (max-width: 720px) {
    .account__layout { grid-template-columns: 1fr; }
}

.account__nav {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    padding: 0.6rem;
    position: sticky;
    top: calc(var(--header-h) + 1rem);
}

.account__nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

@media (max-width: 720px) {
    .account__nav { position: static; }
    .account__nav ul { flex-direction: row; overflow-x: auto; }
}

.account__nav a {
    display: block;
    padding: 0.6rem 0.9rem;
    border-radius: var(--radius-sm);
    color: var(--color-text);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.95rem;
    white-space: nowrap;
}

.account__nav a:hover { color: var(--color-primary); }

.account__nav a.is-active {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.account-details {
    margin: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
}

.account-details__row {
    display: grid;
    grid-template-columns: 10rem minmax(0, 1fr);
    gap: 1rem;
    padding: 0.9rem 1.25rem;
}

.account-details__row + .account-details__row { border-top: 1px solid var(--color-border); }

.account-details dt { color: var(--color-text-soft); font-weight: 600; }
.account-details dd { margin: 0; }

/* orders */
.order-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.order-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding-block: 1rem;
    border-bottom: 1px solid var(--color-border);
    flex-wrap: wrap;
}

.order-row__main {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    flex: 1;
    min-width: 8rem;
}

.order-row__number { font-weight: 700; }
.order-row__date { color: var(--color-text-soft); font-size: 0.85rem; }
.order-row__total { font-weight: 700; white-space: nowrap; }

.order-status {
    display: inline-block;
    padding: 0.25rem 0.8rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    color: var(--color-text-soft);
}

.order-status--completed,
.order-status--delivered { background: #e3f3ea; border-color: #bfe4d0; color: #1e7a4d; }
.order-status--cancelled,
.order-status--refunded { background: #fbe9e7; border-color: #f2c8c4; color: #b3372f; }
.order-status--shipped,
.order-status--processing { background: #e8eafb; border-color: #ccd2f2; color: #2f3eb5; }

.order-head {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

.order-head h1 { margin: 0; }
.order-head__date { color: var(--color-text-soft); margin-block: 0.25rem 1.5rem; }

.order-totals {
    margin-top: 1.5rem;
    max-width: 22rem;
    margin-inline-start: auto;
}

/* notifications */
.notification-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* -------------------------------------------------------------- blog */

.article-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 1.5rem;
    padding-block: 1rem 2rem;
}

.article-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    background: var(--color-bg);
    transition: box-shadow var(--transition);
}

.article-card:hover { box-shadow: var(--shadow); }

.article-card > img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

.article-card__body { padding: 1.1rem 1.25rem 1.25rem; }
.article-card__body h3 { margin-bottom: 0.4rem; }
.article-card__body p {
    margin: 0 0 0.6rem;
    color: var(--color-text-soft);
    font-size: 0.92rem;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}
.article-card__body time { color: var(--color-text-faint); font-size: 0.8rem; }

.article-date { display: block; color: var(--color-text-faint); font-size: 0.85rem; margin-bottom: 1rem; }
.article-cover { width: 100%; border-radius: var(--radius); margin-bottom: 1.5rem; }

/* ------------------------------------------------------------- brands */

.brand-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 1rem;
    padding-block: 1rem 2rem;
}

.brand-card {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 3 / 2;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-bg);
    padding: 1.25rem;
    text-decoration: none;
    transition: border-color var(--transition), box-shadow var(--transition), transform var(--transition);
}

.brand-card:hover {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-sm);
    transform: translateY(-2px);
}

.brand-card img { max-height: 100%; object-fit: contain; }

.brand-card__name { font-weight: 700; color: var(--color-text); text-align: center; }

.brand-head {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.brand-head__logo {
    width: 64px;
    height: 64px;
    object-fit: contain;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.4rem;
    background: var(--color-bg);
}

/* ---------------------------------------------------------- thank you */

.thank-you {
    text-align: center;
    padding-block: 5rem 4rem;
    max-width: 34rem;
}

.thank-you__icon {
    width: 4.5rem;
    height: 4.5rem;
    margin-inline: auto;
    margin-bottom: 1.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: 2rem;
}

.thank-you p { color: var(--color-text-soft); }
.thank-you__order { margin-block: 1rem 1.5rem; }
.thank-you .btn { margin-inline: 0.35rem; }

/* ---------------------------------------------- photo grid + video */

.photo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1rem;
}

@media (max-width: 560px) {
    .photo-grid { grid-template-columns: repeat(2, 1fr); }
}

.photo-tile {
    position: relative;
    display: block;
    border-radius: var(--radius);
    overflow: hidden;
}

.photo-tile img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    display: block;
    transition: transform 300ms ease;
}

a.photo-tile:hover img { transform: scale(1.04); }

.photo-tile__caption {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    padding: 1.5rem 1rem 0.75rem;
    background: linear-gradient(transparent, rgba(10, 12, 16, 0.65));
    color: #fff;
    font-weight: 600;
}

/* portrait video cards — the videos-slider block (reels row) */
.block--videos-slider .f-slider__slide { min-width: 0; }

.video-card {
    position: relative;
    aspect-ratio: 9 / 16;
    border-radius: 18px;
    overflow: hidden;
    background: #14161a;
    box-shadow: 0 10px 28px rgba(15, 23, 32, 0.14);
    transform: translateZ(0);
    transition: transform 0.35s ease, box-shadow 0.35s ease;
}

.video-card:hover { transform: translateY(-4px); box-shadow: 0 18px 40px rgba(15, 23, 32, 0.22); }
.video-card.is-unmuted { box-shadow: 0 0 0 2px var(--color-primary), 0 18px 40px rgba(15, 23, 32, 0.22); }

.video-card__media {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.6s ease;
}
.video-card:hover .video-card__media { transform: scale(1.05); }

/* Frosted-glass sound toggle; the slash lifts when the card is unmuted. */
.video-card__sound {
    position: absolute;
    inset-block-start: 0.7rem;
    inset-inline-end: 0.7rem;
    inline-size: 2.1rem;
    block-size: 2.1rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 50%;
    background: rgba(20, 22, 26, 0.35);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    color: #fff;
    cursor: pointer;
    z-index: 2;
    transition: transform 0.2s ease, background-color 0.2s ease;
}
.video-card__sound:hover { transform: scale(1.08); background: rgba(20, 22, 26, 0.55); }

.video-card__sound-icon {
    position: relative;
    inline-size: 0.9rem;
    block-size: 0.9rem;
    background: currentColor;
    clip-path: polygon(0 35%, 30% 35%, 60% 8%, 60% 92%, 30% 65%, 0 65%);
}
.video-card:not(.is-unmuted) .video-card__sound::after {
    content: "";
    position: absolute;
    inline-size: 1.35rem;
    block-size: 2px;
    border-radius: 2px;
    background: #fff;
    transform: rotate(-45deg);
}

.video-card__caption {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.55rem;
    padding: 3.5rem 1rem 1.1rem;
    background: linear-gradient(180deg, transparent 0%, rgba(10, 14, 18, 0.25) 40%, rgba(10, 14, 18, 0.78) 100%);
    color: #fff;
    z-index: 2;
}
.video-card__title {
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.35;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
}

/* White pill CTA — flips to the store colour on hover. */
.video-card__link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.42rem 1.05rem;
    border: 0;
    border-radius: 999px;
    background: #fff;
    color: #14161a;
    font-size: 0.8rem;
    font-weight: 700;
    text-decoration: none;
    transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
.video-card__link::after { content: "←"; font-size: 0.85em; transition: transform 0.2s ease; }
[dir='ltr'] .video-card__link::after { content: "→"; }
.video-card__link:hover { background: var(--color-primary); color: #fff; transform: translateY(-1px); }

/* Reels-style progress line along the bottom edge. */
.video-card__progress {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    block-size: 3px;
    background: rgba(255, 255, 255, 0.22);
    z-index: 3;
}
.video-card__progress i {
    display: block;
    block-size: 100%;
    inline-size: 0;
    background: var(--color-primary);
    border-radius: 0 2px 2px 0;
}

.video-embed {
    position: relative;
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: #000;
}

.video-embed iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* ------------------------------------------------------- component showcase */
/*
    Layout for the review-only "Component showcase" section. Nothing here styles
    a component — each one brings its own; this just gives them room and a label
    so you can see which tag produced what.
*/

.showcase {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
    gap: 1rem;
}

.showcase__item {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 1.1rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}

/* Lists and carousels need the full row to be judged at all. */
.showcase__item--wide { grid-column: 1 / -1; }

.showcase__tag {
    font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
    font-size: 0.7rem;
    color: var(--color-text-faint);
    letter-spacing: 0.01em;
}

.showcase__row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; }

.showcase__note {
    margin: 0;
    font-size: 0.75rem;
    color: var(--color-text-soft);
}

.showcase__item > falak-accordion,
.showcase__item > falak-products-list,
.showcase__item > falak-products-slider { width: 100%; }

/* ---------------------------------------------------------------- toasts */
/* The visible half of falak.notify(): bottom-centre, colour by type. */
.toasts {
    position: fixed;
    inset-inline: 0;
    bottom: 1.5rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 0 1rem;
    pointer-events: none;
    z-index: 1000;
}
.toast {
    max-width: min(26rem, 100%);
    padding: 0.75rem 1.1rem;
    border-radius: var(--radius-sm);
    background: var(--color-text);
    color: var(--color-bg);
    font-size: 0.9rem;
    font-weight: 600;
    text-align: center;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
    opacity: 0;
    transform: translateY(0.75rem);
    transition: opacity 0.25s ease, transform 0.25s ease;
    pointer-events: auto;
}
.toast.is-in { opacity: 1; transform: none; }
.toast--success { background: var(--color-primary); color: var(--color-on-primary); }
.toast--error { background: #c0392b; color: #fff; }
@media (prefers-reduced-motion: reduce) { .toast { transition: none; transform: none; } }

/* The SDK add button inherits this theme's .btn skin through button-class;
   the host is display:contents so the button takes its place in the layout. */
.buy-box .f-add-product__button { flex: 1 1 auto; }

/* ------------------------------------------------------ cart page v2 */
/* Lines with a quantity stepper and remove; coupon; summary. Extends the
   base .cart-* rules above. */

.cart-item__media { flex: none; }
.cart-item__media img { width: 72px; height: 72px; object-fit: cover; border-radius: var(--radius-sm); }
.cart-item__name { font-weight: 600; color: var(--color-text); text-decoration: none; display: block; }
.cart-item__name:hover { color: var(--color-primary); }
.cart-item__variation { display: block; font-size: 0.85rem; color: var(--color-text-soft); }
/* The colour/image a variant was chosen by, so a cart line shows the same
   swatch the product page did rather than only naming it. The value is
   validated server-side (ProductOptionPresenter::safeDisplay) before it
   reaches the style attribute. */
.cart-item__swatch {
    display: inline-block;
    /* The swatch now stands in for the value's name, so it carries the
       meaning on its own and is sized to be read rather than glanced past. */
    inline-size: 1.05rem;
    block-size: 1.05rem;
    border-radius: 50%;
    vertical-align: -3px;
    box-shadow: 0 0 0 1px rgb(0 0 0 / 18%) inset;
}
/* Sized to the colour dot above rather than larger. An image swatch beside
   13px text reads as a thumbnail once it outgrows the line it sits on, and
   the cart line already carries the product's photograph two columns over —
   this is a marker for which value was picked, not a second picture.

   Scoped under .cart-item deliberately. `.cart-item img` up in the base cart
   rules is (0,1,1) and sizes EVERY image in a line to 76px, so an unscoped
   `.cart-item__swatch--image` (0,1,0) lost to it and the swatch drew at the
   size of the product photograph. This wins on specificity, not order. */
.cart-item img.cart-item__swatch--image {
    inline-size: 1.05rem;
    block-size: 1.05rem;
    border: 0;
    border-radius: 3px;
    object-fit: cover;
}
.cart-item__unit { display: block; font-size: 0.9rem; color: var(--color-text-soft); }
.cart-item__unit del { margin-inline-start: 0.35rem; color: var(--color-text-faint); }

.cart-item__qty {
    flex: none;
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    overflow: hidden;
}
.cart-item__step {
    width: 2.1rem;
    height: 2.1rem;
    border: 0;
    background: transparent;
    color: var(--color-text);
    font: inherit;
    font-size: 1.1rem;
    cursor: pointer;
}
.cart-item__step:hover { background: var(--color-surface); color: var(--color-primary); }
.cart-item__qty-value { min-width: 2rem; text-align: center; font-weight: 600; font-variant-numeric: tabular-nums; }

.cart-item__remove {
    flex: none;
    width: 2.1rem;
    height: 2.1rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--color-text-faint);
    cursor: pointer;
}
.cart-item__remove:hover { background: var(--color-surface); color: var(--color-danger); }

.cart-page.is-busy .cart-layout { opacity: 0.55; pointer-events: none; }

/* Coupon control is <falak-cart-coupons>; it wears the theme's inputs. */
.cart-coupon { display: block; margin-bottom: 1rem; }
.cart-coupon .f-cart-coupons__input { border-radius: var(--radius-sm); background: #fff; }
.cart-coupon .f-cart-coupons__button { border-radius: var(--radius-sm); }

.cart-summary__row--discount { color: var(--color-primary); }
.cart-summary__continue { display: block; margin-top: 0.75rem; text-align: center; font-size: 0.9rem; color: var(--color-text-soft); }

@media (max-width: 767px) {
    .cart-item { flex-wrap: wrap; }
    .cart-item__info { flex: 1 1 60%; }
    .cart-item__line-total { margin-inline-start: auto; }
}
.cart-summary__note { margin: 0.25rem 0 0.5rem; font-size: 0.85rem; color: var(--color-primary); }

/* ------------------------------------------------------ variant chooser */
.product-single__options { margin-block: 0.25rem 1rem; }
.product-single__price del { margin-inline-start: 0.4rem; font-size: 0.85em; font-weight: 400; color: var(--color-text-faint); }
.product-single__options .f-options__pill { border-radius: var(--radius-sm); }

/* ------------------------------------------------------------ wishlist */
/* The card row: buy button + heart square side by side. */
.product-card falak-add-product-button,
.product-card falak-wishlist-button { display: contents; }
.product-card .btn--card-icon {
    position: absolute;
    inset-inline-end: 0.75rem;
    inset-block-start: 0.75rem;
    z-index: 2;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.92);
    color: var(--color-text-soft);
}
.product-card .btn--card-icon:hover,
.product-card .btn--card-icon.is-added { color: var(--color-danger); border-color: var(--color-danger); background: #fff; }
.product-card .btn--card-icon.is-added .f-wishlist__icon { fill: currentColor; }

.buy-box .btn--wishlist {
    flex: none;
    width: 2.75rem;
    padding: 0;
    color: var(--color-text-soft);
}
.buy-box .btn--wishlist:hover,
.buy-box .btn--wishlist.is-added { color: var(--color-danger); border-color: var(--color-danger); background: transparent; }
.buy-box .btn--wishlist.is-added .f-wishlist__icon { fill: currentColor; }

/* ------------------------------------------------------------- search */
/* Header trigger matches the wishlist/account icons; the dropdown panel
   takes the theme's surface, radius and price colours. */
.search-link .f-search__trigger {
    width: 2.5rem;
    height: 2.5rem;
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text);
    transition: border-color var(--transition), color var(--transition);
}
.search-link .f-search__trigger:hover { border-color: var(--color-primary); color: var(--color-primary); }
.topnav-is-dark .site-header .search-link .f-search__trigger { border-color: #3a3f4b; }

/* The dropdown panel. The meta line, clear ×, quick-add button and chevron
   below are markup the falak-search patch at the end of app.js renders —
   the SDK's own markup has none of them.
   Ink is pinned to --color-on-white: the element lives in the header, and
   under a dark topnav (or over the hero) the panel would otherwise inherit
   its light text — the same reason the "overlay surfaces own their ink"
   block at the end of this file exists. */
#falak-search .f-modal__body {
    background: var(--color-surface);
    border-radius: calc(var(--radius) * 1.5);
    color: var(--color-on-white);
}
/* Under 640px the SDK turns the dialog into a full-screen sheet and squares
   its corners. That rule is `#falak-search .f-modal__body` too — same (1,0,1)
   specificity, but it sits up in the embedded SDK block, so the radius above
   wins on order alone and the sheet drew rounded corners with the page
   showing through them at the top of the screen. Restated here, after it. */
@media (max-width: 639px) {
    #falak-search .f-modal__body { border-radius: 0; }
}

#falak-search .f-search__panel { padding: 1.25rem; }

#falak-search .f-search__form .f-search__icon { inset-inline-start: 1.1rem; }
#falak-search .f-search__input {
    background: var(--color-bg);
    /* --color-border alone can vanish on a store whose bg is near-white;
       the mockup draws the pill in a tint of the brand colour. */
    border-color: color-mix(in srgb, var(--color-primary) 30%, var(--color-border));
    border-radius: 999px;
    padding-block: 0.8rem;
    padding-inline: 2.9rem;     /* room for the magnifier and the × */
}
/* Chromium draws its own cancel ×; the injected one is the design's. */
#falak-search .f-search__input::-webkit-search-cancel-button { display: none; }

.f-search__clear {
    position: absolute;
    inset-inline-end: 0.6rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--color-text-soft);
    cursor: pointer;
}
.f-search__clear:hover { color: var(--color-on-white); background: var(--color-bg); }

/* "PRODUCTS — N results" */
.f-search__meta {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-block: 0.25rem 0.6rem;
    font-size: 0.78rem;
    color: var(--color-text-soft);
}
.f-search__meta-label { text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; }

/* Result rows as cards; the <li> (not the SDK's <a>) is the bordered box,
   so the quick-add button and chevron can sit beside the link, not in it.
   The SDK's own .f-search__list is a flex column with a 0.25rem gap — only
   the gap needs restating; list-style/margin/padding are stated so the rule
   still holds if that embedded copy ever stops being display: flex. */
.f-search__list { list-style: none; margin: 0; padding: 0; gap: 0.6rem; }
.f-search__item {
    display: flex;
    align-items: center;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-bg);
    padding-inline-end: 0.9rem;
    transition: border-color var(--transition);
}
.f-search__item:hover { border-color: color-mix(in srgb, var(--color-primary) 45%, var(--color-border)); }
#falak-search .f-search__link { flex: 1 1 auto; min-width: 0; padding: 0.65rem; }
#falak-search .f-search__link:hover { background: transparent; }
#falak-search .f-search__thumb { inline-size: 4rem; block-size: 4rem; border-radius: var(--radius-sm); }
#falak-search .f-search__name { font-weight: 600; white-space: normal; }
#falak-search .f-search__price-now { color: var(--color-primary); }

/* Quick-add — a circled bag between the link and the chevron. */
.f-search__item falak-add-product-button { flex: none; display: inline-flex; }
.f-search__add-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: 50%;
    background: var(--color-surface);
    color: var(--color-on-white);
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition);
}
.f-search__add-btn:hover { border-color: var(--color-primary); color: var(--color-primary); }
.f-add-product--unavailable .f-search__add-btn { opacity: 0.45; cursor: not-allowed; }

.f-search__chevron { flex: none; display: inline-flex; margin-inline-start: 0.5rem; color: var(--color-text-faint); }
[dir="rtl"] .f-search__chevron svg { transform: scaleX(-1); }

/* View all — a full-width dark pill with a forward arrow, replacing the
   SDK's bordered text link. */
#falak-search .f-search__view-all {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-block-start: 0.9rem;
    padding-block: 0.85rem;
    border: 0;
    border-radius: var(--radius);
    background: var(--color-text);
    color: #fff;
    font-weight: 600;
}
#falak-search .f-search__view-all:hover { text-decoration: none; opacity: 0.92; }
#falak-search .f-search__view-all::after { content: '→'; }
[dir="rtl"] #falak-search .f-search__view-all::after { content: '←'; }

/* ------------------------------------------------------ wishlist drawer */
/* Header trigger matches the account avatar / cart link; the panel takes
   the theme's surface, radius and button skins. */
.wishlist-link .f-wishlist-drawer__trigger {
    width: 2.5rem;
    height: 2.5rem;
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text);
    transition: border-color var(--transition), color var(--transition);
}
.wishlist-link .f-wishlist-drawer__trigger:hover { border-color: var(--color-danger); color: var(--color-danger); }
.wishlist-link .f-wishlist-drawer__count { background: var(--color-primary); color: var(--color-on-primary); }
.topnav-is-dark .site-header .wishlist-link .f-wishlist-drawer__trigger { border-color: #3a3f4b; }

.wishlist-link .f-drawer { background: var(--color-bg); color: var(--color-text); }
.wishlist-link .f-drawer__head { background: var(--color-surface); }
.wishlist-link .f-drawer__title { font-size: 1.15rem; }
.wishlist-link .f-drawer__badge { background: var(--color-primary); color: var(--color-on-primary); }
.wishlist-link .f-drawer__close { border-radius: var(--radius-sm); }
.wishlist-link .f-wishlist-drawer__item { background: #fff; border: 1px solid var(--color-border); border-radius: var(--radius); padding: 0.75rem; margin-block: 0.6rem; }
.wishlist-link .f-wishlist-drawer__media { border-radius: var(--radius-sm); }
.wishlist-link .f-wishlist-drawer__name { font-size: 0.92rem; }
.wishlist-link .f-wishlist-drawer__actions .f-add-product__button {
    padding: 0.5rem 0.9rem;
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
}
.wishlist-link .f-wishlist-drawer__actions .f-wishlist__button {
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border-radius: var(--radius-sm);
}
.wishlist-link .f-drawer__foot { background: var(--color-surface); }
.wishlist-link .f-wishlist-drawer__all { border-radius: var(--radius-sm); padding: 0.7rem 1.6rem; min-block-size: auto; }

@media (max-width: 767px) {
    .wishlist-link .f-drawer { inline-size: 100vw; }
}

/* ------------------------------------------------------------- checkout */
/* The platform checkout wearing this theme: card steps, the theme's inputs
   and buttons, the summary as a surface card. */
.checkout-page { padding-block: 1rem 3rem; }
.checkout-page .f-checkout__step { padding: 1.25rem; margin-block-end: 1rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: #fff; }
.checkout-page .f-checkout__step--active { border-color: var(--color-primary); box-shadow: var(--shadow-sm); }
.checkout-page .f-checkout__step-icon { border-radius: var(--radius-sm); }
.checkout-page .f-input { border-radius: var(--radius-sm); background: #fff; }
.checkout-page .f-checkout__method { border-radius: var(--radius-sm); background: #fff; }
.checkout-page .f-checkout__summary { background: var(--color-surface); border-radius: var(--radius); }
/* The list scrolls, so it clips the first item's qty badge (top: -0.35rem). */
.checkout-page .f-checkout__lines { padding-block-start: 0.5rem; }
.checkout-page .f-btn { border-radius: var(--radius-sm); }
.checkout-page .f-btn--primary { background: var(--color-primary); color: var(--color-on-primary); }
.checkout-page .f-btn--primary:hover:not(:disabled) { background: var(--color-primary-dark); opacity: 1; }
.checkout-page .f-checkout__signin { border-radius: var(--radius); }

.payment-status-page { padding-block: 2rem 4rem; }

.thank-you__note { color: var(--color-text-soft); }
.thank-you__items { list-style: none; margin: 1.25rem auto; padding: 0; max-width: 32rem; text-align: start; display: flex; flex-direction: column; gap: 0.6rem; }
.thank-you__items li { display: flex; align-items: center; gap: 0.75rem; padding: 0.6rem 0.75rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: #fff; }
.thank-you__items img { width: 2.75rem; height: 2.75rem; object-fit: cover; border-radius: var(--radius-sm); }
.thank-you__item-name { flex: 1 1 auto; min-width: 0; }
.thank-you__item-qty { color: var(--color-text-soft); }
.thank-you__item-total { font-weight: 700; white-space: nowrap; }
.order-head__address { color: var(--color-text-soft); font-size: 0.9rem; }

/* ------------------------------ availability / size guide / reviews summary */
.product-single__availability { margin-block-start: 0.75rem; }

/* Sold out: add-to-cart already says so — the buy-now twin would only
   repeat it. Hidden here (not in the shared SDK) so it comes back the
   moment a variant with stock is picked. */
.buy-box .f-add-product--quick-buy.f-add-product--unavailable { display: none; }

/* Detail panels: breathe between each other and from whatever sits above
   (notify-me, offers). */
.product-single__panels { display: grid; gap: 0.75rem; margin-block-start: 1.25rem; }
.btn--notify { display: inline-flex; align-items: center; gap: 0.45rem; }
.product-single__size-guide { margin-block: 0.25rem 0.75rem; }
.product-single__reviews > h2 { margin-block-end: 1rem; }
.product-single__reviews-summary { padding: 1.25rem; margin-block-end: 1.5rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: #fff; }


/* ==========================================================================
   Onyx chrome
   --------------------------------------------------------------------------
   Everything above this line is the shared theme base. Below is what Onyx
   adds: a four-row header, the centred block header motif, and the footer
   rows the base does not have. Appended rather than edited in place, so a
   diff against the template stays readable.
   ========================================================================== */

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* --- blocks -------------------------------------------------------------- */

/* One full-bleed band. Sections alternate grounds rather than separating
   themselves with borders — the reference's rhythm, expressed as one token. */
.block {
    padding-block: var(--block-space);
}
.block--surface { background: var(--color-surface); }
.block--flush { padding-block: 0; }

/* Centred title, muted subtitle, ornamental rule. This sits above nearly every
   block on the page, so it is one class rather than a decision each block
   makes again. */
.block-head {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    text-align: center;
    margin-block-end: 3rem;
}
.block-head__title {
    font-size: var(--fs-section);
    font-weight: 700;
    line-height: 1.2;
    text-wrap: balance;
}
.block-head__sub {
    color: var(--color-text-soft);
    font-size: var(--fs-meta);
    max-width: 46ch;
}
.block-head__rule {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-block-start: 0.25rem;
}
.block-head__rule::before,
.block-head__rule::after {
    content: "";
    width: 3.5rem;
    height: 1px;
    background: var(--color-primary);
    opacity: 0.55;
}
.block-head__rule span {
    width: 0.5rem;
    height: 0.5rem;
    background: var(--color-primary);
    transform: rotate(45deg);
}

.page-title {
    font-size: var(--fs-section);
    margin-block-end: 2rem;
}

/* --- header -------------------------------------------------------------- */

.site-header {
    position: relative;
    z-index: 30;
    background: var(--color-header-bg);
    transition: background-color var(--transition), box-shadow var(--transition);
}
.site-header--sticky {
    position: sticky;
    top: 0;
}

/* Row 2 — utility bar. */
.site-header__utility {
    background: var(--color-surface);
    border-block-end: 1px solid var(--color-border);
    font-size: 0.9rem;
    color: var(--color-text-soft);
}
.site-header__utility-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    min-height: 2.5rem;
    flex-wrap: wrap;
}
.site-header__contact,
.site-header__utility-links {
    display: flex;
    align-items: center;
    gap: 1.25rem;
}
.site-header__contact a:hover,
.site-header__utility-links a:hover { color: var(--color-primary); }

/* Row 3 — main bar. Logo centred, actions split to the edges. */
.site-header__bar-inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 1rem;
    min-height: var(--header-h);
}
.site-header__start,
.site-header__end {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
.site-header__end { justify-content: flex-end; }

.site-header__logo {
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: var(--fs-card);
}
.site-header__logo img {
    max-height: 3rem;
    width: auto;
    object-fit: contain;
}

/* Row 4 — navigation.
   Centring is scoped above the drawer breakpoint on purpose: below 860px the
   base turns .main-menu into a fixed off-canvas panel, and centring its
   contents there would fight that layout. */
.site-header__nav {
    border-block-start: 1px solid var(--color-border);
}
@media (min-width: 861px) {
    .site-header__nav .main-menu {
        display: flex;
        justify-content: center;
    }
}
@media (max-width: 860px) {
    /* The wrapper must stay displayed — the drawer IS .main-menu inside it. */
    .site-header__nav { border-block-start: 0; }
}

/* The base sets .main-menu__submenu { display: none } (0,0,1,0), but
   .main-menu ul (0,0,1,1) sets display:flex and outranks it, so submenus
   render open. Two classes win it back without !important — the same
   specificity trap the SDK styling notes call out. Latent in the shared base:
   nothing exercised it because the demo menu has no child items. */
.main-menu .main-menu__submenu { display: none; }
.main-menu .main-menu__item.is-open > .main-menu__submenu { display: flex; }

/* Transparent over the hero.
   --------------------------------------------------------------------------
   Taking the header out of flow is only safe when there is a full-bleed hero
   directly beneath it to float over. Guarding on that is not defensive
   nicety: with an empty home area, main collapses to zero height and an
   absolutely-positioned header lands on top of the footer.

   So the overlay is opt-in on the CONTENT, not on the setting alone — the
   first block in main must be a hero. A browser without :has() simply keeps
   the header in normal flow, which is the safe degradation, and the same is
   true of any page whose first block is not a hero.

   app.js only toggles [data-scrolled]; what "solid" looks like is decided
   here, not in JavaScript. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"] {
    position: absolute;
    inset-inline: 0;
    top: 0;
    background: transparent;
    color: #fff;
}
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"] .site-header__utility,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"] .site-header__nav {
    background: transparent;
    border-color: rgba(255, 255, 255, 0.22);
    color: inherit;
}
/* Pinned: frosted, not filled.

   The reference paints NO background here — it runs backdrop-filter: blur(40px)
   over a transparent bar, so the light of the page beneath is what makes it
   read as white, and the content stays faintly visible through it. Measured
   off its pinned bar, along with the 0 0 5px shadow.

   A tint is layered under the blur anyway: over a dark section, or in dark
   mode, pure blur alone leaves the glyphs sitting on whatever happens to be
   behind them. The tint comes from a token so it inverts with the palette. */
/* NO backdrop-filter here, deliberately.
   It frosted beautifully and broke two things: `backdrop-filter` makes an
   element a containing block for its position:fixed descendants, and both the
   drawer and <falak-search>'s modal are fixed elements living inside this
   header. Their `inset: 0` resolved against the 104px header instead of the
   viewport — the drawer opened 104px tall, and the search panel appeared as a
   band clipped to the header. Both worked at the top of the page, where this
   rule does not apply, and nowhere else.
   A solid ground gets the same legibility with none of that. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] {
    position: fixed;
    background: var(--color-header-bg, var(--color-bg));
    color: var(--color-text);
    box-shadow: 0 1px 12px rgba(0, 0, 0, 0.08);
}

/* (The @supports fallback that used to sit here is gone with the blur — the
   bar is opaque for everyone now.) */

/* The reference's pinned bar is 73px — it condenses from 121. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .site-header__bar-inner {
    min-height: 73px;
}
/* Scrolled state drops the utility and nav rows — the reference condenses to
   the main bar alone, which is what keeps a sticky header short enough to be
   worth having.

   DESKTOP ONLY. Below the drawer breakpoint .site-header__nav is not a row of
   links that can be spared: it is the drawer itself, the thing the hamburger
   opens. Hiding it on scroll meant the menu opened correctly — body.menu-is-open
   was set, the panel was position:fixed at z-index 80 — onto an element with
   display:none, so it measured 0x0 and nothing appeared. The menu worked at the
   top of the page and nowhere else, which is exactly how it was reported. */
@media (min-width: 861px) {
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .site-header__utility,
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .site-header__nav {
        display: none;
    }
}

/* On a phone the utility row still goes — it is genuinely spare there — but the
   nav stays, because the drawer lives in it. */
@media (max-width: 860px) {
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .site-header__utility {
        display: none;
    }
}

/* A home page with no blocks placed yet still has to look like a page rather
   than a header sitting straight on a footer. Not `main:empty` — Twig leaves
   whitespace inside the block, so that selector never matches. A floor on
   main is a no-op the moment any block renders. */
.app-inner > main { min-height: 30vh; }

/* --- footer -------------------------------------------------------------- */

.site-footer {
    margin-block-start: auto;
    background: var(--color-footer-bg);
    color: #fff;
    font-size: var(--fs-meta);
}
.footer-is-dark .site-footer { color: rgba(255, 255, 255, 0.86); }
.site-footer a:hover { color: var(--color-primary-light); }

.site-footer__newsletter {
    border-block-end: 1px solid rgba(255, 255, 255, 0.12);
    padding-block: 2rem;
}
.site-footer__newsletter-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
}
.site-footer__newsletter-title {
    font-size: var(--fs-lead);
    font-weight: 700;
}
.site-footer__newsletter-form {
    display: flex;
    gap: 0.5rem;
    flex: 1 1 22rem;
    max-width: 32rem;
}
.site-footer__newsletter-form input {
    flex: 1;
    min-width: 0;
    padding: 0.75rem 1rem;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: var(--radius-sm);
    background: transparent;
    color: inherit;
    font: inherit;
}
.site-footer__newsletter-form input::placeholder { color: rgba(255, 255, 255, 0.45); }
/* Disabled until a subscribe endpoint exists. Reads as not-ready rather than
   broken, which is the honest state. */
.site-footer__newsletter-form input:disabled,
.site-footer__newsletter-form button:disabled { opacity: 0.5; cursor: not-allowed; }
.site-footer__newsletter-form .btn--outline { border-color: rgba(255, 255, 255, 0.35); color: #fff; }

.site-footer__main {
    display: grid;
    grid-template-columns: 1fr 1.2fr 1fr;
    gap: 2.5rem;
    padding-block: 3rem;
    align-items: start;
}
.site-footer__col { display: flex; flex-direction: column; gap: 1rem; }
.site-footer__col--brand { align-items: center; text-align: center; }

.site-footer__heading {
    font-size: var(--fs-body);
    font-weight: 700;
    color: #fff;
}
.site-footer__links { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.site-footer__logo img { max-height: 3rem; width: auto; object-fit: contain; }
.site-footer__about { color: rgba(255, 255, 255, 0.7); max-width: 34ch; }

/* Two children now, not one: the contact chips and then the social profiles.
   A single centred flex row laid them side by side and <falak-social>'s own
   "تابعنا" heading landed on top of the last chip. Stacked and centred, with
   the gap collapsing to nothing when either component removes itself for want
   of data. */
.site-footer__connect {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.25rem;
    padding-block: 1.5rem;
    border-block-start: 1px solid rgba(255, 255, 255, 0.12);
}
.site-footer__connect > *[hidden] { display: none; }

.site-footer__bottom { border-block-start: 1px solid rgba(255, 255, 255, 0.12); }
.site-footer__bottom-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding-block: 1.25rem;
    color: rgba(255, 255, 255, 0.6);
    font-size: var(--fs-caption);
}

/* ---- footer disclosure (links column) ----------------------------------- */

.site-footer__group { inline-size: 100%; }
.site-footer__group > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    cursor: pointer;
    /* Both spellings: Safari still wants the pseudo-element. */
    list-style: none;
}
.site-footer__group > summary::-webkit-details-marker { display: none; }

.site-footer__group > summary::after {
    content: "";
    inline-size: 0.7rem;
    block-size: 0.7rem;
    flex: none;
    background: currentColor;
    -webkit-mask: var(--onyx-chevron) center / contain no-repeat;
    mask: var(--onyx-chevron) center / contain no-repeat;
    transform: rotate(90deg);
    transition: transform 0.2s ease;
}
.site-footer__group[open] > summary::after { transform: rotate(-90deg); }

/*
 * Desktop has no accordion. The panel ships open and stays open — only the
 * affordance is removed, because there is nothing here to collapse on a wide
 * screen. wireFooterGroups() closes it below this same breakpoint.
 */
@media (min-width: 640px) {
    .site-footer__group > summary { cursor: default; pointer-events: none; }
    .site-footer__group > summary::after { display: none; }
}

@media (max-width: 1023px) {
    .site-footer__main { grid-template-columns: 1fr 1fr; }
    .site-footer__col--brand { grid-column: 1 / -1; order: -1; }
}
@media (max-width: 639px) {
    .site-footer__main { grid-template-columns: 1fr; text-align: center; }
    .site-footer__col { align-items: center; }

    /* The reference's phone order: brand, then the apps, then the links
       accordion last. */
    .site-footer__col--links { order: 1; }

    /*
     * `nowrap` is load-bearing, not tidying.
     *
     * The base rule sets `flex-wrap: wrap` for the desktop bar. Turning the
     * inner into a COLUMN without dropping that made it a multi-line column
     * container, and a wrapping flex line takes its cross size from the widest
     * item's max-content — so `align-items: stretch` stretched the title and
     * the form to the FORM's natural 373px instead of to the 328px container,
     * and the footer overflowed the page by 45px on a 360px phone.
     */
    .site-footer__newsletter-inner {
        flex-direction: column;
        flex-wrap: nowrap;
        align-items: stretch;
        text-align: center;
    }

    /*
     * The form keeps its own row and its own height.
     *
     * `flex: 1 1 22rem` is written for the desktop bar, where the inner is a
     * ROW and 22rem is a width. Turning the inner into a column above made
     * 22rem a HEIGHT, and the email field and its button grew to 352px tall.
     */
    .site-footer__newsletter-form {
        flex: 0 0 auto;
        max-width: none;
    }

    /* Collapsed by default on a phone, and full-width when open. */
    .site-footer__group { text-align: start; }
    .site-footer__group > summary { justify-content: center; }
    .site-footer__group[open] > summary { margin-block-end: 0.75rem; }
    .site-footer__links { align-items: center; }
}

/* --- account and static pages -------------------------------------------- */

.customer-layout {
    display: grid;
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: 2.5rem;
    align-items: start;
}
.customer-nav ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.25rem; }
.customer-nav a {
    display: block;
    padding: 0.6rem 0.9rem;
    border-radius: var(--radius-sm);
    color: var(--color-text-soft);
}
.customer-nav a:hover { background: var(--color-surface); color: var(--color-text); }

/* Width, position, framing and spacing all come from the Content pages settings
   group. The measure is a custom property on ONE panel that wraps the title and
   the body, so the two can never drift out of alignment with each other. */
.static-page { --static-page-measure: 75ch; --static-page-pad: 2.75rem; }
.static-page--narrow { --static-page-measure: 58ch; }
.static-page--medium { --static-page-measure: 75ch; }
.static-page--wide { --static-page-measure: 95ch; }
.static-page--full { --static-page-measure: 100%; }

.static-page--space-compact { --static-page-pad: 1.5rem; }
.static-page--space-normal { --static-page-pad: 2.75rem; }
.static-page--space-roomy { --static-page-pad: 4.5rem; }

.static-page__panel { max-width: var(--static-page-measure); }

/* Centres the COLUMN, not the sentences. Body copy stays start-aligned and only
   the leftover space is split evenly — `text-align: center` here would wreck a
   page of policy text. */
.static-page--center .static-page__panel,
.static-page--center .static-page__crumbs { margin-inline: auto; }

/* Boxed: the whitespace around a readable column reads as deliberate framing
   rather than an empty page, without lengthening the lines. */
.static-page--boxed .static-page__panel {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--static-page-pad);
}

.static-page--boxed.static-page--full .static-page__panel { max-width: 100%; }

.static-page__crumbs { display: block; margin-block-end: 1.25rem; max-width: var(--static-page-measure); }

.static-page__title { font-size: var(--fs-section); margin-block-end: 1.5rem; }
/* ---------------------------------------------- the written page's own body

   Everything below styles HTML the MERCHANT wrote in the customizer's editor,
   which arrives through {{ page.content|raw }} as a flat run of tags. The theme
   has no classes to hang off here, so these are element selectors scoped to the
   body — the one place in this stylesheet where that is the right tool.

   Kept to what the editor can actually produce (see QUILL_TOOLBAR in
   PageDrawers.tsx): headings, lists, quotes, code, links, pictures, embeds and
   Quill's own alignment/indent classes. Anything wider belongs to a section on
   a Customised page, not to a paragraph.
   ------------------------------------------------------------------------- */

.static-page__body { line-height: 1.9; }
.static-page__body > * + * { margin-block-start: 1rem; }

/* Headings rank against the page title rather than the browser's defaults,
   which is what made an h1 in the body compete with the page's own. */
.static-page__body h1,
.static-page__body h2,
.static-page__body h3,
.static-page__body h4 {
    line-height: 1.35;
    font-weight: 700;
    color: var(--color-text);
    text-wrap: balance;
}

.static-page__body h1 { font-size: 1.75rem; }
.static-page__body h2 { font-size: 1.4rem; }
.static-page__body h3 { font-size: 1.15rem; }
.static-page__body h4 { font-size: 1rem; }

/* A heading needs air above it and little below — it belongs to what follows.
   The `* + *` rule above already spaces siblings, so only the extra is added. */
.static-page__body > * + :is(h1, h2, h3, h4) { margin-block-start: 2rem; }
.static-page__body :is(h1, h2, h3, h4) + * { margin-block-start: 0.5rem; }

/*
   A merchant's picture must never be the thing that breaks the page.

   `max-inline-size` rather than a width: a small logo stays its own size
   instead of being stretched across the column, and a 3000px photo comes down
   to the measure. `height: auto` keeps the aspect ratio when it does.
*/
.static-page__body img {
    max-inline-size: 100%;
    block-size: auto;
    border-radius: var(--radius);
}

/* Quill writes alignment as a class on the element itself. Centring an image
   needs the element to be a block first, which an inline <img> is not. */
.static-page__body img.ql-align-center { display: block; margin-inline: auto; }
.static-page__body img.ql-align-right { display: block; margin-inline-start: auto; }

/* An iframe whose src the sanitizer refused (anything but the allowed video
   and map hosts) keeps its tag but loses the attribute — without this it would
   render as a big empty 16:9 box in the middle of the page. */
.static-page__body iframe:not([src]) { display: none; }

/* Video embeds arrive as a bare iframe with fixed width/height attributes —
   the ratio box is what stops a 560x315 embed overflowing a phone. */
.static-page__body iframe {
    inline-size: 100%;
    max-inline-size: 100%;
    aspect-ratio: 16 / 9;
    block-size: auto;
    border: 0;
    border-radius: var(--radius);
}

.static-page__body :is(ul, ol) { padding-inline-start: 1.5rem; }
.static-page__body li + li { margin-block-start: 0.35rem; }

.static-page__body blockquote {
    margin-inline: 0;
    padding: 0.25rem 0 0.25rem 1.1rem;
    border-inline-start: 3px solid var(--color-primary);
    color: var(--color-text-soft);
    font-style: italic;
}

.static-page__body :is(pre, code) {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.9em;
}

.static-page__body code {
    padding: 0.15em 0.4em;
    border-radius: var(--radius-sm);
    background: var(--color-surface);
}

/* A code block holds lines that must not be re-wrapped, so it scrolls on its
   own rather than widening the page — the one element here allowed to. */
.static-page__body pre {
    padding: 1rem;
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    overflow-x: auto;
    direction: ltr;
    text-align: start;
}

.static-page__body pre code { padding: 0; background: none; }

.static-page__body a {
    color: var(--color-primary-dark);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.static-page__body a:hover { color: var(--color-primary); }

.static-page__body hr {
    border: 0;
    border-block-start: 1px solid var(--color-border);
    margin-block: 2rem;
}

/* Quill's indent levels, which it also writes as classes. Logical, so an
   indented Arabic list steps in from the right. */
.static-page__body .ql-indent-1 { padding-inline-start: 2rem; }
.static-page__body .ql-indent-2 { padding-inline-start: 4rem; }
.static-page__body .ql-indent-3 { padding-inline-start: 6rem; }

.static-page__body .ql-align-center { text-align: center; }
.static-page__body .ql-align-right { text-align: end; }
.static-page__body .ql-align-justify { text-align: justify; }

.static-page--title-center .static-page__title { text-align: center; }

/* Full-width header band. Spans the container, not the text column — a page
   that opens on a tinted header with its trail in it stops looking like text
   dropped onto white. */
.page-band {
    background: var(--color-surface);
    border-block-end: 1px solid var(--color-border);
    padding-block: 2.75rem;
}

.page-band__crumbs { display: block; margin-block-end: 0.9rem; }
.page-band__title { font-size: var(--fs-section); margin: 0; }

/* The band already supplies the top spacing, so the body must not add its own
   on top of it — otherwise the two read as disconnected slabs. */
.page-band + .block { margin-block-start: 2.5rem; }

@media (max-width: 48rem) {
    .static-page { --static-page-pad: 1.25rem; }
    .static-page--space-roomy { --static-page-pad: 2rem; }
    .page-band { padding-block: 1.75rem; }
}

@media (max-width: 899px) {
    .customer-layout { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 767px) {
    /* Contact details go; the language and currency switcher stays — it is the
       one thing on this row a visitor actually reaches for. */
    .site-header__contact { display: none; }
    .site-header__utility-inner { justify-content: flex-end; }
    .site-header__bar-inner { grid-template-columns: auto 1fr auto; }
}


/* ===== onyx home blocks ===== */
/* --------------------------------------------------------------------------
   The 28 home blocks. Classes the shared base already defines — .banner,
   .photo-grid, .photo-tile, .features-grid, .feature-card, .testimonials-grid,
   .testimonial-card — are reused as-is and only adjusted where Onyx differs.
   -------------------------------------------------------------------------- */

/* Rendered unconditionally so the customizer can write into them live; hidden
   when the merchant has left them blank. Without this every block carries an
   empty heading's line-height as dead space. */
.block-head__title:empty,
.block-head__sub:empty,
.store-story__body:empty,
.banner__title:empty,
.fixed-banner__title:empty { display: none; }

/* ---- 01 hero slider ---------------------------------------------------- */

.block--hero { position: relative; }
.hero-slide { position: relative; }
.hero-slide__img {
    width: 100%;
    height: clamp(24rem, 46vw, 44rem);
    object-fit: cover;
}
.hero-slide__content {
    position: absolute;
    inset-block-end: clamp(2rem, 6vw, 5rem);
    inset-inline: 0;
    color: #fff;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-3, 0.75rem);
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
}
.hero-slide__title { font-size: var(--fs-hero); max-width: 18ch; }
.hero-slide__text { max-width: 46ch; }
.hero-slide__title:empty, .hero-slide__text:empty { display: none; }

/* ---- 02 contained slider ----------------------------------------------- */

.compact-slide { position: relative; border-radius: var(--radius-lg); overflow: hidden; }
.compact-slide__img { width: 100%; height: clamp(14rem, 28vw, 24rem); object-fit: cover; }
.compact-slide__content {
    position: absolute;
    inset-block-end: 1.5rem;
    inset-inline-start: 1.5rem;
    color: #fff;
    display: grid;
    gap: 0.5rem;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
.compact-slide__title { font-size: var(--fs-block); }

/* ---- 04 / 16 fixed backgrounds ----------------------------------------- */

/* CSS-only parallax. iOS Safari ignores background-attachment: fixed and
   renders a static cover — a graceful fallback, and the reason this is not
   done with a scroll listener. */
.block--fixed-products,
.block--fixed-banner,
.block--store-story.has-background {
    background-size: cover;
    background-position: center;
    background-attachment: fixed;
    color: #fff;
}

/* The categories band keeps the same fixed cover, but on a layer of its own
   so `background_opacity` can fade the picture without fading the text with
   it. Underneath sits the theme's deep ink, which is what the picture fades
   into and what keeps the white headline readable at every setting. */
.block--categories-band.has-background {
    position: relative;
    isolation: isolate;
    background-color: var(--color-text, #101631);
    color: #fff;
}
.block--categories-band__bg {
    position: absolute;
    inset: 0;
    z-index: -1;
    background-image: var(--band-bg);
    background-size: cover;
    background-position: center;
    background-attachment: fixed;
    opacity: calc(var(--band-bg-opacity, 100) / 100);
}

/* The category names come from <falak-categories>, which asks to inherit the
   band's ink — but the SDK sheet lives inside @layer falak, and an unlayered
   rule beats a layered one at any specificity. This theme's own
   "a { color: var(--color-primary) }" was therefore repainting the labels in
   body ink over the picture. Restoring the inheritance the component asked for
   is enough: white on a background image, normal ink without one. A merchant
   who wants a different colour has the Category name style role. */
.block--categories-band .f-categories__link { color: inherit; }
.block--fixed-products .block-head__sub,
.block--fixed-banner .block-head__sub { color: rgba(255, 255, 255, 0.8); }

.block--fixed-banner {
    display: flex;
    align-items: center;
    text-align: center;
}
.block--fixed-banner.is-sm { min-height: 12rem; }
.block--fixed-banner.is-md { min-height: 20rem; }
.block--fixed-banner.is-lg { min-height: 30rem; }
.fixed-banner__content { display: grid; justify-items: center; gap: 1rem; }
.fixed-banner__title { font-size: var(--fs-section); text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45); }

/* ---- 05 two-column feature --------------------------------------------- */

.featured-products__grid {
    display: grid;
    grid-template-columns: 22rem minmax(0, 1fr);
    gap: 2.5rem;
    align-items: center;
}
.block--featured-products.is-flipped .featured-products__panel { order: 2; }
.featured-products__panel { display: grid; gap: 1rem; }
.featured-products__image { width: 100%; border-radius: var(--radius); aspect-ratio: 4 / 5; object-fit: cover; }
.featured-products__body { display: grid; gap: 0.6rem; }
.featured-products__title { font-size: var(--fs-block); }

/* ---- 06 lookbook -------------------------------------------------------- */

.lookbook__grid { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 2rem; }
.lookbook__hero { width: 100%; border-radius: var(--radius); aspect-ratio: 3 / 4; object-fit: cover; }
.lookbook__items { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; align-content: start; }
.lookbook__item a {
    display: grid;
    grid-template-columns: 4.5rem minmax(0, 1fr) auto;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}
.lookbook__item a:hover { border-color: var(--color-primary); }
.lookbook__item img { width: 4.5rem; aspect-ratio: 1; object-fit: cover; border-radius: var(--radius-sm); }
.lookbook__name { font-weight: 600; }
.lookbook__price { color: var(--color-primary); font-weight: 700; white-space: nowrap; }

/* ---- 07 product of the week -------------------------------------------- */

.featured-product__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 3rem; align-items: center; }
.featured-product__image { width: 100%; border-radius: var(--radius); aspect-ratio: 1; object-fit: cover; }
.featured-product__body { display: grid; gap: 1rem; justify-items: start; }
.featured-product__name { font-size: var(--fs-sub); }
.featured-product__price { display: flex; align-items: baseline; gap: 0.75rem; font-size: var(--fs-card); font-weight: 700; color: var(--color-primary); }
.featured-product__price del { color: var(--color-text-faint); font-size: var(--fs-meta); font-weight: 400; }

/* ---- 10 promo with timer ------------------------------------------------ */

.promo-countdown__card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: 2.5rem;
    align-items: center;
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.promo-countdown__image { width: 100%; height: 100%; min-height: 18rem; object-fit: cover; }
.promo-countdown__body { display: grid; gap: 1rem; justify-items: start; padding: 2rem 2rem 2rem 0; padding-inline: 0 2rem; }
.promo-countdown__title { font-size: var(--fs-section); }
.promo-countdown__code {
    display: flex; align-items: center; gap: 0.75rem;
    background: var(--color-bg);
    border: 1px dashed var(--color-primary);
    border-radius: var(--radius-sm);
    padding: 0.6rem 1rem;
}
.promo-countdown__code-label { color: var(--color-text-soft); font-size: var(--fs-meta); }
.promo-countdown__code strong { color: var(--color-primary); letter-spacing: 0.06em; }

/* ---- 11 circle links ---------------------------------------------------- */

.circle-links {
    list-style: none; margin: 0; padding: 0;
    display: grid;
    grid-template-columns: repeat(var(--circle-columns, 6), minmax(0, 1fr));
    gap: 2rem 1rem;
}
.circle-link a { display: grid; justify-items: center; gap: 0.35rem; text-align: center; }
.circle-link__media {
    width: 6.5rem; height: 6.5rem;
    border-radius: 50%;
    overflow: hidden;
    background: var(--color-surface);
    display: block;
}
.circle-link__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--transition); }
.circle-link a:hover .circle-link__media img { transform: scale(1.06); }
.circle-link__title { font-weight: 700; }
.circle-link__caption { color: var(--color-text-soft); font-size: var(--fs-caption); }

/* ---- 13 square links ---------------------------------------------------- */

.square-links {
    list-style: none; margin: 0; padding: 0;
    display: grid;
    grid-template-columns: repeat(var(--square-columns, 6), minmax(0, 1fr));
    gap: 1.25rem;
}
.square-link a { display: grid; gap: 0.5rem; text-align: center; }
.square-link img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--radius); background: var(--color-surface); }
.square-link__title { font-weight: 600; font-size: var(--fs-meta); }

/* ---- 14 photo grid (mosaic variant) ------------------------------------- */

.photo-grid--mosaic { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem; }
.photo-grid--mosaic .photo-tile:first-child { grid-column: span 2; grid-row: span 2; }
.photo-grid--equal { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem; }
.photo-grid--mosaic .photo-tile img,
.photo-grid--equal .photo-tile img { width: 100%; height: 100%; object-fit: cover; }
.photo-grid--mosaic .photo-tile,
.photo-grid--equal .photo-tile { position: relative; border-radius: var(--radius); overflow: hidden; min-height: 12rem; }

/* ---- 17 before / after -------------------------------------------------- */

.block--before-after falak-image-compare { display: block; max-width: 56rem; margin-inline: auto; }

/* ---- 18 stats ----------------------------------------------------------- */

.block--stats.is-dark { background: var(--color-footer-bg); color: #fff; }
.block--stats.is-dark .block-head__sub { color: rgba(255, 255, 255, 0.72); }
.stats {
    list-style: none; margin: 0; padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
    gap: 2rem;
    text-align: center;
}
.stat { display: grid; gap: 0.25rem; }
.stat__value { font-size: var(--fs-section); font-weight: 700; color: var(--color-primary); font-variant-numeric: tabular-nums; }
.stat__label { color: inherit; opacity: 0.75; font-size: var(--fs-meta); }

/* ---- 20 store story ----------------------------------------------------- */

.store-story { display: grid; justify-items: center; text-align: center; gap: 1rem; }
.store-story__body { max-width: 62ch; line-height: 1.9; }

/* ---- 22 video with products --------------------------------------------- */

.video-products__grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 2rem; align-items: center; }
.video-products__media { border-radius: var(--radius); overflow: hidden; background: var(--color-surface); }
.video-products__video,
.video-products__media img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; }

/* ---- 24 faq ------------------------------------------------------------- */

.faq__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 2.5rem; align-items: start; }
.faq__grid.is-single { grid-template-columns: minmax(0, 1fr); max-width: 52rem; margin-inline: auto; }
.faq__image { width: 100%; border-radius: var(--radius); aspect-ratio: 3 / 4; object-fit: cover; }
.faq__list { display: grid; gap: 0.6rem; }
.faq__item { border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); }

/* ---- 26 testimonials ---------------------------------------------------- */

.testimonial-card__who { display: flex; align-items: center; gap: 0.6rem; margin-block-start: 0.75rem; font-weight: 600; }
.testimonial-card__who img { width: 2.25rem; height: 2.25rem; border-radius: 50%; object-fit: cover; }

/* ---- 27 contact --------------------------------------------------------- */

.contact__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: 2.5rem; align-items: start; }
.contact__grid.is-single { grid-template-columns: minmax(0, 1fr); max-width: 44rem; margin-inline: auto; }
.contact__image { width: 100%; border-radius: var(--radius); aspect-ratio: 4 / 5; object-fit: cover; }

/* ---- 28 branches -------------------------------------------------------- */

.branches { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 1.25rem; }
.branch {
    display: grid; gap: 0.4rem; align-content: start;
    padding: 1.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-bg);
}
.branch__city { font-size: var(--fs-card); }
.branch__address, .branch__hours { color: var(--color-text-soft); font-size: var(--fs-meta); }
.branch__phone { color: var(--color-primary); font-weight: 600; }
.branch__map { justify-self: start; margin-block-start: 0.5rem; }

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 1023px) {
    .circle-links { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .square-links { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .featured-products__grid,
    .lookbook__grid,
    .featured-product__grid,
    .video-products__grid,
    .faq__grid,
    .contact__grid,
    .promo-countdown__card { grid-template-columns: minmax(0, 1fr); }
    .block--featured-products.is-flipped .featured-products__panel { order: 0; }
    .promo-countdown__body { padding-inline: 1.5rem; padding-block-end: 1.5rem; }
    .photo-grid--mosaic, .photo-grid--equal { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .photo-grid--mosaic .photo-tile:first-child { grid-column: span 2; grid-row: auto; }
}

@media (max-width: 639px) {
    .circle-links { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem 0.5rem; }
    .circle-link__media { width: 4.75rem; height: 4.75rem; }
    .square-links { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .hero-slide__img { height: 26rem; }
}


/* ===== onyx video wall ===== */
/* --------------------------------------------------------------------------
   Geometry measured off the reference: 272x484 slides (9:16), 10px gutter,
   five in view; a 160x2 rule under a 36px/700 centred title.
   -------------------------------------------------------------------------- */

/* The ornamental rule is one element with a gradient, the way the reference
   draws it — two pseudo-elements and a rotated square was three boxes doing
   what one background can. */
.block-head__rule {
    width: 10rem;
    height: 2px;
    background:
        linear-gradient(90deg,
            var(--color-primary) 0,
            var(--color-primary) 40%,
            transparent 40%,
            transparent 60%,
            var(--color-primary) 60%,
            var(--color-primary) 100%);
    position: relative;
    margin-block-start: 0.75rem;
}
/* The diamond that sits in the gap the gradient leaves. 10px, measured off the
   reference — the band itself was already 160x2 and needed nothing. */
.block-head__rule::after {
    content: "";
    position: absolute;
    inset-inline-start: 50%;
    top: 50%;
    width: 10px;
    height: 10px;
    background: var(--color-primary);
    transform: translate(-50%, -50%) rotate(45deg);
}
[dir="rtl"] .block-head__rule::after { transform: translate(50%, -50%) rotate(45deg); }

.block--videos-slider .block-head__title { font-size: 2.25rem; }

/* ---- the wall ----------------------------------------------------------- */

.video-wall { display: block; }

/* Five 9:16 cards with a 10px gutter. The SDK slider owns the track and the
   scroll; the card is the theme's. */
.block--videos-slider .f-slider__track { gap: 10px; }

.video-card { display: grid; gap: 0.5rem; }

.video-card__frame {
    position: relative;
    aspect-ratio: 9 / 16;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--color-surface);
}

.video-card__poster,
.video-card__frame video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* The stand-in <video> is decoration: the button above it takes every
   click, and the frame must never show native controls. */
.video-card__poster { pointer-events: none; }

.video-card__play {
    position: absolute;
    inset: 0;
    width: 100%;
    display: grid;
    place-items: center;
    background: transparent;
    border: 0;
    cursor: pointer;
    /* A wash so a white play mark stays legible on a bright frame. */
    background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.35));
    transition: background-color var(--transition);
}
.video-card__play:hover { background-color: rgba(0, 0, 0, 0.12); }

.video-card__play-icon {
    width: 3.25rem;
    height: 3.25rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.92);
    display: grid;
    place-items: center;
    box-shadow: var(--shadow);
}
/* A CSS triangle rather than an icon font or an inline SVG per card — it is
   one shape and it inherits the theme's colour. */
.video-card__play-icon::after {
    content: "";
    border-style: solid;
    border-width: 0.5rem 0 0.5rem 0.8rem;
    border-color: transparent transparent transparent var(--color-ink, #14110e);
    margin-inline-start: 0.2rem;
}
/* Deliberately NOT mirrored in RTL. A play mark is a pictogram, not text —
   it points the same way in every locale, the way it does on every player
   and remote control. Flipping it produced something that reads as rewind. */

.video-card__caption {
    position: absolute;
    inset-block-end: 0.6rem;
    inset-inline: 0.6rem;
    color: #fff;
    font-size: var(--fs-caption);
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
    pointer-events: none;
}

.video-card__link {
    justify-self: center;
    font-size: var(--fs-caption);
    color: var(--color-primary);
    font-weight: 600;
}

/* Once playing, the poster and the trigger are gone and the video fills the
   frame with its own controls. */
.video-card.is-playing .video-card__play,
.video-card.is-playing .video-card__poster,
.video-card.is-playing .video-card__caption { display: none; }

@media (max-width: 1023px) {
    .block--videos-slider .block-head__title { font-size: var(--fs-section); }
}

/* ---- header: absolute over the hero, like the reference ----------------- */

/* The reference's header is 169px tall — a 48px utility strip over a 121px
   band carrying the logo row and the nav. */
.site-header__utility-inner { min-height: 48px; }

/* 14px, not 15: the reference's 15px is on the strip, but its links render at
   14 — the same container-vs-anchor mix-up that had the nav at the wrong
   weight. Underlines off; the reference draws these as plain text and relies
   on the separators to divide them. */
.site-header__utility { font-size: 0.875rem; }
.site-header__utility a,
.site-header__contact a,
.site-header__utility-links a {
    text-decoration: none;
    font-size: 0.875rem;
}
.site-header__utility a:hover,
.site-header__contact a:hover { text-decoration: none; color: var(--color-primary); }
/* The logo band's height is set once, further down, from the reference's
   measurement. It used to be pinned to 4.5rem here — a far more specific
   selector, so it silently beat the later rule and the band stayed short. */


/* The reference's hero is a 759px full-bleed band with the header floating on
   top of it. object-fit keeps a 4K landscape file filling that band at every
   width without letterboxing. */
.block--hero .hero-slide { position: relative; }
.hero-slide__img {
    width: 100%;
    height: clamp(30rem, 52vw, 47.5rem);
    object-fit: cover;
    display: block;
    background: var(--color-surface);
}
.hero-slide__video { pointer-events: none; }

/* The header sits over the top of this band in white; a wash keeps it legible
   whatever frame the video happens to be on. */
.block--hero .hero-slide::after {
    content: ;
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 14rem;
    background: linear-gradient(180deg, rgba(0,0,0,0.42), rgba(0,0,0,0));
    pointer-events: none;
    /* Off unless the merchant sets Background dimming in the customizer. */
    opacity: var(--falak-overlay, 0%);
}

@media (max-width: 767px) {
    .hero-slide__img { height: 32rem; }
}


/* The shared base spaces blocks with margin-block: 3.5rem and zeroes it only
   for its own .block--hero-slider. Onyx spaces with padding instead, so the
   inherited margin was stacking on top of the padding on all 28 blocks — and
   on the hero it collapsed through .app-inner and pushed the whole page 56px
   down, leaving a white band above a hero that is supposed to sit under the
   header. Onyx owns the rhythm; the margin goes. */
.block { margin-block: 0; }
.block--hero { margin-block: 0; }

/* Header text over the hero. The bars inherit white from the header, but the
   links carry their own colour from the base and have to be told again —
   .main-menu a is a two-class selector, so this needs to outrank it.

   Scoped to TOP-LEVEL links only. `.main-menu a` also matched the links inside
   an open dropdown, and a dropdown is a white panel of its own, not part of
   the hero — so every submenu item was painted white on white and vanished the
   moment the menu opened. Only the row sitting on the video needs this. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"] .site-header__utility a,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"] .site-header__logo {
    color: #fff;
}

/*
 * The menu links, and ONLY above the drawer breakpoint.
 *
 * Below 861px `.main-menu` is not the row of links sitting on the hero at all
 * — it is the off-canvas drawer, a white panel of its own. Painting its links
 * white there made the whole menu invisible: the drawer opened blank at the top
 * of the page, and its links "appeared" only once the header had gone solid on
 * scroll and this rule stopped applying.
 *
 * That is the third time this rule has caught a surface that is not the hero
 * (the dropdown submenus were the second, see the note above). The rule paints
 * ink for one specific background, so it has to be scoped to the places that
 * actually have that background.
 */
@media (min-width: 861px) {
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"] .main-menu > ul > .main-menu__item > a {
        color: #fff;
    }
}
/* Once solid, they go back to reading against the header's own ground. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .main-menu > ul > .main-menu__item > a,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .site-header__utility a,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .site-header__logo {
    color: var(--color-text);
}


/* ===== onyx header controls ===== */
/* --------------------------------------------------------------------------
   The shared base draws header actions as a bordered pill (cart) and 2.5rem
   ringed buttons (search, wishlist). The reference uses bare glyphs with a
   small count badge — so these are overridden here, in the theme, rather than
   changed in the base where every other theme would inherit it.
   -------------------------------------------------------------------------- */

/* Cart: glyph + badge, no pill. */
.site-header .cart-link {
    padding: 0;
    border: 0;
    border-radius: 0;
    gap: 0;
}
.site-header .cart-link:hover { border-color: transparent; }
.site-header .cart-link .f-cart-summary__icon {
    width: 1.6rem;
    height: 1.6rem;
    color: inherit;
}
/* The count rides the glyph's top corner rather than sitting beside it, which
   is what keeps the control a fixed width as the cart fills up. */
.site-header .cart-link .f-cart-summary__count {
    position: absolute;
    inset-block-start: -0.4rem;
    inset-inline-end: -0.55rem;
    min-width: 1.05rem;
    height: 1.05rem;
    padding-inline: 0.2rem;
    display: grid;
    place-items: center;
    border-radius: 999px;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1;
    margin: 0;
}
.site-header .cart-link .f-cart-summary__link { position: relative; gap: 0; }
.site-header .cart-link .f-cart-summary__total,
.site-header .cart-link .f-cart-summary__label { display: none; }

/* Search and wishlist: same bare glyph treatment. */
.site-header .search-link .f-search__trigger,
.site-header .wishlist-link .f-wishlist-drawer__trigger,
.site-header .f-user__trigger {
    width: 2rem;
    height: 2rem;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: inherit;
}
.site-header .search-link .f-search__trigger:hover,
.site-header .wishlist-link .f-wishlist-drawer__trigger:hover,
.site-header .f-user__trigger:hover {
    border-color: transparent;
    background: transparent;
    color: var(--color-primary);
}

/* Account avatar keeps its circle — it carries the customer's own picture —
   but loses the ring the base draws around the trigger. */
.site-header .f-user__avatar { width: 2rem; height: 2rem; }

.site-header__start,
.site-header__end { gap: 1.1rem; }

/* The white glyphs + drop-shadow that used to be declared here are gone with
   the frosted discs; the icon controls now wear the #f8f8f8 plate in every
   state, and their ink is owned by the "discs do NOT frost over the hero"
   block at the end of the file.

   Worth knowing why it had to go rather than be recoloured: it was NOT scoped
   to :not([data-scrolled]), so it also applied to the pinned white bar. The
   cart had a scrolled override of its own further down and the account never
   matched this selector at all, which is why the search glyph alone stayed
   white after scrolling while the two beside it went brand-coloured. */

/* Utility bar: contact at the start, links and the locale switcher at the end,
   separated by hairlines the way the reference divides them. */
.site-header__contact { gap: 1rem; }
.site-header__contact a,
.site-header__utility-links > a {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}
.site-header__utility-links > a + a,
.site-header__contact a + a {
    padding-inline-start: 1rem;
    border-inline-start: 1px solid currentColor;
}


/* ===== onyx dark mode + header extras ===== */
/* --------------------------------------------------------------------------
   Light / dark store mode.

   Only the tokens are redefined — every component and every one of the 28
   blocks reads through them, so the whole storefront follows without a second
   set of rules. app.js stamps data-store-theme on <html>.
   -------------------------------------------------------------------------- */

:root[data-store-theme="dark"] {
    --color-bg: #12100e;
    --color-surface: #1b1815;
    --color-border: #2e2924;
    --color-line-soft: #241f1b;
    --color-text: #f3efe9;
    --color-ink: #f3efe9;
    --color-text-soft: #b5aca0;
    --color-text-faint: #8a8177;
    --color-header-bg: #12100e;
    --color-header-veil: rgba(18, 16, 14, 0.55);
    --color-footer-bg: #0c0a09;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
    --shadow: 0 4px 16px rgba(0, 0, 0, 0.55);
}

/* The f-* bridge is declared once at :root in the base and would keep the
   light values, so it is re-pointed here rather than left stale. */
:root[data-store-theme="dark"] {
    --f-border: var(--color-border);
    --f-surface: var(--color-surface);
    --f-text: var(--color-text);
    --f-text-soft: var(--color-text-soft);
    --f-text-faint: var(--color-text-faint);
    --f-star-empty: #3a342d;
}

/* Cards and panels the base paints white explicitly. */
:root[data-store-theme="dark"] .f-card,
:root[data-store-theme="dark"] .branch,
:root[data-store-theme="dark"] .faq__item,
:root[data-store-theme="dark"] .f-modal__body,
:root[data-store-theme="dark"] .main-menu__submenu {
    background: var(--color-surface);
    color: var(--color-text);
}

/* ---- the toggle --------------------------------------------------------- */

.theme-toggle {
    width: 2rem;
    height: 2rem;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
}
.theme-toggle:hover { color: var(--color-primary); }

/* Both glyphs are drawn; CSS shows the one that applies. Swapping a background
   image on click would flash on a cold cache. */
.theme-toggle__sun,
.theme-toggle__moon {
    width: 1.15rem;
    height: 1.15rem;
    background: currentColor;
    grid-area: 1 / 1;
}
.theme-toggle__sun {
    -webkit-mask: var(--onyx-sun) center / contain no-repeat;
    mask: var(--onyx-sun) center / contain no-repeat;
}
.theme-toggle__moon {
    -webkit-mask: var(--onyx-moon) center / contain no-repeat;
    mask: var(--onyx-moon) center / contain no-repeat;
    display: none;
}
:root[data-store-theme="dark"] .theme-toggle__sun { display: none; }
:root[data-store-theme="dark"] .theme-toggle__moon { display: block; }

:root {
    --onyx-sun: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4'/%3E%3C/svg%3E");
    --onyx-moon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z'/%3E%3C/svg%3E");
}

/* ---- currency trigger --------------------------------------------------- */

/* Sits beside the language trigger and is styled to match it, so the pair
   reads as two controls rather than a control and a button. */
/* ---- default avatar ----------------------------------------------------- */

/* There is no avatar column in the platform, so the SDK renders initials. The
   header shows a neutral mark instead — the reference's look — while the
   dropdown keeps the initials, which are real information about who is
   signed in. */
.site-header .f-user__avatar {
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2040%2040%22%3E%3Ccircle%20cx%3D%2220%22%20cy%3D%2220%22%20r%3D%2220%22%20fill%3D%22%23d7d2ca%22%2F%3E%3Ccircle%20cx%3D%2220%22%20cy%3D%2215.5%22%20r%3D%226.5%22%20fill%3D%22%23fbfaf8%22%2F%3E%3Cpath%20d%3D%22M6%2039c1.6-8.2%207.3-12.5%2014-12.5S32.4%2030.8%2034%2039z%22%20fill%3D%22%23fbfaf8%22%2F%3E%3C%2Fsvg%3E");
    background-size: cover;
    background-position: center;
    color: transparent;
    font-size: 0;
    overflow: hidden;
}
.site-header .f-user__avatar svg { display: none; }
.site-header .f-user__panel .f-user__avatar--lg {
    background-image: none;
    color: var(--color-on-primary);
    font-size: 1rem;
}

/* ---- dropdown ink ------------------------------------------------------- */

/* Over a hero the header paints its text white, and the account dropdown —
   a light panel — inherited it. Every line inside sets its own colour except
   the greeting name, which the base leaves at inherit, so it went invisible.
   The panel carries its own ink instead of borrowing the header's, in either
   header state and in both store themes. */
.site-header .f-user__panel { color: var(--color-text); }
.site-header .f-user__greeting strong { color: var(--color-text); }

/* The SDK hangs the dropdown off the trigger's END edge, assuming account sits
   at the end of the bar. Onyx puts it at the START, beside search, so the
   panel grew outward past the viewport edge and .app-inner's overflow clip cut
   it in half. Hang it off the start edge instead: it opens toward the middle of
   the bar, in either direction. */
.site-header .f-user__panel {
    inset-inline-end: auto;
    inset-inline-start: 0;
}

/* ---- transparent header: one hairline, under the utility strip ---------- */

/* The reference draws NO rule above its nav, but it does keep a faint one
   under the utility strip — measured as 1px solid rgba(237,237,237,0.35).
   I had removed both when the bands behind the menu were flagged; only the
   nav's was wrong. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"] .site-header__utility {
    border-block-end: 1px solid rgba(237, 237, 237, 0.35);
    background: transparent;
}
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"] .site-header__nav {
    border-color: transparent;
    background: transparent;
}


/* ===== onyx header metrics ===== */
/* --------------------------------------------------------------------------
   Measured against the reference at 1440: a 48px utility strip, a 121px logo
   band, a 48px nav row, and a logo about 61px tall. Onyx was running a 72px
   band with a 42px logo and semibold nav, which is what made the header read
   as a different design even with the same parts in the same places.
   -------------------------------------------------------------------------- */

.site-header__utility-inner { min-height: 48px; }

/* 73px, not 121.

   The reference's .main-nav-container measures 121, but that box holds BOTH
   the logo bar and the nav row — its inner bar is 73 and the nav under it is
   48. Setting the bar itself to 121 put an extra 48px into the header and made
   this row read as far taller than the reference's. 48 + 73 + 48 = the 169px
   header the reference actually has. */
.site-header__bar-inner { min-height: 73px; }

/* The reference's logo is ~61px tall. Ours was capped at 48px and the store's
   own artwork is portrait, so it came out 32px wide — small enough to read as
   an icon rather than a wordmark. */
/* The base sets a fixed 42px square here, so max-height alone never applied —
   the artwork was being letterboxed inside a 42x42 box and came out 32px wide.
   Both dimensions have to be overridden, not just capped. */
.site-header__logo img {
    width: auto;
    height: 3.8rem;
    /* An earlier rule caps this at 3rem. Setting `height` alone left that cap
       in force, so the logo stayed 48px — max-height has to be released too. */
    max-height: none;
    max-width: 12rem;
    object-fit: contain;
}

/* Nav: 14px at 700, measured off the reference's own links. My first pass read
   the weight off the nav container rather than the anchors and set 400. */
.site-header__nav .main-menu { min-height: 48px; align-items: center; }
.site-header__nav .main-menu a {
    font-size: 0.875rem;
    font-weight: 700;
}
.site-header__nav .main-menu ul { gap: 0.5rem; }

/* ===== onyx announcement ===== */
/* The strip carries the brand colour. It was painted from the footer token,
   which on a store with a saved colour has nothing to do with the brand —
   so the bar read as a stray dark band. --color-primary follows the
   merchant's colour when one is saved (master.twig emits it for
   theme.color.source == 'store') and is the theme's navy otherwise.

   The SDK puts .f-announce on the HOST element, not on a child, so this
   selector and the SDK's own `.f-announce { background: var(--f-announce-bg,
   ...) }` are both (0,1,0) matches on the same node and source order is what
   decides. Both onyx blocks sit after the copied SDK sheet, so they win —
   and because the class rule wins, setting only --f-announce-bg above would
   not have changed anything on its own.

   Ink is --color-on-primary, not #fff: it is the computed contrast for
   primary surfaces (cream on the theme navy, near-black on a light brand
   colour), so a pale brand colour does not leave white text on top. */
.site-header__announcement,
.site-header__announcement .f-announce {
    background: var(--color-primary);
    color: var(--color-on-primary);
}
.site-header__announcement .f-announce__text,
.site-header__announcement .f-announce__link,
.site-header__announcement .f-announce__close { color: var(--color-on-primary); }

/* ===== onyx mobile: condensed header + bottom bar ===== */
/* --------------------------------------------------------------------------
   Measured off the reference at 390: a 121px header (a ~40px icon strip over
   an ~81px logo bar) and a 60px bottom bar on rgb(31,11,2) carrying five
   items. Onyx was running the desktop 121px logo band on phones, which put
   the header at 214px and pushed the hero most of the way off screen.
   -------------------------------------------------------------------------- */

@media (max-width: 860px) {
    .site-header__utility-inner { min-height: 40px; }
    .site-header__bar-inner { min-height: 81px; }
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .site-header__bar-inner { min-height: 60px; }

    .site-header__logo img { height: 2.6rem; }

    /* Contact collapses to glyphs — the addresses do not fit and the icons
       carry the meaning. */
    .site-header__contact { display: flex; gap: 0.75rem; }
    .site-header__contact a { font-size: 0; gap: 0; }
    .site-header__contact a::before {
        content: "";
        width: 1.05rem;
        height: 1.05rem;
        background: currentColor;
        -webkit-mask: var(--onyx-mail) center / contain no-repeat;
        mask: var(--onyx-mail) center / contain no-repeat;
    }
    .site-header__contact a[href^="tel"]::before {
        -webkit-mask-image: var(--onyx-phone);
        mask-image: var(--onyx-phone);
    }
    .site-header__contact a + a { padding-inline-start: 0.75rem; }

    /* The page has to clear the bar, or the last block sits under it. */
    body { padding-block-end: 60px; }
}

/* ---- bottom bar --------------------------------------------------------- */

.bottom-nav { display: none; }

@media (max-width: 860px) {
    .bottom-nav {
        position: fixed;
        inset-inline: 0;
        inset-block-end: 0;
        z-index: 70;
        display: grid;
        grid-template-columns: repeat(5, 1fr);
        align-items: center;
        min-height: 60px;
        background: var(--color-bottom-nav-bg);
        color: #fff;
        /* Keeps the bar clear of the home indicator on a notched phone. */
        padding-block-end: env(safe-area-inset-bottom, 0);
    }

    .bottom-nav__item {
        display: grid;
        justify-items: center;
        gap: 0.15rem;
        padding: 0.4rem 0.2rem;
        border: 0;
        background: transparent;
        color: inherit;
        font: inherit;
        cursor: pointer;
        text-align: center;
    }
    .bottom-nav__item:hover { color: var(--color-primary-light); }

    .bottom-nav__icon {
        width: 1.35rem;
        height: 1.35rem;
        background: currentColor;
        -webkit-mask-position: center;
        mask-position: center;
        -webkit-mask-size: contain;
        mask-size: contain;
        -webkit-mask-repeat: no-repeat;
        mask-repeat: no-repeat;
    }
    .bottom-nav__icon--home   { -webkit-mask-image: var(--onyx-home);   mask-image: var(--onyx-home); }
    .bottom-nav__icon--grid   { -webkit-mask-image: var(--onyx-grid);   mask-image: var(--onyx-grid); }
    .bottom-nav__icon--user   { -webkit-mask-image: var(--onyx-user);   mask-image: var(--onyx-user); }
    .bottom-nav__icon--search { -webkit-mask-image: var(--onyx-search); mask-image: var(--onyx-search); }

    .bottom-nav__label { font-size: 0.68rem; line-height: 1.2; }

    /* The cart tile keeps its count badge and total, like the reference's. */
    .bottom-nav__item--cart { padding-inline: 0; }
    .bottom-nav .f-cart-summary__link { flex-direction: column; gap: 0.1rem; color: inherit; }
    .bottom-nav .f-cart-summary__icon { width: 1.35rem; height: 1.35rem; }
    .bottom-nav .f-cart-summary__total { font-size: 0.62rem; display: block; }
    .bottom-nav .f-cart-summary__count {
        position: absolute;
        inset-block-start: -0.3rem;
        inset-inline-end: -0.5rem;
        min-width: 1rem;
        height: 1rem;
        display: grid;
        place-items: center;
        border-radius: 999px;
        background: var(--color-primary);
        color: var(--color-on-primary);
        font-size: 0.6rem;
        font-weight: 700;
    }
}

:root {
    /* Dark brown, matching the reference's bar. A token so a merchant palette
       and dark mode both reach it. */
    --color-bottom-nav-bg: #1f0b02;

    --onyx-home:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 10.5 12 3l9 7.5V21H3z'/%3E%3C/svg%3E");
    --onyx-grid:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 6h16M4 12h16M4 18h16'/%3E%3Ccircle cx='2' cy='6' r='.6' fill='%23000'/%3E%3Ccircle cx='2' cy='12' r='.6' fill='%23000'/%3E%3Ccircle cx='2' cy='18' r='.6' fill='%23000'/%3E%3C/svg%3E");
    --onyx-user:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 21c1.4-4.5 4.3-6.5 8-6.5s6.6 2 8 6.5'/%3E%3C/svg%3E");
    --onyx-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
    --onyx-mail:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='m3 7 9 6 9-6'/%3E%3C/svg%3E");
    --onyx-phone:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Cpath d='M5 4h4l2 5-2.5 1.5a12 12 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z'/%3E%3C/svg%3E");
}

@media (max-width: 860px) {
    /* The strip was wrapping to two rows (80px instead of 40) because the page
       links, the locale and the contacts cannot share 390px. The reference
       keeps only the contact glyphs and the two locale controls here; the page
       links are already in the drawer and the footer. */
    .site-header__utility-links > a { display: none; }
    .site-header__utility-inner { flex-wrap: nowrap; }
    .site-header__utility-links { gap: 0.75rem; }
}

/* ===== onyx: single-slide sliders stay full width ===== */
/* The base narrows the track on small screens so a carousel shows a peek of
   the next card — right for product rails, wrong for a one-per-view hero. At
   390 it made the slide 78% wide, which is where the white gutter beside the
   hero video and the compact slider came from. Two classes, so it wins over
   the base's media queries without !important. */
falak-slider[slides-per-view="1"] .f-slider__track {
    grid-auto-columns: 100%;
}

/* ===== onyx animated text strip ===== */
/* 46px on black with 15px/400 text and a 10s linear cycle, measured off the
   reference's band. */
.block--animated-text { overflow: hidden; }

.animated-text__inner {
    display: flex;
    align-items: center;
    min-height: 46px;
    width: max-content;
}

.animated-text__track {
    display: flex;
    align-items: center;
    gap: 3rem;
    margin: 0;
    padding: 0 1.5rem 0 0;
    list-style: none;
    flex: 0 0 auto;
    font-size: 0.9375rem;
    font-weight: 400;
    white-space: nowrap;
    animation: onyx-text-marquee var(--marquee-duration, 10s) linear infinite;
}
.animated-text__track li { white-space: nowrap; }
.animated-text__track a { text-decoration: none; }

/* One composited transform for the pair, rather than an animation per item.
   Direction flips with the writing mode so the text always travels the way it
   reads. */
@keyframes onyx-text-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(calc(var(--rtl-flip, -1) * 100%)); }
}
[dir="rtl"] .animated-text__track { --rtl-flip: 1; }

/* Motion is decoration here; the sentence is still readable stopped. */
@media (prefers-reduced-motion: reduce) {
    .animated-text__track { animation: none; }
    .animated-text__inner { width: 100%; overflow-x: auto; }
    .animated-text__track + .animated-text__track { display: none; }
}

/* ===== onyx block rhythm, matched to the reference ===== */
/* The reference puts 64px between sections — margin-top: 64px on each block,
   no padding. Onyx was padding 96px top AND bottom, so the gap between two
   sections came to 192px: three times the reference, and the white band above
   the brands row is where it showed.

   Kept as padding rather than switching to margins, because a block that
   paints a background needs the space inside it — a margin would leave the
   tint hugging the text. Half the gap on each side gives the same 64px
   between neighbours. */
:root { --block-space: 2rem; }

@media (max-width: 767px) {
    :root { --block-space: 1.25rem; }
}

/* Blocks that carry a ground of their own need real room inside it, or the
   tint reads as a stripe behind the text rather than a section. */
.block--surface,
.block--stats,
.block--fixed-products,
.block--fixed-banner,
.has-background {
    padding-block: 4rem;
}
@media (max-width: 767px) {
    .block--surface,
    .block--stats,
    .block--fixed-products,
    .block--fixed-banner,
    .has-background {
        padding-block: 2.5rem;
    }
}

/* ===== onyx product videos ===== */
/* Four portrait cards in a row. Card is white with a hairline and a soft
   radius; the media is 9:16 with the badge in its start corner. */

.vp-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    /* Named so the scroller below can derive its slide width from the same
       number the gutter uses. */
    --vp-gap: 1.25rem;
    gap: var(--vp-gap);
}

.vp-card {
    display: flex;
    flex-direction: column;
    background: var(--color-bg);
    border: 1px solid var(--color-line-soft);
    border-radius: var(--radius);
    overflow: hidden;
    transition: box-shadow var(--transition), border-color var(--transition);
}
.vp-card:hover {
    border-color: var(--color-border);
    box-shadow: var(--shadow);
}

.vp-card__media {
    position: relative;
    display: block;
    aspect-ratio: 9 / 16;
    background: var(--color-surface);
    overflow: hidden;
}
/* Covers the media so the whole frame is the product link, while the hover
   controls sit above it on their own layer. */
.vp-card__media-link { position: absolute; inset: 0; z-index: 1; }

.vp-card__video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* The last-resort empty state, rendered only when even the platform's
   placeholder URL is missing from the config — the same faint tint the SDK's
   f-card uses, so the box reads as "no picture" rather than as broken. */
.vp-card__placeholder { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.05); }

/* 74x19 pill on rgba(0,0,0,.55), in the start corner — measured off the
   reference's badge, which sits on the media rather than the card. */
.vp-card__badge {
    position: absolute;
    inset-block-start: 0.6rem;
    /* The reference sets data-badge-position="left", i.e. the visual
       left — which in RTL is the inline END, not start. */
    inset-inline-end: 0.6rem;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    font-size: 0.6875rem;
    line-height: 1.45;
    white-space: nowrap;
}

.vp-card__body {
    display: grid;
    justify-items: center;
    gap: 0.6rem;
    padding: 0.9rem 0.75rem 1.1rem;
    text-align: center;
}
.vp-card__name {
    font-size: 0.9375rem;
    font-weight: 700;
    line-height: 1.5;
}
/* The name is a link but must read as text — the base underlines and
   colours anchors, which turned every card title into a primary-coloured
   underlined line. */
.vp-card__name a { color: var(--color-text); text-decoration: none; }
.vp-card__name a:hover { color: var(--color-primary); text-decoration: none; }

.vp-card__sizes {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    gap: 0.35rem;
}
.vp-card__sizes li {
    min-width: 2.1rem;
    padding: 0.15rem 0.45rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    color: var(--color-text-soft);
}

.vp-card__price {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--color-text-soft);
}
.vp-card__price del { font-size: 0.8125rem; font-weight: 400; color: var(--color-text-faint); }

/* "View all", centred between two rules — the reference closes its product
   rows this way. */
.block-footer {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 1.25rem;
    margin-block-start: 2rem;
}
.block-footer::before,
.block-footer::after {
    content: "";
    height: 1px;
    background: var(--color-border);
}
.block-footer__link {
    padding: 0.5rem 1.25rem;
    border: 1px solid var(--color-primary);
    border-radius: var(--radius-sm);
    color: var(--color-primary);
    font-size: 0.9375rem;
    font-weight: 600;
    white-space: nowrap;
}
.block-footer__link:hover { background: var(--color-primary); color: var(--color-on-primary); }

@media (max-width: 1023px) { .vp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 599px)  { .vp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); --vp-gap: 0.75rem; } }

/* ===== onyx product-video card: hover controls ===== */
/* Measured on the reference: the add-to-cart pill is white with primary text,
   fully rounded, 40px tall, and transitions over 0.3s ease-in-out. The icon
   pair sits above it. Both are laid over the media and revealed together.

   The card is the hover target, not the media — the reference reveals these
   while the pointer is anywhere on the card, including over the name. */
.vp-card { position: relative; }

.vp-card__hover {
    position: absolute;
    inset-inline: 0.75rem;
    /* Anchored inside the media, so the controls sit over the video the way
       the reference places them — not over the card's text. */
    inset-block-end: 0.75rem;
    z-index: 2;
    display: grid;
    justify-items: center;
    gap: 0.6rem;
    opacity: 0;
    transform: translateY(0.5rem);
    transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
    pointer-events: none;
}
.vp-card:hover .vp-card__hover,
.vp-card:focus-within .vp-card__hover {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.vp-card__actions { display: flex; gap: 0.6rem; }

.vp-card__icon {
    width: 2.5rem;
    height: 2.5rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: #fff;
    color: var(--color-on-white);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
    cursor: pointer;
}
.vp-card__icon:hover { color: var(--color-primary); }

.vp-card__icon-glyph {
    width: 1.15rem;
    height: 1.15rem;
    background: currentColor;
    -webkit-mask-position: center; mask-position: center;
    -webkit-mask-size: contain;    mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.vp-card__icon-glyph--eye   { -webkit-mask-image: var(--onyx-eye);   mask-image: var(--onyx-eye); }
.vp-card__icon-glyph--heart { -webkit-mask-image: var(--onyx-heart); mask-image: var(--onyx-heart); }

.vp-card__cart {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    height: 40px;
    border-radius: 9999px;
    background: #fff;
    color: var(--color-primary);
    font-size: 0.875rem;
    font-weight: 700;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
    cursor: pointer;
}
.vp-card__cart:hover { background: var(--color-primary); color: var(--color-on-primary); }

.vp-card__cart-glyph {
    width: 1.1rem;
    height: 1.1rem;
    background: currentColor;
    -webkit-mask: var(--onyx-bag) center / contain no-repeat;
    mask: var(--onyx-bag) center / contain no-repeat;
}

/* The SDK buttons are skinned to the same shapes rather than re-implemented,
   so a card with a product id keeps real cart and wishlist behaviour. */
.vp-card__hover falak-wishlist-button.vp-card__icon .f-wishlist__button,
.vp-card__hover falak-add-product-button.vp-card__cart .f-add-product__button {
    width: 100%;
    height: 100%;
    border: 0;
    background: transparent;
    color: inherit;
    border-radius: inherit;
    font: inherit;
}

/* No hover on touch: the controls are always visible there, or they are
   unreachable. */
@media (hover: none) {
    .vp-card__hover { opacity: 1; transform: none; pointer-events: auto; }
}

@media (prefers-reduced-motion: reduce) {
    .vp-card__hover { transition: none; }
}

:root {
    --onyx-eye:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Cpath d='M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
    --onyx-heart: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M12 20s-7-4.4-7-9.3A3.9 3.9 0 0 1 12 8a3.9 3.9 0 0 1 7 2.7c0 4.9-7 9.3-7 9.3z'/%3E%3C/svg%3E");
    --onyx-bag:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z'/%3E%3Cpath d='M3 6h18'/%3E%3Cpath d='M16 10a4 4 0 0 1-8 0'/%3E%3C/svg%3E");
}


/* ===== onyx hero: the reference's exact proportions ===== */
/* The hero is WIDTH-driven, not a clamped height. Measured across five
   viewports on the reference, height/width is 0.52734 every time — exactly
   1080/2048 — so it is a fixed aspect ratio, and it grows with the window
   instead of stopping at a cap. That cap is why ours stayed 760px on a 1920
   screen while the reference filled 1013px of it.

   Below 640 the ratio inverts to portrait, which is where their phone-shaped
   clip belongs. 640 is the reference's own switch point: 600 renders portrait,
   640 renders landscape.

   These come last in the file and carry no media query on the base rule, so
   they replace the earlier clamped heights rather than sit beside them. */
.hero-slide__img {
    width: 100%;
    height: auto;
    aspect-ratio: 2048 / 1080;
    object-fit: cover;
}

@media (max-width: 639px) {
    .hero-slide__img {
        height: auto;
        aspect-ratio: 1080 / 2048;
    }
}

/* ===== onyx product card: the reference's hover animations ===== */
/* Every value below is lifted from the reference's own stylesheet rather than
   eyeballed:
     .product-card__buttons > div      opacity 0, translateY(50px), all .3s ease
     :nth-child(2)/(3)/(4)             transition-delay .1s / .2s / .3s
     > div button                      40x40, radius 50%, 0 0 10px 2px rgba(0,0,0,.039)
     .product-card__image img:hover    transform: scale(1.05), .5s
     with-shine-animation :after       skewX(-25deg) gradient sweeping left -> 125% over .75s
   Both `with-zoom-animation` and `with-shine-animation` are active on the
   reference, so the card does two things at once on hover. */

/* The container no longer animates — each control does, so they can stagger. */
.vp-card__hover {
    opacity: 1;
    transform: none;
    transition: none;
}

.vp-card__control {
    position: relative;
    opacity: 0;
    visibility: hidden;
    transform: translateY(50px);
    transition: all 0.3s ease;
}
/* Staggered, in reading order: icons first, the cart bar last. */
.vp-card__actions .vp-card__control:nth-child(2) { transition-delay: 0.1s; }
.vp-card__control--cart { transition-delay: 0.2s; }

.vp-card:hover .vp-card__control,
.vp-card:focus-within .vp-card__control {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* Tooltip above each control, from data-title — the reference's black bubble. */
.vp-card__control[data-title]::before {
    content: attr(data-title);
    position: absolute;
    inset-block-end: calc(100% + 10px);
    inset-inline-start: 50%;
    transform: translateX(50%);
    padding: 0 10px;
    background: #000;
    color: #fff;
    font-size: 12px;
    line-height: 23px;
    white-space: nowrap;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    z-index: 10;
}
[dir="ltr"] .vp-card__control[data-title]::before { transform: translateX(-50%); }
.vp-card__control[data-title]:hover::before { opacity: 1; visibility: visible; }

/* 40x40 circles with the reference's shadow. */
.vp-card__icon {
    width: 40px;
    height: 40px;
    box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.039);
    transition: background-color 0.2s ease, color 0.2s ease;
}
.vp-card__icon:hover {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.vp-card__control--cart { width: 100%; }
.vp-card__cart {
    background: var(--color-primary);
    color: var(--color-on-primary);
    box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.039);
    transition: background-color 0.2s ease, color 0.2s ease;
}
.vp-card__cart:hover { background: var(--color-primary-dark); color: var(--color-on-primary); }

/* --- the card's own animations ------------------------------------------- */

/* Zoom: the media scales while the frame stays put, so the crop tightens
   rather than the card growing and shifting its neighbours. */
.vp-card__media { position: relative; overflow: hidden; }
.vp-card__video {
    transition: transform 0.5s ease;
    transform-origin: center;
}
.vp-card:hover .vp-card__video { transform: scale(1.05); }

/* Shine: a skewed translucent band sweeping across the media. Desktop only on
   the reference — it is a pointer affordance, and it costs a repaint. */
@media (min-width: 991px) {
    .vp-card__media::after {
        content: "";
        position: absolute;
        top: 0;
        left: -100%;
        width: 50%;
        height: 100%;
        background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.3));
        transform: skewX(-25deg);
        pointer-events: none;
        z-index: 1;
    }
    .vp-card:hover .vp-card__media::after { animation: onyx-shine 0.75s; }
}
@keyframes onyx-shine { to { left: 125%; } }

@media (prefers-reduced-motion: reduce) {
    .vp-card__control,
    .vp-card__video { transition: none; }
    .vp-card:hover .vp-card__video { transform: none; }
    .vp-card:hover .vp-card__media::after { animation: none; }
}

/* ===== onyx add-to-cart: fill sweep on hover ===== */
/* The button keeps its normal colour at rest; on hover a second colour sweeps
   across it from the start edge — right to left in Arabic, and mirrored in
   English so it always travels the way the text reads.

   A scaled pseudo-element rather than an animated background-position: one
   composited transform instead of repainting a gradient every frame. */
.vp-card__cart {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    /* The fill replaces the flat colour change from before. */
    transition: color 0.2s ease;
}

.vp-card__cart::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--color-primary-dark);
    transform: scaleX(0);
    transform-origin: right center;
    transition: transform 0.35s ease;
    z-index: -1;
}
[dir="ltr"] .vp-card__cart::before { transform-origin: left center; }

.vp-card__cart:hover::before { transform: scaleX(1); }

/* Content rides above the sweep. */
.vp-card__cart-glyph,
.vp-card__cart-label,
.vp-card__cart .f-add-product__button {
    position: relative;
    z-index: 1;
}

/* Cancels the flat swap set earlier — the sweep is the effect now. */
.vp-card__cart:hover { background: var(--color-primary); color: var(--color-on-primary); }

@media (prefers-reduced-motion: reduce) {
    .vp-card__cart::before { transition: none; }
}

/* ===== onyx product tabs ===== */
/* Pill row measured off the reference: 1px solid #eee container at radius
   9999px with 4.8px padding; each pill 8px 24px, 16px/500, 36px tall; the
   active one filled with the brand colour. */
.product-tabs { display: block; }

.product-tabs .f-tabs__header {
    display: inline-flex;
    gap: 0;
    margin: 0 auto 2rem;
    padding: 4.8px;
    border: 1px solid #eee;
    border-radius: 9999px;
    background: var(--color-bg);
    /* inline-flex plus auto margins keeps the row centred without a wrapper */
    justify-content: center;
}
.block--product-tabs .f-tabs__header { display: flex; width: max-content; }

.product-tabs .f-tabs__tab {
    padding: 8px 24px;
    min-height: 36px;
    border: 0;
    border-radius: 9999px;
    background: transparent;
    color: var(--color-text);
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.25;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 0.2s ease, color 0.2s ease;
}
.product-tabs .f-tabs__tab:hover { color: var(--color-primary); }
.product-tabs .f-tabs__tab.is-active {
    background: var(--color-primary);
    color: var(--color-on-primary);
}
.product-tabs .f-tabs__tab.is-active:hover { color: var(--color-on-primary); }

/* The header is centred by the block rather than by the component, so the
   component keeps working wherever else it is used. */
.block--product-tabs .product-tabs { text-align: center; }
.block--product-tabs .f-slider,
.block--product-tabs falak-products-slider { text-align: initial; }

@media (max-width: 639px) {
    .product-tabs .f-tabs__header { max-width: 100%; overflow-x: auto; }
    .product-tabs .f-tabs__tab { padding: 8px 16px; font-size: 0.9375rem; }
}

/* The component appends its header after the panels, so the pills rendered
   BELOW the products. Reordering with flex fixes it in the theme — the SDK
   keeps its DOM order, and any other theme that relies on it is unaffected. */
.product-tabs {
    display: flex;
    flex-direction: column;
}
.product-tabs .f-tabs__header { order: -1; }

/* Panels come through as display:inline, which collapses their box. */
.product-tabs .f-tabs__content:not([hidden]) { display: block; }

/* ===== onyx card: hover overlays, matched to the reference ===== */
/* Lifted from the reference's stylesheet, not estimated:
     .product-card__addToCart      bottom:0; left:0; right:0; all .3s ease
                                   translateY(100%) -> 0 on hover
     …__addToCart__btn salla-button  rgba(0,0,0,.5); #fff; height/line 40px; 15px
     .product-card__buttons        bottom:60px, centred
     …__buttons > div              translateY(50px), all .3s ease, delays .1/.2
     options input:checked + div   background: primary

   Supersedes the earlier single-stack overlay: the icons and the bar are two
   independent layers with different travel, which is why one stack could never
   look right. */

.vp-card__media { position: relative; overflow: hidden; }

/* --- icon pair: floats above the bar ------------------------------------- */
.vp-card__actions {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 60px;
    display: flex;
    justify-content: center;
    gap: 10px;
    z-index: 2;
}

.vp-card__control {
    position: relative;
    opacity: 0;
    visibility: hidden;
    transform: translateY(50px);
    transition: all 0.3s ease;
}
.vp-card__control:nth-child(2) { transition-delay: 0.1s; }
.vp-card:hover .vp-card__control,
.vp-card:focus-within .vp-card__control {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* --- cart bar: flush to the media's foot --------------------------------- */
.vp-card__addcart {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 2;
    opacity: 0;
    visibility: hidden;
    /* Slides up from under the media edge, not from a floating offset. */
    transform: translateY(100%);
    transition: all 0.3s ease;
}
.vp-card:hover .vp-card__addcart,
.vp-card:focus-within .vp-card__addcart {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.vp-card__cart,
.vp-card__addcart .f-add-product__button {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    height: 40px;
    line-height: 40px;
    /* A wash, not the brand colour — it sits over artwork and must not fight
       whatever frame the video happens to be on. */
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
    font-size: 15px;
    font-weight: 500;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    cursor: pointer;
    transition: background-color 0.2s ease;
}
.vp-card__cart:hover,
.vp-card__addcart .f-add-product__button:hover {
    background: var(--color-primary);
    color: var(--color-on-primary);
}
/* The fill sweep belongs to the old floating pill; the bar is a flat wash. */
.vp-card__cart::before { content: none; }

/* --- selected variant --------------------------------------------------- */
/* The reference fills the chosen pill with the brand colour. The SDK marks it
   with aria-checked, so the state comes from the component rather than a class
   this theme would have to maintain. */
.vp-card__options .f-options__pill[aria-checked="true"] {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-on-primary);
}
.vp-card__options .f-options__pill:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
}
.vp-card__options .f-options__pill[aria-checked="true"]:hover { color: var(--color-on-primary); }

/* ===== onyx card: SDK buttons wear the card's own shapes ===== */
/* The wishlist control is <falak-wishlist-button>, which renders its own
   <button class="f-wishlist__button f-btn f-btn--outline …">. The earlier skin
   for it was rooted at .vp-card__hover, a wrapper that no longer exists after
   the overlays were split into __actions and __addcart — so the selector
   stopped matching and the inner button fell back to the base f-btn look,
   which is why the heart came out filled while the eye stayed a white circle.

   Rooted at .vp-card__icon now, so it holds regardless of what wraps it. */
.vp-card__icon .f-wishlist__button,
.vp-card__icon .f-btn {
    width: 100%;
    height: 100%;
    min-height: 0;
    padding: 0;
    border: 0;
    border-radius: inherit;
    background: transparent;
    color: inherit;
    box-shadow: none;
}
.vp-card__icon .f-wishlist__button:hover,
.vp-card__icon .f-btn:hover {
    background: transparent;
    border: 0;
    color: inherit;
}
.vp-card__icon .f-wishlist__icon,
.vp-card__icon svg {
    width: 1.15rem;
    height: 1.15rem;
}

/* Saved state: the heart fills, the circle stays white — same as the reference,
   where only the glyph changes. */
.vp-card__icon .f-wishlist__button[aria-pressed="true"] .f-wishlist__icon {
    fill: currentColor;
    color: var(--color-sale);
}

/* The host keeps ownership of the circle so both controls are identical. */
.vp-card__icon {
    display: grid;
    place-items: center;
    overflow: hidden;
}

/* ===== onyx card: identical controls, and the sweep restored ===== */

/* A custom element is display:inline by default, so <falak-wishlist-button>
   had no box at all — measured 0x0 while the plain <a> beside it was 40x40.
   That is why the heart looked nothing like the eye: the circle was being
   painted by the inner button's own base styling, not by the card. */
.vp-card__icon,
.vp-card__actions falak-wishlist-button.vp-card__icon {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    border-radius: 50%;
    background: #fff;
    color: var(--color-on-white);
    box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.039);
    overflow: hidden;
    transition: background-color 0.25s ease, color 0.25s ease;
}

/* Hovering EITHER control fills it with the brand colour — same treatment for
   both, which is what the reference does. */
.vp-card__icon:hover,
.vp-card__icon:focus-within {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

/* --- add to cart: the right-to-left sweep, back ------------------------- */
/* It was lost when the floating pill became a flush bar. The bar keeps its
   rgba(0,0,0,.5) wash at rest and the brand colour sweeps across it from the
   start edge — right to left in Arabic, mirrored in English so it always
   travels the way the text reads. */
.vp-card__cart,
.vp-card__addcart .f-add-product__button {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.vp-card__cart::before,
.vp-card__addcart .f-add-product__button::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--color-primary);
    transform: scaleX(0);
    transform-origin: right center;
    transition: transform 0.35s ease;
    z-index: -1;
}
[dir="ltr"] .vp-card__cart::before,
[dir="ltr"] .vp-card__addcart .f-add-product__button::before { transform-origin: left center; }

.vp-card__cart:hover::before,
.vp-card__addcart .f-add-product__button:hover::before { transform: scaleX(1); }

/* The wash stays put; the sweep is what changes. Without this the flat
   background swap from the earlier rule would race the sweep. */
.vp-card__cart:hover,
.vp-card__addcart .f-add-product__button:hover {
    background: rgba(0, 0, 0, 0.5);
    color: var(--color-on-primary);
}

/* Label and glyph ride above the sweep — a bare text node cannot take one. */
.vp-card__cart > *,
.vp-card__addcart .f-add-product__button > * { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
    .vp-card__cart::before,
    .vp-card__addcart .f-add-product__button::before { transition: none; }
}

/* The base rule above uses a compound selector to give the custom element a
   box — `.vp-card__actions falak-wishlist-button.vp-card__icon` (0,0,3,1) —
   which outranks a plain `.vp-card__icon:hover` (0,0,2,0). So the heart's
   white base beat its own hover and the colour never changed, while the eye
   (a plain <a>, matching only the simple selector) worked fine.
   The hover has to be stated at the same weight to win it back. */
.vp-card__icon:hover,
.vp-card__icon:focus-within,
.vp-card__actions falak-wishlist-button.vp-card__icon:hover,
.vp-card__actions falak-wishlist-button.vp-card__icon:focus-within {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

/* The glyph rides the host's colour, so the saved-state red must not be
   pinned while the control is being hovered. */
.vp-card__icon:hover .f-wishlist__icon { color: inherit; }

/* Column count is a customizer choice; the grid still collapses on smaller
   screens regardless of what was picked. */
.vp-grid { grid-template-columns: repeat(var(--vp-columns, 4), minmax(0, 1fr)); }

/*
   More products than columns: one row that SCROLLS, not a second row.

   app.js sets [data-scroll-rail] when the wall holds more than it can show
   across, and the same attribute is what the theme's rail machinery attaches
   its progress line and drag-to-scroll to — so this is only the geometry.

   Large screens only. On a phone the wall stays the two-up grid it already is;
   scrolling there belongs to the viewer, which opens as a reel.

   The slide width is derived from --vp-columns rather than fixed, so the
   merchant's own column count still decides how many are in view and the
   scroller shows exactly the same card size the static grid would.
*/
/*
   EVERY width, not just the desk.

   The attribute is only set when the wall holds MORE products than it shows
   across, so the ordinary two-up phone grid is untouched — with the default of
   four products it simply never matches. What this covers is the case the
   raised cap allows: a merchant who asks for forty used to get twenty stacked
   rows on a phone, about eleven thousand pixels of column, and ten rows on a
   tablet. One swipeable row is the right answer at all three sizes.
*/
.vp-grid[data-scroll-rail] {
    /*
       How many cards are in view.

       Two on a phone or a tablet, which is exactly what the static grid shows
       at those widths (see the 1023px rule above), so a card is the same size
       whether or not the row happens to scroll. The large-screen block below
       raises it to the merchant's own column count.
    */
    --vp-visible: 2;

    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: calc(
        (100% - (var(--vp-visible) - 1) * var(--vp-gap, 1.25rem)) / var(--vp-visible)
    );
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    scroll-snap-type: x mandatory;
    /* The theme draws its own progress line under the row; a native bar on top
       of that is two scrollbars saying the same thing. */
    scrollbar-width: none;
}

.vp-grid[data-scroll-rail]::-webkit-scrollbar { display: none; }

.vp-grid[data-scroll-rail] > * { scroll-snap-align: start; }

/* The scroll affordances under the row. Here the progress line arrives wrapped
   in a foot, with a pair of arrows at its inline end — the one rail in the
   theme that has them, matching the reference theme's video wall. */
.block--video-products .onyx-rail-foot {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-block-start: 1.25rem;
}

.block--video-products .onyx-rail-foot[hidden] { display: none; }

/* Inside the foot the flex row owns the spacing; the line's own top margin
   would push it below the arrows' centre. */
.block--video-products .onyx-rail-foot .onyx-rail {
    flex: 1;
    margin-block-start: 0;
}

/* The arrows are for the mouse. A thumb already scrolls the row natively and
   two tap targets under it would only crowd the band, so they appear at the
   same 64rem where the grid starts following the merchant's column count. */
.onyx-rail__nav { display: none; }

@media (min-width: 64rem) {
    .onyx-rail__nav {
        display: flex;
        gap: 0.5rem;
    }
}

.onyx-rail__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.5rem;
    block-size: 2.5rem;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: 50%;
    background: var(--color-surface);
    color: var(--color-text);
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
}

.onyx-rail__btn:hover:not(:disabled) {
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.onyx-rail__btn:disabled {
    opacity: 0.35;
    cursor: default;
}

/* app.js draws ONE chevron, pointing toward inline-start. The next button
   mirrors it, and RTL mirrors the pair again — both arrows, one path. */
.onyx-rail__btn[data-rail-next] svg,
[dir="rtl"] .onyx-rail__btn[data-rail-prev] svg { transform: scaleX(-1); }

[dir="rtl"] .onyx-rail__btn[data-rail-next] svg { transform: none; }

@media (min-width: 64rem) {
    .vp-grid[data-scroll-rail] { --vp-visible: var(--vp-columns, 4); }
}
@media (max-width: 1023px) { .vp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 599px)  { .vp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); --vp-gap: 0.75rem; } }

/* ===== onyx card body, matched to the reference ===== */
/* Measured side by side. The reference's content box is 20px/10px with its
   rows spanning the full width; ours was 14.4/12/17.6 with `justify-items:
   center`, which shrank the title to 99px and the price to 80px inside a
   317px card. Shrink-to-fit is what made the body read as loose: the text sat
   in a narrow column with air either side, and a long name wrapped early.

   Rows stretch now and centre their own text, and the line-height comes down
   from 22.5px to the reference's 18px so a two-line name is compact instead of
   airy. */
.vp-card__body {
    display: grid;
    justify-items: stretch;
    gap: 0.5rem;
    padding: 20px 10px;
    text-align: center;
}

.vp-card__name {
    font-size: 15px;
    line-height: 18px;
    font-weight: 700;
    /* Two lines, then ellipsis — a long name must not push the price of one
       card out of line with its neighbours. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.vp-card__price {
    justify-content: center;
    font-size: 16px;
    line-height: 28px;
    gap: 16px;
}

/* The variant row matches the reference's 28px line, and its pills tighten to
   the size their card CSS uses (11px / 1.75rem). */
.vp-card__options { line-height: 26px; }
.vp-card__options .f-options__pills { justify-content: center; gap: 0.35rem; }
.vp-card__options .f-options__pill {
    font-size: 11px;
    min-height: 1.75rem;
    padding: 0.125rem 0.45rem;
    min-width: 2.1rem;
}

/* ===== onyx card: no trailing dead space ===== */
/* Grid items stretch to the tallest sibling. In a row where one product has
   variant chips and another has none, the shorter card was padded out and the
   slack piled up UNDER the price — a block of empty white with nothing in it.
   The reference never shows this because every one of its cards carries chips.

   The fix is to let the MEDIA absorb the difference instead of the body: the
   aspect ratio sets the media's natural height, and flex-grow lets it take
   whatever is left over. Within a row every card is the same height with no
   dead space; between rows the media may differ slightly, which nobody sees. */
.vp-grid > li { display: flex; }

.vp-card {
    display: flex;
    flex-direction: column;
    width: 100%;
}

.vp-card__media {
    flex: 1 1 auto;
    /* Still the basis, so a lone card keeps the reference's 9:16. */
    aspect-ratio: 9 / 16;
    min-height: 0;
}

/* The body sizes to its content and sits at the foot, where it belongs. */
.vp-card__body { flex: 0 0 auto; }

/* ===== onyx product rows: the reference's card and slider ===== */
/* Measured off the reference's tabbed row, which is a different card from the
   video wall's — near-square media, not 9:16:
     card    300x461, radius 10px, 1px solid #f0f0f0, white
     media   298x318  -> ratio 0.937, radius 10px 10px 0 0
     slide   320 wide with 0 10px padding -> 20px between cards, four in view
     swatch  45x28, radius 8px
     track   .swiper-scrollbar 2px, rgba(0,0,0,.1), radius 10px            */

.vp-card {
    border: 1px solid #f0f0f0;
    border-radius: 10px;
    background: var(--color-bg);
    overflow: hidden;
}

.vp-card__media { border-radius: 10px 10px 0 0; }

/* A product ROW is near-square. The video wall keeps 9:16 because its media is
   a portrait clip — same card, two media shapes, chosen by the section rather
   than baked into the card. */
.block--product-tabs .vp-card__media,
.block--products-slider .vp-card__media {
    aspect-ratio: 298 / 318;
}

/* Stars between the name and the variants. */
.vp-card__stars {
    display: flex;
    justify-content: center;
    min-height: 20px;
}
.vp-card__stars .f-stars__count { display: none; }

/* Swatches at the reference's size. */
.vp-card__options .f-options__pill {
    min-width: 45px;
    min-height: 28px;
    border-radius: 8px;
    background: var(--color-bg);
}

/* --- slider: gutter and progress track ---------------------------------- */

/* The SDK derives its column width from a hardcoded 1rem gap, so the gap and
   the calc have to move together or the last card overhangs the viewport. */
.block--product-tabs .f-slider__track {
    gap: 20px;
    grid-auto-columns: calc((100% - (var(--f-slider-per-view, 4) - 1) * 20px) / var(--f-slider-per-view, 4));
}

/* The reference's 2px progress line, drawn by wireRailProgress() rather than
   by the track's own scrollbar — see the note there. */
.onyx-rail {
    position: relative;
    block-size: 2px;
    margin-block-start: 1.75rem;
    border-radius: 10px;
    background: rgba(0, 0, 0, 0.1);
}
.onyx-rail__thumb {
    position: absolute;
    inset-block: 0;
    border-radius: 10px;
    background: var(--color-primary);
    transition: inset-inline-start 0.15s linear;
}

/* --- product rows: hold the media, flex the body ------------------------- */
/* The video wall lets its media absorb leftover height, because every clip
   there is the same portrait shape and the slack has nowhere better to go. A
   product row is the opposite case: the cards carry uneven bodies (only some
   products have variants), so letting the media stretch makes each one a
   different shape — ours measured 0.715 against the reference's 0.937.
   So here the media is frozen at the reference's ratio and the BODY takes the
   slack, with the price pinned to the bottom edge so the rows still line up
   and no gap opens under the text. */
.block--product-tabs custom-falak-product-card .vp-card__media,
.block--products-slider custom-falak-product-card .vp-card__media {
    flex: 0 0 auto;
    aspect-ratio: 298 / 318;
    block-size: auto;
}

.block--product-tabs custom-falak-product-card .vp-card__body,
.block--products-slider custom-falak-product-card .vp-card__body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}



/* Swatches at the reference's 45x28, which its padding alone overshot to
   57x32. Fixed height rather than a minimum: a chip that grows with its label
   makes a ragged row the moment one variant is named "XXL". */
.block--product-tabs .vp-card__options .f-options__pill,
.block--products-slider .vp-card__options .f-options__pill {
    min-width: 45px;
    block-size: 28px;
    padding-inline: 0.5rem;
    padding-block: 0;
    font-size: 0.8125rem;
    line-height: 26px;
}

/* --- product rows: one chip row, one name height ------------------------- */
/* The reference's card shows a SINGLE row of chips — the sizes — never a
   stacked Size-then-Colour list. <falak-product-options> renders every group
   it is given, and eco has one product with two of them, which alone made the
   whole rail 70px taller than the rest of the cards needed. The chips here are
   a preview, not the real picker (a variant product's button sends the shopper
   to the product page to choose), so showing the first group is honest. */
.block--product-tabs .vp-card__options .f-options__group ~ .f-options__group,
.block--products-slider .vp-card__options .f-options__group ~ .f-options__group {
    display: none;
}

/* No reserved second line and no bottom-pinned price: in the reference each
   card is exactly as tall as what it holds, so a plain product is shorter than
   one carrying stars and swatches, and the row tops line up. Reserving the
   rows instead opened a band of white between every name and its price. */

/* The price is a <p>, so it inherits the base sheet's paragraph margin — 16px
   of dead space under the last line of every card, which then set the height
   of the whole rail. The auto top margin above it does the bottom-pinning; the
   inherited one below it only pushes the card taller. */
.block--product-tabs custom-falak-product-card .vp-card__price,
.block--products-slider custom-falak-product-card .vp-card__price {
    margin-block-end: 0;
}

/* --- product rows: one card height, the media absorbs ------------------- */
/* Corrected after a closer read of the reference: its cards in a row are all
   the SAME height, and it is the IMAGE that gives way — a card carrying stars
   and a swatch row shows a shorter image than the plain card beside it, and
   both cards end on the same line.
   So the row keeps the grid's default stretch, and the flex weights are the
   other way round from what they were: the body takes exactly the height its
   contents need, and the media takes whatever is left. The aspect ratio stays
   as the media's natural basis, which is what a card with the tallest body
   settles at; the lighter cards simply grow their image past it. */
.block--product-tabs .f-slider__track,
.block--products-slider .f-slider__track {
    align-items: stretch;
}

.block--product-tabs custom-falak-product-card .vp-card__media,
.block--products-slider custom-falak-product-card .vp-card__media {
    flex: 1 1 auto;
    /* Without this a flex item refuses to shrink below its content, and the
       media would push the card taller instead of giving way. */
    min-block-size: 0;
}

.block--product-tabs custom-falak-product-card .vp-card__body,
.block--products-slider custom-falak-product-card .vp-card__body {
    flex: 0 0 auto;
}

/* The rail advances on its own; the arrows the SDK insists on are not part of
   the reference's design for this block. */
.block--product-tabs .f-slider__controls,
.block--product-tabs .f-slider__arrow,
.block--videos-slider .f-slider__controls,
.block--videos-slider .f-slider__arrow {
    display: none;
}

/* "Starts from", ahead of a variant product's cheapest price. */
.vp-card__from {
    color: var(--color-text-soft);
    font-weight: 400;
}

/* The body is a flex column whose spacing is its gap. Its children are an <h3>
   and a <p>, which arrive carrying the base sheet's heading and paragraph
   margins — 11.25px under the name and 16px over the price. Stacked on the 8px
   gap, that is the band of white the design reads as empty. */
.vp-card__body > * {
    margin-block: 0;
}

/* The rail is draggable, so it says so. While a drag is in flight the cursor
   holds and text/images stop trying to select or ghost-drag under it. */
.block--product-tabs .f-slider__track,
.block--products-slider .f-slider__track,
.block--videos-slider .f-slider__track {
    cursor: grab;
}
.block--product-tabs .f-slider__track.is-dragging,
.block--products-slider .f-slider__track.is-dragging {
    cursor: grabbing;
    user-select: none;
}
.block--product-tabs .f-slider__track :where(a, img),
.block--products-slider .f-slider__track :where(a, img) {
    -webkit-user-drag: none;
}

/* ===== onyx tab pills: the refinement pass ===== */
/* The metrics stay exactly as measured off the reference — 4.8px track, 36px
   pills, 8px/24px, 16px/500, radius 9999. What is added here is the finish the
   flat version was missing: the track reads as a physical groove, the active
   pill lifts out of it, and an idle pill answers the pointer instead of only
   changing colour on the way past. */

.product-tabs .f-tabs__header {
    /* A hairline border alone leaves the row floating on the page. One very
       soft shadow seats it without turning it into a card. */
    box-shadow: 0 1px 2px rgba(20, 17, 14, 0.04), 0 4px 12px rgba(20, 17, 14, 0.03);
}

.product-tabs .f-tabs__tab {
    /* Shadow and transform join the transition so the lift below animates
       rather than snapping. */
    transition: background-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}

/* An idle pill is a target, so it says so before it is clicked — a wash of the
   brand colour at 8%, which reads on both grounds without competing with the
   filled pill beside it. */
.product-tabs .f-tabs__tab:not(.is-active):hover {
    background: color-mix(in srgb, var(--color-primary) 12%, transparent);
}

.product-tabs .f-tabs__tab.is-active {
    /* Tinted rather than neutral: a grey shadow under a warm pill turns the
       colour muddy, so the shadow is mixed from the pill's own hue. */
    box-shadow: 0 1px 2px color-mix(in srgb, var(--color-primary) 30%, transparent),
                0 2px 8px color-mix(in srgb, var(--color-primary) 30%, transparent);
}

/* Keyboard users get a real ring. The pills are buttons, and the default
   outline traces a rectangle around a 9999px shape. */
.product-tabs .f-tabs__tab:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* On a phone the row scrolls rather than wraps; the scrollbar under a pill
   track looks like damage, and each pill snaps so it never rests half cut. */
@media (max-width: 639px) {
    .product-tabs .f-tabs__header {
        scrollbar-width: none;
        scroll-snap-type: x proximity;
    }
    .product-tabs .f-tabs__header::-webkit-scrollbar { display: none; }
    .product-tabs .f-tabs__tab { scroll-snap-align: center; }
}

/* #eee is a light-mode value: on a dark ground it is a bright line rather than
   a hairline, and the shadows have nothing to darken. */
:root[data-store-theme="dark"] .product-tabs .f-tabs__header {
    border-color: rgba(255, 255, 255, 0.12);
    background: rgba(255, 255, 255, 0.04);
    box-shadow: none;
}
:root[data-store-theme="dark"] .product-tabs .f-tabs__tab:not(.is-active):hover {
    background: rgba(255, 255, 255, 0.08);
}

@media (prefers-reduced-motion: reduce) {
    .product-tabs .f-tabs__tab { transition: none; }
}

/* ===== onyx product rows: responsive ===== */
/* <falak-slider> writes --f-slider-per-view inline on its host, and an inline
   style outranks any rule aimed at that host — so the count is re-declared on
   the TRACK instead. The track is where grid-auto-columns reads the variable,
   and a custom property redefined on the element that uses it wins there
   without touching the SDK or fighting !important.
   Four cards is a desktop number: at 490px it left each card ~110px wide, with
   the name on two lines and the price broken across three. */
@media (max-width: 1023px) {
    .block--product-tabs .f-slider__track,
    .block--products-slider .f-slider__track { --f-slider-per-view: 3; }
}

@media (max-width: 767px) {
    .block--product-tabs .f-slider__track,
    .block--products-slider .f-slider__track {
        --f-slider-per-view: 2;
        gap: 14px;
        grid-auto-columns: calc((100% - (var(--f-slider-per-view) - 1) * 14px) / var(--f-slider-per-view));
    }
}

@media (max-width: 479px) {
    /* A fraction rather than 1: the sliver of the next card is what tells a
       phone visitor the row scrolls at all, now that the arrows are gone. */
    .block--product-tabs .f-slider__track,
    .block--products-slider .f-slider__track { --f-slider-per-view: 1.35; }
}

@media (max-width: 767px) {
    /* The price is one figure and must never break across lines. */
    .block--product-tabs .vp-card__price,
    .block--products-slider .vp-card__price {
        white-space: nowrap;
    }

    .block--product-tabs .vp-card__body,
    .block--products-slider .vp-card__body {
        padding: 14px 10px;
        gap: 6px;
    }

    .block--product-tabs .vp-card__name,
    .block--products-slider .vp-card__name {
        font-size: 14px;
        line-height: 17px;
    }

    /* Chips shrink with the card rather than forcing it wider. */
    .block--product-tabs .vp-card__options .f-options__pill,
    .block--products-slider .vp-card__options .f-options__pill {
        min-width: 38px;
        block-size: 26px;
        line-height: 24px;
        font-size: 0.75rem;
    }
}

/* ===== onyx card icons: matched hover lift ===== */
/* Measured both controls at rest and hovered, in the video wall and in the
   product rail: the entrance is already symmetric — each rises from
   translateY(50px) on card hover, the heart 0.1s behind the eye. What neither
   circle had was a lift of its own when the pointer reaches IT, so the eye
   answered a hover only by changing colour. Added to both, because the pair
   has to move as one; the eye alone would just move the asymmetry. */
.vp-card__icon {
    transition: background-color 0.2s ease, color 0.2s ease,
                transform 0.2s ease, box-shadow 0.2s ease;
}

/* Stated at the compound weight as well, for the same reason the colour hover
   above it is: the rule that gives the custom element its box is
   `.vp-card__actions falak-wishlist-button.vp-card__icon` (0,0,3,1), and its
   resting box-shadow outranks a plain `.vp-card__icon:hover` (0,0,2,0). The
   transform lands either way — the base rule does not set one — but without
   this the heart would lift while keeping its flat resting shadow. */
.vp-card__control:hover .vp-card__icon,
.vp-card__icon:hover,
.vp-card__icon:focus-visible,
.vp-card__actions falak-wishlist-button.vp-card__icon:hover,
.vp-card__actions falak-wishlist-button.vp-card__icon:focus-within {
    transform: translateY(-3px);
    box-shadow: 0 6px 14px rgba(0, 0, 0, 0.12);
}

@media (prefers-reduced-motion: reduce) {
    .vp-card__control:hover .vp-card__icon,
    .vp-card__icon:hover { transform: none; }
}

/* ===== onyx fixed products: the reference's "best sellers" band ===== */
/* Measured off the reference at 1440:
     section  padding 0 30px
     title    30px/700, centred, 36 tall
     rule     160x2 with a 10x10 lozenge in the primary at its centre
     wrapper  FLEX, gap 24, centred — not a stretched grid
     card     331x516, radius 10, 1px solid #f0f0f0, white, text centred
     image    329x329 -> ratio 1, NOT the 0.937 the tabbed rail uses
     subtitle 14px/400 #949494
     price    16px, gap 16, centred
   Named block--best-sellers, not block--fixed-products: that class already
   belongs to the base theme's parallax banner (white text on a fixed cover),
   which is why this heading first rendered white on white.

   The mini-cart button measured 0x0: the reference ships it but hides it on
   desktop, which is why the design shows no button under the price. Kept for
   touch, where there is no hover and the card would otherwise have no way to
   add anything. */

.block--best-sellers .best-sellers__head {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.85rem;
    margin-block-end: 2.25rem;
}

.block--best-sellers .best-sellers__title {
    margin: 0;
    font-size: 1.875rem;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
    text-wrap: balance;
}

/* The rule fades at both ends so the lozenge reads as its centre rather than
   as a bead stuck on a hard line. */
.block--best-sellers .best-sellers__rule {
    position: relative;
    display: block;
    inline-size: 160px;
    block-size: 2px;
    background: linear-gradient(
        to right,
        transparent,
        var(--color-border, #e5e5e5) 22%,
        var(--color-border, #e5e5e5) 78%,
        transparent);
}
.block--best-sellers .best-sellers__rule::before {
    content: "";
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    inline-size: 10px;
    block-size: 10px;
    background: var(--color-primary);
    transform: translate(-50%, -50%) rotate(45deg);
}

/* Centred flex, not the stretched grid the SDK defaults to: two cards must sit
   together in the middle of a 1380px row, not span half of it each. */
.block--best-sellers .f-list__grid {
    /* <falak-products-list> writes the customizer's column count onto itself
       as --f-list-columns; custom properties inherit, so the grid reads it
       here. Without this the basis was a flat 331px and the row simply fitted
       as many as would go — three at 1328px, whatever the merchant chose. */
    --best-sellers-cols: var(--f-list-columns, 2);
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 24px;
    /* The reference's card is 331 wide and must not stretch past it. Capping
       each CARD instead looked right but broke the count: at two columns the
       share is 652, every card clamped back to 331, and three then fitted on
       the row the merchant had asked to hold two. Capping the ROW keeps both
       true — the chosen number per row, and a card that never exceeds 331. */
    max-inline-size: calc(
        var(--best-sellers-cols) * 331px + (var(--best-sellers-cols) - 1) * 24px);
    margin-inline: auto;
}
.block--best-sellers .f-list__grid > * {
    flex: 0 1 calc((100% - (var(--best-sellers-cols) - 1) * 24px) / var(--best-sellers-cols));
}

/* Square media here. Same absorb-the-slack rule as the rail, so a card with a
   category line and stars keeps the row's height and gives up image instead. */
.block--best-sellers custom-falak-product-card .vp-card__media {
    flex: 1 1 auto;
    min-block-size: 0;
    aspect-ratio: 1 / 1;
}
.block--best-sellers custom-falak-product-card .vp-card__body {
    flex: 0 0 auto;
}

.block--best-sellers .vp-card__subtitle {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 400;
    line-height: 1.5;
    color: #949494;
}

/* --- the mini cart under the price -------------------------------------- */
.vp-card__minicart {
    display: none;
    flex-direction: column;
    gap: 0.75rem;
    margin-block-start: 0.75rem;
}
.vp-card__minicart-rule {
    display: block;
    block-size: 1px;
    background: var(--color-border, #f0f0f0);
}
.vp-card__minicart-btn .f-btn,
.vp-card__minicart-btn button {
    inline-size: 100%;
    justify-content: center;
    border: 1px solid var(--color-primary);
    border-radius: 8px;
    background: transparent;
    color: var(--color-primary);
    font-size: 0.875rem;
    font-weight: 700;
}
.vp-card__minicart-btn .f-btn:hover,
.vp-card__minicart-btn button:hover {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

/* The merchant's column count is an upper bound, not a fixed one: four cards
   across a 768px tablet came out 166px wide. min() keeps a smaller choice
   intact — someone who picked two still gets two here. */
@media (max-width: 1023px) {
    .block--best-sellers .f-list__grid {
        --best-sellers-cols: min(var(--f-list-columns, 2), 3);
    }
}

@media (max-width: 767px) {
    .block--best-sellers .best-sellers__title { font-size: 1.5rem; }
    /* Two per row on a phone whatever the desktop count is, so the row cap
       has to come off with it. */
    .block--best-sellers .f-list__grid { gap: 14px; max-inline-size: none; }
    .block--best-sellers .f-list__grid > * { flex: 1 1 calc(50% - 7px); }
}

/* ===== onyx header: the submenu owns its own text colour ===== */
/* Over the hero the header paints its links white so they read against the
   video. A submenu is not part of that ground: it is a white panel of its own,
   and inheriting the header's white left every dropdown item invisible in
   light mode — white on white. A surface with its own background has to
   declare its own foreground, which is the same reason the dark-theme rule
   further up sets both together. */
.main-menu__submenu {
    color: var(--color-text);
}

.main-menu__submenu a,
.site-header .main-menu__submenu a {
    color: var(--color-text);
    border-radius: var(--radius-sm, 6px);
    transition: background-color 0.15s ease, color 0.15s ease;
}

.main-menu__submenu a:hover,
.main-menu__submenu a:focus-visible,
.site-header .main-menu__submenu a:hover {
    background: color-mix(in srgb, var(--color-primary) 10%, transparent);
    color: var(--color-primary);
}

/* The current page's entry in an open dropdown. */
.main-menu__submenu a[aria-current="page"] {
    color: var(--color-primary);
    font-weight: 700;
}

/* A link-based clip plays in an iframe, which has to fill the same frame the
   <video> does — an iframe defaults to 300x150 regardless of its container. */
.video-card__frame iframe {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    border: 0;
    border-radius: inherit;
}

/* A link-based card with no derivable thumbnail (Vimeo needs an API call for
   one) keeps its <img> empty and hidden. .video-card__poster sets display,
   which beats the hidden attribute's UA rule — so it has to be said here, or
   the card shows a broken-image glyph instead of nothing. */
.video-card__poster[hidden] { display: none; }

/* ===== onyx block heads: the gap is the gap ===== */
/* .block-head is a flex column with an 8px gap, but its children are an <h2>
   and a <p>, which arrive carrying the base sheet's 27px and 14px margins.
   Flex does not collapse margins, so they stacked on the gap and every section
   title sat 49px above its subtitle. Zeroing them puts the spacing back under
   the one property that is supposed to control it. */
.block-head > * {
    margin-block: 0;
}
.block-head {
    gap: 0.75rem;
}

/* ===== onyx offer band: full-bleed countdown over image or video ===== */
/* The reference runs the media edge to edge and centres a narrow column of
   white text on it: headline, one-line subtitle, a paragraph, the clock as
   dark translucent tiles, then a primary pill. */

.offer-band {
    position: relative;
    isolation: isolate;
    display: grid;
    place-items: center;
    min-block-size: clamp(22rem, 42vw, 34rem);
    padding-block: clamp(3rem, 7vw, 6rem);
    padding-inline: 1.25rem;
    overflow: hidden;
    color: #fff;
    /* No 100vw breakout: the block area (main > .app-inner) is already the full
       window width with no padding, so a plain block fills it. 100vw would also
       have counted the classic scrollbar gutter and pushed a sliver of
       horizontal scroll onto every desktop that shows one — invisible in a
       headless check, where scrollbars are overlaid. */
    inline-size: auto;
}

.offer-band__media,
.offer-band__media > * {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
}
.offer-band__media > * {
    object-fit: cover;
    /* A background clip is decoration: it must not be reachable or grabbable. */
    pointer-events: none;
    -webkit-user-drag: none;
}

/* The scrim, on its own layer so the media keeps its own colours underneath
   and the dimming is one number the merchant controls. */
.offer-band__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        180deg,
        rgba(0, 0, 0, calc(var(--offer-overlay, 0.45) * 0.75)),
        rgba(0, 0, 0, var(--offer-overlay, 0.45)));
}

.offer-band__inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.9rem;
    max-inline-size: 46rem;
    text-align: center;
}
.offer-band__inner > * { margin-block: 0; }

.offer-band__title {
    font-size: clamp(1.5rem, 3.2vw, 2.4rem);
    font-weight: 700;
    line-height: 1.25;
    text-wrap: balance;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.35);
}

.offer-band__subtitle {
    font-size: clamp(1rem, 1.6vw, 1.15rem);
    font-weight: 500;
    opacity: 0.95;
}

.offer-band__text {
    font-size: 0.9375rem;
    line-height: 1.9;
    opacity: 0.85;
    max-inline-size: 40rem;
}

/* --- the clock ---------------------------------------------------------- */
/* <falak-countdown> is left to render its own list; only the skin is set here,
   so the component keeps working the same way in every other theme. */
.offer-band__clock {
    margin-block-start: 0.75rem;
}
.offer-band__clock .f-countdown__list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.6rem;
    margin: 0;
    padding: 0;
    list-style: none;
}
/* color="light" brings its own boxed skin —
   .f-countdown[data-color="light"].f-countdown--boxed .f-countdown__item, which
   is four classes and outranks a plain two-class override. Stated at the same
   shape plus the band, so this wins without !important. */
.offer-band .f-countdown[data-color="light"].f-countdown--boxed .f-countdown__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
    min-inline-size: 4.25rem;
    padding: 0.55rem 0.75rem;
    /* A hairline edge, because the tile sits on moving footage: a plain dark
       fill is invisible over the dark half of a clip, which left the days and
       hours boxless while the minutes and seconds had boxes. The border reads
       on both ends of the range. */
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 0.85rem;
    background: rgba(0, 0, 0, 0.38);
    backdrop-filter: blur(6px);
}
.offer-band__clock .f-countdown__value {
    font-size: clamp(1.35rem, 2.4vw, 1.9rem);
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.offer-band__clock .f-countdown__label {
    font-size: 0.75rem;
    opacity: 0.8;
}

/* --- the call to action -------------------------------------------------- */
.offer-band__cta {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    margin-block-start: 0.5rem;
    padding: 0.7rem 1.6rem;
    border-radius: 9999px;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: 0.9375rem;
    font-weight: 700;
    text-decoration: none;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
    transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
}
.offer-band__cta:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.34);
    color: var(--color-on-primary);
    text-decoration: none;
}
/* An arrow that leans toward the reading direction, and nudges on hover. */
.offer-band__cta-arrow {
    --onyx-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 12H5'/%3E%3Cpath d='m12 19-7-7 7-7'/%3E%3C/svg%3E");
    inline-size: 1.05rem;
    block-size: 1.05rem;
    background: currentColor;
    /* Defined here rather than as a token: it is the only arrow in the theme,
       and a var() that resolves to `none` would leave a silent empty box. */
    -webkit-mask: var(--onyx-arrow) center / contain no-repeat;
    mask: var(--onyx-arrow) center / contain no-repeat;
    transition: translate 0.2s ease;
}
.offer-band__cta:hover .offer-band__cta-arrow { translate: -0.2rem 0; }
[dir="ltr"] .offer-band__cta-arrow { scale: -1 1; }
[dir="ltr"] .offer-band__cta:hover .offer-band__cta-arrow { translate: 0.2rem 0; }

@media (prefers-reduced-motion: reduce) {
    .offer-band__cta,
    .offer-band__cta-arrow { transition: none; }
    .offer-band__cta:hover { transform: none; }
}

@media (max-width: 639px) {
    .offer-band { min-block-size: 26rem; }
    .offer-band__clock .f-countdown__item { min-inline-size: 3.6rem; padding: 0.45rem 0.55rem; }
}

/* ---- expired offer ---- */
/* The live page drops an expired band server-side; `is-ended` is the page
   that was open when the clock ran out (app.js, on the component's `ended`).
   `is-expired` is the customizer's view: the band stays, greyed, and the note
   is a pencil to the date that brings it back. Same for the promo card. */
.block--offer-countdown.is-ended,
.block--promo-countdown.is-ended { display: none; }

.block--offer-countdown.is-expired .offer-band__media,
.block--promo-countdown.is-expired .promo-countdown__image { filter: grayscale(1); }

/* A solid badge, not a tint of the band: it has to read on a photo, a video
   and a grey card alike, and it is the one thing on an expired band the
   merchant must not miss. */
.offer-band__expired,
.promo-countdown__expired {
    margin: 0;
    padding: 0.6rem 0.9rem;
    border: 1px dashed rgba(0, 0, 0, 0.4);
    border-radius: 0.5rem;
    background: rgba(255, 255, 255, 0.94);
    color: #1a1a1a;
    font-size: 0.85rem;
    line-height: 1.5;
    text-align: center;
}

/* ===== onyx video wall: matched to the reference ===== */
/* Measured off .s-block--videos-gallery at 1440:
     heading  36px/700, centred
     rule     160x2 with a 10px lozenge (.block-head__rule already did 160x2;
              only its diamond needed to grow from 8px)
     slide    272 wide, 10px gutter, five in view
     media    272x484 -> 9:16, radius 0, overflow hidden
     play     60x60 circle, rgba(255,255,255,.15), 1px rgba(255,255,255,.2)
     track    2px, rgba(0,0,0,.1) radius 10, thumb in the primary
   The corners really are square: every element in their slide measured
   border-radius 0, and the rounding a screenshot suggests is compression. */

.block--videos-slider .video-card__frame {
    border-radius: 0;
    background: var(--color-surface);
}

/* No wash over the frame: the reference plays its clips at full brightness and
   relies on the button's own frosting to stay legible. */
.block--videos-slider .video-card__play {
    background-image: none;
}
.block--videos-slider .video-card__play:hover {
    background-color: rgba(0, 0, 0, 0.08);
}

/* A frosted ring rather than a solid white disc. */
.block--videos-slider .video-card__play-icon {
    width: 60px;
    height: 60px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    background: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(2px);
    box-shadow: none;
    transition: background-color 0.2s ease, transform 0.2s ease;
}
.block--videos-slider .video-card__play:hover .video-card__play-icon {
    background: rgba(255, 255, 255, 0.28);
    transform: scale(1.06);
}

/* The triangle rides on the frosted ring, so it is white, not the dark ink it
   was drawn in for the old solid disc.
   PHYSICAL left, not inline-start: the shape is a left border with the other
   three transparent, and on this RTL storefront inline-start is the RIGHT
   edge — colouring that would paint a triangle pointing the wrong way and
   leave the real one invisible. */
.block--videos-slider .video-card__play-icon::after {
    border-left-color: #fff;
}

@media (prefers-reduced-motion: reduce) {
    .block--videos-slider .video-card__play-icon,
    .block--videos-slider .video-card__play:hover .video-card__play-icon {
        transition: none;
        transform: none;
    }
}

/* .video-card carries an 18px radius and a drop shadow from the shared card
   skin. The reference's wall has neither — every element in its slide measured
   border-radius 0 — so the frames sit square and flush here. */
.block--videos-slider .video-card {
    border-radius: 0;
    box-shadow: none;
    background: transparent;
}
.block--videos-slider .video-card:hover {
    transform: none;
    box-shadow: none;
}

/* ===== onyx card on touch: the reference's phone layout ===== */
/* No hover exists here, so nothing can be revealed by one. The reference pins
   the two icons to the media's top corner and lays a solid add-to-cart across
   the card's foot, under the price. app.js moves the cart button into
   .vp-card__addcart--foot at this breakpoint rather than rendering a second
   one, so a card still holds exactly one add button. */
@media (hover: none), (max-width: 767px) {
    /* Top corner, stacked, always visible — there is no stagger, because there
       is nothing for them to stagger in from. In RTL inline-start is the right
       edge, which is where the reference puts them. */
    .vp-card__actions {
        inset-block: 0.6rem auto;
        inset-inline-start: 0.6rem;
        inset-inline-end: auto;
        flex-direction: column;
        justify-content: flex-start;
        gap: 0.5rem;
    }

    .vp-card__control {
        opacity: 1;
        visibility: visible;
        transform: none;
        transition-delay: 0s;
    }

    /* The tooltip is a pointer affordance; a tap would only make it flash. */
    .vp-card__control[data-title]::before { content: none; }

    .vp-card__icon {
        width: 34px;
        height: 34px;
    }
    .vp-card__icon .f-wishlist__icon,
    .vp-card__icon svg,
    .vp-card__icon-glyph { width: 1rem; height: 1rem; }

    /* The cart bar leaves the media and becomes the card's last row. */
    .vp-card__addcart--foot {
        position: static;
        inset: auto;
        margin-block-start: auto;
        opacity: 1;
        visibility: visible;
        transform: none;
    }
    .vp-card__addcart--foot .f-btn,
    .vp-card__addcart--foot button {
        position: relative;
        width: 100%;
        justify-content: center;
        border: 0;
        border-radius: 0;
        background: var(--color-primary);
        color: var(--color-on-primary);
        font-weight: 700;
    }
    /* The plus sits at the far edge with the label centred, as in the
       reference — so it is positioned, not a flex item. As a flex child it
       stretched to the button's full 190x40 and never read as a glyph. */
    .vp-card__addcart--foot .f-btn::before,
    .vp-card__addcart--foot button::before {
        content: "+";
        position: absolute;
        /* The add-to-cart's hover-sweep pseudo sets inset: 0 on this same
           element. Anchoring only one edge left the other three pinned, so the
           glyph stretched to 175x20 instead of shrink-wrapping. */
        inset-inline-start: auto;
        inset-inline-end: 0.9rem;
        top: 50%;
        bottom: auto;
        width: auto;
        translate: 0 -50%;
        font-size: 1.25em;
        font-weight: 400;
        line-height: 1;
        background: none;
    }
}

/* ===== onyx: touch card icons, one size ===== */
/* The eye is a plain <a class="vp-card__icon">, the heart is
   <falak-wishlist-button class="vp-card__icon">. The rule that gives the custom
   element a box is `.vp-card__actions falak-wishlist-button.vp-card__icon`
   (0,0,3,1), so a plain `.vp-card__icon` override reached only the eye — the
   pair came out 34 and 40. Stated at both weights here. Every section's card
   is the same element, so this squares the rails with the grids too. */
@media (hover: none), (max-width: 767px) {
    .vp-card__icon,
    .vp-card__actions falak-wishlist-button.vp-card__icon {
        width: 34px;
        height: 34px;
        flex: 0 0 34px;
    }
}

/* ===== onyx header: what stays white when the bar turns white ===== */
/* Over the hero the bar is transparent and everything in it is white. When it
   frosts on scroll the header flips to dark text, but two things were pinned
   white and vanished against it: the cart link, which sets its own colour, and
   the logo, which is ARTWORK rather than text and no colour rule can reach.
   Most visible on a phone, where the frosted bar is most of what is on screen.

   The brand colour rather than the ink: this selector reaches .cart-link a,
   which IS the disc, and it outranks the solid-bar rule that paints every
   other glyph on the row. Left on --color-text it made the bag the one dark
   icon among brand-coloured neighbours once the bar pinned. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .cart-link,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .cart-link a {
    color: var(--color-primary);
}

/* (The brightness(0) "flatten a white logo to black on scroll" fallback that
   used to live here is gone: Onyx shows the one store logo as uploaded on
   every ground, and the filter was painting coloured marks black.) */

/* ===== onyx bottom nav: labels, no underlines ===== */
.bottom-nav__item,
.bottom-nav__item:hover,
.bottom-nav__item .bottom-nav__label {
    text-decoration: none;
}

/* The cart tile reads differently from the other four on purpose: its caption
   is the running total, and the item count rides the icon as a badge. Only the
   component's own word-label is dropped — the total takes the place the other
   tiles give to their caption, at the same size and colour so the row still
   scans as one strip. */
.bottom-nav__item--cart .f-cart-summary__label { display: none; }

.bottom-nav__item--cart .f-cart-summary__link {
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
}
.bottom-nav__item--cart .f-cart-summary__content,
.bottom-nav__item--cart .f-cart-summary__total {
    display: block;
    font-size: 0.6875rem;
    line-height: 1.2;
    color: inherit;
    white-space: nowrap;
}
/* The count sits on the bag rather than beside it. */
.bottom-nav__item--cart .f-cart-summary__count {
    position: absolute;
    inset-block-start: -0.35rem;
    inset-inline-end: -0.5rem;
    margin: 0;
    min-inline-size: 1.05rem;
    padding: 0 0.25rem;
    border-radius: 999px;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: 0.625rem;
    line-height: 1.05rem;
    text-align: center;
}
.bottom-nav__item--cart .f-cart-summary__icon { position: relative; }

/* ===== onyx categories mosaic ===== */
/* Five picture tiles in a fixed arrangement, proportioned from the reference:
   5 columns of ~218px with 11px gaps, two rows of ~201px — 1136 x 414 at 1440,
   which is the 2.744 aspect the whole block keeps as it scales.

       | 1  1 | 2  2 | 5 |
       | 1  1 | 3  4 | 5 |

   In RTL column 1 is the right-hand edge, so the merchant's first tile is the
   tall one on the right. */

.cat-mosaic {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    grid-template-rows: repeat(2, minmax(0, 1fr));
    gap: 11px;
    aspect-ratio: 1136 / 414;
}

/* Explicit placement, not spans alone: with auto-flow the browser fills the
   top-right corner first and the third tile lands in row 1. Only at five —
   any other count keeps the even grid below, so a half-built section still
   reads while the merchant is adding tiles. */
.cat-mosaic[data-count="5"] > :nth-child(1) { grid-column: 1 / span 2; grid-row: 1 / span 2; }
.cat-mosaic[data-count="5"] > :nth-child(2) { grid-column: 3 / span 2; grid-row: 1; }
.cat-mosaic[data-count="5"] > :nth-child(3) { grid-column: 3; grid-row: 2; }
.cat-mosaic[data-count="5"] > :nth-child(4) { grid-column: 4; grid-row: 2; }
.cat-mosaic[data-count="5"] > :nth-child(5) { grid-column: 5; grid-row: 1 / span 2; }

/* Any other count: an even row of square-ish tiles rather than a broken grid. */
.cat-mosaic:not([data-count="5"]) {
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    grid-template-rows: none;
    aspect-ratio: auto;
}
.cat-mosaic:not([data-count="5"]) > * { aspect-ratio: 1 / 1; }

.cat-mosaic__tile {
    position: relative;
    display: block;
    overflow: hidden;
    background: var(--color-surface);
    text-decoration: none;
}
.cat-mosaic__tile:hover { text-decoration: none; }

.cat-mosaic__image,
.cat-mosaic__placeholder {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    transition: transform 0.45s ease;
}
.cat-mosaic__tile:hover .cat-mosaic__image { transform: scale(1.04); }

/* The caption sits on the picture, so it carries its own legibility: a scrim
   that fades out downward rather than a pill, which is what the reference
   shows — the text reads over faces and pale backgrounds alike. */
.cat-mosaic__tile::after {
    content: "";
    position: absolute;
    inset-block-start: 0;
    inset-inline: 0;
    block-size: 40%;
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.38), transparent);
    pointer-events: none;
}

.cat-mosaic__label {
    position: absolute;
    inset-block-start: 0.9rem;
    inset-inline-start: 1rem;
    z-index: 1;
    color: #fff;
    font-size: 0.9375rem;
    font-weight: 500;
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
}

@media (prefers-reduced-motion: reduce) {
    .cat-mosaic__image { transition: none; }
    .cat-mosaic__tile:hover .cat-mosaic__image { transform: none; }
}

/* The mosaic needs room: five across a 768px tablet gives 140px tiles, which
   is too small for a photograph to say anything. It holds down to 1024 and
   pairs up below that, the lead tile keeping its prominence. This is wider
   than the theme's usual 767 phone switch on purpose — a picture grid runs
   out of room sooner than a text one. */
@media (max-width: 1023px) {
    .cat-mosaic,
    .cat-mosaic[data-count="5"] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        grid-template-rows: none;
        gap: 8px;
        aspect-ratio: auto;
    }
    .cat-mosaic[data-count="5"] > :nth-child(n) {
        grid-column: auto;
        grid-row: auto;
        aspect-ratio: 1 / 1;
    }
    .cat-mosaic[data-count="5"] > :nth-child(1) { grid-column: 1 / span 2; aspect-ratio: 16 / 9; }
}

/* ===== onyx categories circles ===== */
/* Proportioned from the reference at 1478: six columns on a 240px step, a 96px
   disc, the name at 15px/700 and the category's own description at 13px in the
   soft text colour. Rows are ~90px apart. */

.cat-circles {
    display: grid;
    grid-template-columns: repeat(var(--cat-circles-columns, 6), minmax(0, 1fr));
    gap: 2.5rem 1rem;
    justify-items: center;
}

.cat-circle {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.65rem;
    max-inline-size: 12rem;
    text-align: center;
    text-decoration: none;
    color: inherit;
}
.cat-circle:hover { text-decoration: none; color: inherit; }

/* The disc keeps its tint when a category has no picture, so a half-filled
   catalogue still reads as a row of tiles rather than a row of holes. */
.cat-circle__figure {
    display: grid;
    place-items: center;
    inline-size: 96px;
    block-size: 96px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--color-surface);
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.cat-circle__image {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

.cat-circle:hover .cat-circle__figure {
    transform: translateY(-3px);
    box-shadow: 0 10px 22px rgba(20, 17, 14, 0.14);
}

.cat-circle__name {
    font-size: 0.9375rem;
    font-weight: 700;
    line-height: 1.3;
}
.cat-circle:hover .cat-circle__name { color: var(--color-primary); }

.cat-circle__text {
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--color-text-soft);
}

@media (prefers-reduced-motion: reduce) {
    .cat-circle__figure { transition: none; }
    .cat-circle:hover .cat-circle__figure { transform: none; }
}

/* Six 96px discs need ~1440. Below that the count steps down rather than the
   discs shrinking — a shrunken circular crop stops being readable well before
   a narrower grid does. */
@media (max-width: 1199px) {
    .cat-circles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 767px) {
    .cat-circles {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 1.75rem 0.5rem;
    }
    .cat-circle__figure { inline-size: 72px; block-size: 72px; }
    .cat-circle__name { font-size: 0.8125rem; }
    /* The description is the first thing to go when the tile is 100px wide. */
    .cat-circle__text { display: none; }
}
@media (max-width: 429px) {
    .cat-circles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ===== onyx category feature: panel + rail ===== */
/* Proportioned from the reference at 1349: the panel is ~446 against ~870 of
   rail, so 1fr : 2fr, and the panel runs the full height of the band.

   `panel_side` flips which edge the panel sits on. Done with grid-column on
   the two children rather than `direction` or `flex-direction: row-reverse`,
   both of which would also flip the rail's own scroll axis. */

.cat-feature {
    display: grid;
    align-items: stretch;
    gap: 1.5rem;
}

/* start = the row's leading edge, which is the right in RTL and the left in
   LTR — the browser resolves that, which is the point of using columns rather
   than row-reverse (that would flip the rail's own scroll axis too).

   The narrow column has to move WITH the panel. Sizing the track once as
   `1fr 2fr` and only swapping which child sat in which column gave the `end`
   variant a 944px panel next to a 472px rail — the proportions inverted. */
.cat-feature--start {
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
}
.cat-feature--end {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
}

/* grid-ROW as well as grid-column, on both children.

   Auto-placement is sparse: it walks the grid in DOM order and never goes
   back. The panel comes first in the markup, so on `end` it took row 1 /
   column 2, the cursor moved past column 1, and the rail — asking for column 1
   — could only be placed on a NEW row. The band rendered as a panel with the
   slider stranded underneath it.

   `start` happened to work because there the panel takes column 1 and the rail
   column 2, which is the direction the cursor already travels. Pinning the row
   makes both variants explicit instead of one relying on that coincidence. */
.cat-feature--start .cat-feature__panel { grid-column: 1; grid-row: 1; }
.cat-feature--start .cat-feature__rail  { grid-column: 2; grid-row: 1; }
.cat-feature--end   .cat-feature__panel { grid-column: 2; grid-row: 1; }
.cat-feature--end   .cat-feature__rail  { grid-column: 1; grid-row: 1; }

.cat-feature__panel {
    position: relative;
    isolation: isolate;
    display: grid;
    place-items: center;
    min-block-size: 22rem;
    padding: 2rem;
    overflow: hidden;
    color: #fff;
    text-align: center;
}
.cat-feature__image {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    z-index: -1;
}
/* The copy sits on a photograph, so the panel carries its own scrim rather
   than relying on the picture being dark enough. */
.cat-feature__panel::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0.55));
}

.cat-feature__copy {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.85rem;
    max-inline-size: 24rem;
}
.cat-feature__copy > * { margin-block: 0; }

.cat-feature__title {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1.3;
    text-shadow: 0 1px 10px rgba(0, 0, 0, 0.35);
}
.cat-feature__text {
    font-size: 0.8125rem;
    line-height: 1.9;
    opacity: 0.88;
}

.cat-feature__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 8rem;
    padding: 0.55rem 1.4rem;
    border: 1px solid rgba(255, 255, 255, 0.75);
    color: #fff;
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
    transition: background-color 0.2s ease, color 0.2s ease;
}
.cat-feature__cta:hover {
    background: #fff;
    color: var(--color-on-white);
    text-decoration: none;
}

.cat-feature__rail { min-inline-size: 0; }

/* The rail's own arrows sit under it in the reference, not over the cards. */
.cat-feature__rail .f-slider__controls { justify-content: flex-start; }

@media (prefers-reduced-motion: reduce) {
    .cat-feature__cta { transition: none; }
}

/* Below the tablet breakpoint the two columns stop being two columns: the
   panel goes full width above the rail, whichever side it was on. */
@media (max-width: 1023px) {
    .cat-feature {
        grid-template-columns: minmax(0, 1fr);
        gap: 1.25rem;
    }
    /* The row has to be released along with the column: both children are
       pinned to row 1 on desktop, and a single-column grid would then stack
       them on top of each other instead of one after the other. */
    .cat-feature--start .cat-feature__panel,
    .cat-feature--end .cat-feature__panel,
    .cat-feature--start .cat-feature__rail,
    .cat-feature--end .cat-feature__rail {
        grid-column: 1;
        grid-row: auto;
    }
    .cat-feature__panel { min-block-size: 15rem; }
}

/* --- the band's edges and its arrows ------------------------------------- */
/* The reference runs the panel flush to the page edge and insets only the far
   side of the rail, so the gutter has to follow the toggle rather than sit on
   both ends. */
.cat-feature--start { padding-inline-end: 1.5rem; }
.cat-feature--end   { padding-inline-start: 1.5rem; }

/* <falak-slider> puts its controls in .f-slider__head, above the track. The
   reference has them under the cards, so the head is re-ordered — the slider
   itself is untouched, which keeps every other rail's arrows where they are. */
.cat-feature__rail falak-slider,
.cat-feature__rail falak-products-slider > falak-slider {
    display: flex;
    flex-direction: column;
}
.cat-feature__rail .f-slider__head {
    order: 2;
    margin-block: 0.75rem 0;
}

@media (max-width: 1023px) {
    .cat-feature--start,
    .cat-feature--end { padding-inline: 1rem; }
}

/* --- the feature rail's scroll line and arrows ---------------------------- */
/* The reference shows a thin progress line under the cards with two bare
   arrows beneath it, at the rail's leading edge — beside the panel, not away
   from it. */

/* .f-slider__head is space-between with an empty headings div, which pushed
   the arrows to the far end of the row. */
.cat-feature__rail .f-slider__head {
    justify-content: flex-start;
}

/* The line sits between the track and the arrows: the track is order 0, the
   head was moved to order 2, so the rail takes the slot between them. */
.cat-feature__rail .onyx-rail {
    order: 1;
    margin-block-start: 1.25rem;
}

/* Bare glyphs. The shared skin draws a 36px disc with a border and a tinted
   ground, which is not what this band uses. */
.cat-feature__rail .f-slider__arrow {
    inline-size: auto;
    block-size: auto;
    padding: 0.25rem 0.5rem;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--color-text);
    font-size: 1.25rem;
}
.cat-feature__rail .f-slider__arrow:hover {
    background: transparent;
    color: var(--color-primary);
}
.cat-feature__rail .f-slider__controls { gap: 0.75rem; }

/* --- this band's cards are product cards, not video cards ---------------- */
/* The card defaults to the video wall's 9:16 media, and only the product rails
   were opted into the near-square 298/318 measured off the reference. This band
   never was, so at 185px wide its media came out 329 tall and the card 446 —
   a tall, narrow card against a panel of a different height, which is what read
   as the rail not lining up with the picture.
   Same treatment as the rails: near-square media that absorbs the row's slack,
   a body sized to its content, one chip row, and the price pinned so the cards
   in a row end on the same line. */
.block--category-feature custom-falak-product-card .vp-card__media {
    flex: 1 1 auto;
    min-block-size: 0;
    aspect-ratio: 298 / 318;
}
.block--category-feature custom-falak-product-card .vp-card__body {
    flex: 0 0 auto;
}
.block--category-feature .vp-card__options .f-options__group ~ .f-options__group {
    display: none;
}

/* With the cards at their proper height the rail no longer fills the panel's
   column, so the stack is centred against it rather than sitting at the top. */
.cat-feature__rail falak-slider,
.cat-feature__rail falak-products-slider > falak-slider {
    justify-content: center;
}

/* --- breathing room, equal top and bottom -------------------------------- */
/* The rail sat flush against the panel's top edge while its foot carried the
   line and the arrows, so the stack read as pushed up. Padding the rail on
   both block edges insets the cards from the panel's top by the same amount
   the arrows clear its bottom — the panel grows to whichever column is taller,
   so the two stay bracketed. The line's own gap comes down to keep the band
   from getting taller than it needs to be. */
.cat-feature__rail {
    padding-block: 1.5rem;
}
.cat-feature__rail .onyx-rail {
    margin-block-start: 1rem;
}

/* --- the feature rail on narrow screens ---------------------------------- */
/* Five-per-view is a desktop number, and below 480 the shared base falls back
   to `grid-auto-columns: 78%`, which put ONE card across the whole viewport —
   and when that card was a product with no picture the band looked empty.
   Explicit widths per breakpoint, the same way the product rails do it. */
@media (max-width: 1023px) {
    .cat-feature__rail .f-slider__track {
        --f-slider-per-view: 3;
        gap: 14px;
        grid-auto-columns: calc((100% - 2 * 14px) / 3);
    }
}
@media (max-width: 767px) {
    .cat-feature__rail .f-slider__track {
        --f-slider-per-view: 2;
        grid-auto-columns: calc((100% - 14px) / 2);
    }
}
@media (max-width: 479px) {
    /* A fraction, so the sliver of the next card shows the row scrolls. */
    .cat-feature__rail .f-slider__track {
        --f-slider-per-view: 1.4;
        grid-auto-columns: calc((100% - 0.4 * 14px) / 1.4);
    }
}

/* ===== onyx style banner: cards hanging off a picture ===== */
/* Proportioned from the reference at 1741: the picture is 418 tall, the cards
   are 261x252 with a 15px gutter, and they start 137 into the picture so 115
   of each card hangs below it. That 115 is the one number the layout turns on:
   the background stops that far short of the section's foot and the section
   reserves the same amount of padding there, so the cards have room to hang
   into and the next block is not walked over. */

.style-banner {
    /* Deep enough for the part of the picture that hangs below the band plus
       the caption under it — the reference drops 170px of picture and about
       40px of label past the banner's foot. */
    --style-overlap: 13rem;
    position: relative;
    isolation: isolate;
    padding-block: clamp(3rem, 7vw, 6rem) var(--style-overlap);
    padding-inline: 1.25rem;
    color: #fff;
    text-align: center;
}

/* Stops short of the foot — that gap is what the cards hang into. */
.style-banner__bg {
    position: absolute;
    inset-block: 0 var(--style-overlap);
    inset-inline: 0;
    z-index: -1;
    overflow: hidden;
}
.style-banner__image {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}
.style-banner__bg::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, var(--style-overlay, 0.35));
}

.style-banner__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}
.style-banner__inner > * { margin-block: 0; }

.style-banner__title {
    font-size: clamp(1.4rem, 2.6vw, 2rem);
    font-weight: 700;
    line-height: 1.3;
    text-wrap: balance;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.35);
}

/* A quiet link, not a button: the reference underlines it with a hairline
   rather than boxing it. */
.style-banner__cta {
    padding-block-end: 0.4rem;
    border-block-end: 1px solid rgba(255, 255, 255, 0.7);
    color: #fff;
    font-size: 0.875rem;
    text-decoration: none;
    transition: border-color 0.2s ease, color 0.2s ease;
}
.style-banner__cta:hover {
    border-block-end-color: #fff;
    color: #fff;
    text-decoration: none;
}

.style-banner__subtitle {
    font-size: 0.875rem;
    opacity: 0.9;
}

/* --- the rail ------------------------------------------------------------ */
/* A scroller, not a wrapped grid: the row is longer than the band and moves on
   its own. Measured off the reference at 1685 — 221x294 pictures on a 20px
   gutter, captions under them rather than laid over. */
.style-banner__rail {
    --tile-width: 221px;
    --tile-gap: 20px;
    /* Five across, and the sixth onwards scroll.
       The rail is capped at exactly five tiles and centred on the page, so the
       visible group sits in the same place whether the merchant added four
       categories or twelve — the extra ones scroll INSIDE this width instead
       of widening the row and shifting the design. */
    max-inline-size: calc(5 * var(--tile-width) + 4 * var(--tile-gap));
    margin-inline: auto;
    display: flex;
    gap: var(--tile-gap);
    /* The wrapper centres its children, which sized this to its content — so
       scrollWidth equalled clientWidth and the row could never scroll, however
       many tiles it held. It has to span the container to overflow it. */
    align-self: stretch;
    inline-size: 100%;
    /* Centred while the tiles fit, and only then. `safe` is what makes that
       usable on a scroller: plain `center` pushes overflow past the START edge,
       where no amount of scrolling can reach it — the first tiles would be
       permanently unreachable. With `safe` the browser falls back to
       start-alignment the moment the row is wider than the band. */
    justify-content: safe center;
    /* Pulled down so the row finishes level with the section's foot, which is
       what puts the bottom of each card below the picture. */
    margin-block-start: 2.5rem;
    margin-block-end: calc(-1 * var(--style-overlap));
    overflow-x: auto;
    scrollbar-width: none;
    /* No snapping: the row glides, and a snap point would fight it. */
    overscroll-behavior-inline: contain;
    cursor: grab;
}
.style-banner__rail::-webkit-scrollbar { display: none; }
.style-banner__rail.is-dragging { cursor: grabbing; user-select: none; }

.style-banner__tile {
    flex: 0 0 var(--tile-width, 221px);
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    text-decoration: none;
    color: #fff;
}
.style-banner__tile:hover { text-decoration: none; color: #fff; }

.style-banner__tile-figure {
    display: block;
    aspect-ratio: 221 / 294;
    border-radius: 0.75rem;
    overflow: hidden;
    background: var(--color-surface);
}
.style-banner__tile-image,
.style-banner__tile-placeholder {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    transition: transform 0.45s ease;
    -webkit-user-drag: none;
}
.style-banner__tile:hover .style-banner__tile-image { transform: scale(1.05); }

/* The caption sits under the picture, on the page's own ground — so it takes
   the page's text colour, not the banner's white. */
.style-banner__tile-label {
    text-align: center;
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--color-text);
}

@media (prefers-reduced-motion: reduce) {
    .style-banner__tile-image,
    .style-banner__cta { transition: none; }
    .style-banner__tile:hover .style-banner__tile-image { transform: none; }
}

/* On a phone the cards pair up and the overhang shrinks with them. */
@media (max-width: 767px) {
    .style-banner { --style-overlap: 9rem; }
    /* The tokens drive both the tile and the five-across cap, so a phone gets
       smaller tiles without the cap drifting out of step with them. */
    .style-banner__rail {
        --tile-width: 150px;
        --tile-gap: 12px;
    }
}

/* ---- banner with products ----------------------------------------------- */

/*
 * A full-bleed picture carrying a brand's copy, with that brand's products
 * hanging off its bottom edge.
 *
 * Same trick as .style-banner above: --bp-overlap is applied TWICE — the
 * background stops that far short of the section's foot, and the section
 * reserves the same amount of bottom padding — so the cards start inside the
 * picture, finish on the page's own ground, and the next block is not walked
 * over. One number to retune the whole overlap.
 *
 * The cards themselves are <falak-product-card> straight out of
 * <falak-products-slider>, i.e. the theme's one card. Nothing here restyles
 * f-card__*; a product in this section is meant to look identical to the same
 * product in a grid, a tab row or a search result.
 */
.banner-products {
    /* Deep enough for the part of the card that hangs past the picture. A
       card is roughly 27rem tall here and the reference leaves a little over
       half of it below the banner. */
    --bp-overlap: 15rem;
    position: relative;
    isolation: isolate;
    padding-inline: clamp(1rem, 4vw, 3rem);
    color: #fff;
}

/*
 * The padding has to be two classes to survive.
 *
 * `.block { padding-block: var(--block-space) }` is declared LATER in this
 * file (the onyx override layer) at the same specificity as `.banner-products`,
 * so it won on source order and flattened the section to 2rem top and bottom.
 * That silently removed the bottom reserve the overhang depends on, and the
 * row of cards finished 208px below the section box, on top of whatever came
 * next.
 */
.banner-products.block {
    padding-block: clamp(3rem, 7vw, 6rem) var(--bp-overlap);
}

/* Stops short of the foot — that gap is what the cards hang into. */
.banner-products__bg {
    position: absolute;
    inset-block: 0 var(--bp-overlap);
    inset-inline: 0;
    z-index: -1;
    overflow: hidden;
}

.banner-products__image {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

.banner-products__bg::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, var(--bp-overlay, 0.45));
}

/* A flex column, exactly like .style-banner__inner — and for the same
   reason. In a plain block container the rail's negative bottom margin
   collapses with the wrapper's, and the section stops accounting for the
   overhang: measured at 1440px the row finished 208px BELOW the section box
   and would have walked over whatever followed. Flex children do not
   collapse margins, so the section's height tracks the pulled-up rail and
   the reserved padding lines up with what actually hangs. */
.banner-products__inner {
    display: flex;
    flex-direction: column;
    max-inline-size: var(--container, 1400px);
    margin-inline: auto;
}

/* The copy sits at the LEADING edge — the right in Arabic, the left in
   English — rather than centred like style-banner's. align-self, not an auto
   margin: this is a flex child, and `margin-inline-start: auto` pushed it to
   the far side instead (the left in Arabic, which is where it must not be). */
.banner-products__copy {
    align-self: flex-start;
    max-inline-size: 34rem;
    text-align: start;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.9rem;
    margin-block-end: clamp(1.5rem, 4vw, 2.5rem);
}

.banner-products__title {
    margin: 0;
    /* The theme colours every h2 dark navy; on the picture that is unreadable,
       and inheriting from the section is not enough to beat an element rule. */
    color: #fff;
    font-size: clamp(1.5rem, 3vw, 2.25rem);
    font-weight: 700;
    line-height: 1.25;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.35);
}

.banner-products__text {
    margin: 0;
    font-size: 0.9375rem;
    line-height: 1.9;
    opacity: 0.92;
}

/* A pill, not style-banner's hairline link: the reference boxes this one. */
.banner-products__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-block-size: 2.75rem;
    padding-inline: 2rem;
    border: 1px solid rgba(255, 255, 255, 0.75);
    border-radius: 999px;
    color: #fff;
    font-size: 0.9375rem;
    font-weight: 600;
    text-decoration: none;
    transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.banner-products__cta:hover {
    background: #fff;
    border-color: #fff;
    color: var(--color-text, #15161a);
    text-decoration: none;
}

/* --- the rail ------------------------------------------------------------ */

/*
 * Pulled down so the row straddles the picture's bottom edge. The negative
 * margin is what makes the cards overlap; --bp-overlap above is what reserves
 * the room for them to overlap INTO.
 */
.banner-products__rail {
    margin-block-end: calc(var(--bp-overlap) * -1);
    position: relative;
}

/*
 * The slider's arrows, lifted out of the row and parked above it at the
 * TRAILING edge — over the picture, opposite the copy, which is where the
 * reference puts them. Absolute against .banner-products__rail so they travel
 * with the row rather than with the section's padding.
 *
 * SPECIFICITY, twice over. The onyx layer later in this file pins every
 * slider's arrows to the sides of its frame with `.block .f-slider__controls`
 * and `.block .f-slider .f-slider__arrow` — two and three classes, both after
 * these rules, so a plain `.banner-products__rail ...` lost on source order
 * and the arrows stayed centred on the card row. Matching `.block` here is
 * what wins. Its `top`/`bottom`/`padding-inline` have to be undone explicitly
 * for the same reason.
 */
.block.banner-products .f-slider__controls {
    position: absolute;
    top: auto;
    bottom: calc(100% + 1rem);
    inset-inline-end: 0;
    inset-inline-start: auto;
    block-size: auto;
    padding-inline: 0;
    z-index: 2;
}

.block.banner-products .f-slider .f-slider__arrow {
    inline-size: 2.5rem;
    block-size: 2.5rem;
    margin: 0;
    border: 1px solid rgba(255, 255, 255, 0.6);
    border-radius: 50%;
    background: transparent;
    box-shadow: none;
    color: #fff;
}
.block.banner-products .f-slider .f-slider__arrow:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.15);
}
.block.banner-products .f-slider .f-slider__arrow:disabled { opacity: 0.35; }

/*
 * NO background on .f-card__inner here — deliberately.
 *
 * Onyx leaves the card inner transparent and lets the rounded .f-card__media
 * (white, 14px) be the only surface. Painting the inner white to "lift" the
 * card off the picture put a SQUARE white ground behind a ROUNDED media, so
 * over the dark banner each card showed four white corners. It also made this
 * card differ from the same card everywhere else in the theme, which is the
 * one thing this section must not do.
 */

/*
 * Responsive card count, the onyx way: <falak-slider> writes
 * --f-slider-per-view INLINE on its host, and an inline style outranks any
 * rule aimed at that host — so the count is re-declared on the TRACK, which
 * is where grid-auto-columns actually reads it. Same approach as the
 * product-tabs / products-slider rows above; four across is a desktop number
 * and left each card about 90px wide on a phone.
 */
@media (max-width: 1023px) {
    .block--banner-products .f-slider__track { --f-slider-per-view: 3; }
}

@media (max-width: 767px) {
    /* One-and-a-bit cards in view leave far less hanging below the picture. */
    .banner-products { --bp-overlap: 11rem; }

    .banner-products__copy { max-inline-size: none; }

    .block--banner-products .f-slider__track {
        --f-slider-per-view: 2;
        gap: 14px;
        grid-auto-columns: calc((100% - (var(--f-slider-per-view) - 1) * 14px) / var(--f-slider-per-view));
    }

    /* Above the row there is no longer spare picture to park them on. */
    .block.banner-products .f-slider__controls {
        position: static;
        justify-content: center;
        margin-block-end: 1rem;
    }
}

@media (max-width: 479px) {
    /* A fraction rather than 1: the sliver of the next card is what tells a
       phone visitor the row scrolls at all. */
    .block--banner-products .f-slider__track { --f-slider-per-view: 1.35; }
}

/* ---- product page: payment block + gallery badge ----------------------- */

/* --- the labelled payment row ------------------------------------------- */

.buybox__payments-block { margin-block-start: 1.25rem; }

.buybox__payments-title {
    margin: 0 0 0.5rem;
    font-size: var(--fs-meta);
    font-weight: 600;
    color: var(--color-text-soft, #6b7280);
}

/* --- the gallery's discount hexagon -------------------------------------- */

/*
 * The same shape and ground the cards use, so a product carries one discount
 * mark whether it is met in a grid or on its own page. Pinned to the gallery's
 * leading edge, clear of .gallery__tools at the trailing edge.
 */
.gallery__badge {
    position: absolute;
    inset-block-start: 1rem;
    inset-inline-start: 1rem;
    z-index: 2;

    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 4.25rem;
    block-size: 4.75rem;

    background: var(--color-announce);
    color: #fff;
    /* pointy-top hexagon, as .f-card__badge */
    clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);

    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.01em;
    text-align: center;
}

@media (max-width: 767px) {
    .gallery__badge {
        inline-size: 3.25rem;
        block-size: 3.6rem;
        font-size: 0.875rem;
        inset-block-start: 0.5rem;
        inset-inline-start: 0.5rem;
    }

}

/* ===== onyx: air between the last section and the footer ===== */
/* The footer carries `margin-block-start: auto` so it sinks to the bottom of a
   short page. That is a sticky-footer trick, not spacing — on a full page auto
   resolves to 0 and the dark band started immediately under the last block.
   A length cannot share that property with `auto`, so the gap goes on main's
   foot instead, where it does not disturb the sticky behaviour. */
.app-inner > main {
    margin-block-end: clamp(2.5rem, 5vw, 4.5rem);
}

/* ===== onyx reveals: sections arriving as you reach them ===== */
/* The hidden state hangs off [data-reveal], which only app.js sets. Nothing is
   hidden by the stylesheet on its own, so a page whose script never ran shows
   its content rather than a column of blank space.

   `translate` and `opacity` only — both composited, so a grid of twenty cards
   costs no layout work. `will-change` is deliberately absent: on a page with
   this many reveal targets it would pin a layer for each one. */

[data-reveal] {
    opacity: 0;
    /* The travel is slower than the fade on purpose: the element is fully
       readable before it has finished settling, so the movement reads as
       unhurried rather than as a wait. */
    transition:
        opacity 0.7s cubic-bezier(0.22, 0.7, 0.3, 1),
        translate 0.95s cubic-bezier(0.22, 0.7, 0.3, 1);
    transition-delay: var(--reveal-delay, 0ms);
}

/* Text rises into place. 18px — far enough to read as movement, close enough
   that it never looks like the page is assembling itself. */
[data-reveal="up"] { translate: 0 18px; }

/* Cards arrive from alternating sides with a little lift. The offsets are
   physical, so they are mirrored for RTL rather than sliding the wrong way. */
[data-reveal="from-start"] { translate: -26px 10px; }
[data-reveal="from-end"]   { translate: 26px 10px; }
[dir="rtl"] [data-reveal="from-start"] { translate: 26px 10px; }
[dir="rtl"] [data-reveal="from-end"]   { translate: -26px 10px; }

/* A feature band's picture comes in from the edge it already occupies. */
[data-reveal="panel"] { translate: 0 22px; }
.cat-feature--start [data-reveal="panel"] { translate: -32px 0; }
.cat-feature--end   [data-reveal="panel"] { translate: 32px 0; }
[dir="rtl"] .cat-feature--start [data-reveal="panel"] { translate: 32px 0; }
[dir="rtl"] .cat-feature--end   [data-reveal="panel"] { translate: -32px 0; }

/* Stated at the weight of the heaviest offset rule above it.
   A plain `.is-revealed` (0,0,1,0) lost to `[dir="rtl"] [data-reveal="from-start"]`
   (0,0,2,0) and to the panel's `[dir="rtl"] .cat-feature--start [data-reveal]`
   (0,0,3,0) — so cards faded in but never travelled: they sat at their 26px
   offset for good, and the "slide" was only ever a fade. */
[data-reveal].is-revealed,
[dir] [data-reveal].is-revealed {
    opacity: 1;
    translate: none;
}

/* A card inside a rail that scrolls itself must not be caught mid-transition
   when the row moves, so its delay is dropped once it has played. */
.style-banner__tile.is-revealed,
.f-slider__slide.is-revealed { transition-delay: 0ms; }

@media (prefers-reduced-motion: reduce) {
    /* app.js does not mark anything in this case; this is the belt to that
       braces, for a preference switched on after the page loaded. */
    [data-reveal] {
        opacity: 1;
        translate: none;
        transition: none;
    }
}

/* ===== onyx header on small screens: one consistent row ===== */
/* The bar had five controls at four different sizes — a 42px boxed hamburger,
   32px search / theme / account, and a 26px cart — which is what made it read
   as unfinished. The reference gives every control the same bare, evenly
   spaced target and lets the logo be the only thing with weight.
   40px each: comfortably tappable without turning the bar into a toolbar. */
@media (max-width: 860px) {
    .site-header__bar-inner {
        gap: 0.5rem;
        padding-inline: 0.75rem;
    }

    .site-header__start,
    .site-header__end {
        gap: 0.25rem;
    }

    .site-header .menu-toggle,
    .site-header .theme-toggle,
    .site-header .search-link,
    .site-header .f-search__trigger,
    .site-header .f-user__trigger,
    .site-header .cart-link,
    .site-header .cart-link .f-cart-summary__link {
        inline-size: 40px;
        block-size: 40px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex: none;
    }

    /* The hamburger loses its box: it is one icon among five, not a button
       that needs to announce itself differently from the rest.

       Its three bars are <span>s with no width of their own — they were
       stretching to the button's content box. The shared sizing above sets
       `align-items: center`, which collapsed all three to 0px wide and left an
       empty 40px gap where the menu button used to be. So the bars are given a
       width, and the stack is put back on its column axis. */
    .site-header .menu-toggle {
        flex-direction: column;
        gap: 5px;
        border: 0;
        border-radius: 0;
        background: transparent;
        padding: 0;
    }
    .site-header .menu-toggle span {
        inline-size: 20px;
        block-size: 2px;
        border-radius: 2px;
        background: currentColor;
    }

    /* The count keeps riding the bag rather than widening the tile. */
    .site-header .cart-link .f-cart-summary__content,
    .site-header .cart-link .f-cart-summary__total,
    .site-header .cart-link .f-cart-summary__label { display: none; }
    .site-header .cart-link .f-cart-summary__icon { position: relative; }
    .site-header .cart-link .f-cart-summary__count {
        position: absolute;
        inset-block-start: -0.3rem;
        inset-inline-end: -0.45rem;
        margin: 0;
        min-inline-size: 1rem;
        padding: 0 0.2rem;
        border-radius: 999px;
        background: var(--color-primary);
        color: var(--color-on-primary);
        font-size: 0.625rem;
        line-height: 1rem;
        text-align: center;
    }
}

/* ===== onyx cart page ===== */
.cart-page { padding-block: 1.5rem 0; }

.cart-page__head {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    margin-block-end: 1.5rem;
}
.cart-page__title {
    margin: 0;
    font-size: clamp(1.35rem, 2.4vw, 1.9rem);
    font-weight: 700;
}
.cart-page__count { margin: 0; color: var(--color-text-soft); font-size: 0.875rem; }

/* The list carries the page; the summary is a column beside it that sticks
   while the list scrolls, so the total and the checkout button stay in reach
   on a long cart. */
.cart-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(18rem, 22rem);
    align-items: start;
    gap: 1.5rem;
}

.cart-items {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* image | name and variant | stepper | line total | bin */
.cart-item {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr) auto auto auto;
    align-items: center;
    gap: 1rem;
    padding: 0.85rem;
    border: 1px solid var(--color-border);
    border-radius: 0.75rem;
    background: var(--color-bg);
}

.cart-item__media {
    display: block;
    inline-size: 88px;
    aspect-ratio: 1;
    border-radius: 0.5rem;
    overflow: hidden;
    background: var(--color-surface);
}
/* .cart-item__clip is the seeked first frame of a video-commerce product's clip,
   standing in where the merchant uploaded neither a photograph nor a poster. It
   is a thumbnail, so it fills the tile exactly as a photograph would. */
.cart-item__media img,
.cart-item__clip,
.cart-item__placeholder {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

.cart-item__info { display: flex; flex-direction: column; gap: 0.3rem; min-inline-size: 0; }
.cart-item__name {
    font-weight: 700;
    font-size: 0.9375rem;
    line-height: 1.4;
    color: var(--color-text);
    text-decoration: none;
}
.cart-item__name:hover { color: var(--color-primary); text-decoration: none; }
.cart-item__variation { margin: 0; font-size: 0.8125rem; color: var(--color-text-soft); }
.cart-item__unit { margin: 0; font-size: 0.875rem; color: var(--color-text-soft); }
.cart-item__unit del { margin-inline-start: 0.4rem; opacity: 0.7; }

.cart-item__line-total {
    margin: 0;
    font-weight: 700;
    font-size: 0.9375rem;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.cart-item__remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 36px;
    block-size: 36px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--color-text-soft);
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
}
.cart-item__remove:hover { background: var(--color-surface); color: var(--color-sale, #c0392b); }

/* --- the summary --------------------------------------------------------- */
.cart-summary {
    position: sticky;
    top: 6rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.25rem;
    border: 1px solid var(--color-border);
    border-radius: 0.75rem;
    background: var(--color-bg);
}
.cart-summary__title { margin: 0; font-size: 1.05rem; font-weight: 700; }

.cart-summary__rows { display: flex; flex-direction: column; gap: 0.6rem; }
.cart-summary__row {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    font-size: 0.9375rem;
    font-variant-numeric: tabular-nums;
}
.cart-summary__row--credit { color: var(--color-sale, #c0392b); }
.cart-summary__row--total {
    padding-block-start: 0.6rem;
    border-block-start: 1px solid var(--color-border);
    font-size: 1.05rem;
    font-weight: 700;
}
.cart-summary__note {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--color-primary);
}

.cart-summary__checkout {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-block-size: 46px;
    border-radius: 9999px;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-weight: 700;
    text-decoration: none;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.cart-summary__checkout:hover {
    color: var(--color-on-primary);
    text-decoration: none;
    transform: translateY(-1px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.16);
}
.cart-summary__continue {
    text-align: center;
    font-size: 0.875rem;
    color: var(--color-text-soft);
}

.cart-summary__badges { margin-block-start: 0.25rem; }

/* While a change is in flight the page is dimmed and inert — the reload that
   follows is the real feedback, and a second tap in the meantime would race. */
.cart-page.is-busy { opacity: 0.6; pointer-events: none; }

.cart-page__empty { display: block; padding-block: 3rem; }

@media (max-width: 899px) {
    .cart-layout { grid-template-columns: minmax(0, 1fr); }
    .cart-summary { position: static; }
}

@media (max-width: 599px) {
    /* The row folds: picture and name on top, then the stepper, total and bin
       on one line under them. */
    .cart-item {
        grid-template-columns: 72px minmax(0, 1fr) auto;
        gap: 0.75rem;
    }
    .cart-item__media { inline-size: 72px; }
    .cart-item__qty { grid-column: 2; }
    .cart-item__line-total { grid-column: 3; }
    .cart-item__remove { grid-row: 1; grid-column: 3; }
}

/* ===== onyx checkout, thank-you, payment status ===== */
/* <falak-checkout> owns the flow and ships its own structural CSS. What is set
   here is only this theme's language on top of it — the same card, radius and
   pill the cart page uses — so the two pages read as one journey. */

.checkout-page,
.payment-status-page,
.thank-you { padding-block: 1.5rem 0; }

.checkout-page__head { margin-block-end: 1.5rem; }
.checkout-page__title {
    margin: 0;
    font-size: clamp(1.35rem, 2.4vw, 1.9rem);
    font-weight: 700;
}

/* The panels: same card as the cart's summary. */
.checkout-page .f-checkout__main,
.checkout-page .f-checkout__aside,
.checkout-page .f-checkout__signin {
    border: 1px solid var(--color-border);
    border-radius: 0.75rem;
    background: var(--color-bg);
    padding: 1.25rem;
}

/* A guest sees only the sign-in card, so it is centred and given a readable
   measure rather than stretched across the full grid. */
.checkout-page .f-checkout__signin {
    max-inline-size: 30rem;
    margin-inline: auto;
    text-align: center;
}
.checkout-page .f-checkout__signin .f-checkout__back { display: inline-block; margin-block-start: 0.75rem; }

.checkout-page .f-checkout__aside { position: sticky; top: 6rem; }

/* --- thank you ----------------------------------------------------------- */
.thank-you {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.85rem;
    text-align: center;
    padding-block-end: 2rem;
}
.thank-you > * { margin-block: 0; }

.thank-you__mark {
    display: grid;
    place-items: center;
    inline-size: 64px;
    block-size: 64px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-primary) 16%, var(--color-bg));
    color: var(--color-primary);
}
.thank-you__title { font-size: clamp(1.35rem, 2.4vw, 1.9rem); font-weight: 700; }
.thank-you__message { color: var(--color-text-soft); }
.thank-you__order { font-size: 0.9375rem; }
.thank-you__total { margin-inline-start: 0.5rem; font-weight: 700; }
.thank-you__note {
    padding: 0.6rem 1rem;
    border-radius: 0.5rem;
    background: var(--color-surface);
    font-size: 0.875rem;
    color: var(--color-text-soft);
}

.thank-you__summary {
    display: block;
    inline-size: min(100%, 34rem);
    margin-block-start: 0.5rem;
    text-align: start;
}
.thank-you__items { display: flex; flex-direction: column; gap: 0.6rem; margin: 0; padding: 0; list-style: none; }
.thank-you__item {
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem;
    border: 1px solid var(--color-border);
    border-radius: 0.6rem;
}
.thank-you__item-image { inline-size: 48px; block-size: 48px; object-fit: cover; border-radius: 0.4rem; }
.thank-you__item-name { font-size: 0.875rem; font-weight: 700; }
.thank-you__item-qty,
.thank-you__item-total { font-size: 0.875rem; color: var(--color-text-soft); font-variant-numeric: tabular-nums; }

.thank-you__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem; margin-block-start: 0.5rem; }
.thank-you__primary {
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;
    padding-inline: 1.6rem;
    border-radius: 9999px;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-weight: 700;
    text-decoration: none;
}
.thank-you__primary:hover { color: var(--color-on-primary); text-decoration: none; }
.thank-you__secondary {
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;
    padding-inline: 1.6rem;
    border: 1px solid var(--color-border);
    border-radius: 9999px;
    color: var(--color-text);
    text-decoration: none;
}
.thank-you__secondary:hover { border-color: var(--color-primary); color: var(--color-primary); text-decoration: none; }

/* --- payment status ------------------------------------------------------ */
/* The component reports its own state; the page only gives it room. */
.payment-status-page {
    display: grid;
    place-items: center;
    min-block-size: 40vh;
    text-align: center;
}

@media (max-width: 899px) {
    .checkout-page .f-checkout__aside { position: static; }
}

/* ==========================================================================
   Cart drawer
   --------------------------------------------------------------------------
   The panel is the theme's — the library has no cart drawer — but the parts
   inside it are the platform's, so most of what follows is skin: sizing the
   stepper, the coupon row and the payment marks down to drawer scale rather
   than restyling them.

   Slide direction is the inline END, which is the same edge the header's cart
   control sits on. `translate` cannot be expressed logically, so the closed
   position is flipped for RTL; `.cart-drawer.is-open .cart-drawer__panel`
   (0,0,3,0) outranks the `[dir="rtl"]` restatement (0,0,2,0), so the open
   state does not need its own restatement.
   ========================================================================== */

.cart-drawer {
    position: fixed;
    inset: 0;
    z-index: 1120;
}

.cart-drawer[hidden] { display: none; }

.cart-drawer__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(20, 17, 14, 0.42);
    opacity: 0;
    transition: opacity 0.3s ease;
}

.cart-drawer.is-open .cart-drawer__backdrop { opacity: 1; }

.cart-drawer__panel {
    position: absolute;
    inset-block: 0;
    inset-inline-end: 0;
    /* 100% of the fixed inset:0 root, not 100vw: the viewport unit includes
       the scrollbar gutter and the panel would hang off the start edge. */
    inline-size: min(25.5rem, 100%);
    display: flex;
    flex-direction: column;
    background: var(--color-bg);
    box-shadow: -18px 0 48px rgba(20, 16, 12, 0.16);
    translate: 100% 0;
    transition: translate 0.32s cubic-bezier(0.22, 0.7, 0.3, 1);
}

[dir="rtl"] .cart-drawer__panel {
    box-shadow: 18px 0 48px rgba(20, 16, 12, 0.16);
    translate: -100% 0;
}

.cart-drawer.is-open .cart-drawer__panel { translate: none; }

/* The page behind must not scroll while the panel is over it — a drawer that
   scrolls the page under itself is the classic mobile bug. */
body.cart-drawer-is-open { overflow: hidden; }

/* A mutation is in flight: the list stops taking taps so a second one cannot
   queue behind a request that has not answered yet. */
.cart-drawer.is-busy .cart-drawer__body { opacity: 0.55; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
    .cart-drawer__panel,
    .cart-drawer__backdrop { transition: none; }
}

/* ---------------------------------------------------------------- header */

.cart-drawer__head {
    flex: none;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1.1rem 1.25rem;
    border-block-end: 1px solid var(--color-border);
}

.cart-drawer__title {
    margin: 0;
    margin-inline-end: auto;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--color-text);
}

.cart-drawer__count {
    color: var(--color-text-soft);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.cart-drawer__close {
    flex: none;
    inline-size: 2rem;
    block-size: 2rem;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: var(--color-surface);
    color: var(--color-text-soft);
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
}

.cart-drawer__close:hover {
    background: var(--color-primary-tint);
    color: var(--color-text);
}

/* ------------------------------------------------------------------ list */

.cart-drawer__body {
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0.5rem 1.25rem;
}

.cart-drawer__loading {
    margin: 2rem 0;
    text-align: center;
    color: var(--color-text-faint);
    font-size: 0.9rem;
}

.cart-drawer__empty { display: block; padding-block: 2.5rem; }

.cart-drawer__items {
    margin: 0;
    padding: 0;
    list-style: none;
}

.cart-drawer__item {
    display: grid;
    grid-template-columns: 4.5rem 1fr auto;
    align-items: start;
    gap: 0.8rem;
    padding-block: 0.95rem;
    border-block-end: 1px solid var(--color-border);
}

.cart-drawer__item:last-child { border-block-end: 0; }

.cart-drawer__media {
    display: block;
    inline-size: 4.5rem;
    block-size: 4.5rem;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--color-surface);
}

/* .cart-drawer__clip is the seeked first frame of a video-commerce product's
   clip, standing in where the merchant uploaded neither a photograph nor a
   poster. A thumbnail, so it fills the tile exactly as a photograph would. */
.cart-drawer__media img,
.cart-drawer__clip {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

.cart-drawer__placeholder {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    background: var(--color-surface);
}

.cart-drawer__info {
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

/* The base sheet gives <p> and <a> their own margins, which would stack on
   top of this gap. Zeroed once here rather than per child. */
.cart-drawer__info > * { margin-block: 0; }

.cart-drawer__name {
    font-size: 0.88rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--color-text);
    text-decoration: none;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cart-drawer__name:hover { color: var(--color-primary); }

/*
 * The chosen options, drawn as the product page's selected pills.
 *
 * The drawer reuses the SDK's `.f-options__pill` / `.f-options__swatch`
 * classes (app.js, optionHtml) so a colour swatch, an image swatch or a text
 * pill looks exactly as it did in the picker the shopper just used — only
 * scaled down, since a drawer line is a fraction of the buybox's width. The
 * pills are inert <span>s: nothing to hover, press or focus.
 */
.cart-drawer__variation {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.65rem;
    font-size: 0.76rem;
    color: var(--color-text-faint);
}

.cart-drawer__option {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.cart-drawer__option-name {
    font-weight: 600;
    color: var(--color-text-soft);
}

.cart-drawer__option-name::after { content: ":"; }

.cart-drawer__variation .f-options__pill {
    min-inline-size: 0;
    min-block-size: 1.5rem;
    padding: 0.1rem 0.55rem;
    border-radius: var(--radius-sm);
    font-size: 0.72rem;
    line-height: 1.2;
    cursor: default;
    pointer-events: none;
}

.cart-drawer__variation .f-options__pill--swatch {
    padding: 0.15rem;
    border-radius: 50%;
}

.cart-drawer__variation .f-options__pill--image { border-radius: var(--radius-sm); }

.cart-drawer__variation .f-options__swatch {
    inline-size: 1.15rem;
    block-size: 1.15rem;
}

.cart-drawer__variation .f-options__pill--image .f-options__swatch {
    inline-size: 1.5rem;
    block-size: 1.5rem;
    border-radius: calc(var(--radius-sm) - 2px);
}

.cart-drawer__unit {
    font-size: 0.82rem;
    color: var(--color-text-soft);
    font-variant-numeric: tabular-nums;
}

.cart-drawer__unit del {
    margin-inline-start: 0.4rem;
    color: var(--color-text-faint);
    font-size: 0.76rem;
}

.cart-drawer__controls {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    margin-block-start: 0.15rem;
}

.cart-drawer__line-total {
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--color-text);
    font-variant-numeric: tabular-nums;
}

/* The platform's stepper, sized for a 25rem panel. */
.cart-drawer__qty .f-qty {
    border-radius: 999px;
    background: var(--color-surface);
    border-color: transparent;
}

.cart-drawer__qty .f-qty__step {
    inline-size: 1.75rem;
    block-size: 1.75rem;
    font-size: 0.95rem;
}

.cart-drawer__qty .f-qty__input {
    inline-size: 2rem;
    font-size: 0.85rem;
    font-weight: 600;
    background: transparent;
}

.cart-drawer__remove {
    flex: none;
    /* The grid is `start`-aligned so the thumbnail lines up with the product
       name; the bin is a single glyph and belongs on the row's centre line. */
    align-self: center;
    inline-size: 1.85rem;
    block-size: 1.85rem;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: rgba(155, 44, 44, 0.1);
    color: var(--color-danger);
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
}

.cart-drawer__remove:hover {
    background: var(--color-danger);
    color: #fff;
}

/* ---------------------------------------------------------------- footer */

.cart-drawer__foot {
    flex: none;
    padding: 1rem 1.25rem 1.25rem;
    border-block-start: 1px solid var(--color-border);
    background: var(--color-bg);
}

.cart-drawer__foot[hidden] { display: none; }

.cart-drawer__coupon { display: block; margin-block-end: 0.9rem; }
.cart-drawer__coupon .f-cart-coupons__label { font-size: 0.8rem; }
.cart-drawer__coupon .f-cart-coupons__input { border-radius: var(--radius-sm); }
.cart-drawer__coupon .f-cart-coupons__button {
    border-radius: var(--radius-sm);
    min-inline-size: 4.75rem;
}

.cart-drawer__totals {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.cart-drawer__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    font-size: 0.87rem;
    color: var(--color-text-soft);
}

/* <dl> children carry a UA margin-inline-start on <dd>; the flex gap above is
   the only spacing wanted. */
.cart-drawer__row > dt,
.cart-drawer__row > dd {
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.cart-drawer__row[hidden] { display: none; }

.cart-drawer__row--credit { color: var(--color-primary-dark); }

.cart-drawer__row--total {
    margin-block-start: 0.35rem;
    padding-block-start: 0.6rem;
    border-block-start: 1px solid var(--color-border);
    font-size: 1.02rem;
    font-weight: 700;
    color: var(--color-text);
}

.cart-drawer__mark {
    margin-inline-start: 0.15rem;
    color: var(--color-danger);
}

.cart-drawer__note,
.cart-drawer__tax {
    margin: 0.45rem 0 0;
    font-size: 0.74rem;
    color: var(--color-text-faint);
}

.cart-drawer__note { color: var(--color-primary-dark); }
.cart-drawer__note[hidden] { display: none; }

.cart-drawer__actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
    margin-block-start: 0.9rem;
}

.cart-drawer__view,
.cart-drawer__checkout {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    min-block-size: 2.85rem;
    border-radius: var(--radius-sm);
    font-size: 0.88rem;
    font-weight: 600;
    text-decoration: none;
    transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.cart-drawer__view {
    border: 1px solid var(--color-border);
    color: var(--color-text);
    background: transparent;
}

.cart-drawer__view:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.cart-drawer__checkout {
    border: 1px solid var(--color-primary);
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.cart-drawer__checkout:hover {
    background: var(--color-primary-dark);
    border-color: var(--color-primary-dark);
}

.cart-drawer__continue {
    display: block;
    inline-size: 100%;
    margin-block-start: 0.7rem;
    padding: 0.25rem;
    border: 0;
    background: none;
    color: var(--color-text-soft);
    font-family: inherit;
    font-size: 0.84rem;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}

.cart-drawer__continue:hover { color: var(--color-primary); }

.cart-drawer__payments {
    display: block;
    margin-block-start: 0.9rem;
    padding-block-start: 0.85rem;
    border-block-start: 1px solid var(--color-border);
}

.cart-drawer__payments .f-payments__list {
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.4rem;
    list-style: none;
}

.cart-drawer__payments .f-payments__item {
    display: grid;
    place-items: center;
    block-size: 1.65rem;
    padding-inline: 0.4rem;
    border: 1px solid var(--color-border);
    border-radius: 0.3rem;
    background: var(--color-bg);
}

.cart-drawer__payments .f-payments__item svg,
.cart-drawer__payments .f-payments__logo { block-size: 1rem; inline-size: auto; }

.cart-drawer__payments .f-payments__label {
    font-size: 0.62rem;
    color: var(--color-text-faint);
    white-space: nowrap;
}

/* ---------------------------------------------------------------- phones */

@media (max-width: 480px) {
    /* 408px inside a 430px phone leaves a 22px sliver of backdrop that reads as
       a mistake rather than a peek. Full width below this. */
    .cart-drawer__panel { inline-size: 100%; }
    .cart-drawer__head { padding-inline: 1rem; }
    .cart-drawer__body { padding-inline: 1rem; }
    .cart-drawer__foot { padding-inline: 1rem; }
    .cart-drawer__item { grid-template-columns: 4rem 1fr auto; }
    .cart-drawer__media { inline-size: 4rem; block-size: 4rem; }
}

/* A short viewport — a landscape phone — has to keep the footer reachable, so
   the list is what gives up height rather than the totals scrolling away. */
@media (max-height: 560px) {
    .cart-drawer__coupon { margin-block-end: 0.6rem; }
    .cart-drawer__payments { display: none; }
}

/* ==========================================================================
   Product page
   --------------------------------------------------------------------------
   Three columns, in DOM order aside / gallery / buy box — which in RTL puts
   the promises on the right, the image in the middle and the buying controls
   on the left, matching the reference.

   Most of what follows is skin over library components: the stepper, the
   variant pills, the two buttons, the tab strip, the review summary and the
   payment marks are all the platform's, sized and coloured for this theme.
   ========================================================================== */

.product-page { padding-block-end: 1rem; }

.product-page__crumbs { display: block; margin-block-end: 1.25rem; }

.product-main {
    display: grid;
    grid-template-columns: 20rem minmax(0, 1fr) 24rem;
    gap: 2.5rem;
    align-items: start;
}

/*
 * Two columns, both capped, and the pair centred.
 *
 * `minmax(0, 1fr)` for the gallery was right while the aside took 20rem of the
 * row; with the aside gone the gallery absorbed every freed pixel and grew from
 * about 504px to 876px. The stage is square, so that is also its HEIGHT — the
 * product photo became 876px tall and swamped the page (and upscaled a small
 * packshot while it was at it).
 *
 * Capping both tracks keeps the gallery near the size it had in the
 * three-column layout, and justify-content centres the pair rather than
 * leaving all the slack on one side.
 */
.product-main--no-aside {
    grid-template-columns: minmax(0, 32rem) minmax(0, 24rem);
    justify-content: center;
}

/* ----------------------------------------------------------------- aside */

.product-aside {
    display: flex;
    flex-direction: column;
    gap: 2rem;
    position: sticky;
    top: 6.5rem;
}

.promises {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 1.4rem;
}

.promise {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
}

.promise__icon {
    flex: none;
    display: grid;
    place-items: center;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    color: var(--color-primary);
}

.promise__text {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-inline-size: 0;
}

.promise__text strong {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--color-text);
}

.promise__text span,
.promise__text a {
    font-size: 0.82rem;
    line-height: 1.6;
    color: var(--color-text-faint);
    text-decoration: none;
    overflow-wrap: anywhere;
}

.promise__text a:hover { color: var(--color-primary); }

.picks__title {
    margin: 0 0 1rem;
    font-size: 1rem;
    font-weight: 700;
    color: var(--color-text);
}

/* One card per row. The list renders <custom-falak-product-card> children,
   so the card itself is untouched — only the track it sits in changes. */
.picks__list { display: block; }

.picks__list .f-products-list__grid,
.picks__list .f-products-list {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.85rem;
}

/* --------------------------------------------------------------- gallery */

.gallery {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.gallery__tools {
    position: absolute;
    inset-block-start: 0.9rem;
    inset-inline-end: 0.9rem;
    z-index: 3;
    display: flex;
    gap: 0.5rem;
}

.gallery__tool { position: relative; display: block; }

/* One tile shape for both, whether the button is the theme's own (share) or
   the wishlist component's, which takes the class through `button-class`. */
.gallery__tool-btn {
    inline-size: 2.6rem;
    block-size: 2.6rem;
    display: grid;
    place-items: center;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-text-soft);
    cursor: pointer;
    transition: color 0.2s ease, border-color 0.2s ease, translate 0.2s ease;
}

.gallery__tool-btn:hover {
    color: var(--color-primary);
    border-color: var(--color-primary);
    translate: 0 -2px;
}

.gallery__tool-btn[aria-pressed="true"],
.gallery__tool .f-wishlist-btn.is-added { color: var(--color-danger); }

/* The share row, parked as a popover under its trigger. The component still
   renders its own list; this only decides when it is on screen. */
.gallery__share-sheet {
    position: absolute;
    inset-block-start: calc(100% + 0.5rem);
    inset-inline-end: 0;
    padding: 0.45rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    box-shadow: var(--shadow);
    opacity: 0;
    visibility: hidden;
    translate: 0 -6px;
    transition: opacity 0.2s ease, translate 0.2s ease, visibility 0.2s;
}

.gallery__share.is-open .gallery__share-sheet {
    opacity: 1;
    visibility: visible;
    translate: none;
}

.gallery__share-sheet .f-social__list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    gap: 0.3rem;
}

.gallery__share-sheet .f-social__link {
    inline-size: 2.1rem;
    block-size: 2.1rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    color: var(--color-text-soft);
    transition: background 0.2s ease, color 0.2s ease;
}

.gallery__share-sheet .f-social__link:hover {
    background: var(--color-primary-tint);
    color: var(--color-primary-dark);
}

.gallery__stage {
    position: relative;
    aspect-ratio: 1 / 1;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--color-bg);
}

.gallery__slide {
    position: absolute;
    inset: 0;
    margin: 0;
    display: grid;
    place-items: center;
    opacity: 0;
    transition: opacity 0.35s ease;
}

.gallery__slide.is-active { opacity: 1; }

/*
 * The photo fills the stage and is letterboxed, never cropped.
 *
 * Positioned rather than sized in percentages, because two separate things
 * were stretching it: the global `img { height: auto }` reset at the top of
 * this file, and a percentage block-size resolving against a grid row that is
 * sized to its own content. Between them a 231x441 packshot rendered 876x1672
 * inside an 876x876 stage with overflow:hidden — blown up nearly four times
 * and cropped to its middle.
 *
 * With `inset: 0` on an absolutely positioned image the box is the stage, full
 * stop: `height: auto` then means "fill between top and bottom" rather than
 * "keep the natural aspect", and object-fit does the letterboxing.
 */
.gallery__slide img {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: contain;
}

.gallery__slide--empty { background: var(--color-surface); opacity: 1; }

.gallery__thumbs {
    display: flex;
    gap: 0.6rem;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    scrollbar-width: none;
    padding-block-end: 0.15rem;
}

.gallery__thumbs::-webkit-scrollbar { display: none; }

.gallery__thumb {
    flex: none;
    inline-size: 4.75rem;
    block-size: 4.75rem;
    padding: 0.3rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    cursor: pointer;
    transition: border-color 0.2s ease;
}

.gallery__thumb img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: contain;
}

.gallery__thumb.is-active,
.gallery__thumb:hover { border-color: var(--color-primary); }

/* --------------------------------------------------------------- buy box */

.buybox { display: flex; flex-direction: column; gap: 0.7rem; }

/* The base sheet gives headings and paragraphs their own margins, which would
   stack on top of the flex gap above. Zeroed once, for every child. */
.buybox > * { margin-block: 0; }

/* The product's categories, a row of links above the title. */
.buybox__categories {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0;
    font-size: 0.85rem;
    line-height: 1.5;
}

.buybox__categories a {
    color: var(--color-primary);
    text-decoration: none;
}

.buybox__categories a:hover { text-decoration: underline; text-underline-offset: 3px; }

.buybox__categories a + a::before {
    content: "/";
    display: inline-block;
    margin-inline: 0.55rem;
    color: var(--color-text-faint);
    pointer-events: none;
}

.buybox__title {
    font-size: 1.6rem;
    line-height: 1.4;
    font-weight: 700;
    color: var(--color-text);
    text-wrap: balance;
}

.buybox__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    font-size: 0.82rem;
    color: var(--color-text-faint);
}

.buybox__meta a { color: var(--color-text-soft); text-decoration: none; }
.buybox__meta a:hover { color: var(--color-primary); }

.buybox__rating {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    inline-size: fit-content;
}

.buybox__price {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.buybox__amount {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--color-primary-dark);
    font-variant-numeric: tabular-nums;
}

.buybox__was {
    font-size: 1rem;
    color: var(--color-text-faint);
    font-variant-numeric: tabular-nums;
}

.buybox__tax { font-size: 0.78rem; color: var(--color-text-faint); }

.buybox__summary {
    margin: 0;
    font-size: 0.92rem;
    line-height: 1.8;
    color: var(--color-text-soft);
    white-space: pre-line;
    overflow-wrap: anywhere;
}

/*
 * The short description, clamped.
 *
 * Three lines at rest; `.is-open` on the wrapper lets it run. The clamp is
 * CSS alone, so a visitor whose script never runs still sees a tidy three
 * lines — only the toggle needs JavaScript, which is why the button ships
 * `hidden` and app.js reveals it just when the text overflows the clamp.
 */
.buybox__pitch:not(.is-open) .buybox__summary {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}

/* A text button in the primary, flush with the paragraph: it belongs to the
   text, not to the buy form below it. */
.buybox__more {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-block-start: 0.35rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 0.86rem;
    font-weight: 600;
    color: var(--color-primary);
    cursor: pointer;
}

.buybox__more:hover .buybox__more-label { text-decoration: underline; }

.buybox__more[hidden] { display: none; }

.buybox__more-icon { transition: transform var(--transition); }

/* The two labels swap with the state; the chevron turns. */
.buybox__pitch:not(.is-open) [data-pitch-less],
.buybox__pitch.is-open [data-pitch-more] { display: none; }

.buybox__pitch.is-open .buybox__more-icon { transform: rotate(180deg); }

.buybox__form {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    margin-block-start: 0.6rem;
    padding-block-start: 1.1rem;
    border-block-start: 1px solid var(--color-border);
}

.buybox__options { display: block; }
.buybox__size-guide { display: block; }

/*
    Weight and dimensions, under the variant picker. Tinted chips in the
    store's own primary (color-mix, so it follows the merchant's colour
    rather than a fixed theme tint), the value set in the darker shade.
*/
.product-specs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.product-specs__item {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    padding: 0.4rem 0.75rem;
    border: 1px solid color-mix(in srgb, var(--color-primary) 30%, transparent);
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--color-primary) 12%, transparent);
    font-size: 0.82rem;
    line-height: 1.3;
}

.product-specs__label { color: var(--color-text-soft); }
.product-specs__value { font-weight: 600; color: var(--color-primary-dark); }

.buybox__rows {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.buybox__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.buybox__row > dt {
    margin: 0;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--color-text);
}

.buybox__row > dd {
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.buybox__row-price {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--color-text);
}

.buybox__qty .f-qty {
    border-radius: var(--radius-sm);
    background: var(--color-bg);
}

.buybox__qty .f-qty__step { inline-size: 2.6rem; block-size: 2.6rem; }
.buybox__qty .f-qty__input { inline-size: 3rem; font-weight: 600; }

.buybox__stock {
    margin: 0;
    font-size: 0.82rem;
    color: var(--color-danger);
}

.buybox__actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.7rem;
}

/* The two CTAs are library components; only their inner buttons are skinned,
   so the components keep every one of their own states (busy, out of stock,
   "choose options") and only look like this theme. */
.buybox__add-btn,
.buybox__buy-btn,
.buybox__notify-btn {
    inline-size: 100%;
    min-block-size: 3.1rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.buybox__add-btn {
    border: 1px solid var(--color-primary);
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.buybox__add-btn:hover:not(:disabled) {
    background: var(--color-primary-dark);
    border-color: var(--color-primary-dark);
}

.buybox__buy-btn,
.buybox__notify-btn {
    border: 1px solid var(--color-primary);
    background: transparent;
    color: var(--color-primary-dark);
}

.buybox__buy-btn:hover:not(:disabled),
.buybox__notify-btn:hover:not(:disabled) {
    background: var(--color-primary-tint);
}

.buybox__add-btn:disabled,
.buybox__buy-btn:disabled { opacity: 0.5; cursor: default; }

.buybox__notify { display: block; }

.buybox__chips {
    margin: 0.3rem 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
    gap: 0.6rem;
}

.chip {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    padding: 0.7rem 0.5rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--color-text-soft);
    text-align: center;
}

.chip svg { flex: none; color: var(--color-primary); }

.buybox__payments {
    display: block;
    margin-block-start: 0.5rem;
    padding-block-start: 1rem;
    border-block-start: 1px solid var(--color-border);
}

.buybox__payments .f-payments__title { display: none; }

.buybox__payments .f-payments__list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
}

.buybox__payments .f-payments__item {
    display: grid;
    place-items: center;
    block-size: 1.9rem;
    padding-inline: 0.5rem;
    border: 1px solid var(--color-border);
    border-radius: 0.35rem;
    background: var(--color-bg);
}

.buybox__payments .f-payments__item svg,
.buybox__payments .f-payments__logo { block-size: 1.1rem; inline-size: auto; }

.buybox__payments .f-payments__label {
    font-size: 0.62rem;
    color: var(--color-text-faint);
    white-space: nowrap;
}

/* "Ask on WhatsApp": the merchant's per-product contact. The key is
   WhatsApp's own green rather than the theme primary so it reads as the
   app, not as one more buy button. */
.buybox__whatsapp {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    color: var(--color-text);
    text-decoration: none;
    transition: border-color 0.2s ease, background 0.2s ease;
}

.buybox__whatsapp:hover,
.buybox__whatsapp:focus-visible { border-color: #25d366; background: rgba(37, 211, 102, 0.07); }

.buybox__whatsapp-icon {
    flex: none;
    display: grid;
    place-items: center;
    inline-size: 2.5rem;
    block-size: 2.5rem;
    border-radius: 50%;
    background: #25d366;
    color: #fff;
}

.buybox__whatsapp-icon svg { inline-size: 1.5rem; block-size: 1.5rem; }

.buybox__whatsapp-text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-inline-size: 0;
}

.buybox__whatsapp-text strong { font-size: 0.9rem; font-weight: 700; }

.buybox__note {
    font-size: 0.8rem;
    line-height: 1.7;
    color: var(--color-text-faint);
}

/* --------------------------------------------------------------- details */

.product-details { margin-block-start: 4rem; }

.product-details__body {
    max-inline-size: 52rem;
    font-size: 0.95rem;
    line-height: 1.9;
    color: var(--color-text-soft);
}

.product-details__body img { max-inline-size: 100%; block-size: auto; }
.product-details__body :first-child { margin-block-start: 0; }
.product-details__body :last-child { margin-block-end: 0; }

/* ------------------------------------------------------------------- cta */

.product-cta {
    margin-block-start: 3rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
    padding: 1.6rem 2rem;
    border-radius: var(--radius);
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.product-cta__text h2 {
    margin: 0 0 0.25rem;
    font-size: 1.25rem;
    font-weight: 700;
}

.product-cta__text p { margin: 0; font-size: 0.9rem; opacity: 0.9; }

.product-cta__button {
    flex: none;
    min-block-size: 2.9rem;
    padding-inline: 1.75rem;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-primary-dark);
    font-family: inherit;
    font-size: 0.92rem;
    font-weight: 600;
    cursor: pointer;
    transition: translate 0.2s ease;
}

.product-cta__button:hover { translate: 0 -2px; }

/* ------------------------------------------------------------ reviews tab */

/* The condensed sticky header measures 215px on this theme (announcement bar,
   topbar, main bar, nav). Anything less than that here and jumping to
   #product-reviews lands with the tab strip already hidden under it. */
.review-tabs { margin-block-start: 4rem; scroll-margin-top: 14.5rem; }

/* The tab strip is <falak-tabs>' own markup; this is the reference's
   underline treatment over it, centred rather than left-packed. */
/* Every property the strip needs is stated, not only the ones that differ:
   the base sheet's .f-tabs__header (app.css 2637) already gives it a border
   and padding, and a partial restatement would leave half of that showing. */
.review-tabs .f-tabs__header {
    display: flex;
    justify-content: center;
    gap: 2rem;
    margin: 0;
    padding: 0;
    border: 0;
    border-block-end: 1px solid var(--color-border);
    border-radius: 0;
    background: none;
    overflow-x: auto;
    scrollbar-width: none;
}

.review-tabs .f-tabs__header::-webkit-scrollbar { display: none; }

.review-tabs .f-tabs__tab {
    flex: none;
    padding: 0.85rem 0.25rem;
    margin: 0;
    border: 0;
    border-radius: 0;
    background: none;
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    color: var(--color-text-faint);
    cursor: pointer;
    position: relative;
    transition: color 0.2s ease;
}

.review-tabs .f-tabs__tab:hover { color: var(--color-text); }

.review-tabs .f-tabs__tab[aria-selected="true"],
.review-tabs .f-tabs__tab.is-active { color: var(--color-primary-dark); }

.review-tabs .f-tabs__tab[aria-selected="true"]::after,
.review-tabs .f-tabs__tab.is-active::after {
    content: '';
    position: absolute;
    inset-inline: 0;
    inset-block-end: -1px;
    block-size: 2px;
    background: var(--color-primary);
}

/*
 * `display: block` is load-bearing, not tidiness.
 *
 * <falak-tabs-content> is a custom element with no display of its own, so it
 * lays out as INLINE — and vertical padding on an inline box does not move
 * anything. The panel sat flush against the tab strip with a 2.5rem padding
 * that was doing nothing at all. Setting display also means [hidden] has to be
 * restated, or the inactive panel stays on screen.
 */
.review-tabs .f-tabs__content {
    display: block;
    padding-block-start: 2.75rem;
}

.review-tabs .f-tabs__content[hidden] { display: none; }

.reviews {
    display: grid;
    grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    gap: 3rem;
    align-items: start;
}

.reviews__summary { display: block; }
.reviews__list { display: block; }

/* <falak-comments> heads its list with the product's average and count — the
   same figures <falak-reviews-summary> is already showing beside it, in far
   more detail. One of the two has to go, and it is not the one with the bars.
   The component keeps rendering it; only this placement hides it. */
.reviews__list .f-comments__head { display: none; }

/* With no reviews there is nothing for the summary to summarise, and it was
   printing its own "no reviews yet" beside the list's — the same sentence
   twice. `hide-empty` on the element makes it render nothing; this reclaims
   the column it was holding open. */
.reviews:has(.reviews__summary[hidden]) { grid-template-columns: minmax(0, 1fr); }

/* ------------------------------------------------------------------ rails */

.product-rail { margin-block-start: 4rem; }

/* The rail excludes the product the page is on (data-exclude-product in
   single.twig), so a product that is alone in its category now leaves the
   slider empty — it hides itself, and the "bought with" head above it must
   not stay behind as an orphan. Same for the sidebar picks on a store with
   a single product: the list's "none found" message is no pick. */
.product-rail:has(falak-products-slider[hidden]) { display: none; }
.picks:has(.f-list__message--empty) { display: none; }

/* ------------------------------------------------------- review side tab */

/*
 * Physical top/right, NOT the logical pair.
 *
 * `writing-mode: vertical-rl` below turns this element's own block axis
 * horizontal, and inset-block/inset-inline on a positioned element resolve in
 * ITS writing mode — so `inset-block-start: 50%` became a horizontal offset
 * and parked the handle off the top of the screen. Physical properties cannot
 * be re-axed. The reference keeps it on the physical right in RTL too, which
 * is what `right` gives in both directions.
 */
.review-tab {
    position: fixed;
    right: 0;
    top: 50%;
    z-index: 70;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.9rem 0.55rem;
    border-top-left-radius: var(--radius-sm);
    border-bottom-left-radius: var(--radius-sm);
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: 0.78rem;
    font-weight: 600;
    text-decoration: none;
    /* Rotated into a vertical strip. `writing-mode` keeps the Arabic glyphs
       upright and correctly joined, which a rotate() transform does not. */
    writing-mode: vertical-rl;
    translate: 0 -50%;
    box-shadow: var(--shadow);
}

.review-tab svg { rotate: 90deg; }
.review-tab:hover { background: var(--color-primary-dark); }

/* ------------------------------------------------------------ sticky bar */

.buybar {
    position: fixed;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 80;
    padding: 0.7rem 0;
    background: var(--color-bg);
    border-block-start: 1px solid var(--color-border);
    box-shadow: 0 -8px 28px rgba(20, 16, 12, 0.1);
    translate: 0 100%;
    transition: translate 0.3s cubic-bezier(0.22, 0.7, 0.3, 1);
}

.buybar[hidden] { display: none; }
.buybar.is-shown { translate: none; }

.buybar__inner {
    inline-size: min(75rem, 100% - 2rem);
    margin-inline: auto;
    display: flex;
    align-items: center;
    gap: 1rem;
}

.buybar__image {
    flex: none;
    inline-size: 3.25rem;
    block-size: 3.25rem;
    object-fit: contain;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
}

.buybar__info {
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    margin-inline-end: auto;
}

.buybar__name {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--color-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.buybar__price {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--color-primary-dark);
    font-variant-numeric: tabular-nums;
}

.buybar__actions { flex: none; display: flex; gap: 0.5rem; }

.buybar__add-btn,
.buybar__buy-btn {
    min-block-size: 2.7rem;
    padding-inline: 1.4rem;
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-size: 0.88rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.buybar__add-btn {
    border: 1px solid var(--color-primary);
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.buybar__buy-btn {
    border: 1px solid var(--color-primary);
    background: transparent;
    color: var(--color-primary-dark);
}

/* The cart drawer and the login sheet sit above this; the bar must not float
   over a panel that has taken the screen. */
body.cart-drawer-is-open .buybar,
body.cart-drawer-is-open .review-tab { display: none; }

@media (prefers-reduced-motion: reduce) {
    .buybar,
    .gallery__slide,
    .product-cta__button { transition: none; }
}

/* -------------------------------------------------------- narrower screens */

@media (max-width: 1199px) {
    /* The aside's promises move under the buy box and the picks rail is
       dropped: a third column at this width squeezes the image below the
       point where the product is legible. */
    .product-main,
    .product-main--no-aside {
        grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    }

    .product-aside {
        grid-column: 1 / -1;
        grid-row: 2;
        position: static;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 2.5rem;
    }

    .promises {
        flex: 1 1 100%;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 1.5rem 2.5rem;
    }

    .promise { flex: 1 1 14rem; }
    .picks { display: none; }
}

@media (max-width: 899px) {
    .product-main,
    .product-main--no-aside {
        grid-template-columns: minmax(0, 1fr);
        gap: 1.75rem;
    }

    /* Explicit rows, because with one column sparse auto-placement would
       leave the aside wherever its `grid-row: 2` above put it. */
    .gallery { grid-row: 1; }
    .buybox { grid-row: 2; }
    .product-aside { grid-row: 3; }

    .buybox__title { font-size: 1.3rem; }

    .reviews { grid-template-columns: minmax(0, 1fr); gap: 2rem; }

    .review-tabs .f-tabs__header { gap: 1.25rem; justify-content: flex-start; }

    .product-cta { padding: 1.3rem 1.4rem; }

    /* The side handle and the sticky bar would sit on top of each other, and
       the bar is the one that sells. */
    .review-tab { display: none; }
}

@media (max-width: 599px) {
    .buybox__actions { grid-template-columns: 1fr; }
    .gallery__thumb { inline-size: 3.75rem; block-size: 3.75rem; }

    /* The bar keeps only the primary action; the name and price are already
       one scroll away and the row must not wrap. */
    .buybar__image,
    .buybar__buy { display: none; }
    .buybar__inner { inline-size: calc(100% - 1.5rem); gap: 0.75rem; }
    .buybar__actions { flex: 1 1 auto; }
    .buybar__add-btn { inline-size: 100%; }

}

/* The phone bar owns the bottom of the screen from 860px down — the same
   breakpoint it appears at, NOT the 599px one above — so the buy bar and the
   contact keys stack above it rather than under it. The height is published
   here rather than guessed: 60px is the bar's min-height and the safe-area
   inset is what keeps it clear of a notched phone's home indicator. */
@media (max-width: 860px) {
    :root {
        --bottom-nav-height: calc(60px + env(safe-area-inset-bottom, 0px));
        /* Read by the platform's floating WhatsApp button, so it clears the bar too. */
        --falak-floating-offset: var(--bottom-nav-height);
    }

    .buybar { inset-block-end: var(--bottom-nav-height); }
}

/* --------------------------------------------------------------------------
   "Selected products" — the same card, laid out horizontally.

   The card element is the theme's own <custom-falak-product-card> and is NOT
   redefined here: only the box it sits in changes, so the rail shares one
   definition of what a product looks like with every other rail on the site.
   A full-size card in a 20rem column is taller than the gallery beside it.
   -------------------------------------------------------------------------- */

.picks__list custom-falak-product-card.vp-card {
    display: grid;
    grid-template-columns: 5rem minmax(0, 1fr);
    gap: 0.75rem;
    align-items: center;
    padding: 0.6rem;
}

.picks__list .vp-card__media {
    inline-size: 5rem;
    block-size: 5rem;
    aspect-ratio: auto;
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.picks__list .vp-card__body {
    padding: 0;
    text-align: start;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    align-items: flex-start;
}

.picks__list .vp-card__body > * { margin-block: 0; }

.picks__list .vp-card__name {
    font-size: 0.82rem;
    line-height: 1.45;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.picks__list .vp-card__price { font-size: 0.85rem; }
.picks__list .vp-card__stars { transform: scale(0.85); transform-origin: inline-start center; }

/* Hover actions, the mini-cart strip and the footer add have nowhere to go in
   an 80px tile — the card is a link to the product here, nothing more. */
.picks__list .vp-card__actions,
.picks__list .vp-card__addcart,
.picks__list .vp-card__minicart,
.picks__list .vp-card__subtitle,
.picks__list .vp-card__options { display: none; }

/* --------------------------------------------------------------------------
   Special-offer ribbon on the card.

   Opposite corner to .vp-card__badge, which sits at the inline END — a product
   that is both discounted and in an offer carries both marks, and they must
   not stack. The ribbon names the offer and never quotes its value; see
   loadOffer() in app.js for why.
   -------------------------------------------------------------------------- */

/* The saving (opposite corner to the offer ribbon) and the free-shipping
   promise (bottom corner), both the legacy card's marks. */
/* Sale sits in the START corner as on the legacy card (the offer ribbon no
   longer claims it), "hot" under it; the clip's own pill keeps the END
   corner, so nothing shares a corner. */
.vp-card__sale {
    position: absolute;
    inset-block-start: 0.6rem;
    inset-inline-start: 0.6rem;
    z-index: 2;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: var(--color-danger, #dc2626);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.45;
    white-space: nowrap;
}
.vp-card__hot {
    position: absolute;
    inset-block-start: 2.35rem;
    inset-inline-start: 0.6rem;
    z-index: 2;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: linear-gradient(135deg, #f97316, #ea580c);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.45;
    white-space: nowrap;
}
.vp-card__ship {
    position: absolute;
    inset-block-end: 0.6rem;
    inset-inline-end: 0.6rem;
    z-index: 2;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: var(--f-success, #059669);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    line-height: 1.45;
    white-space: nowrap;
}
.vp-card__offer {
    position: absolute;
    inset-block-start: 0.6rem;
    inset-inline-start: 0.6rem;
    z-index: 2;
    max-inline-size: 62%;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: var(--color-danger);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.45;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The pick tiles are 80px of image — there is nowhere for a ribbon to go, and
   the offer is stated in full on the product page the tile links to. */
.picks__list .vp-card__offer { display: none; }

/* --------------------------------------------------------------------------
   Special offers below the product.
   -------------------------------------------------------------------------- */

.product-offers { display: block; margin-block-start: 0.5rem; }
.product-offers[hidden] { display: none; }

.product-offers .f-offers__grid {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.product-offers .f-offers__card {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.9rem 1rem;
    border: 1px dashed var(--color-primary);
    border-radius: var(--radius-sm);
    background: var(--color-primary-tint);
}

.product-offers .f-offers__benefit {
    align-self: flex-start;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: 0.72rem;
    font-weight: 700;
}

.product-offers .f-offers__name {
    margin: 0;
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--color-text);
}

.product-offers .f-offers__text {
    margin: 0;
    font-size: 0.82rem;
    line-height: 1.6;
    color: var(--color-text-soft);
}

.product-offers .f-offers__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.9rem;
    font-size: 0.76rem;
    color: var(--color-text-faint);
}

/* The offer's countdown, sized into the offer card's meta row. */
.product-offers .f-offers__countdown {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    font-size: 0.76rem;
    color: var(--color-primary-dark);
}

.product-offers .f-offers__countdown .f-countdown__prefix { color: var(--color-text-faint); }

.product-offers .f-offers__countdown .f-countdown__value,
.product-offers .f-offers__countdown .f-countdown__item {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--color-primary-dark);
}

/* ==========================================================================
   Search results
   ========================================================================== */

.search-page { padding-block-end: 2rem; }

/* Centred under the centred block-head, not parked at the inline start —
   `margin-inline: auto` needs the max-inline-size above to have any effect. */
.search-form {
    display: flex;
    gap: 0.6rem;
    max-inline-size: 34rem;
    margin-block: 0.5rem 1.75rem;
    margin-inline: auto;
}

.search-form__field {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-inline-size: 0;
    padding-inline: 0.9rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    transition: border-color 0.2s ease;
}

.search-form__field:focus-within { border-color: var(--color-primary); }

.search-form__icon {
    flex: none;
    display: grid;
    place-items: center;
    color: var(--color-text-faint);
}

.search-form__input {
    flex: 1 1 auto;
    min-inline-size: 0;
    min-block-size: 2.9rem;
    border: 0;
    background: none;
    color: var(--color-text);
    font-family: inherit;
    font-size: 0.95rem;
}

.search-form__input:focus { outline: none; }

/* Chrome draws its own clear button on type=search, which sits on top of the
   border and does not follow the theme. */
.search-form__input::-webkit-search-cancel-button { -webkit-appearance: none; }

.search-form__submit {
    flex: none;
    min-block-size: 2.9rem;
    padding-inline: 1.5rem;
    border: 1px solid var(--color-primary);
    border-radius: var(--radius-sm);
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-family: inherit;
    font-size: 0.92rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease;
}

.search-form__submit:hover {
    background: var(--color-primary-dark);
    border-color: var(--color-primary-dark);
}

.search-page__count {
    margin: 0 0 0.25rem;
    text-align: center;
    font-size: 0.88rem;
    color: var(--color-text-soft);
    font-variant-numeric: tabular-nums;
}

.search-page__empty { display: block; padding-block: 3rem 1rem; }

.search-page__hint,
.search-page__prompt {
    margin: 0;
    padding-block: 0.5rem 3rem;
    text-align: center;
    font-size: 0.88rem;
    color: var(--color-text-faint);
}

.search-page__prompt { padding-block: 3rem 4rem; }

@media (max-width: 599px) {
    .search-form { flex-direction: column; }
    .search-form__submit { inline-size: 100%; }
}

/* ==========================================================================
   Header logo — one mark per ground
   --------------------------------------------------------------------------
   The header is white on every page except the top of the home page, where it
   is transparent over the hero, and the theme also has a dark mode. A single
   light-ink logo therefore vanished on every page but the home page.

   Two <img> are rendered and CSS shows whichever matches the ground. Both
   fall back to the platform's store logo when a slot is empty, so a merchant
   who sets neither sees exactly what they saw before.
   ========================================================================== */

.site-header__logo-img--on-dark { display: none; }

/* --- dark mode: every header surface is dark, so the light-ink mark wins --- */

:root[data-store-theme="dark"] .site-header__logo-img--on-light { display: none; }
:root[data-store-theme="dark"] .site-header__logo-img--on-dark { display: block; }

/* --- light mode, transparent header sitting on the hero -------------------
   Only while UNSCROLLED: once the bar goes solid white the ink has to flip
   back. `[data-scrolled]` is what the header sets on itself, so the two rules
   below are the two halves of that one state. */

.header-is-transparent .app-inner:has(> main > .block--hero:first-child)
    .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__logo-img--on-light { display: none; }

.header-is-transparent .app-inner:has(> main > .block--hero:first-child)
    .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__logo-img--on-dark { display: block; }

/* ==========================================================================
   Account pages — orders, wishlist, notifications, profile
   --------------------------------------------------------------------------
   All four are shells over library components (the wishlist grid excepted),
   so most of what follows sizes and skins those rather than laying out forms
   this theme does not own.
   ========================================================================== */

.account-page { padding-block-end: 2rem; }

.account-layout {
    display: grid;
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: 2.5rem;
    align-items: start;
}

.account-nav {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.6rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-bg);
    position: sticky;
    top: 6.5rem;
}

.account-nav__item {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.7rem 0.85rem;
    border-radius: var(--radius-sm);
    color: var(--color-text-soft);
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    transition: background 0.2s ease, color 0.2s ease;
}

.account-nav__item svg { flex: none; }

.account-nav__item:hover {
    background: var(--color-surface);
    color: var(--color-text);
}

.account-nav__item.is-active {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.account-body { min-inline-size: 0; }

/* The grid already exists for the listing; on this page it starts at the top
   of its column rather than under a filter bar. */
.account-body .product-grid { padding-block-start: 0; }
.account-body .product-grid[hidden] { display: none; }

.account-empty { display: block; padding-block: 3rem; }
.account-empty[hidden] { display: none; }

.account-back {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-block-end: 1rem;
    color: var(--color-text-soft);
    font-size: 0.85rem;
    text-decoration: none;
}

.account-back::before { content: '\2039'; font-size: 1.1rem; line-height: 1; }
[dir="rtl"] .account-back::before { content: '\203A'; }
.account-back:hover { color: var(--color-primary); }

.account-notifications {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.account-orders,
.account-profile,
.account-order { display: block; }

@media (max-width: 899px) {
    .account-layout { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }

    /* The sidebar becomes a scrolling row of pills above the content. */
    .account-nav {
        position: static;
        flex-direction: row;
        overflow-x: auto;
        scrollbar-width: none;
    }

    .account-nav::-webkit-scrollbar { display: none; }
    .account-nav__item { flex: none; white-space: nowrap; }
}

/* ==========================================================================
   Footer — customizer preview shells
   --------------------------------------------------------------------------
   A band with nothing in it renders as a dashed shell under theme.mode
   'preview' only, so the customizer has a place to pin the band's pencil.
   Shoppers never see these: the live render hides empty bands as it always
   did. Dimmed and dashed so sample chrome can't be mistaken for content.
   ========================================================================== */

.site-footer__social-wrap {
    display: grid;
    gap: 0.5rem;
}

.site-footer__about.is-placeholder,
.site-footer__group.is-placeholder .site-footer__heading {
    opacity: 0.55;
}

.site-footer__add {
    margin: 0;
    padding: 0.5rem 0.75rem;
    border: 1px dashed rgba(255, 255, 255, 0.35);
    border-radius: 0.5rem;
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.6);
}

.site-footer__add--inline {
    display: inline-block;
}

/* ==========================================================================
   Listing — sidebar, toolbar, grid, pager
   --------------------------------------------------------------------------
   The sidebar is <falak-filters>' own markup; most of what follows skins it
   rather than laying it out, so a filter type the server adds later (a new
   `values` group, say) arrives already styled.
   ========================================================================== */

.listing-page { padding-block-end: 2rem; }
.listing-page__crumbs { display: block; margin-block-end: 1.25rem; }

/* Sections the merchant placed in the `listing_top` area — the slot above the
   grid in product/index.twig. They sit INSIDE the page's own .container, and
   every home block wraps itself in a .container too, so without this each one
   would draw a second gutter and read as inset from the listing beneath it.
   Zeroed here rather than in the blocks, which need their own gutter on the
   home page. */
.listing-page > .block > .container { padding-inline: 0; }

.listing-layout {
    display: grid;
    grid-template-columns: 15.5rem minmax(0, 1fr);
    gap: 2.5rem;
    align-items: start;
}

.listing-aside { position: sticky; top: 6.5rem; }

/* The toggle is phone-only; on desktop the panel is simply open. */
.listing-aside__toggle { display: none; }

.listing-filters { display: block; }

/* ---- the component's widgets ---- */

.listing-filters .f-filters__widget {
    padding-block: 1.1rem;
    border-block-end: 1px solid var(--color-border);
}

.listing-filters .f-filters__widget:first-child { padding-block-start: 0; }
.listing-filters .f-filters__widget:last-child { border-block-end: 0; }

.listing-filters .f-filters__title {
    inline-size: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0;
    border: 0;
    background: none;
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--color-text);
    cursor: pointer;
}

.listing-filters .f-filters__plusminus { color: var(--color-primary); font-weight: 400; }
.listing-filters .f-filters__values { margin-block-start: 0.6rem; }
.listing-filters .f-filters__option-name { flex: 1 1 auto; }

/* Applied filters, shown as removable chips above the widgets. */
.listing-filters .f-filters__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-block-end: 0.9rem;
}

.listing-filters .f-filters__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: var(--color-primary-tint);
    color: var(--color-primary-dark);
    font-size: 0.78rem;
}

.listing-filters .f-filters__chip-remove {
    border: 0;
    background: none;
    padding: 0;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.listing-filters .f-filters__option {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding-block: 0.35rem;
    font-size: 0.87rem;
    color: var(--color-text-soft);
    cursor: pointer;
}

.listing-filters .f-filters__option:hover { color: var(--color-text); }

.listing-filters input[type="checkbox"],
.listing-filters input[type="radio"] {
    inline-size: 1rem;
    block-size: 1rem;
    accent-color: var(--color-primary);
    cursor: pointer;
}

.listing-filters .f-filters__count { color: var(--color-text-faint); font-size: 0.8rem; }

.listing-filters .f-filters__more {
    margin-block-start: 0.35rem;
    border: 0;
    background: none;
    padding: 0;
    color: var(--color-primary);
    font: inherit;
    font-size: 0.83rem;
    cursor: pointer;
}

.listing-filters .f-price-range__numbers { display: flex; align-items: center; gap: 0.5rem; }

.listing-filters .f-price-range__number {
    min-inline-size: 0;
    inline-size: 100%;
    min-block-size: 2.4rem;
    padding-inline: 0.6rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-text);
    font: inherit;
    font-size: 0.85rem;
}

/* ---- toolbar ---- */

.listing-main { min-inline-size: 0; }

.listing-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    padding-block-end: 1.1rem;
    border-block-end: 1px solid var(--color-border);
}

.listing-toolbar__title {
    margin: 0;
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--color-text);
}

.listing-toolbar__count {
    margin: 0;
    font-size: 0.83rem;
    color: var(--color-text-faint);
    font-variant-numeric: tabular-nums;
}

.listing-sort {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.listing-sort__label { font-size: 0.85rem; color: var(--color-text-soft); white-space: nowrap; }

.listing-sort__select {
    min-block-size: 2.6rem;
    padding-inline: 0.9rem 2rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-text);
    font: inherit;
    font-size: 0.87rem;
    cursor: pointer;
}

/* Three across beside the sidebar, as the reference has it. The shared
   .product-grid is auto-fill from a 210px minimum, which gave four narrow
   cards in the space left over — fine for a full-width grid, too tight when a
   15.5rem column has already been taken out. */
.listing-grid {
    padding-block: 1.5rem 0;
    grid-template-columns: repeat(3, minmax(0, 1fr));
}
.listing-empty { display: block; padding-block: 4rem; }

/* ---- pager ---- */

.pager {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-block-start: 2.5rem;
}

.pager__page,
.pager__step {
    min-inline-size: 2.5rem;
    min-block-size: 2.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-inline: 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    color: var(--color-text-soft);
    font-size: 0.87rem;
    font-weight: 600;
    text-decoration: none;
    font-variant-numeric: tabular-nums;
    transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
}

.pager__page:hover,
.pager__step:hover:not(.is-disabled) {
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.pager__page.is-current {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-on-primary);
}

.pager__step.is-disabled { opacity: 0.4; cursor: default; }
.pager__gap { padding-inline: 0.25rem; color: var(--color-text-faint); }

/* ---- narrow ---- */

@media (max-width: 899px) {
    .listing-layout { grid-template-columns: minmax(0, 1fr); gap: 1rem; }

    .listing-aside { position: static; }

    /* The sidebar collapses behind a button rather than pushing the grid a
       screen down. */
    .listing-aside__toggle {
        display: inline-flex;
        align-items: center;
        gap: 0.45rem;
        min-block-size: 2.7rem;
        padding-inline: 1rem;
        border: 1px solid var(--color-border);
        border-radius: var(--radius-sm);
        background: var(--color-bg);
        color: var(--color-text);
        font: inherit;
        font-size: 0.88rem;
        font-weight: 600;
        cursor: pointer;
    }

    .listing-aside__panel { display: none; padding-block-start: 1rem; }
    .listing-aside.is-open .listing-aside__panel { display: block; }

    .listing-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .listing-toolbar__title { font-size: 1.15rem; }
    .listing-sort { margin-inline-start: 0; inline-size: 100%; }
    .listing-sort__select { flex: 1 1 auto; }
}

/* --------------------------------------------------------------------------
   Product grid: card height.

   The base .vp-card__media is 9/16 — the PORTRAIT VIDEO ratio the reels row
   uses. Every rail already overrides it (298/318), so the plain grid was the
   only surface still inheriting it: a 331px-wide card carried a 584px image
   and stood 688px tall, which is one and a half cards per screen.

   4/5 is the reference's own listing proportion and still portrait enough for
   apparel. `flex: 0 0 auto` matters as much as the ratio — the base sets
   `flex: 1 1 auto`, which lets the media grow past whatever aspect-ratio asks
   for; the slider override includes the same pair for the same reason.

   Scoped to .product-grid, so the listing, search and wishlist grids change
   and the rails, the video wall and the reels row do not.
   -------------------------------------------------------------------------- */

.product-grid .vp-card__media {
    flex: 0 0 auto;
    aspect-ratio: 4 / 5;
    block-size: auto;
}

/* ==========================================================================
   Loading placeholders — one shimmer for every async section
   --------------------------------------------------------------------------
   The base sheet ships TWO treatments: .f-skeleton shimmers (a moving
   gradient) and .f-card--skeleton only pulses its opacity. The sliders and
   lists emit the second, so the busiest surfaces on the site had the quieter
   effect. This gives them all the same shimmer.

   A placeholder also has to be the SHAPE of what replaces it, or the layout
   jumps the moment the products land — which is the one thing a skeleton
   exists to prevent. So the ratios below track the real cards: 4/5 in a
   product grid, 298/318 in a rail.
   ========================================================================== */

.f-card--skeleton,
.vp-skeleton {
    border-radius: var(--radius);
    /* Same gradient the base gives .f-skeleton, in this theme's ink. */
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--color-text) 7%, transparent) 25%,
        color-mix(in srgb, var(--color-text) 13%, transparent) 37%,
        color-mix(in srgb, var(--color-text) 7%, transparent) 63%);
    background-size: 400% 100%;
    animation: f-shimmer 1.4s ease infinite;
}

/* Rails: the ratio the rail's real cards use. */
.block--products-slider .f-card--skeleton,
.block--product-tabs .f-card--skeleton,
.product-rail .f-card--skeleton { aspect-ratio: 298 / 318; }

/* Grids: the ratio the grid's real cards use. */
.product-grid .f-card--skeleton,
.f-list__grid .f-card--skeleton { aspect-ratio: 4 / 5; }

/* The "selected products" column is 5rem tiles, not cards — a full-size
   placeholder there would be four screens of shimmer for four small rows. */
.picks__list .f-card--skeleton {
    aspect-ratio: auto;
    block-size: 5rem;
}

.picks__list .f-list__grid { grid-template-columns: 1fr; gap: 0.85rem; }

/* "Made just for you" — the video wall's tiles are portrait, like its cards. */
.vp-skeleton {
    aspect-ratio: 9 / 16;
    list-style: none;
}

@media (prefers-reduced-motion: reduce) {
    .f-card--skeleton,
    .vp-skeleton { animation: none; }
}

/* Newsletter form result line — inline, because the form reports its own
   outcome rather than raising a toast that says the same thing twice. */
.site-footer__newsletter-status {
    margin: 0.6rem 0 0;
    font-size: 0.83rem;
    line-height: 1.6;
}

.site-footer__newsletter-status[hidden] { display: none; }
.site-footer__newsletter-status.is-success { color: var(--color-primary-light); }
.site-footer__newsletter-status.is-error { color: #e88; }

.site-footer__newsletter-form button[disabled] { opacity: 0.6; cursor: default; }

/* ===== onyx latest duo: two department columns ===== */
/* Measured off the design at 1650:
     grid       two columns, 1fr each, ~44px between
     heading    20px/700 centred, an 88x2 rule with the primary lozenge under it
     body       feature and stack share the column, 1fr 1fr, ~34px apart
     feature    the column's full height, caption laid over the foot of the photo
     row card   331x164, radius 10, 1px #f0f0f0; a 96px thumbnail at the inline
                start, name and price start-aligned, the two round controls
                centred under them — the design's own asymmetry, not a slip
   The feature sits FIRST in the DOM, so it lands at the inline end in Arabic
   and the inline start in English; the design shows it on the right of each
   half, which is what inline-end means there. */

.block--latest-duo .latest-duo__grid {
    display: grid;
    /* auto-fit rather than a hard two: the collection allows a third column,
       and a merchant who adds one must not get a 50%-wide orphan on a row of
       its own. */
    /* ONE COLUMN UNTIL 1024, like the reference's .two-cols .inner. Splitting
       earlier left a row card about 170px wide holding a 14rem thumbnail —
       the thumbnail ladder below is written against a full-width column, the
       way the reference's is. auto-fit rather than a hard two, because the
       collection allows a third. */
    grid-template-columns: minmax(0, 1fr);
    /* 1.25rem, measured off the reference — the columns sit closer together
       than the two halves inside one of them. */
    gap: 1.25rem;
}
@media (min-width: 1024px) {
    .block--latest-duo .latest-duo__grid {
        grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    }
}

.block--latest-duo .latest-duo__head {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-block-end: 1.75rem;
}

.block--latest-duo .latest-duo__title {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.4;
    text-align: center;
    text-wrap: balance;
}

/* Shorter than the page-wide rule: this one heads half a row, not the whole
   container. `width`, not `inline-size` — the base declares `width`, and two
   different properties resolving to the same box is a cascade nobody should
   have to reason about. */
.block--latest-duo .block-head__rule { width: 5.5rem; }

/* ---- the set: one grid, the lead spanning it ---------------------------- */

/* All four cards are children of ONE <falak-products-list> grid, so the split
   is a placement rule rather than two containers: the lead takes column one
   for every row the stack occupies, and the row cards flow down column two on
   their own. --duo-rows carries the merchant's stack count in from the
   template, because the stylesheet cannot know it.

   These selectors outrank the SDK's own responsive rules — which drop the grid
   to three columns under 1024 and two under 640 — rather than fighting them
   with !important. */
.block--latest-duo .latest-duo__set { display: block; }
.block--latest-duo .latest-duo__set .f-list__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    /* Row gap, then column gap: the stack's cards sit closer to each other
       than the two halves of the column do. */
    gap: 32px;
}
.block--latest-duo .latest-duo__set .f-list__grid > :first-child {
    grid-column: 1;
    grid-row: 1 / span var(--duo-rows, 3);
}

/* ---- the lead ---------------------------------------------------------- */

/* Two rows: the photo, and whatever the card grows under it — on touch it
   appends a full-width add-to-cart below the media. The caption then shares
   the PHOTO's cell rather than floating against the card, which is the whole
   reason for the inner grid. */
.block--latest-duo .vp-card--lead {
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    /* A floor for the case the category returns fewer products than asked:
       with one row card beside it the span collapses to that card's height,
       and the photo would be a letterbox. */
    min-block-size: 320px;
}

/* The photo takes the spanned height instead of its own ratio, so the two
   halves of the column end level however many row cards there are. */
.block--latest-duo .vp-card--lead .vp-card__media {
    grid-area: 1 / 1;
    aspect-ratio: auto;
    border-radius: 10px;
}
/* The lead renders no foot cart at all — its caption carries the controls, so
   the card is exactly its photo at every width. This only guards against the
   ordinary markup reaching it. */
.block--latest-duo .vp-card--lead .vp-card__addcart--foot { display: none; }

/* The caption's controls: .product-card__full-image-actions in the reference —
   flex, gap-2, justify-center, mt-4, and outline discs in white ink. They sit
   in the caption rather than in the hover overlay, which is why they show on a
   phone too. The caption is transparent to the pointer, so they take their own
   clicks back. */
.block--latest-duo .vp-card__lead-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-block-start: 1rem;
    pointer-events: auto;
}

/* The caption sits at the foot of the PHOTO, in flow rather than absolutely
   placed. Anchored to the card instead — which is what inset-block-end: 0
   means — it landed on top of the add-to-cart bar the card grows on touch,
   where the card is taller than the photo it wraps. */
.block--latest-duo .vp-card--lead .vp-card__body {
    grid-area: 1 / 1;
    align-self: end;
    z-index: 2;
    display: grid;
    justify-items: center;
    gap: 0.35rem;
    /* 1.25rem 2.5rem 1.75rem — the reference's own figures. NO SCRIM: its
       full-image card lays plain white text straight on the photo, and a
       gradient here was the single thing making this card read as a different
       component from the three beside it. Legibility over a pale product shot
       is the reference's own trade-off, kept rather than corrected. */
    padding: 1.25rem 2.5rem 1.75rem;
    text-align: center;
    /* Transparent to the pointer so the strip of photo behind it still opens
       the product; the name inside takes its clicks back. */
    pointer-events: none;
}
.block--latest-duo .vp-card--lead .vp-card__name {
    font-size: 1.125rem;
    line-height: 1.5;
}
.block--latest-duo .vp-card--lead .vp-card__name a { pointer-events: auto; }
.block--latest-duo .vp-card--lead .vp-card__name a,
.block--latest-duo .vp-card--lead .vp-card__name a:hover { color: #fff; }
.block--latest-duo .vp-card--lead .vp-card__price {
    justify-content: center;
    color: #fff;
}
.block--latest-duo .vp-card--lead .vp-card__price del { color: rgba(255, 255, 255, 0.7); }

/* ---- the row cards ----------------------------------------------------- */

/* A height of its own rather than a share of the lead's: the row cards set the
   span the lead fills, not the other way round. Measured at 178 against a 332
   card in the reference. */
.block--latest-duo .vp-card--inline {
    display: grid;
    /* 8rem / 14rem / 7rem across the reference's three breakpoints — a fixed
       strip, not a share of the card, so the thumbnail keeps its size when the
       column narrows. */
    grid-template-columns: 8rem minmax(0, 1fr);
    align-items: stretch;
    min-block-size: 11rem;
}
@media (min-width: 640px) {
    .block--latest-duo .vp-card--inline { grid-template-columns: 14rem minmax(0, 1fr); }
}
@media (min-width: 1024px) {
    .block--latest-duo .vp-card--inline { grid-template-columns: 7rem minmax(0, 1fr); }
}
.block--latest-duo .vp-card--inline .vp-card__media {
    aspect-ratio: auto;
    block-size: 100%;
    border-radius: 0;
    background: var(--color-surface);
}
/* The reference's card emits object-cover on every image that is not a
   placeholder, and its thumbnail tile is filled edge to edge. Fitting the
   image instead left it floating in a band of surface colour, which is what
   made these three read as a different card from the reference's. */
.block--latest-duo .vp-card--inline .vp-card__video { object-fit: cover; }

.block--latest-duo .vp-card--inline .vp-card__body {
    display: grid;
    align-content: center;
    justify-items: start;
    gap: 0.5rem;
    padding: 0.9rem 1rem;
    text-align: start;
}
.block--latest-duo .vp-card--inline .vp-card__name {
    font-size: 0.875rem;
    line-height: 1.5;
}
.block--latest-duo .vp-card--inline .vp-card__price {
    justify-content: flex-start;
    gap: 0.5rem;
    font-size: 0.9375rem;
    line-height: 1.4;
}

/* Start-aligned text over centred controls, as measured. */
.block--latest-duo .vp-card__row-actions {
    justify-self: center;
    display: flex;
    /* margin: 0 5px a side in the reference. */
    gap: 10px;
}
.block--latest-duo .vp-card__row-actions .vp-card__icon {
    /* 40px, no border, a barely-there halo — .product-card__buttons > div
       button in the reference. */
    width: 40px;
    height: 40px;
    border: 0;
    background: var(--color-bg);
    box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.04);
    color: var(--color-text);
}
.block--latest-duo .vp-card__row-actions .vp-card__icon:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
}
/* The SDK's cart button is skinned into the disc rather than re-implemented,
   so the control keeps real add-to-cart behaviour and its own states. */
.block--latest-duo .vp-card__row-actions falak-add-product-button.vp-card__icon .f-add-product__button {
    width: 100%;
    height: 100%;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    border-radius: inherit;
    font: inherit;
}

.vp-card__icon-glyph--bag { -webkit-mask-image: var(--onyx-bag); mask-image: var(--onyx-bag); }

/* fill="outline" over a photo: no ground, a hairline ring, white ink. */
.block--latest-duo .vp-card__icon--ghost {
    width: 40px;
    height: 40px;
    border: 1px solid rgba(255, 255, 255, 0.7);
    background: transparent;
    box-shadow: none;
    color: #fff;
}
.block--latest-duo .vp-card__icon--ghost:hover {
    background: #fff;
    color: var(--color-text);
    border-color: #fff;
}
.block--latest-duo .vp-card__lead-actions falak-add-product-button.vp-card__icon .f-add-product__button,
.block--latest-duo .vp-card__lead-actions falak-wishlist-button.vp-card__icon .f-wishlist__button {
    width: 100%;
    height: 100%;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    border-radius: inherit;
    font: inherit;
}

/* ---- the row card's small-screen bar ----------------------------------- */

/* .product-card__addToCart.mobile in the reference: absolute across the foot
   of the CONTENT column — not the whole card, which is why it stops at the
   thumbnail — 40px on rgba(0,0,0,.5), white label, and the two discs give way
   to it. The 991 breakpoint is the reference's own. */
.block--latest-duo .vp-card__row-cart { display: none; }

@media (max-width: 990px) {
    .block--latest-duo .vp-card__row-actions { display: none; }

    .block--latest-duo .vp-card--inline .vp-card__body { position: relative; }
    .block--latest-duo .vp-card__row-cart {
        display: block;
        position: absolute;
        inset-inline: 0;
        inset-block-end: 0;
    }
    .block--latest-duo .vp-card__row-cart-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.5rem;
        width: 100%;
        height: 40px;
        background: rgba(0, 0, 0, 0.5);
        color: #fff;
        font-size: 15px;
        transition: background var(--transition);
    }
    .block--latest-duo .vp-card__row-cart-btn:hover { background: var(--color-primary); }
    .block--latest-duo .vp-card__row-cart-btn .f-add-product__button {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.5rem;
        width: 100%;
        height: 100%;
        padding: 0;
        border: 0;
        background: transparent;
        color: inherit;
        font: inherit;
    }
    .block--latest-duo .vp-card__row-cart-glyph {
        width: 1.05rem;
        height: 1.05rem;
        background: currentColor;
        -webkit-mask: var(--onyx-bag) center / contain no-repeat;
        mask: var(--onyx-bag) center / contain no-repeat;
    }
    /* The bar sits where the discs were, so the text must not run under it. */
    .block--latest-duo .vp-card--inline .vp-card__body { padding-block-end: 3.25rem; }
}

/* Under 768 the set becomes a single file: a thumbnail beside a name beside a
   full-height photo is three things in a 320px row. The lead stops spanning
   and simply leads. */
@media (max-width: 767px) {
    .block--latest-duo .latest-duo__grid { gap: 2.5rem; }
    .block--latest-duo .latest-duo__set .f-list__grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 20px;
    }
    .block--latest-duo .latest-duo__set .f-list__grid > :first-child {
        grid-column: auto;
        grid-row: auto;
    }
    .block--latest-duo .vp-card--lead { min-block-size: 380px; }
}

/* ===== onyx blog: the card, the rail, the index, the article ===== */
/* Measured off the reference at 1536:
     card     466 wide, radius 10, media 16:9, body on --color-surface
     meta     13px, muted, a date and an author with a 14px glyph each
     title    16px/700, two lines then ellipsis
     excerpt  14px muted, one line then ellipsis
     more     14px with a chevron, primary on hover
     rail     three in view, 24px between, arrows in the header
     article  content column + a 300px sidebar of related posts
   The card is ONE definition in two places — pages.partials.blog-card and the
   rail's JS build the same elements with the same classes. Keep them in step. */

/* The card is a custom element now, so it needs the box the .blog-card class
   used to get for free from an <article>. Both selectors carry the skin: the
   element adds .blog-card to itself, and the class is what the stylesheet
   below is written against. */
custom-falak-blog-card { display: block; height: 100%; }

.blog-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--color-bg);
    border-radius: 10px;
    overflow: hidden;
    transition: box-shadow var(--transition), border-color var(--transition);
}
.blog-card:hover { box-shadow: var(--shadow); }

.blog-card__media {
    display: block;
    aspect-ratio: 16 / 9;
    background: var(--color-surface);
    overflow: hidden;
}
.blog-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.4s ease;
}
.blog-card:hover .blog-card__media img { transform: scale(1.04); }
.blog-card__placeholder { display: block; width: 100%; height: 100%; }

/* The body carries the ground, not the card: the reference's card is a photo
   sitting on a tinted panel rather than a bordered box. */
.blog-card__body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 1rem 1.15rem 1.25rem;
    background: var(--color-surface);
}

.blog-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin: 0;
    font-size: 0.8125rem;
    color: var(--color-text-soft);
}
.blog-card__meta-item { display: inline-flex; align-items: center; gap: 0.4rem; }

.blog-card__meta-glyph {
    width: 0.875rem;
    height: 0.875rem;
    flex: none;
    background: currentColor;
    -webkit-mask-position: center; mask-position: center;
    -webkit-mask-size: contain;    mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.blog-card__meta-glyph--date { -webkit-mask-image: var(--onyx-calendar); mask-image: var(--onyx-calendar); }
.blog-card__meta-glyph--user { -webkit-mask-image: var(--onyx-user);     mask-image: var(--onyx-user); }

.blog-card__title {
    margin: 0;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.6;
    /* Two lines, then ellipsis — a long headline must not push the "read more"
       of one card out of line with its neighbours in the rail. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.blog-card__title a { color: var(--color-text); text-decoration: none; }
.blog-card__title a:hover { color: var(--color-primary); text-decoration: none; }

.blog-card__excerpt {
    margin: 0;
    font-size: 0.875rem;
    line-height: 1.7;
    color: var(--color-text-faint);
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Pushed to the foot so it lines up across a row of cards whose excerpts run
   to different lengths. */
.blog-card__more {
    margin-block-start: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    align-self: flex-start;
    font-size: 0.875rem;
    color: var(--color-text);
    text-decoration: none;
}
.blog-card__more:hover { color: var(--color-primary); text-decoration: none; }

.blog-card__more-chevron {
    width: 0.7rem;
    height: 0.7rem;
    background: currentColor;
    -webkit-mask: var(--onyx-chevron) center / contain no-repeat;
    mask: var(--onyx-chevron) center / contain no-repeat;
}
/* The chevron points the way the language reads. */
[dir="rtl"] .blog-card__more-chevron { transform: scaleX(-1); }

:root {
    --onyx-calendar: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E");
    --onyx-user:     url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 21c0-4.4 3.6-7 8-7s8 2.6 8 7'/%3E%3C/svg%3E");
    --onyx-chevron:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 5 7 7-7 7'/%3E%3C/svg%3E");
    --onyx-tag:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.6 13.4 12 22l-9-9V3h10l7.6 7.6a2 2 0 0 1 0 2.8Z'/%3E%3Ccircle cx='7.5' cy='7.5' r='1.5'/%3E%3C/svg%3E");
}

/* ---- the home rail ------------------------------------------------------ */

/* The card IS the slide — <falak-slider> puts .f-slider__slide on each child of
   its items slot — so `> *` here reaches the card's own parts rather than the
   card. Harmless on this card, which has no absolutely-positioned piece, but
   it is the rule that stretched the testimonial card's quote glyph across its
   whole width. Stated the same way in both places. */
.blog-rail__slider .f-slider__slide { align-self: stretch; }

/* The reference's footer for this block: a hairline across the row with the
   "view all" pill sitting in a gap at its centre. One element and a background
   rather than two rules and a spacer. */
.blog-rail__all {
    display: flex;
    justify-content: center;
    margin-block-start: 2rem;
    position: relative;
}
.blog-rail__all::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-start: 50%;
    block-size: 1px;
    background: var(--color-border);
}
.blog-rail__all-link {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.55rem 1.5rem;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background: var(--color-bg);
    color: var(--color-primary);
    font-size: 0.9375rem;
    text-decoration: none;
}
.blog-rail__all-link:hover {
    border-color: var(--color-primary);
    background: var(--color-primary);
    color: var(--color-on-primary);
    text-decoration: none;
}

/* The rail holds a spinner while its request is in flight — it renders no
   markup of its own until the articles land, so without this the band is a
   heading over empty space. Centred across the full width rather than left
   where the first card would be, because there is no first card yet. */
.blog-rail__loading,
.testimonials__loading {
    justify-content: center;
    inline-size: 100%;
    padding-block: 2.5rem;
}

.blog-rail__empty {
    margin: 0;
    padding: 2.5rem 1rem;
    text-align: center;
    color: var(--color-text-faint);
}

/* ---- the index ---------------------------------------------------------- */

.blog-grid {
    display: grid;
    /* auto-FIT, not auto-fill: three articles in a container wide enough for
       four left an empty track and pushed the row off to one side. */
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 1.5rem;
}

/* Card-shaped blanks while the request is out, so the grid does not jump when
   the articles land. */
.blog-card--skeleton {
    min-block-size: 22rem;
    background: var(--color-surface);
    border-radius: 10px;
}

.blog-index__filter {
    margin: 0 0 1.5rem;
    font-size: 0.9375rem;
    color: var(--color-text-soft);
}
.blog-index__filter a { margin-inline-start: 0.75rem; }

.blog-index__empty {
    padding: 3rem 1rem;
    text-align: center;
    color: var(--color-text-faint);
}

/* ---- the article -------------------------------------------------------- */

.blog-post__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
}
/* The sidebar arrives only when there is room for it beside the prose; below
   that the related list follows the article instead of squeezing it. */
@media (min-width: 1024px) {
    .blog-post__grid { grid-template-columns: minmax(0, 1fr) 300px; }
}

.blog-post__title {
    margin: 0 0 0.9rem;
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.5;
    text-wrap: balance;
}

.blog-post__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
    margin: 0 0 1.5rem;
    font-size: 0.875rem;
    color: var(--color-text-soft);
}
.blog-post__meta-item { display: inline-flex; align-items: center; gap: 0.4rem; }
.blog-post__category { color: var(--color-primary); text-decoration: none; }

.blog-post__figure {
    margin: 0 0 1.75rem;
    border-radius: 10px;
    overflow: hidden;
    background: var(--color-surface);
}
/* A wide crop, as in the reference. Article heroes arrive at whatever ratio
   the merchant uploaded, and a portrait product shot rendered at its natural
   height pushed the whole article below the fold. */
.blog-post__figure img {
    width: 100%;
    aspect-ratio: 3 / 2;
    object-fit: cover;
    display: block;
}

/* Merchant HTML from the admin editor lands here, so the tags it may contain
   are given a house style rather than left to the browser's defaults. */
.blog-post__body { font-size: 1rem; line-height: 1.9; color: var(--color-text-soft); }
.blog-post__body > * + * { margin-block-start: 1.1rem; }
.blog-post__body h2,
.blog-post__body h3 { color: var(--color-text); font-weight: 700; line-height: 1.5; }
.blog-post__body h2 { font-size: 1.25rem; }
.blog-post__body h3 { font-size: 1.0625rem; }
.blog-post__body ul,
.blog-post__body ol { padding-inline-start: 1.35rem; }
.blog-post__body li + li { margin-block-start: 0.4rem; }
.blog-post__body img { max-width: 100%; height: auto; border-radius: 10px; }
.blog-post__body a { color: var(--color-primary); }
.blog-post__body blockquote {
    margin-inline: 0;
    padding-inline-start: 1rem;
    border-inline-start: 3px solid var(--color-primary);
    color: var(--color-text);
}
/* A pasted table must scroll inside the article rather than widen the page. */
.blog-post__body table { display: block; overflow-x: auto; max-width: 100%; }

.blog-post__tags {
    list-style: none;
    margin: 2rem 0 0;
    padding: 1.5rem 0 0;
    border-block-start: 1px solid var(--color-border);
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
}
.blog-post__tags a {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.9rem;
    border-radius: 999px;
    background: var(--color-surface);
    color: var(--color-text-soft);
    font-size: 0.8125rem;
    text-decoration: none;
}
.blog-post__tags a:hover {
    background: var(--color-primary);
    color: var(--color-on-primary);
    text-decoration: none;
}
.blog-post__tag-glyph {
    width: 0.8rem;
    height: 0.8rem;
    background: currentColor;
    -webkit-mask: var(--onyx-tag) center / contain no-repeat;
    mask: var(--onyx-tag) center / contain no-repeat;
}

.blog-post__aside { display: grid; gap: 1rem; align-content: start; }

.blog-post__aside-title {
    margin: 0 0 0.25rem;
    font-size: 1.125rem;
    font-weight: 700;
}

.blog-aside-card {
    display: grid;
    grid-template-columns: 5rem minmax(0, 1fr);
    gap: 0.9rem;
    align-items: center;
    padding: 0.75rem;
    border-radius: 10px;
    background: var(--color-surface);
    text-decoration: none;
    transition: box-shadow var(--transition);
}
.blog-aside-card:hover { box-shadow: var(--shadow); text-decoration: none; }

.blog-aside-card__media {
    display: block;
    aspect-ratio: 1;
    border-radius: 8px;
    overflow: hidden;
    background: var(--color-bg);
}
.blog-aside-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

.blog-aside-card__body { display: grid; gap: 0.35rem; }
.blog-aside-card__date {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.75rem;
    color: var(--color-text-faint);
}
.blog-aside-card__title {
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1.6;
    color: var(--color-text);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.blog-aside-card:hover .blog-aside-card__title { color: var(--color-primary); }

@media (max-width: 767px) {
    .blog-post__title { font-size: 1.375rem; }
    .blog-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---- the comment thread ------------------------------------------------- */
/* Measured off the reference's article foot: a hairline above the block, the
   thread, then a bordered textarea with the submit sitting at its inline end. */

.blog-comments {
    margin-block-start: 2.5rem;
    padding-block-start: 2rem;
    border-block-start: 1px solid var(--color-border);
}

.blog-comments__title {
    margin: 0 0 1.25rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.125rem;
    font-weight: 700;
}
.blog-comments__count {
    min-inline-size: 1.5rem;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: var(--color-surface);
    color: var(--color-text-soft);
    font-size: 0.8125rem;
    font-weight: 400;
    text-align: center;
}

.blog-comments__list {
    list-style: none;
    margin: 0 0 1.75rem;
    padding: 0;
    display: grid;
    gap: 1rem;
}

.blog-comment {
    display: grid;
    grid-template-columns: 2.5rem minmax(0, 1fr);
    gap: 0.85rem;
    align-items: start;
}

/* No customer avatars on this platform, so the author's initial stands in. */
.blog-comment__avatar {
    inline-size: 2.5rem;
    block-size: 2.5rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--color-primary-tint);
    color: var(--color-primary-dark);
    font-weight: 700;
}

.blog-comment__body {
    padding: 0.85rem 1rem;
    border-radius: 10px;
    background: var(--color-surface);
}

.blog-comment__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.75rem;
    margin: 0 0 0.35rem;
}
.blog-comment__author { font-weight: 700; font-size: 0.9375rem; }
.blog-comment__date { font-size: 0.75rem; color: var(--color-text-faint); }

/* Shopper-written prose: wrap long words rather than let one unbroken string
   widen the article. */
.blog-comment__text {
    margin: 0;
    font-size: 0.9375rem;
    line-height: 1.8;
    color: var(--color-text-soft);
    overflow-wrap: anywhere;
    white-space: pre-line;
}

.blog-comments__empty {
    margin: 0 0 1.75rem;
    color: var(--color-text-faint);
    font-size: 0.9375rem;
}

/* ---- the form ----------------------------------------------------------- */

.blog-comments__form { display: grid; gap: 0.75rem; }

.blog-comments__input {
    inline-size: 100%;
    padding: 0.9rem 1rem;
    border: 1px solid var(--color-border);
    border-radius: 8px;
    background: var(--color-bg);
    color: var(--color-text);
    font: inherit;
    font-size: 0.9375rem;
    line-height: 1.7;
    resize: vertical;
}
.blog-comments__input:focus {
    outline: none;
    border-color: var(--color-primary);
}
.blog-comments__input::placeholder { color: var(--color-text-faint); }

/* The reference puts the button at the inline end under the box. */
.blog-comments__submit { justify-self: end; min-inline-size: 8rem; }

.blog-comments__status {
    margin: 0;
    font-size: 0.875rem;
    color: var(--color-danger);
}
.blog-comments__status[hidden] { display: none; }

.blog-comments__signin {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.15rem 1.25rem;
    border-radius: 10px;
    background: var(--color-surface);
}
.blog-comments__signin p { margin: 0; color: var(--color-text-soft); font-size: 0.9375rem; }

/* ===== onyx testimonials: the customer-voices band ===== */
/* Measured off the reference:
     card    ~400 wide, radius 10, on --color-surface, ~28px padding
     quote   a large glyph at the top inline END, faint, decorative
     text    15px/1.9, start-aligned, three lines then ellipsis
     who     avatar 44px, name 15px/600, stars beneath the name
     rail    three in view, 24px between, progress line, "view all" below
   The quote sits opposite the author block — end-top against start-bottom —
   and mirrors with direction, which is why it is an inset-inline-end rather
   than a right. */

.block--testimonials[hidden] { display: none; }

custom-falak-testimonial-card { display: block; height: 100%; }

.testimonial-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    height: 100%;
    padding: 1.75rem;
    border-radius: 10px;
    background: var(--color-surface);
    overflow: hidden;
    /* The theme's older .testimonial-card — from the grid this block used to
       render — paints a bordered white box with a shadow. Both are cleared
       here rather than edited there, because that rule still dresses the same
       class anywhere else it is used. */
    border: 0;
    box-shadow: none;
}
/* Same reason: the old rule lifts and outlines the card on hover, which the
   reference's flat panel does not do. */
.block--testimonials .testimonial-card:hover {
    border-color: transparent;
    box-shadow: none;
    transform: none;
}

.testimonial-card__quote {
    position: absolute;
    inset-block-start: 0.9rem;
    inset-inline-end: 1.25rem;
    inline-size: 2.5rem;
    block-size: 2.5rem;
    background: var(--color-border);
    -webkit-mask: var(--onyx-quote) center / contain no-repeat;
    mask: var(--onyx-quote) center / contain no-repeat;
    pointer-events: none;
}

.testimonial-card__text {
    margin: 0;
    /* Clear of the glyph, so a long first line does not run under it. */
    padding-inline-end: 2rem;
    font-size: 0.9375rem;
    line-height: 1.9;
    color: var(--color-text-soft);
    /* Three lines, then ellipsis — the cards in a row have to end level, and
       a review is free text with no length anyone controls. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Pushed to the foot so the author line agrees across a row of cards whose
   quotes run to different lengths. */
.testimonial-card__who {
    margin-block-start: auto;
    display: flex;
    align-items: center;
    gap: 0.85rem;
}

.testimonial-card__avatar {
    inline-size: 2.75rem;
    block-size: 2.75rem;
    flex: none;
    border-radius: 50%;
    object-fit: cover;
    background: var(--color-bg);
}
.testimonial-card__avatar--initial {
    display: grid;
    place-items: center;
    background: var(--color-primary-tint);
    color: var(--color-primary-dark);
    font-weight: 700;
}

.testimonial-card__meta { display: grid; gap: 0.2rem; }
.testimonial-card__name { font-size: 0.9375rem; font-weight: 600; color: var(--color-text); }

/* The SDK's stars, tightened to the size this card uses. */
.testimonial-card__stars { --f-rating-size: 0.9rem; line-height: 1; }
.testimonial-card__stars .f-rating__count { display: none; }

/* THE CARD IS THE SLIDE. <falak-slider> puts .f-slider__slide on each child of
   its items slot, which here is <custom-falak-testimonial-card> itself — so a
   `.f-slider__slide > *` rule reaches the card's own parts, and the width:100%
   it was given stretched the absolutely-positioned quote glyph across the
   whole card. The card already carries flex + height:100%, so the slide needs
   nothing beyond being allowed to stretch. */
.testimonials__slider .f-slider__slide { align-self: stretch; }

:root {
    --onyx-quote: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M10 7H6.5A2.5 2.5 0 0 0 4 9.5V12h3.5v5H4v-2h1.5v-1.5H4V9.5A2.5 2.5 0 0 1 6.5 7H10zm10 0h-3.5A2.5 2.5 0 0 0 14 9.5V12h3.5v5H14v-2h1.5v-1.5H14V9.5A2.5 2.5 0 0 1 16.5 7H20z'/%3E%3C/svg%3E");
}


/* ==================================================== quick-add dialog (onyx)

   Onyx's own layout for the SDK's "choose options" dialog. Everything here is
   this theme's, written below the generated SDK block so it overrides the
   defaults without editing them — other themes keep the SDK's own single
   column look.

   The dialog's markup is a flat pair (the picture and the name/price together,
   then the form), so `display: contents` on that wrapper promotes the image and
   the meta to grid items and lets one grid place all three: picture down the
   side, name/price and choices stacked beside it.
   ------------------------------------------------------------------------- */

.f-quick-add .f-modal__body {
    /* Narrower than the SDK's `md` slot allows to grow: this is a short list of
       choices, and a wider box just added empty space around it. */
    max-inline-size: 40rem;
    display: grid;
    grid-template-columns: 12.5rem minmax(0, 1fr);
    grid-template-areas:
        "head  head"
        "media meta"
        "media form";
    grid-template-rows: auto auto 1fr;
    column-gap: 1.35rem;
    align-items: start;
}

.f-quick-add .f-modal__header { grid-area: head; }

/* The wrapper itself lays nothing out; its two children are the grid items. */
.f-quick-add .f-quick-add__product { display: contents; }

.f-quick-add .f-quick-add__image {
    grid-area: media;
    /* A square 200x200 box, pinned to the top of its column rather than
       stretched down it. Filling the full height made the render 200x300 and
       cropped the photo to a portrait it was never shot as; a fixed square
       shows it the way the card does, and the room left under it is the price
       of that. `cover` still crops rather than distorts. */
    align-self: start;
    inline-size: 12.5rem;
    block-size: 12.5rem;
    border-radius: var(--radius);
    object-fit: cover;
}

.f-quick-add .f-quick-add__meta {
    grid-area: meta;
    gap: 0.2rem;
    margin-block-end: 1.1rem;
    padding-block-end: 0.9rem;
    border-block-end: 1px solid var(--color-border);
}

.f-quick-add .f-quick-add__name {
    font-size: 1.05rem;
    line-height: 1.4;
    /* A long name is the one thing that can drive the dialog taller than the
       photo beside it. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.f-quick-add .f-quick-add__price { font-size: 1.3rem; font-weight: 700; }
.f-quick-add .f-quick-add__form { grid-area: form; }

/*
   The missing-group message, once.

   reportValidity() flags the group itself — the hint beside its name turns
   danger-coloured and bold — and then prints the same sentence again under the
   pills, so "Choose color" appeared twice. Kept in the DOM with its role=alert,
   and out of sight, so a screen reader still hears it exactly once.
*/
.f-options__error {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/*
   Phone: the photo becomes a thumbnail beside the name, and the choices take
   the FULL width underneath. Keeping them in a narrow second column left them
   cramped against a tall strip of image with dead space beside it.
*/
@media (max-width: 40rem) {
    .f-quick-add .f-modal__body {
        grid-template-columns: 5rem minmax(0, 1fr);
        grid-template-areas:
            "head  head"
            "media meta"
            "form  form";
        column-gap: 0.9rem;
    }

    .f-quick-add .f-quick-add__image {
        align-self: start;
        block-size: 5rem;
        min-block-size: 0;
    }

    .f-quick-add .f-quick-add__meta { margin-block-end: 0.9rem; padding-block-end: 0.7rem; }
    .f-quick-add .f-quick-add__name { font-size: 0.95rem; }
    .f-quick-add .f-quick-add__price { font-size: 1.1rem; }

    /* Side by side at this width leaves the button too narrow to read. */
    .f-quick-add .f-quick-add__actions { flex-direction: column; }
}

/* =================================================== quick-view dialog (onyx)

   The card's eye icon opens the product here instead of leaving the listing:
   the gallery down one side, a short buy box down the other. Built by
   <custom-falak-quick-view> in app.js.

   Everything is written in LOGICAL properties, and the two columns are placed
   in DOM order — so the picture sits on the left in English and on the right in
   Arabic without a second rule, which is exactly how the reference behaves.

   Sized against the DIALOG, not the viewport: this is a preview, and a box that
   fills the screen has stopped being one. 64rem wide with a stage that is never
   taller than 60% of the viewport keeps the add-to-cart on screen on a laptop,
   which is the whole point of not sending the shopper to the page.
   ------------------------------------------------------------------------- */

.f-quick-view .f-modal__body {
    max-inline-size: 64rem;
    padding: 0;
    overflow: hidden;
}

/*
   The header is only ever the close button here — no title. Lifting it out of
   the flow and into the corner is what lets the picture run to the dialog's top
   edge; left in place it pushed both columns down by a row of empty space.
*/
.f-quick-view .f-modal__header {
    position: absolute;
    inset-block-start: 0.75rem;
    inset-inline-end: 0.75rem;
    z-index: 4;
}

.f-quick-view .f-modal__close {
    inline-size: 2.4rem;
    block-size: 2.4rem;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    color: var(--color-text-soft);
    font-size: 1.5rem;
    transition: color 0.2s ease, border-color 0.2s ease;
}

.f-quick-view .f-modal__close:hover {
    background: var(--color-bg);
    color: var(--color-primary);
    border-color: var(--color-primary);
}

/* The dialog and its skeleton stacked in one cell; the skeleton on top until
   the dialog is ready, then faded off and removed. */
.qv-shell { display: grid; }

.qv-shell > .qv { grid-area: 1 / 1; }

.qv {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: stretch;
    min-block-size: 22rem;
}

.qv--loading {
    position: relative;
    z-index: 3;
    background: var(--color-bg);
    transition: opacity 0.25s ease;
}

.qv--loading.is-done { opacity: 0; pointer-events: none; }

/* ------------------------------------------------------------------ media */

/*
   The gallery is a padded column: a tinted, rounded frame holding the photo,
   and a strip of thumbs under it. The frame is SQUARE — the one shape that
   treats portrait, square and landscape photographs all decently with
   `contain` — but capped, so on a short laptop screen it gives up height
   before it pushes the thumbs out of the dialog.
*/
.qv__media {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1rem;
    min-inline-size: 0;
    background: var(--color-bg);
}

/* Fills the whole column, however tall the buy box beside it makes the
   dialog — a fixed square left empty bands around the picture. */
.qv__frame {
    position: relative;
    flex: 1 1 auto;
    inline-size: 100%;
    min-block-size: 20rem;
    border-radius: var(--radius);
    background: var(--color-surface);
    overflow: hidden;
}

.qv__stage {
    position: absolute;
    inset: 0;
    overflow: hidden;
}

.qv__slide {
    position: absolute;
    inset: 0;
    margin: 0;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.qv__slide.is-active { opacity: 1; }

/*
   Pinned to the slide rather than laid out inside it — a centring grid sizes
   its row to the media's intrinsic height and a portrait clip overflowed the
   stage. `cover`, so the picture always fills the frame edge to edge whatever
   its own shape — letterboxing left blank bands beside it.
*/
.qv__slide img,
.qv__slide video {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

.qv__slide--empty { background: var(--color-surface); opacity: 1; }

.qv__nav {
    position: absolute;
    inset-block-start: 50%;
    translate: 0 -50%;
    z-index: 2;
    inline-size: 2.4rem;
    block-size: 2.4rem;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--color-bg);
    color: var(--color-text);
    box-shadow: var(--shadow-icon-disc);
    cursor: pointer;
    transition: color 0.2s ease, box-shadow 0.2s ease;
}

.qv__nav:hover { color: var(--color-primary); box-shadow: var(--shadow-icon-disc-hover); }

.qv__nav--prev { inset-inline-start: 0.75rem; }
.qv__nav--next { inset-inline-end: 0.75rem; }

/* The chevrons are drawn for LTR; in Arabic "previous" sits on the right and
   must point right. */
[dir="rtl"] .qv__nav svg { scale: -1 1; }

.qv__badge {
    position: absolute;
    inset-block-start: 0.75rem;
    inset-inline-start: 0.75rem;
    z-index: 2;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    background: var(--color-sale, var(--color-danger));
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1.4;
    font-variant-numeric: tabular-nums;
}

.qv__counter {
    position: absolute;
    inset-block-end: 0.75rem;
    inset-inline-end: 0.75rem;
    z-index: 2;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    background: rgba(16, 22, 49, 0.6);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.5;
    font-variant-numeric: tabular-nums;
}

.qv__thumbs {
    display: flex;
    gap: 0.5rem;
    overflow-x: auto;
    scrollbar-width: none;
    /* Room for the active tile's ring, which the scroller would clip. */
    padding: 2px;
}

.qv__thumbs::-webkit-scrollbar { display: none; }

.qv__thumb {
    flex: 0 0 auto;
    inline-size: 3.75rem;
    block-size: 3.75rem;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.qv__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }

.qv__thumb:hover { border-color: var(--color-primary); }

.qv__thumb.is-active {
    border-color: var(--color-primary-dark);
    box-shadow: 0 0 0 1px var(--color-primary-dark);
}

/* ------------------------------------------------------------------- info */

/*
   A scrolling body over a pinned footer: however many option groups the
   product has, the stepper and the add button never leave the dialog.
*/
.qv__info {
    display: flex;
    flex-direction: column;
    min-block-size: 0;
    max-block-size: min(80vh, 40rem);
    border-inline-start: 1px solid var(--color-border);
    background: var(--color-bg);
}

.qv__body {
    flex: 1 1 auto;
    min-block-size: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1.25rem 1.5rem 1.5rem;
}

.qv__body > * { margin-block: 0; }

/*
   Category on the start edge; wishlist, share, a hairline and then the
   dialog's own close button on the end edge. The close button is the modal's
   and is positioned absolutely onto this row (see .f-modal__header below), so
   the row keeps room for it.
*/
.qv__tools {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    padding-inline-end: 3rem;
    min-block-size: 2.25rem;
}

.qv__tools::after {
    content: "";
    inline-size: 1px;
    block-size: 1.25rem;
    margin-inline-start: 0.35rem;
    background: var(--color-border);
}

.qv__eyebrow {
    margin-inline-end: auto;
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.8rem;
    color: var(--color-text-faint);
    text-decoration: none;
}

a.qv__eyebrow:hover { color: var(--color-primary); }

.qv__tool { position: relative; display: block; }

/* One shape for both, whether the button is the theme's own (share) or the
   wishlist component's, which takes the class through `button-class`. */
.qv__tool-btn {
    inline-size: 2.25rem;
    block-size: 2.25rem;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--color-text);
    cursor: pointer;
    transition: color 0.2s ease, background 0.2s ease;
}

.qv__tool-btn:hover { color: var(--color-primary); background: var(--color-surface); }

.qv__tool-btn[aria-pressed="true"],
.qv__tool .f-wishlist-btn.is-added { color: var(--color-danger); }

/* The share row, parked as a popover under its trigger. The component still
   renders its own list; this only decides when it is on screen. */
.qv__share-sheet {
    position: absolute;
    inset-block-start: calc(100% + 0.5rem);
    inset-inline-end: 0;
    z-index: 3;
    /* Without max-content the absolutely positioned sheet shrink-fits inside
       its 2.25rem trigger and the networks wrap into a vertical strip. */
    inline-size: max-content;
    padding: 0.45rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    box-shadow: var(--shadow);
    opacity: 0;
    visibility: hidden;
    translate: 0 -6px;
    transition: opacity 0.2s ease, translate 0.2s ease, visibility 0.2s;
}

.qv__share.is-open .qv__share-sheet { opacity: 1; visibility: visible; translate: none; }

.qv__share-sheet .f-social__list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    gap: 0.3rem;
}

.qv__share-sheet .f-social__link {
    inline-size: 2.1rem;
    block-size: 2.1rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    color: var(--color-text-soft);
    transition: background 0.2s ease, color 0.2s ease;
}

.qv__share-sheet .f-social__link:hover {
    background: var(--color-primary-tint);
    color: var(--color-primary-dark);
}

.qv__title {
    font-size: 1.6rem;
    line-height: 1.3;
    font-weight: 700;
    color: var(--color-text);
    text-wrap: balance;
}

.qv__title a { color: inherit; text-decoration: none; }
.qv__title a:hover { color: var(--color-primary); }

.qv__price {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.qv__amount {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--color-primary-dark);
    font-variant-numeric: tabular-nums;
}

.qv__was {
    font-size: 0.95rem;
    color: var(--color-text-faint);
    font-variant-numeric: tabular-nums;
}

.qv__was[hidden] { display: none; }

.qv__rating {
    display: inline-flex;
    align-items: center;
    inline-size: fit-content;
    text-decoration: none;
}

/*
   Stock · SKU · VAT on one quiet line. It carries the divider because it is
   the one row that is always there, whichever of the rest a product has.
*/
.qv__status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0;
    padding-block-end: 1rem;
    border-block-end: 1px solid var(--color-border);
    font-size: 0.8rem;
    color: var(--color-text-faint);
}

.qv__status > * + *::before {
    content: "·";
    margin-inline: 0.5rem;
    color: var(--color-text-faint);
}

.qv__status > [hidden] { display: none; }

.qv__stock {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 600;
    color: var(--color-success);
}

/* Always the line's first item, so its ::before is free for the dot. */
.qv__stock::before {
    content: "";
    inline-size: 0.45rem;
    block-size: 0.45rem;
    border-radius: 50%;
    background: currentColor;
}

.qv__stock--out { color: var(--color-danger); }

.qv__options { display: block; }

/* ----------------------------------------------------------------- footer */

.qv__footer {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1rem 1.5rem 1.15rem;
    border-block-start: 1px solid var(--color-border);
    background: var(--color-bg);
}

/* The stepper is only ever as wide as its three cells; the button takes the
   rest. */
.qv__actions {
    display: flex;
    align-items: stretch;
    gap: 0.75rem;
}

.qv__add { flex: 1 1 auto; min-inline-size: 0; }

/* Skinned through its inner button only, so the component keeps every one of
   its own states (busy, sold out, "choose options"). */
.qv__add-btn {
    inline-size: 100%;
    min-block-size: 3rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
}

.qv__qty { flex: 0 0 auto; display: flex; align-items: stretch; }
.qv__qty .f-qty { block-size: 100%; border-radius: var(--radius-sm); background: var(--color-bg); }
.qv__qty .f-qty__step { inline-size: 2.6rem; block-size: 100%; color: var(--color-text); }
/* One outlined box, no dividers between the cells — the reference's stepper. */
.qv__qty .f-qty__input { inline-size: 2.25rem; block-size: 100%; border-inline: 0; font-weight: 600; }

.qv__notify { display: block; }

.qv__foot-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    font-size: 0.8rem;
}

.qv__summary {
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-text-faint);
}

.qv__details {
    flex: 0 0 auto;
    margin-inline-start: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-weight: 600;
    color: var(--color-text);
    text-decoration: none;
}

.qv__details:hover { color: var(--color-primary); }

[dir="rtl"] .qv__arrow { scale: -1 1; }

/* ---------------------------------------------------- loading and failure */

/* Centred over the frame; the disc keeps it readable on any photograph. */
.qv__spinner {
    position: absolute;
    inset: 0;
    z-index: 2;
    inline-size: 2.5rem;
    block-size: 2.5rem;
    margin: auto;
    border: 3px solid var(--color-border);
    border-block-start-color: var(--color-primary);
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-bg) 80%, transparent);
    animation: f-spin 0.7s linear infinite;
}

/* The skeleton's placeholder bars, in the same shimmer as the card skeletons. */
.qv__bone {
    display: block;
    block-size: 0.9rem;
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--color-text) 7%, transparent) 25%,
        color-mix(in srgb, var(--color-text) 13%, transparent) 37%,
        color-mix(in srgb, var(--color-text) 7%, transparent) 63%);
    background-size: 400% 100%;
    animation: f-shimmer 1.4s ease infinite;
}

.qv__bone--fill { position: absolute; inset: 0; block-size: auto; border-radius: 0; }
.qv__bone--thumb { flex: 0 0 auto; inline-size: 3.75rem; block-size: 3.75rem; }
.qv__bone--eyebrow { inline-size: 30%; block-size: 0.75rem; }
.qv__bone--title { inline-size: 80%; block-size: 1.5rem; }
.qv__bone--price { inline-size: 35%; block-size: 1.6rem; margin-block-end: 0.5rem; }
.qv__bone--line { inline-size: 100%; }
.qv__bone--short { inline-size: 60%; }
.qv__bone--qty { flex: 0 0 auto; inline-size: 7.5rem; block-size: 3rem; }
.qv__bone--button { flex: 1 1 auto; block-size: 3rem; }

.qv__failed {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 3rem 1.5rem;
    text-align: center;
    color: var(--color-text-soft);
}

/* ---------------------------------------------------------------- desktop */

/*
   The close button joins the tools row: borderless, at the row's end edge,
   past the hairline. Desktop only — on a phone it stays the disc on the
   picture's corner.
*/
@media (min-width: 48.01rem) {
    .f-quick-view .f-modal__header {
        inset-block-start: 1.25rem;
        inset-inline-end: 1.25rem;
    }

    .f-quick-view .f-modal__close,
    .f-quick-view .f-modal__close:hover {
        inline-size: 2.25rem;
        block-size: 2.25rem;
        border-color: transparent;
        background: transparent;
    }

    .f-quick-view .f-modal__close { color: var(--color-text); }
    .f-quick-view .f-modal__close:hover { color: var(--color-primary); }
}

/* ------------------------------------------------------------------ phone */

/*
   One column, picture first, and the whole dialog scrolls as one — two
   independently scrolling columns on a 380px screen is a trap. The desktop
   additions that only cost height here (thumbs, the hairline in the tools
   row) are dropped.
*/
@media (max-width: 48rem) {
    .f-quick-view .f-modal__body { max-inline-size: 100%; }

    .qv { grid-template-columns: minmax(0, 1fr); min-block-size: 0; }

    .qv__media { padding: 0; gap: 0; }

    .qv__frame { flex: none; min-block-size: 0; aspect-ratio: 1 / 1; max-block-size: 50vh; border-radius: 0; }

    .qv__thumbs { display: none; }

    .qv__info { max-block-size: none; border-inline-start: 0; }

    .qv__body { overflow: visible; padding: 1.25rem 1.25rem 0.5rem; }

    /* The close button is up on the picture at this width. */
    .qv__tools { padding-inline-end: 0; }
    .qv__tools::after { content: none; }

    .qv__title { font-size: 1.1rem; }
    .qv__amount { font-size: 1.25rem; }

    .qv__footer { border-block-start: 0; padding: 0.5rem 1.25rem 1.25rem; }

    /* Side by side at this width leaves the button too narrow to read. */
    .qv__actions { flex-direction: column; }
    .qv__qty { align-self: flex-start; }

    /* Stacked, the row no longer lends the stepper the button's height. */
    .qv__qty .f-qty__step,
    .qv__qty .f-qty__input { block-size: 2.75rem; }
}

/* A shopper who asked for less motion gets the slide swapped, not faded. */
@media (prefers-reduced-motion: reduce) {
    .qv__slide { transition: none; }
    .qv__bone { animation: none; }
}


/* ============================================== video-commerce viewer (nova)

   The wall's own dialog, built by <custom-falak-video-view> in app.js: the clip
   full-bleed, with the name, the price, the variant picker and the add laid
   over its foot. The quick-view dialog above is unchanged and still serves
   every other card in the theme.

   The shape is 9:16 because the clips are — a merchant filming a garment films
   it in portrait, and a reel letterboxed into a landscape dialog is two black
   bars and a thin strip of product. The panel is therefore sized off the
   VIEWPORT HEIGHT and the width derived from it, which is the only order that
   guarantees the whole clip is on screen: sizing by width instead produces a
   box taller than the window on any laptop, and the add-to-cart is the part
   that falls off the bottom.

   Everything is written in logical properties, so the corner controls swap
   sides with the document's direction without a second rule.
   ------------------------------------------------------------------------- */

/* Darker than the library's default scrim. The dialog is a lit rectangle in a
   dark room here, not a card floating over a page the shopper is still meant to
   read. */
.f-video-view .f-modal__overlay { background: rgba(6, 8, 10, 0.82); }

.f-video-view .f-modal__body {
    /* The one measurement everything else is derived from. 86vh leaves the
       overlay visible at the top and bottom, so the dialog still reads as a
       dialog; 45rem stops it growing absurdly tall on a very tall monitor. */
    --vv-block: min(86vh, 45rem);

    block-size: var(--vv-block);
    inline-size: min(calc(var(--vv-block) * 9 / 16), 100%);
    /* The width modifier from the `width` attribute would otherwise cap this
       at its own value and break the ratio. */
    max-inline-size: none;
    padding: 0;
    overflow: hidden;
    background: #0a0b0d;
    border-radius: var(--radius-lg);
}

/*
   The header is only ever the close button here — no title. Lifted out of the
   flow and into the corner, exactly as the quick view does it, so the clip runs
   to the dialog's top edge instead of starting a row down.

   Restyling the LIBRARY's button rather than drawing a second one is what keeps
   Escape, the backdrop click and the focus return working: turning the
   library's × off (is-closable="false") turns all three off with it.
*/
.f-video-view .f-modal__header {
    position: absolute;
    inset-block-start: 0.85rem;
    /* End side, which is the quick view's corner too — the physical LEFT on
       this theme's Arabic pages, where the reference design puts it. */
    inset-inline-end: 0.85rem;
    z-index: 4;
}

/*
   A frosted white disc with dark ink, for both corner controls.

   White-on-glass rather than the theme's surface token: these sit on a moving
   photograph whose brightness is unknown and changes frame to frame, and a
   translucent white disc is the one treatment that stays legible over both a
   pale studio backdrop and a night shot. --color-on-white is the ink that
   deliberately does NOT follow the dark theme, for exactly this reason.

   The shadow is not decoration, it is the disc's only edge on a WHITE frame —
   a garment shot against a studio backdrop opens with the corner over plain
   white, and a white disc on white left the glyph floating with no control
   around it. On a dark frame it is invisible and the disc provides its own
   contrast, so one rule covers both.
*/
.f-video-view .f-modal__close,
.vv__chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.4rem;
    block-size: 2.4rem;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.88);
    color: var(--color-on-white);
    box-shadow: 0 2px 12px rgba(4, 6, 8, 0.35);
    cursor: pointer;
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    transition: background var(--transition), color var(--transition);
}

.f-video-view .f-modal__close { font-size: 1.45rem; line-height: 1; }

.f-video-view .f-modal__close:hover,
.vv__chip:hover {
    background: #fff;
    color: var(--color-primary-dark);
}

.vv {
    position: relative;
    block-size: 100%;
    overflow: hidden;
}

/* ------------------------------------------------------------------- reel */

/*
   The wall, swipeable.

   On a phone the slides are a full-height vertical scroll-snap column: a swipe
   up is the next product, exactly the gesture every product reel has trained
   people to use, and a shopper who came to browse video never has to close the
   dialog to see the next clip. app.js gives only the slide being watched — and
   its two neighbours — a source, so a reel of twelve is still one download.

   On a larger screen the reel collapses to the active slide (below): a
   full-height snap column is a thumb gesture, and a pointer has the wall itself
   behind the dialog to go back to.
*/
.vv__reel {
    block-size: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    scroll-snap-type: y mandatory;
    /* The page behind must not start scrolling when the reel hits its end. */
    overscroll-behavior-y: contain;
    scrollbar-width: none;
}

.vv__reel::-webkit-scrollbar { display: none; }

.vv__slide {
    position: relative;
    block-size: 100%;
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

/*
   One at a time above the phone breakpoint.

   `display: none` rather than a transform or a height of zero: a hidden slide
   must not be reachable by the tab key, must not contribute a scroll position,
   and — the reason it matters here — its <falak-product-options> must not be
   found by anything looking for a picker, which is what would let one slide's
   variant end up on another slide's add-to-cart.
*/
@media (min-width: 48.0625rem) {
    .vv__reel { overflow: hidden; scroll-snap-type: none; }
    .vv__slide { display: none; }
    .vv__slide.is-active { display: block; }
}


/* ------------------------------------------------------------------- stage */

/* The stage owns the dark ground. It used to sit on .vv__video, where it was an
   OPAQUE layer painted over the poster beneath — the clip has to be transparent
   until it has frames for the poster to be worth having at all. */
.vv__stage {
    position: absolute;
    inset: 0;
    background: #0a0b0d;
}

/*
   `cover`, not `contain`. A merchant's clip is not reliably 9:16 — phones shoot
   portrait, but a re-encode or a crop can arrive at 3:4 or 1:1 — and `contain`
   answers that with pillarboxes, which read as a broken player. Cover fills the
   panel in every case, and the foot's scrim is deep enough that what it takes
   off the bottom is the part being covered by the buy box anyway.
*/
/* Stacked in the same box: the poster underneath, the clip over it. Both cover,
   so they crop identically and the swap from one to the other is invisible. */
.vv__poster,
.vv__video {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

/* Transparent on purpose — see above. A background here hides the poster. */
.vv__video { background: transparent; }

/* No clip and no photograph: a flat ground rather than a broken-image glyph. */
.vv__placeholder {
    position: absolute;
    inset: 0;
    background: #1b1d21;
}

/*
   Buffering.

   Laid over the poster, not instead of it: the shopper keeps seeing the product
   while the file arrives, and the spinner is only saying which of the two
   states a motionless frame is in. app.js sets `data-loading` on the stage in
   the markup itself, so this is on screen in the frame the dialog opens, and
   clears it on the first moving frame.

   `pointer-events: none` because the speaker sits above this and has to stay
   clickable while the clip is still loading — unmuting is often exactly what a
   shopper does during that wait.
*/
.vv__loader {
    position: absolute;
    inset: 0;
    display: none;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    /*
       ABOVE the scrim, which is its sibling and comes after it in the markup.
       Without this the gradient painted straight over the spinner: the scrim
       covers the bottom 72% of the stage and the spinner is centred inside
       that, so it sat under about 70% black and dimmed to a grey smudge
       nobody could see. It reads as "there is no loader".
    */
    z-index: 1;
}

.vv__stage[data-loading] .vv__loader { display: flex; }

/*
   The clip did not arrive.

   Shown INSTEAD of the spinner, never beside it: those two say opposite things
   and a shopper looking at both learns nothing. The buy box underneath is
   untouched — a video that will not play is no reason to stop someone buying
   the product — so this only covers the picture.
*/
.vv__lost {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.9rem;
    padding: 1.5rem;
    text-align: center;
    color: #fff;
}

.vv__slide[data-vv-failed] .vv__lost { display: flex; }

/* Both belong to a clip that is not coming: the frozen frame it never had, and
   a speaker for audio that does not exist. */
.vv__slide[data-vv-failed] .vv__video,
.vv__slide[data-vv-failed] .vv__loader { display: none; }

.vv__lost-text {
    margin: 0;
    font-size: var(--fs-meta);
    color: rgba(255, 255, 255, 0.82);
    max-inline-size: 18rem;
}

/* White on the clip's own dark ground rather than the theme's outline skin,
   which is drawn for a light surface and reads as a smudge here. */
.vv__lost-retry {
    border-color: rgba(255, 255, 255, 0.55);
    color: #fff;
    background: rgba(255, 255, 255, 0.08);
}

.vv__lost-retry:hover {
    border-color: #fff;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
}

/*
   A ring with a dark translucent middle, rather than a bare ring: the poster
   behind it is the merchant's photograph and may be a white studio backdrop or
   a night shot, and a white ring alone disappears into the first of those.
*/
.vv__loader::after {
    content: "";
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border: 3px solid rgba(255, 255, 255, 0.45);
    border-block-start-color: #fff;
    border-radius: 50%;
    background: rgba(6, 8, 10, 0.45);
    box-shadow: 0 2px 16px rgba(4, 6, 8, 0.55);
    animation: nova-spin 0.75s linear infinite;
}

/*
   The gradient the foot is read against.

   A separate element rather than a background on .vv__foot, because the foot is
   only as tall as its contents and the fade has to start well above them — a
   gradient that begins at the product name puts a hard edge across the middle
   of the clip. Two stops rather than one: a linear fade to transparent looks
   grey over the whole lower half, while a fast rise to 72% and a slow tail is
   read as light falling off.
*/
.vv__scrim {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    block-size: 72%;
    background: linear-gradient(
        to top,
        rgba(4, 6, 8, 0.94) 0%,
        rgba(4, 6, 8, 0.72) 30%,
        rgba(4, 6, 8, 0) 100%
    );
    pointer-events: none;
}

.vv__chip { position: absolute; z-index: 4; }

/* The opposite corner from the close button, so the two never collide and the
   shopper's thumb reaching for one cannot dismiss the dialog with the other. */
.vv__chip--sound {
    inset-block-start: 0.85rem;
    inset-inline-start: 0.85rem;
}

/*
   The reel's arrows: mid-height on the OVERLAY, flanking the panel, pointer
   screens only. Below the breakpoint the next clip is a swipe away and two
   discs would just crowd the frame; above it the reel cannot scroll at all
   (only the active slide is drawn), and these are a mouse's one way from clip
   to clip. app.js disables the arrow with nothing left on its side, and here a
   disabled step disappears rather than greying out over the scrim.

   position: fixed is what gets them OUT of the dialog: they are rendered
   inside the panel, whose overflow:hidden (the corner radius clip) would
   swallow anything hung past its edge — fixed re-homes them to the viewport,
   which the full-screen modal already covers. The one thing that would break
   that is a transformed ancestor, and the body's f-rise entrance is exactly
   that for its 0.2s — so the arrows fade in only after it has finished.
*/
.vv__chip--step {
    display: none;
    position: fixed;
    inset-block-start: 50%;
    translate: 0 -50%;
    /* The panel's own width formula — --vv-block is inherited from the modal
       body above — so the arrows track the dialog's edge at every viewport
       instead of hugging the screen's. */
    --vv-panel: min(calc(var(--vv-block, 45rem) * 9 / 16), 100vw);
    animation: f-fade 0.18s ease 0.22s backwards;
}

@media (min-width: 48.0625rem) {
    .vv__chip--step { display: inline-flex; }
    .vv__chip--step:disabled { display: none; }
}

/* A 1rem breath from the panel's edge, but never pushed off a screen that is
   barely wider than the dialog. */
.vv__chip--prev { inset-inline-start: max(0.75rem, calc(50% - var(--vv-panel) / 2 - 3.4rem)); }
.vv__chip--next { inset-inline-end: max(0.75rem, calc(50% - var(--vv-panel) / 2 - 3.4rem)); }

/* One chevron, drawn pointing toward inline-start: the next arrow mirrors it,
   and RTL mirrors the pair again. */
.vv__chip--next svg,
[dir="rtl"] .vv__chip--prev svg { transform: scaleX(-1); }

[dir="rtl"] .vv__chip--next svg { transform: none; }

/*
   Tinted while the sound is ON.

   The clip always starts muted — a browser refuses to autoplay audio — so the
   speaker is the one control whose state the shopper has actually chosen, and
   it has to be readable at a glance from across the panel. aria-pressed is both
   the accessible state and the styling hook, so there is no second copy of it
   to fall out of step.
*/
.vv__chip--sound[aria-pressed="true"] {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.vv__chip--sound[aria-pressed="true"]:hover {
    background: var(--color-primary-dark);
    color: var(--color-on-primary);
}

/* Before the record lands, when the viewer was opened from the bus with only an
   id and has nothing to paint yet. */
.vv__stage--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #14161a;
}

.vv__spinner {
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border: 2px solid rgba(255, 255, 255, 0.25);
    border-block-start-color: #fff;
    border-radius: 50%;
    animation: nova-spin 0.7s linear infinite;
}

@keyframes nova-spin { to { transform: rotate(360deg); } }

.vv__failed {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    block-size: 100%;
    padding: 2rem;
    text-align: center;
    color: #fff;
}

/* --------------------------------------------------------------- buy box */

.vv__foot {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 3;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 1.1rem;
    color: #fff;
}

.vv__name {
    font-size: var(--fs-lead);
    font-weight: 700;
    line-height: 1.35;
    color: #fff;
    text-decoration: none;
}

.vv__name:hover { text-decoration: underline; }

.vv__price {
    margin: 0;
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

.vv__amount { font-size: 1.15rem; font-weight: 700; color: #fff; }
.vv__was { font-size: 0.9rem; color: rgba(255, 255, 255, 0.65); }

.vv__buy {
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    margin-block-start: 0.5rem;
}

/*
   The picker gets its own opaque card.

   It is the one part of the foot a shopper has to READ rather than glance at —
   labels, values, which values are sold out — and white text over a moving
   picture is exactly the wrong surface for that. On its own ground the SDK's
   pills, swatches and <select> skins all apply unchanged, which is the other
   half of the reason: they are written for a page, not for a photograph.

   Capped and scrollable because the number of groups is the merchant's
   decision, not the theme's: four of them unrolled would push the add-to-cart
   off the bottom of the panel, and the add is the one thing that must never go.
*/
.vv__panel {
    background: var(--color-bg);
    color: var(--color-text);
    border-radius: var(--radius-lg);
    padding: 0.9rem 1rem;
    max-block-size: 32vh;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.vv__add { display: block; }
.vv__add-btn { inline-size: 100%; }

.vv__notify { display: block; }
.vv__notify .btn { inline-size: 100%; }

/*
   Edge to edge on a phone.

   The panel's whole point is that the clip is the screen; 1rem of overlay
   showing down each side of a 390px window is not a frame, it is a waste of the
   only thing there is. 100dvh rather than 100vh so the browser's collapsing
   address bar does not leave the add-to-cart under it.
*/
@media (max-width: 48rem) {
    .f-video-view .f-modal__wrapper { padding: 0; }

    .f-video-view .f-modal__body {
        inline-size: 100%;
        block-size: 100dvh;
        border-radius: 0;
    }

    /* Clear of a notch, and of the home indicator at the foot. */
    .f-video-view .f-modal__header {
        inset-block-start: max(0.85rem, env(safe-area-inset-top));
    }

    .vv__chip {
        inset-block-start: max(0.85rem, env(safe-area-inset-top));
    }

    .vv__foot {
        padding-block-end: max(1.1rem, env(safe-area-inset-bottom));
    }
}

/* Slowed rather than stopped. A spinner is the only thing telling the shopper
   the clip is still coming; removing the motion removes the message with it. */
@media (prefers-reduced-motion: reduce) {
    .vv__spinner,
    .vv__loader::after { animation-duration: 2s; }
}

/*
   ONYX ONLY — this theme's own dialog rules, out-specified for this one dialog.

   Further down this sheet Onyx caps every `.f-modal__body` at `100dvh - 4rem`
   and gives it `overflow: auto`, and pads `.f-modal__wrapper` by `2rem 1rem`.
   Both are right for an ordinary dialog and both are wrong for this one: the
   viewer IS the screen. Left alone they letterboxed the clip inside a scrolling
   box — measured at 361x788 in a 393x852 window, so the 9:16 panel came out at
   0.458 and the shopper could scroll the video away from under the buy box.

   Three class selectors against Onyx's two, so these win wherever they sit
   rather than depending on source order. Kept OUT of the block above, which is
   a straight copy of the same section in the other themes and stays that way so
   the next change to it can still be applied to all of them at once.
*/
.theme-onyx .f-video-view .f-modal__body {
    max-block-size: none;
    overflow: hidden;
}

@media (max-width: 48rem) {
    .theme-onyx .f-video-view .f-modal__wrapper { padding: 0; }
}


/* ============================================ overlay surfaces: own their ink

   Every surface that paints its own background must also state its own text
   colour, because two of them are rendered INSIDE the header — <falak-search>'s
   modal and the off-canvas drawer are children of .site-header in the DOM — and
   over the hero that header is `color: #fff`.

   Inheriting it made the search results white on the dialog's cream ground:
   contrast 1.11, product names completely invisible while the price beside them
   read fine (it sets its own colour). Stating the colour here fixes it for every
   dialog at once and, more to the point, means a dialog can be hosted anywhere
   in the document without its legibility depending on where.
   ------------------------------------------------------------------------- */

.f-modal__body { color: var(--color-text); }

/* The name is the only part of a search result that inherited; the price and
   the "was" price both name their own colour. Stated anyway, so the row does
   not depend on the modal rule above still being there. */
.f-search__name { color: var(--color-text); }

/* "View all results" used to be a bare text link on the dialog's cream, and a
   merchant whose brand is a light tan (this store's is #d4a574) got 2.0:1 out
   of `--color-primary` — below the 4.5:1 a text link needs — so it was repainted
   in `--color-primary-dark` here.
   The redesign makes it a filled pill instead: `--color-text` ground, #fff ink,
   stated in the search block above. That colour must NOT be overridden here —
   this rule carries the same (1,0,1) specificity and sits later in the file, so
   restoring it would paint brand-dark text on the dark pill. The contrast
   problem it solved belongs to the pill's own two colours now. */

/* ================================================== account: orders and nav */

/*
   An order number is one unbreakable 23-character token, and the row is a flex
   line: `#ORD202608301414527745` needed 216px in the 126px column left over
   after the status pill and the total, and — with nothing to break on and
   `overflow: visible` — simply PAINTED across them. The number ran underneath
   the pill on a phone.

   `anywhere` rather than `break-word`: break-word will not break a token that
   is alone on its line, which is exactly this case. The number keeps its full
   value and wraps instead of escaping, so nothing is truncated.
*/
.f-orders__number { overflow-wrap: anywhere; }

/*
   Below 560px the pill and the total drop to their own line rather than
   squeezing the number into a 126px column it has to wrap three times to fit.
   The row stays one card; only the arrangement changes.
*/
@media (max-width: 35rem) {
    .f-orders__row { flex-wrap: wrap; row-gap: 0.6rem; }
    .f-orders__main { flex: 1 0 100%; }
    .f-orders__total { margin-inline-start: auto; }
}

/*
   The account nav is a scrolling row of pills on a phone with its scrollbar
   deliberately hidden, so a chopped-off fourth item read as a layout bug rather
   than as "there is more this way". The same fade the header's own nav strip
   uses, which is where this pattern already lives in this stylesheet.
*/
@media (max-width: 899px) {
    /* `data-more` is set by app.js only while there is actually something
       further along to scroll to, so the last pill is never dimmed once the
       row has been scrolled to its end — and a nav whose items all fit is not
       faded at all. The gradient is physical, so RTL states its own: the
       overflow is off the LEFT edge when the row reads right-to-left. */
    .account-nav[data-more] {
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent);
        mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent);
    }

    [dir="rtl"] .account-nav[data-more] {
        -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 2.5rem), transparent);
        mask-image: linear-gradient(to left, #000 calc(100% - 2.5rem), transparent);
    }
}

/* ========================================================================
   ONYX CHROME
   ========================================================================

   Everything above this line is the shared base Onyx inherits from the 2026 /
   Nova lineage. This section is Onyx's own, and it is deliberately LAST in the
   file: it restyles the shared chrome by source order rather than by forking
   it, so the base stays diffable against the other themes.

   The design it implements, measured off the reference storefront:

     header      two stacked rows — a 64px white control row (search, account,
                 language | centred logo | locale pill, cart) and a 53px cream
                 category strip. Solid white always; no transparent-over-hero
                 state, no light/dark switch.
     sections    centred bold title, no ornament, no rule. Bands alternate
                 white / #f5f5f5 rather than being separated by whitespace.
     cards       square media at 14px radius, centred title, struck-through was
                 price beside a red now price, one full-width 45px action.
     footer      navy ground, cream headings, 75%-white body, circular socials.

   ==================================================================== */


/* ------------------------------------------------------- header: shell */

/*
 * Onyx's header never goes transparent. The base ships a transparent-over-hero
 * mode driven by [data-transparent="1"] and body.header-is-transparent; the
 * theme.json default is off, but a store carried over from another theme can
 * still have the setting stored as on. Neutralising it here means the header
 * cannot end up unreadable over a dark hero on a store we did not set up.
 */
.site-header,
.site-header[data-transparent="1"] {
    position: relative;
    background: var(--color-header-bg);
    border-bottom: 1px solid var(--color-hairline);
    box-shadow: none;
}

.site-header--sticky {
    position: sticky;
    top: 0;
    z-index: 60;
}

/* The scrolled state adds nothing here — the header already looks like this —
   but the base leans on it for the transparent mode, so it is pinned to the
   same values rather than left to inherit whatever the base decided. */
.site-header[data-scrolled] {
    background: var(--color-header-bg);
    backdrop-filter: none;
}

/* ------------------------------------------------ header: control row */

.site-header__bar {
    background: var(--color-header-bg);
}

/*
 * Three zones on one line, logo dead centre.
 *
 * `1fr auto 1fr` rather than flex with space-between: the logo must be centred
 * on the VIEWPORT, not on whatever is left after two clusters of unequal width.
 * The cart badge changes width as items go in, and with space-between that
 * shifts the logo sideways on every add — visible, and exactly the kind of jitter
 * the reference does not have.
 */
.site-header__bar-inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 1rem;
    min-height: var(--header-row-h);
}

.site-header__start,
.site-header__end {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.site-header__end {
    justify-content: flex-end;
}

.site-header .site-header__logo {
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    color: var(--color-text);
    font-weight: 700;
    font-size: var(--fs-lead);
    /* Breathing room inside the control row: without it the mark sits flush
       against the announcement bar above and the category strip below, which
       reads as a rendering fault rather than a tight header. Paired with the
       cap below so the padded link still measures exactly --header-row-h and
       --header-h stays the true header height for sticky offsets. */
    padding-block: 0.5rem;
}

/* The reference runs its wordmark at 250px — wide enough to carry a bilingual
   lockup (latin name, hexagon, arabic name) without the arabic half collapsing.

   Selector carries .site-header only to outrank the inherited
   `.site-header__logo img` (0,1,1), which sets height: 3.8rem and releases
   max-height — that is what filled the row edge to edge here. Capped off
   --header-row-h so the mark plus its padding is exactly one row tall. */
.site-header .site-header__logo-img {
    width: auto;
    max-width: min(15.625rem, 42vw);
    height: auto;
    max-height: calc(var(--header-row-h) - 1rem);
    object-fit: contain;
    /* drop-shadow rather than box-shadow: it follows the mark's own outline,
       so a rounded or transparent logo is not boxed in by a rectangle. */
    filter: var(--logo-shadow);
}

:root { --logo-shadow: drop-shadow(0 2px 6px rgb(0 0 0 / 0.18)); }

/* Onyx has one header ground (white), so the on-dark logo never applies. The
   base swaps them on body.header-is-transparent; with that mode off, pinning
   the pair here keeps a store with a stale setting from showing both marks. */
.site-header__logo-img--on-dark { display: none; }
.site-header__logo-img--on-light { display: block; }

/*
 * NOTE ON SPECIFICITY
 *
 * These selectors are written `.site-header .site-header__bar-inner .x` rather
 * than `.site-header__bar-inner .x`. The inherited chrome styles the same
 * triggers at three classes (e.g. `.site-header .search-link
 * .f-search__trigger`, which sets them to a bare 32px glyph). A two-class
 * selector loses to that however late it sits in the file, so the search
 * control kept rendering without its disc while the cart — which had no
 * competing rule — picked one up. Being last is only decisive at equal
 * specificity.
 */
/* --------------------------------------------- header: round controls */

/*
 * Every header control is the same 44px disc on the same translucent grey.
 *
 * The SDK components render their own trigger markup, and each names it
 * differently — .f-search__trigger, .f-user__trigger, .f-cart-summary__link,
 * .f-locale__trigger. So the shape is applied to the trigger classes by name
 * rather than to `button`, which matched some of them and missed the cart's
 * anchor entirely, leaving it the only control on the row without a disc.
 *
 * The HOSTS have to be sized too. Left alone they shrink-wrap to their icon
 * (32px), so the disc inside them was clipped and the search and account
 * controls sat visibly smaller than the locale pills beside them.
 */
.site-header .site-header__bar-inner .search-link,
.site-header__bar-inner falak-user-menu,
.site-header .site-header__bar-inner .cart-link,
.site-header .site-header__bar-inner .wishlist-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--icon-btn);
    block-size: var(--icon-btn);
    flex: none;
}

.site-header .site-header__bar-inner .f-search__trigger,
.site-header .site-header__bar-inner .f-user__trigger,
.site-header .site-header__bar-inner .f-cart-summary__link,
.site-header .site-header__bar-inner .wishlist-link button,
.site-header .site-header__bar-inner .theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--icon-btn);
    block-size: var(--icon-btn);
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--color-icon-disc);
    color: var(--color-primary);
    box-shadow: var(--shadow-icon-disc);
    text-decoration: none;
    transition: transform var(--transition), box-shadow var(--transition);
}

/*
 * Hover is a nudge, not a repaint. The plate is the one constant across the
 * whole row and across both header states, so tinting it on hover made the
 * control look like it had changed material; a small scale reads as the same
 * disc responding.
 *
 * transform, so the 44px box is unchanged and the icons beside it do not
 * shift. The global prefers-reduced-motion rule flattens the timing.
 *
 * The plate has to be RESTATED here even though nothing is changing it: the
 * inherited bare-glyph rules up at "Search and wishlist" set
 * background: transparent on :hover at (0,4,0), one class more than this
 * selector carries. Drop this line and the search and wishlist discs alone
 * lose their ground under the pointer.
 */
.site-header .site-header__bar-inner .f-search__trigger:hover,
.site-header .site-header__bar-inner .f-user__trigger:hover,
.site-header .site-header__bar-inner .f-cart-summary__link:hover,
.site-header .site-header__bar-inner .wishlist-link button:hover,
.site-header .site-header__bar-inner .theme-toggle:hover,
.site-header .site-header__bar-inner .menu-toggle:hover {
    background: var(--color-icon-disc);
    box-shadow: var(--shadow-icon-disc-hover);
    transform: scale(1.08);
}

.site-header .site-header__bar-inner .f-search__trigger:active,
.site-header .site-header__bar-inner .f-user__trigger:active,
.site-header .site-header__bar-inner .f-cart-summary__link:active,
.site-header .site-header__bar-inner .wishlist-link button:active,
.site-header .site-header__bar-inner .theme-toggle:active,
.site-header .site-header__bar-inner .menu-toggle:active {
    transform: scale(0.96);
}

/* The glyphs themselves stay a consistent size inside the discs — the
   components ship them at different natural sizes. */
.site-header .site-header__bar-inner .f-search__trigger svg,
.site-header .site-header__bar-inner .f-user__avatar svg,
.site-header .site-header__bar-inner .f-cart-summary__icon svg {
    inline-size: 1.25rem;
    block-size: 1.25rem;
}

/*
 * The cart is a bare glyph with a count badge on the disc's corner — no running
 * total. A total in the header is a pill that changes width every time it
 * changes, which shifts the centred logo sideways on every add.
 */
.site-header .site-header__bar-inner .f-cart-summary__content { display: none; }

.site-header .site-header__bar-inner .f-cart-summary__icon {
    position: relative;
    display: inline-flex;
}

/*
 * The component hides this with the `hidden` attribute when the cart is empty.
 * `display: inline-flex` below is more specific than the UA's `[hidden]` rule,
 * so without this the badge came back and every visitor saw a red "0" pinned to
 * the bag. Restated rather than reordered — `[hidden]` has to out-specify the
 * rule that styles the badge, not merely precede it.
 */
.site-header .site-header__bar-inner .f-cart-summary__count[hidden] { display: none; }

.site-header .site-header__bar-inner .f-cart-summary__count {
    position: absolute;
    inset-block-start: -0.5rem;
    inset-inline-end: -0.5rem;
    min-inline-size: 1.125rem;
    block-size: 1.125rem;
    padding-inline: 0.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--color-announce);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1;
}

/*
 * The drawer toggle is a phone control. The base hides it above the drawer
 * breakpoint by leaving it `display: none`, but the disc styling above gave it
 * a background and a size, and it came back as an empty grey circle at the head
 * of the row on desktop. It is hidden here explicitly and shown again in the
 * phone block below.
 */
.site-header .site-header__bar-inner .menu-toggle { display: none; }

/* ------------------------------------------- header: locale controls */

/*
 * Language and country/currency are pills, not discs — they carry a word, and
 * a word in a circle needs a circle too big for everything else on the row.
 *
 * Targeted by the component's own trigger class rather than by `button`: the
 * language control is a custom element whose host is a plain block, so styling
 * the host alone left a 36px-tall pill next to 44px discs.
 */
.site-header .site-header__bar-inner .locale-trigger { display: inline-flex; }

.site-header .site-header__bar-inner .f-locale__trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-block-size: var(--icon-btn);
    padding-inline: 0.875rem;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--color-icon-disc);
    color: var(--color-icon-disc-ink);
    font: inherit;
    font-size: var(--fs-nav);
    line-height: 1.2;
    cursor: pointer;
    white-space: nowrap;
    box-shadow: var(--shadow-icon-disc);
    transition: transform var(--transition), box-shadow var(--transition);
}

/* The pills sit in the same plate as the discs and are hovered in the same
   sweep of the pointer, so they answer the same way. */
.site-header .site-header__bar-inner .f-locale__trigger:hover {
    box-shadow: var(--shadow-icon-disc-hover);
    transform: scale(1.06);
}

.site-header .site-header__bar-inner .f-locale__trigger:active {
    transform: scale(0.98);
}

/* The reference's language control is a word and a caret. The component also
   renders a globe; at this size it crowds a four-letter label. */
.site-header .site-header__bar-inner .f-locale__globe { display: none; }

/* The currency dropdown is the same pill as the language control beside it;
   its coin icon goes for the same reason the globe does. */
.site-header .site-header__bar-inner .f-currency__field {
    min-block-size: var(--icon-btn);
    padding-inline: 0.875rem;
    border-radius: var(--radius-sm);
    background: var(--color-icon-disc);
    color: var(--color-icon-disc-ink);
    font-size: var(--fs-nav);
    line-height: 1.2;
}

.site-header .site-header__bar-inner .f-currency__field {
    box-shadow: var(--shadow-icon-disc);
    transition: transform var(--transition), box-shadow var(--transition);
}

.site-header .site-header__bar-inner .f-currency__field:hover {
    box-shadow: var(--shadow-icon-disc-hover);
    transform: scale(1.06);
}

.site-header .site-header__bar-inner .f-currency__icon { display: none; }

/* ------------------------------------------ header: cream nav strip */

/*
 * The category strip. It is the one warm surface in the chrome, and it is what
 * makes the header read as this brand's rather than as a default white bar.
 *
 * Full-bleed cream with the menu centred inside the container — the colour runs
 * edge to edge, the links stay on the grid.
 */
.site-header__nav {
    background: var(--color-navstrip-bg);
    border: 0;
}

.site-header__nav .main-menu {
    display: flex;
    justify-content: center;
    min-height: var(--navstrip-h);
}

.site-header__nav .main-menu > ul {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.site-header__nav .main-menu__item > a {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 0.875rem;
    border-radius: var(--radius-sm);
    color: var(--color-text-soft);
    font-size: var(--fs-nav);
    font-weight: 400;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--transition), color var(--transition);
}

.site-header__nav .main-menu__item > a:hover {
    color: var(--color-text);
    background: color-mix(in srgb, var(--color-primary) 12%, transparent);
}

/*
 * The current section is a filled navy pill with cream text — the only place in
 * the chrome where the two brand colours meet, and the reason the strip does
 * not need a underline, a bolder weight or a colour change to say where you are.
 *
 * [aria-current] is what the platform sets; .is-active covers menus whose
 * active item is resolved in app.js instead.
 */
.site-header__nav .main-menu__item > a[aria-current],
.site-header__nav .main-menu__item > a.is-active,
.site-header__nav .main-menu__item.is-active > a {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

/* Submenus drop onto white, not cream: a cream panel over a cream strip has no
   edge, and the panel needs to read as sitting above the page. */
.site-header__nav .main-menu__submenu {
    background: var(--color-bg);
    border: 1px solid var(--color-hairline);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 0.5rem;
}

.site-header__nav .main-menu__submenu a {
    display: block;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-sm);
    color: var(--color-text-soft);
    font-size: var(--fs-nav);
    text-decoration: none;
}

.site-header__nav .main-menu__submenu a:hover {
    background: var(--color-surface);
    color: var(--color-text);
}

/* ---- the More panel -----------------------------------------------------
   The overflow dropdown is a list of a dozen categories, not a two-entry
   submenu, so it does not share the submenu's look. What the shared rules
   gave it: rows centred under the bar's text-align, links shrink-wrapped so
   a hover tinted the width of the word, every row in the same bold soft ink
   whether it was a category or a collapsed parent's child, and a list that
   scrolled with nothing to say so.

   Here: rows full width and start-aligned, a chevron that slides in at the
   reading end on hover, a parent's children grouped under it behind a guide
   line with a hairline before the next top-level row, a thin scrollbar in
   the ink, and a short drop-in when it opens. Background and border are
   NOT restated - the shared rule above and the dark-mode rule already
   decide those between them.

   (0,4,0), one class above the shared submenu rules, so these win on
   specificity rather than on position. */
.site-header__nav .main-menu__more .main-menu__submenu--more {
    min-width: 16.5rem;
    /* --more-room is the space left below the pill, measured by
       wireNavOverflow() on open; 70vh is only the no-JS fallback. */
    max-height: min(28rem, var(--more-room, 70vh));
    padding: 0.5rem;
    /* The shared submenu is a flex column with an 8px gap. Here the rows
       touch: the gap spaced a dozen 40px rows out to 48, and it cut the
       children's guide line into dashes. Section spacing comes from the
       hairline rule below instead. */
    gap: 0;
    top: calc(100% + 0.4rem);
    box-shadow: 0 1px 2px rgba(16, 22, 49, 0.05), 0 14px 36px rgba(16, 22, 49, 0.12);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--color-text) 18%, transparent) transparent;
    text-align: start;
}

/* The 0.4rem of air between pill and panel is bridged on the ITEM, not the
   panel: the panel scrolls, and overflow clips a pseudo-element that hangs
   outside it. The item is the menu's hover target, so a pointer crossing
   the gap stays inside it. */
.site-header__nav .main-menu__more.is-open::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 100%;
    height: 0.5rem;
}

.site-header__nav .main-menu__more.is-open > .main-menu__submenu--more {
    animation: more-panel-drop 160ms ease-out;
}
@keyframes more-panel-drop {
    from { opacity: 0; translate: 0 -6px; }
}

.site-header__nav .main-menu__more .main-menu__submenu--more > li {
    display: block;
    width: 100%;
}

.site-header__nav .main-menu__more .main-menu__submenu--more a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    min-height: 2.5rem;
    padding: 0.5rem 0.85rem;
    border-radius: 0.625rem;
    color: var(--color-text);
    font-size: var(--fs-nav);
    font-weight: 600;
    line-height: 1.2;
    text-align: start;
    text-decoration: none;
    transition: background-color var(--transition), color var(--transition);
}

/* The chevron: a mask so it takes the row's ink, hidden a few px short of
   its place and sliding in on hover. Mirrored in RTL, where the reading end
   is the left and "onward" points that way. */
.site-header__nav .main-menu__more .main-menu__submenu--more a::after {
    content: "";
    flex: none;
    inline-size: 0.8rem;
    block-size: 0.8rem;
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5'/%3E%3C/svg%3E") center / contain no-repeat;
    opacity: 0;
    translate: -4px 0;
    transition: opacity var(--transition), translate var(--transition);
}
[dir="rtl"] .site-header__nav .main-menu__more .main-menu__submenu--more a::after {
    scale: -1 1;
    translate: 4px 0;
}

.site-header__nav .main-menu__more .main-menu__submenu--more a:hover,
.site-header__nav .main-menu__more .main-menu__submenu--more a:focus-visible {
    background: color-mix(in srgb, var(--color-primary) 12%, transparent);
    color: var(--color-primary);
}
.site-header__nav .main-menu__more .main-menu__submenu--more a:hover::after,
.site-header__nav .main-menu__more .main-menu__submenu--more a:focus-visible::after {
    opacity: 1;
    translate: 0 0;
}

/* A collapsed parent's children: indented behind a 2px guide, lighter in
   weight and ink, a step shorter. The guide is the row's own start border,
   so it runs unbroken down the group because the rows touch. */
.site-header__nav .main-menu__more .main-menu__submenu--more a.main-menu__more-child {
    margin-inline-start: 0.85rem;
    padding-inline-start: 0.85rem;
    min-height: 2.25rem;
    border-inline-start: 2px solid var(--color-hairline);
    border-start-start-radius: 0;
    border-end-start-radius: 0;
    color: var(--color-text-soft);
    font-size: calc(var(--fs-nav) - 1px);
    font-weight: 500;
}
.site-header__nav .main-menu__more .main-menu__submenu--more a.main-menu__more-child:hover,
.site-header__nav .main-menu__more .main-menu__submenu--more a.main-menu__more-child:focus-visible {
    border-inline-start-color: var(--color-primary);
    color: var(--color-primary);
}

/* The next top-level row after a group of children sits behind a hairline,
   so the panel reads as sections rather than one undifferentiated column. */
.site-header__nav .main-menu__more .main-menu__submenu--more > .main-menu__more-row--child + .main-menu__more-row:not(.main-menu__more-row--child) {
    margin-block-start: 0.35rem;
    padding-block-start: 0.35rem;
    border-block-start: 1px solid var(--color-hairline);
}

/* ---------------------------------------------- header: announcement */

/*
 * The announcement strip is the one loud surface in the theme: the brand
 * colour, bold contrasting text, and it sits ABOVE the header rather than
 * inside it. --color-announce stays the token for the sale/urgency accents
 * elsewhere; it is not the brand, so the bar no longer reads from it.
 */
.site-header__announcement {
    display: block;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: var(--fs-nav);
    font-weight: 700;
    line-height: 1.4;
}

.site-header__announcement a { color: inherit; }

/* ------------------------------------------------- header: phone rows */

@media (max-width: 767px) {
    /*
     * On a phone the reference collapses to hamburger | logo | cart. Search and
     * account move into the bottom bar, the locale pills into the drawer, and
     * the cream strip disappears entirely — its categories are what the drawer
     * is for, and repeating them in a scrolling strip is how a phone header
     * ends up three rows tall.
     */
    .site-header__bar-inner {
        gap: 0.5rem;
    }

    .site-header__nav {
        display: none;
    }

    .site-header__bar-inner falak-user-menu,
    .site-header .site-header__bar-inner .locale-trigger {
        display: none;
    }

    /* Search hides its trigger, NOT its host: the <falak-modal> lives inside
       <falak-search>, and the bottom bar's search tile opens it by clicking
       this hidden trigger. `display: none` on the host took the modal with
       it, so the tile opened nothing. */
    .site-header .site-header__bar-inner .search-link {
        display: contents;
    }

    .site-header .site-header__bar-inner .search-link .f-search__trigger {
        display: none;
    }

    /* ...and the drawer toggle comes back, as the only control at the start. */
    .site-header .site-header__bar-inner .menu-toggle {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: var(--icon-btn);
        block-size: var(--icon-btn);
        padding: 0;
        border: 0;
        border-radius: 50%;
        background: var(--color-icon-disc);
        color: var(--color-primary);
        box-shadow: var(--shadow-icon-disc);
    }

    /* Same specificity bump as the desktop cap, or that rule would outrank
       this one and the phone header would keep the desktop size. */
    .site-header .site-header__logo-img {
        max-height: 2.25rem;
    }
}

/* The drawer is the only place the categories exist on a phone, so it carries
   the cream ground the strip has on desktop — the association survives. */
@media (max-width: 767px) {
    body.menu-is-open .site-header__nav {
        display: block;
        background: var(--color-navstrip-bg);
    }
}


/* --------------------------------------------------- section rhythm */

/*
 * Bands, not gaps.
 *
 * The reference gives every block 36px of its own padding and lets adjacent
 * blocks differ by GROUND colour instead of by whitespace: white, then
 * #f5f5f5, then white. Two blocks of the same colour meeting simply read as
 * one longer block, which is why its home page feels continuous rather than
 * like a stack of cards.
 *
 * So .block gets padding rather than margin — margins would collapse between
 * neighbours and the band colour would show through the gap as a stripe.
 */
.block {
    padding-block: var(--block-space);
    margin-block: 0;
}

/*
 * Re-stated here, after the rule above.
 *
 * `.block--flush` is declared far earlier in this file, and it carries the same
 * specificity as `.block` — so the padding above simply won the cascade by
 * being later, and every band meant to run edge to edge (the scrolling text
 * strip, the fixed banner, the countdown) picked up 2rem top and bottom. The
 * text strip is measured at 46px; it was rendering at about 110.
 *
 * Nova has no equivalent late `.block` rule, which is why the same markup and
 * the same strip CSS look right there and wrong here.
 */
.block--flush { padding-block: 0; }

/* nth-of-type would be wrong: .block is a class on several different elements,
   and the count has to run over the blocks themselves. app.js tags alternates
   with .block--band; this is the fallback for a server-rendered page. */
.block--band,
.block--surface {
    background: var(--color-surface);
}

/* ----------------------------------------------- section head */

/*
 * A centred bold title and nothing else.
 *
 * The base ships a three-part head — title, subtitle, and an ornamental rule
 * with a diamond in it. That ornament is Nova's signature and it is wrong here:
 * this design gets its formality from weight and spacing, not decoration. The
 * rule is removed outright; the subtitle stays available for merchants who fill
 * it in but is given no default presence.
 */
.block-head {
    text-align: center;
    margin-block-end: 1.5625rem;
}

.block-head__title {
    margin: 0;
    font-size: var(--fs-section);
    font-weight: 700;
    line-height: 1.23;
    color: var(--color-text);
}

.block-head__sub {
    margin: 0.375rem 0 0;
    font-size: var(--fs-body);
    color: var(--color-text-soft);
}

.block-head__sub:empty { display: none; }

/* The ornament, gone. Kept as a rule rather than deleted from the markup so the
   shared templates stay shared. */
.block-head__rule { display: none; }


/* ------------------------------------------------------------ footer */

.site-footer {
    background: var(--color-footer-bg);
    color: rgba(255, 255, 255, 0.75);
    padding-block: var(--block-space);
}

.site-footer h2,
.site-footer h3,
.site-footer h4,
.site-footer__title,
.site-footer__col-title {
    color: var(--color-cream);
    font-size: var(--fs-card);
    /* Medium, not bold: at 23px on a dark ground bold headings vibrate, and the
       reference runs them at 500 for exactly that reason. */
    font-weight: 500;
    margin-block-end: 0.75rem;
}

.site-footer a {
    color: rgba(255, 255, 255, 0.75);
    text-decoration: none;
    font-size: var(--fs-nav);
    transition: color var(--transition);
}

.site-footer a:hover { color: var(--color-cream); }

/* Social handles are discs on a barely-there white wash — the same disc idea as
   the header controls, inverted for the dark ground. */
.site-footer .f-social__link,
.site-footer__social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--icon-btn);
    block-size: var(--icon-btn);
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    transition: background var(--transition);
}

.site-footer .f-social__link:hover,
.site-footer__social a:hover {
    background: rgba(255, 255, 255, 0.3);
    color: #fff;
}

/* The legal line, divided off rather than boxed. */
.site-footer__bottom {
    margin-block-start: 1.875rem;
    padding-block-start: 1.875rem;
    border-block-start: 1px solid rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.75);
}


/* ------------------------------------------- header: the icon set */

/*
 * One icon family across the whole bar.
 *
 * The three header controls come from three different SDK components, each
 * shipping its own glyph drawn at its own weight — a heavy filled avatar beside
 * a hairline magnifier beside a bag from a fourth set. Side by side in matching
 * discs, the mismatch is the first thing the eye catches.
 *
 * The glyphs are the reference storefront's own, applied as MASKS rather than
 * by editing the components: a mask keeps `currentColor` working, so the icons
 * still follow the theme's ink, invert on a dark ground, and dim when a control
 * is disabled — none of which a background-image would do. The components stay
 * shared and untouched; only this theme wears these shapes.
 */
.site-header .site-header__bar-inner .f-search__trigger > svg,
.site-header .site-header__bar-inner .f-user__trigger > .f-user__avatar,
.site-header .site-header__bar-inner .f-user__trigger > svg,
.site-header .site-header__bar-inner .f-cart-summary__icon > svg {
    display: none;
}

.site-header .site-header__bar-inner .f-search__trigger::before,
.site-header .site-header__bar-inner .f-user__trigger::before,
.site-header .site-header__bar-inner .f-cart-summary__icon::before {
    content: "";
    display: block;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
}

/* Search and account share an 18x19 grid, so they render at one size and their
   stroke weights already agree. */
.site-header .site-header__bar-inner .f-search__trigger::before,
.site-header .site-header__bar-inner .f-user__trigger::before {
    inline-size: 1.125rem;
    block-size: 1.1875rem;
}

/* The bag is drawn on a 24x24 grid at a lighter stroke, so it is set slightly
   larger to carry the same visual weight as the two solid glyphs. */
.site-header .site-header__bar-inner .f-cart-summary__icon::before {
    inline-size: 1.375rem;
    block-size: 1.375rem;
}

.site-header .site-header__bar-inner .f-search__trigger::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2018%2019%22%20fill=%22none%22%3E%3Cpath%20fill-rule=%22evenodd%22%20clip-rule=%22evenodd%22%20d=%22M11.03%2011.68A5.784%205.784%200%20112.85%203.5a5.784%205.784%200%20018.18%208.18zm.26%201.12a6.78%206.78%200%2011.72-.7l5.4%205.4a.5.5%200%2011-.71.7l-5.41-5.4z%22%20fill=%22%23000%22/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2018%2019%22%20fill=%22none%22%3E%3Cpath%20fill-rule=%22evenodd%22%20clip-rule=%22evenodd%22%20d=%22M11.03%2011.68A5.784%205.784%200%20112.85%203.5a5.784%205.784%200%20018.18%208.18zm.26%201.12a6.78%206.78%200%2011.72-.7l5.4%205.4a.5.5%200%2011-.71.7l-5.41-5.4z%22%20fill=%22%23000%22/%3E%3C/svg%3E");
}

.site-header .site-header__bar-inner .f-user__trigger::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2018%2019%22%20fill=%22none%22%3E%3Cpath%20fill-rule=%22evenodd%22%20clip-rule=%22evenodd%22%20d=%22M6%204.5a3%203%200%20116%200%203%203%200%2001-6%200zm3-4a4%204%200%20100%208%204%204%200%20000-8zm5.58%2012.15c1.12.82%201.83%202.24%201.91%204.85H1.51c.08-2.6.79-4.03%201.9-4.85C4.66%2011.75%206.5%2011.5%209%2011.5s4.35.26%205.58%201.15zM9%2010.5c-2.5%200-4.65.24-6.17%201.35C1.27%2012.98.5%2014.93.5%2018v.5h17V18c0-3.07-.77-5.02-2.33-6.15-1.52-1.1-3.67-1.35-6.17-1.35z%22%20fill=%22%23000%22/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2018%2019%22%20fill=%22none%22%3E%3Cpath%20fill-rule=%22evenodd%22%20clip-rule=%22evenodd%22%20d=%22M6%204.5a3%203%200%20116%200%203%203%200%2001-6%200zm3-4a4%204%200%20100%208%204%204%200%20000-8zm5.58%2012.15c1.12.82%201.83%202.24%201.91%204.85H1.51c.08-2.6.79-4.03%201.9-4.85C4.66%2011.75%206.5%2011.5%209%2011.5s4.35.26%205.58%201.15zM9%2010.5c-2.5%200-4.65.24-6.17%201.35C1.27%2012.98.5%2014.93.5%2018v.5h17V18c0-3.07-.77-5.02-2.33-6.15-1.52-1.1-3.67-1.35-6.17-1.35z%22%20fill=%22%23000%22/%3E%3C/svg%3E");
}

.site-header .site-header__bar-inner .f-cart-summary__icon::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2024%2024%22%20fill=%22none%22%20stroke=%22%23000%22%20stroke-width=%221%22%3E%3Cpath%20stroke-linecap=%22round%22%20stroke-linejoin=%22round%22%20d=%22M15.75%2010.5V6a3.75%203.75%200%201%200-7.5%200v4.5m11.356-1.993%201.263%2012c.07.665-.45%201.243-1.119%201.243H4.25a1.125%201.125%200%200%201-1.12-1.243l1.264-12A1.125%201.125%200%200%201%205.513%207.5h12.974c.576%200%201.059.435%201.119%201.007ZM8.625%2010.5a.375.375%200%201%201-.75%200%20.375.375%200%200%201%20.75%200Zm7.5%200a.375.375%200%201%201-.75%200%20.375.375%200%200%201%20.75%200Z%22/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2024%2024%22%20fill=%22none%22%20stroke=%22%23000%22%20stroke-width=%221%22%3E%3Cpath%20stroke-linecap=%22round%22%20stroke-linejoin=%22round%22%20d=%22M15.75%2010.5V6a3.75%203.75%200%201%200-7.5%200v4.5m11.356-1.993%201.263%2012c.07.665-.45%201.243-1.119%201.243H4.25a1.125%201.125%200%200%201-1.12-1.243l1.264-12A1.125%201.125%200%200%201%205.513%207.5h12.974c.576%200%201.059.435%201.119%201.007ZM8.625%2010.5a.375.375%200%201%201-.75%200%20.375.375%200%200%201%20.75%200Zm7.5%200a.375.375%200%201%201-.75%200%20.375.375%200%200%201%20.75%200Z%22/%3E%3C/svg%3E");
}

/* The count badge sits over the bag, so the icon box has to be the positioning
   context rather than the disc — otherwise the badge rides the disc's corner
   and drifts as the glyph size changes. */
.site-header .site-header__bar-inner .f-cart-summary__icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}


/* --------------------------------------------------- product card */

/*
 * The card is <custom-falak-product-card> from the SDK, so this restyles
 * .f-card__* rather than owning any markup. Four things make it this design's:
 *
 *   1  the media is a white square tile with its own 14px radius — the frame
 *      is around the PHOTO, not around the whole card
 *   2  everything below the tile is unframed and centred, sitting directly on
 *      the section band
 *   3  one full-width action, never a row of icon buttons
 *   4  the now-price is red and the was-price is struck through beside it
 *
 * Point 2 is the one that carries the look: because the body has no frame, a
 * grid of these reads as a row of photographs with captions rather than a row
 * of boxes, which is what makes the page feel like a catalogue.
 */

.f-card__inner {
    display: flex;
    flex-direction: column;
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
}

/* No lift, no shadow, no border colour change. The reference's cards do not
   move on hover; the image inside them does (below). */
.f-card__inner:hover {
    background: transparent;
    border: 0;
    box-shadow: none;
    transform: none;
}

/*
 * The photo tile. White ground rather than transparent, so a product shot with
 * a cut-out background still reads as a tile on the grey band — on the
 * reference every product photo is already on white, and a transparent tile
 * would make the grey band show through and break the row.
 */
.f-card__media {
    position: relative;
    aspect-ratio: 1 / 1;
    background: #fff;
    border: 1px solid var(--color-hairline);
    border-radius: var(--radius);
    overflow: hidden;
}

.f-card__media img {
    inline-size: 100%;
    block-size: 100%;
    /* contain, not cover: these are packshots. Cropping a bottle to fill a
       square cuts the cap off, which is exactly what the reference avoids. */
    object-fit: contain;
    transition: transform 400ms ease;
}

.f-card__inner:hover .f-card__media img {
    transform: scale(1.04);
}

/* ---- body ---- */

/*
 * Content sits tight under the picture; the button is pinned to the card's foot.
 *
 * Measured on the reference: every card in a row is the same height and the
 * price sits a constant 17px above the button. It gets that for free because
 * its product names are short enough to stay on one line, so no card in a row
 * has spare height to distribute.
 *
 * Two earlier attempts here were both wrong. Letting the body absorb the spare
 * height dropped it all between the price and the button (46px, and varying
 * card to card). Letting the TITLE absorb it instead centred the title in a
 * grown box, which opened gaps above AND below it — further from the reference
 * than where it started.
 *
 * What is right: nothing stretches. The body keeps its natural height, the
 * title is capped at two lines so one long name cannot drive a whole row, and
 * the spare height — when a row has any — collects below the button rather than
 * inside the card's copy, where it is invisible.
 */
.f-card__body {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    /* no growing: the body is exactly as tall as its content */
    flex: 0 0 auto;
    gap: 0.25rem;
    padding: 1.0625rem 0.625rem;
    text-align: center;
}

/*
 * Two lines maximum.
 *
 * The reference's names fit one line; this catalogue has names running to four,
 * which pushed the media rows apart and made every row ragged. Clamping keeps a
 * long name from setting the height of everything beside it. The full name is
 * still the link's text, so it is intact for a screen reader and for search.
 */
.f-card__title {
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: var(--fs-card);
    /*
     * 600, not the reference's 700.
     *
     * The reference sets its card names bold, but it sets them in Greta Arabic,
     * whose bold is noticeably lighter than IBM Plex Sans Arabic's. Matching the
     * NUMBER here would not match the look — at this size Plex's 700 reads as a
     * much heavier block of Arabic than the reference ever shows. Semibold lands
     * where the reference's bold sits optically.
     */
    font-weight: 600;
    line-height: 1.23;
}

.f-card__link {
    color: var(--color-text);
    text-decoration: none;
}

.f-card__link:hover { color: var(--color-primary-light); }

/* ---- price ---- */

/*
 * Was-price FIRST, now-price second, both on one centred line.
 *
 * The SDK emits now-then-was; the reference reads was-then-now, and in Arabic
 * that ordering is what makes the discount parse ("it was X, it is now Y").
 * `order` rather than re-templating, so the SDK keeps owning the markup.
 */
.f-card__price {
    display: flex;
    align-items: baseline;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
}

.f-card__price-was {
    order: 1;
    font-size: var(--fs-meta);
    font-weight: 400;
    color: var(--color-text-soft);
    text-decoration: line-through;
}

.f-card__price-now {
    order: 2;
    font-size: var(--fs-body);
    font-weight: 400;
    color: var(--color-text);
}

/*
 * Red only when there is something to compare against.
 *
 * :has() on the price row rather than a colour on .f-card__price-now outright:
 * a product with no discount has a now-price too, and painting every price red
 * turns the red into decoration instead of a signal. With the was-price present,
 * the pair reads as a markdown.
 */
.f-card__price:has(.f-card__price-was) .f-card__price-now {
    color: var(--color-sale);
}

.f-card__stock {
    font-size: var(--fs-caption);
    color: var(--color-text-soft);
}

/* ---- action ---- */

/* Pinned to the foot: whatever spare height a row has collects here, so the
   buttons still line up across the row without pushing the copy around. */
.f-card__actions {
    margin-block-start: auto;
    padding: 0 0 0.25rem;
}

/*
 * One button, full width, filled with the band it sits on.
 *
 * `transparent` rather than a fixed grey: on the white sections it reads as an
 * outlined button and on the #f5f5f5 bands as a recessed one, which is what the
 * reference does — and it does it with one rule instead of a band-aware variant.
 */
.f-card__add {
    inline-size: 100%;
    min-block-size: var(--control-h);
    padding-inline: 0.75rem;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    font-size: var(--fs-control);
    font-weight: 400;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}

.f-card__add:hover:not(:disabled) {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-on-primary);
}

/* Sold out stays a button-shaped placeholder rather than disappearing, so the
   row keeps its baseline and the grid does not go ragged. */
.f-card__add:disabled {
    opacity: 1;
    background: transparent;
    border-color: var(--color-hairline);
    color: var(--color-text-faint);
}

/*
 * The reference has no wishlist heart on its cards, and its action row is one
 * full-width button. Hiding it here rather than passing an attribute keeps the
 * shared product-card partial shared.
 */
.f-card__wishlist { display: none; }

/* ---- second image on hover ---- */

/*
 * Injected by wireHoverImages() in app.js from the product's own images[] —
 * see the note there for why this is theme-side rather than an SDK feature.
 * The two photos crossfade: the second fades in over the first, and the first
 * fades out underneath so a pair of packshots with transparency never shows as
 * two bottles ghosted over each other.
 */
.f-card__hover-img {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: contain;
    opacity: 0;
    transition: opacity 350ms ease;
    pointer-events: none;
}

.f-card__inner:hover .f-card__hover-img { opacity: 1; }

/* Fade the primary out ONLY when there is a second photo underneath to fade
   in. wireHoverImages() appends .f-card__hover-img just for products that
   have a second DISTINCT image, so without the :has() guard a one-image
   product faded its only photo to nothing and hovering showed the empty
   media box. :has() is the right test rather than a class the JS sets,
   because it asks the question the rule actually depends on — and if an
   engine ever lacked it the whole rule drops, which merely disables the
   crossfade instead of hiding the image. */
.f-card__inner:hover .f-card__media:has(.f-card__hover-img) img:not(.f-card__hover-img) { opacity: 0; }

/* opacity joins the transform the base already transitions, so the fade-out
   runs at the same pace as the fade-in above it. */
.f-card__media img:not(.f-card__hover-img) {
    transition: transform 400ms ease, opacity 350ms ease;
}

/* ---- hexagonal badges ---- */

/*
 * The discount badge is a hexagon, not a pill.
 *
 * On the reference these are baked into the product photography, which means
 * they cannot follow the actual price and go stale the moment a campaign ends.
 * Ours is drawn in CSS from the live discount, so it is always right — and
 * because it is a clip-path on a square, it stays a regular hexagon at any size
 * without an asset.
 */
.f-card__badge {
    position: absolute;
    inset-block-start: 0.625rem;
    /* The component pins the badge to the START edge. Setting only the end
       inset left BOTH in force, and with an auto width the start edge wins —
       so the hexagon stayed on the left while the reference puts it on the
       right. Clearing the start inset explicitly is what moves it. */
    inset-inline-start: auto;
    inset-inline-end: 0.625rem;
    z-index: 2;

    /*
     * flex, NOT grid.
     *
     * As a grid the badge had two items — the anonymous box holding the
     * component's "Sale" text node, and the ::after carrying the percentage —
     * so they stacked in two rows (22.3px + 37.7px) and the number centred
     * inside the LOWER row, about 11px below the hexagon's middle. Flex plus an
     * absolutely-positioned ::after takes the label out of the equation
     * entirely.
     */
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 3.375rem;
    block-size: 3.75rem;
    padding: 0;

    background: var(--color-announce);
    color: #fff;
    border: 0;
    border-radius: 0;
    /* pointy-top hexagon */
    clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);

    font-size: var(--fs-nav);
    font-weight: 700;
    line-height: 1.1;
    text-align: center;
    letter-spacing: -0.01em;
}

/*
 * The hexagon carries the DISCOUNT, not the word "Sale".
 *
 * The component's badge text is a fixed label; the reference's hexagons carry a
 * number ("50%", "96"), which is the whole reason the shape earns its place —
 * a shopper reads the saving without reading the prices. The SDK now emits the
 * computed percentage as `data-discount` alongside its label, so the number is
 * rendered here and the label stays in the accessibility tree for a screen
 * reader rather than being deleted.
 *
 * font-size: 0 rather than `display: none` on the text for exactly that reason:
 * the word is still announced, it just takes no space.
 */
.f-card__badge { font-size: 0; }

/*
 * Absolutely filling the badge, so the percentage is centred on the HEXAGON
 * rather than on whatever space the hidden label leaves behind.
 */
.f-card__badge[data-discount]::after {
    content: attr(data-discount) "%";
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fs-nav);
    font-weight: 700;
    line-height: 1.1;
}

/*
 * The SDK card now prints the percentage itself, as <b class="f-card__badge-pct">
 * before the "Sale" label, and the shared card styles give that <b> its own
 * 0.85rem — which escapes the font-size: 0 on the badge above. Left alone it
 * rendered a second "7%" under the ::after's, slightly off-centre, so the
 * hexagon showed two overlapping numbers. The pseudo-element is the one that
 * draws the number here (it is the one centred on the hexagon), so the inline
 * copy takes no space either. It stays in the DOM for a screen reader.
 */
.f-card__badge[data-discount] .f-card__badge-pct { font-size: 0; margin: 0; }

/* No percentage to show (an offer with no computable saving) — fall back to the
   component's own label rather than an empty hexagon. */
.f-card__badge:not([data-discount]) { font-size: var(--fs-caption); }

/* The offer ribbon keeps the opposite corner and the second brand colour, so a
   product that is both discounted and in an offer shows two distinct marks
   rather than two red hexagons. */
.f-card__offer {
    background: var(--color-success);
    color: #fff;
    border-radius: var(--radius-sm);
}

/* ---- grid ---- */

/*
 * Four across on desktop, two on a phone — never one. A single-column product
 * list on a phone means one product per screen and a page nobody scrolls to the
 * end of; the reference stays at two the whole way down.
 */
.f-products-list,
.products-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--grid-gap);
}

@media (max-width: 1023px) {
    .f-products-list,
    .products-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 767px) {
    .f-products-list,
    .products-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* The card title is a 23px display size on desktop; at two-up on a phone it
       would wrap to three lines and push the button below the fold. */
    .f-card__title { font-size: var(--fs-body); }
    .f-card__body { padding: 0.75rem 0.375rem; }
    /*
     * Size only — the font-size must stay 0 here.
     *
     * Setting it on the badge un-hid the component's "Sale" text node, which
     * then rendered UNDER the absolutely-positioned percentage: the phone badge
     * showed both strings stacked on top of each other. The type size for the
     * number belongs on the pseudo-element that actually draws it.
     */
    .f-card__badge { inline-size: 2.75rem; block-size: 3rem; }
    .f-card__badge[data-discount]::after { font-size: var(--fs-caption); }
    .f-card__badge:not([data-discount]) { font-size: 0.625rem; }
}

/* ---- "view all" under a block ---- */

.block__view-all {
    display: flex;
    justify-content: center;
    margin-block-start: 0.625rem;
}

.block__view-all > a {
    min-inline-size: 7.5rem;
    min-block-size: var(--control-h);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-inline: 1.875rem;
    background: var(--color-primary);
    color: var(--color-on-primary);
    border-radius: var(--radius-sm);
    font-size: var(--fs-control);
    font-weight: 500;
    text-decoration: none;
    transition: background var(--transition);
}

.block__view-all > a:hover { background: var(--color-primary-light); }

/* The products grid takes the pill form: an outlined capsule carrying the
   label and a round ink chip with the arrow. On hover the capsule fills with
   ink, the chip inverts, and the arrow nudges forward. The generic
   `.block__view-all > a` button rules above are undone here because the
   wrapper is shared; the pill itself is defined once under .view-all-pill. */
.block__view-all.block__view-all--link { margin-block-start: 1.5rem; }
.block__view-all.block__view-all--link > a {
    min-inline-size: 0;
    min-block-size: 0;
    font-weight: 600;
    gap: 0.875rem;
    padding-block: 0.3125rem;
    padding-inline: 1.375rem 0.3125rem;
    background: transparent;
    color: var(--pill-ink);
    border-radius: 999px;
    transition:
        background-color 0.3s var(--pill-ease),
        color 0.3s var(--pill-ease),
        border-color 0.3s var(--pill-ease),
        transform 0.3s var(--pill-ease),
        box-shadow 0.3s var(--pill-ease);
}
.block__view-all.block__view-all--link > a:hover,
.block__view-all.block__view-all--link > a:focus-visible { background: var(--pill-ink); color: var(--pill-paper); }
.block__view-all.block__view-all--link:not([hidden]) { animation: view-all-in 0.45s var(--pill-ease, ease-out) both; }

.view-all-pill {
    --pill-ink: var(--color-primary);
    --pill-paper: var(--color-bg);
    --pill-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
    display: inline-flex;
    align-items: center;
    gap: 0.875rem;
    padding-block: 0.3125rem;
    padding-inline: 1.375rem 0.3125rem;
    border: 1.5px solid var(--pill-ink);
    border-radius: 999px;
    background: transparent;
    color: var(--pill-ink);
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    transition:
        background-color 0.3s var(--pill-ease),
        color 0.3s var(--pill-ease),
        border-color 0.3s var(--pill-ease),
        transform 0.3s var(--pill-ease),
        box-shadow 0.3s var(--pill-ease);
}

.view-all-pill__chip {
    display: grid;
    place-items: center;
    flex: none;
    inline-size: 2.125rem;
    block-size: 2.125rem;
    border-radius: 50%;
    background: var(--pill-ink);
    color: var(--pill-paper);
    transition:
        background-color 0.3s var(--pill-ease),
        color 0.3s var(--pill-ease),
        transform 0.3s var(--pill-ease);
}

/* The arrow is drawn pointing right — forward in English — and mirrored in
   Arabic. The hover nudge is composed after the mirror so it always moves
   the arrow in the reading direction. */
.view-all-pill svg { display: block; transition: transform 0.3s var(--pill-ease); }
[dir="rtl"] .view-all-pill svg { transform: scaleX(-1); }

.view-all-pill:hover,
.view-all-pill:focus-visible {
    background: var(--pill-ink);
    color: var(--pill-paper);
    transform: translateY(-1px);
    box-shadow: 0 10px 24px -12px var(--pill-ink);
    outline: none;
}

.view-all-pill:hover .view-all-pill__chip,
.view-all-pill:focus-visible .view-all-pill__chip {
    background: var(--pill-paper);
    color: var(--pill-ink);
    transform: scale(1.06);
}

.view-all-pill:hover svg,
.view-all-pill:focus-visible svg { transform: translateX(3px); }
[dir="rtl"] .view-all-pill:hover svg,
[dir="rtl"] .view-all-pill:focus-visible svg { transform: scaleX(-1) translateX(3px); }

.view-all-pill:active { transform: translateY(0); box-shadow: none; }

/* Entrance: the link is revealed by app.js once the component reports more
   products than it shows, so it animates in rather than popping. */
@keyframes view-all-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .view-all-pill,
    .view-all-pill__chip,
    .view-all-pill svg { transition: none; }
    .view-all-pill:hover,
    .view-all-pill:focus-visible { transform: none; box-shadow: none; }
    .view-all-pill:hover .view-all-pill__chip,
    .view-all-pill:focus-visible .view-all-pill__chip { transform: none; }
    .view-all-pill:hover svg,
    .view-all-pill:focus-visible svg { transform: none; }
    [dir="rtl"] .view-all-pill:hover svg,
    [dir="rtl"] .view-all-pill:focus-visible svg { transform: scaleX(-1); }
}

/* On the navy ground the pill inverts with the rest of the block. */
.block--bg-ink .view-all-pill {
    --pill-ink: var(--color-cream);
    --pill-paper: var(--color-primary);
}
.block--bg-ink .block__view-all.block__view-all--link > a { background: transparent; color: var(--pill-ink); }
.block--bg-ink .block__view-all.block__view-all--link > a:hover,
.block--bg-ink .block__view-all.block__view-all--link > a:focus-visible { background: var(--pill-ink); color: var(--pill-paper); }

@media (prefers-reduced-motion: reduce) {
    .block__view-all.block__view-all--link:not([hidden]) { animation: none; }
}

/* app.js unhides it once the grid reports more products than it shows. */
.block__view-all[hidden] { display: none; }


/* ------------------------------------------------------ section grounds */

/*
 * Per-block ground, chosen by the merchant (`background` in each schema).
 *
 * The reference does not separate sections with whitespace — it butts them
 * together and changes the GROUND, so "Products for 96 SAR" on grey and "50%
 * off" on white read as two sections with no gap between them at all. Blush is
 * not decoration either: its Rose Collection band is pink because the products
 * in it are, and the band is doing the same job a heading would.
 */
.block--bg-default { background: var(--color-bg); }
.block--bg-surface { background: var(--color-surface); }
.block--bg-cream   { background: var(--color-cream); }
.block--bg-blush   { background: #ffe9ea; }

/* On the navy ground everything inverts: the base's ink-on-white defaults are
   unreadable there, so the whole subtree is re-inked rather than each part. */
.block--bg-ink {
    background: var(--color-primary);
    color: rgba(255, 255, 255, 0.75);
}
.block--bg-ink .block-head__title,
.block--bg-ink h2,
.block--bg-ink h3,
.block--bg-ink .f-card__link { color: var(--color-cream); }
.block--bg-ink .block-head__sub,
.block--bg-ink .f-card__price-now { color: rgba(255, 255, 255, 0.75); }
.block--bg-ink .f-card__add {
    border-color: rgba(255, 255, 255, 0.35);
    color: #fff;
}
.block--bg-ink .f-card__add:hover:not(:disabled) {
    background: var(--color-cream);
    border-color: var(--color-cream);
    color: var(--color-primary);
}
.block--bg-ink .block__view-all > a {
    background: var(--color-cream);
    color: var(--color-primary);
}


/* ------------------------------------------------------------ hero slider */

/*
 * Inset and rounded, matching the reference: 18px corners, sitting on the page
 * grid rather than bleeding to the viewport edge.
 */
.block--hero {
    padding-block: 1.5625rem 0;
}

/*
 * The radius belongs to the ARTWORK, not to the slider element.
 *
 * <falak-slider> is taller than its media because it also holds the dot row, so
 * rounding it curved empty space below the picture while the picture's own
 * bottom corners stayed square. Rounding the slide and the image instead means
 * the corners land on the thing you actually see, whatever the dots do.
 */
.hero-slider {
    display: block;
}

.hero-slide {
    position: relative;
    border-radius: var(--radius-lg);
    overflow: hidden;
}

/* Also on the image itself: the slide is only as tall as its content, but a
   video poster or a slow-loading still can briefly exceed it. */
.hero-slide__img {
    border-radius: var(--radius-lg);
}

/*
 * The reference's slides are finished artwork — the headline, the price and the
 * app badges are all inside the image file. So the slide's job is to show the
 * picture undistorted and nothing else.
 *
 * aspect-ratio rather than a fixed height: at 1300x480 the reference runs
 * roughly 2.7:1, and a fixed height would letterbox or crop it on any other
 * viewport width.
 */
.hero-slide__img {
    display: block;
    inline-size: 100%;
    aspect-ratio: 2.7 / 1;
    object-fit: cover;
    background: var(--color-surface);
}

/*
 * Text over the slide is hidden unless the merchant actually typed some.
 *
 * With artwork-style slides the overlay would print a second headline on top of
 * the one already in the picture. :has() lets the same template serve both
 * kinds of slide — typed copy shows, empty copy leaves the artwork alone.
 */
.hero-slide__content {
    position: absolute;
    inset-block-end: 2rem;
    inset-inline-start: 0;
    inset-inline-end: 0;
    color: #fff;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
}

.hero-slide__content:not(:has(.hero-slide__title:not(:empty))):not(:has(.btn)) {
    display: none;
}

.hero-slide__title {
    margin: 0 0 0.5rem;
    color: #fff;
    font-size: var(--fs-hero);
}

.hero-slide__text {
    margin: 0 0 1rem;
    font-size: var(--fs-lead);
}

/*
    Block layout, so the section's "Text alignment" control does something.

    This column used to be a flex column with `align-items: flex-start`, which
    shrink-wraps every child to its own content width. `text-align` moves words
    inside a box — it can never move a flex item, and a box with no slack has
    nothing to move them in. Choosing centre or end in the customizer changed
    the computed value and nothing on screen.

    The measures go with it. A capped box stays anchored at the start, so a
    centred headline sat centred inside 18ch of a 66ch column — left of centre,
    while the button (inline-flex, so genuinely inline-level) centred across the
    whole column. Half-centred reads as broken. Per-element width and box
    position are what the element style roles are for; this blueprint declares
    none yet.

    The margins carry the spacing the flex `gap` used to add on top of each
    child's own margin, so the default start-aligned hero is unchanged.
*/
.hero-slide__content { display: block; }
.hero-slide__title { max-width: none; margin: 0 0 1.25rem; }
.hero-slide__text { max-width: none; margin: 0 0 1.75rem; }

/* ---- slider controls, shared by every rail ---- */

/*
 * Arrows and dots, measured off the reference rather than estimated:
 *
 *   arrow   35px white disc, NO shadow, 10px inside the slide's edge,
 *           centred on the MEDIA (not on the slider box, which is taller
 *           because it also holds the dot row)
 *   dot     10px ring — 1px of half-strength ink, transparent centre
 *   active  the same ring, filled with solid ink
 *   pitch   20px, i.e. a 10px dot with a 10px gap
 *
 * The base pulls the arrows OUTSIDE the frame with a negative margin, which is
 * right for a rail sitting in open space and wrong for a hero, where they ended
 * up floating on the page margin instead of over the artwork.
 *
 * That rule is `.f-slider:not(.f-slider--controls-outer) .f-slider__arrow` —
 * three classes, because a `:not()` argument counts toward specificity. So the
 * override is written `.block .f-slider .f-slider__arrow` to match it and win
 * on order; at two classes it silently lost and the arrows kept both the
 * negative margin and the shadow.
 */
.block .f-slider__controls {
    /* Stretch from the top of the slider to just above the dot row, then centre
       the arrows in what is left. Centring on the slider's own box would sit
       them low by half the dot row's height. */
    top: 0;
    bottom: var(--slider-dots-space, 1.875rem);
    height: auto;
    align-items: center;
    padding-inline: 0.625rem;
}

.block .f-slider .f-slider__arrow {
    inline-size: 2.1875rem;
    block-size: 2.1875rem;
    /* The base's negative margin is what put these outside the frame. */
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: #fff;
    color: var(--color-text-soft);
    box-shadow: none;
    opacity: 1;
}

.block .f-slider .f-slider__arrow:hover {
    background: #fff;
    color: var(--color-text);
}

/*
 * Dots sit BELOW the media on the page's own ground, never over the artwork.
 *
 * The reference keeps them off the image entirely — over a photograph a dot row
 * is either invisible or needs a scrim, and a scrim across the bottom of
 * finished artwork is a grey smear over someone's design.
 */
.block .f-slider__dots {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.625rem;
    /* Equal space above and below, so the row reads as attached to the slider
       rather than drifting toward whatever follows it. This is also the value
       .f-slider__controls reserves above. */
    margin-block: 0.625rem;
}

.block .f-slider__dot {
    inline-size: 0.625rem;
    block-size: 0.625rem;
    padding: 0;
    border: 1px solid color-mix(in srgb, var(--color-primary) 50%, transparent);
    border-radius: 50%;
    background: transparent;
    transition: background var(--transition);
}

.block .f-slider__dot[aria-selected="true"],
.block .f-slider__dot.is-active {
    background: var(--color-primary);
}

/*
 * One slide is a banner, not a carousel: no dots, no arrows.
 *
 * Three classes deliberately. `.f-slider--static .f-slider__dots` (the base
 * rule `static-when-single` relies on) is two, and so is `.block
 * .f-slider__dots` above — which, being later in this file, won on order and
 * put the dot back.
 */
.block .f-slider--static .f-slider__dots,
.block .f-slider--static .f-slider__controls { display: none; }

/* A dot the rail can never stop on is hidden by app.js (wireSliderDots);
   the rule above sets display on the dot, so the attribute needs its own. */
.block .f-slider__dot[hidden] { display: none; }

/* ------------------------------------------- products rail as a grid */

/*
 * The reference's "featured collection" is a static row, not a carousel: four
 * cards, no arrows, and a view-all pill underneath.
 *
 * The controls are hidden rather than turned off at the component, because
 * <falak-products-slider> renders them whether or not `show-controls` is
 * passed. Hiding them keeps swipe working on a phone — which the reference has
 * too — while removing the desktop furniture it does not have.
 */
.block--products-slider .f-slider__controls { display: none; }

/* The component's own head is unused — this template renders .block-head
   instead — but it still emits an empty one, which would otherwise add a gap
   above every section. */
.block--products-slider .f-slider__head:empty { display: none; }

.block__view-all {
    display: flex;
    justify-content: center;
    margin-block-start: 0.625rem;
}

.block__view-all > a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 7.5rem;
    min-block-size: var(--control-h);
    padding-inline: 1.875rem;
    background: var(--color-primary);
    color: var(--color-on-primary);
    border-radius: var(--radius-sm);
    font-size: var(--fs-control);
    font-weight: 500;
    text-decoration: none;
    transition: background var(--transition);
}

.block__view-all > a:hover { background: var(--color-primary-light); }


/* ----------------------------------------------------------- banner */

/*
 * A promotional banner is a picture with rounded corners, full stop. Any typed
 * copy lays over it; most of the reference's banners have none, because the
 * artwork carries its own.
 */
.block--banner .banner {
    position: relative;
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.block--banner .banner__image {
    display: block;
    inline-size: 100%;
    object-fit: cover;
    background: var(--color-surface);
}

.block--banner .banner__content {
    position: absolute;
    inset-block-end: 2rem;
    inset-inline-start: 2rem;
    color: #fff;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
}

.block--banner .banner__content:not(:has(.banner__title:not(:empty))):not(:has(.btn)) {
    display: none;
}

.block--banner .banner__title {
    margin: 0 0 0.5rem;
    color: #fff;
}

/* Full-bleed variant keeps the corners square — a rounded card that touches
   both viewport edges reads as a rendering error rather than a choice. */
.block--banner.is-full .banner { border-radius: 0; }


/* --------------------------------------------- image + copy panel */

/*
 * The reference's "image with text": artwork on one side, a CREAM panel of copy
 * on the other, both the same height, no gap between them.
 *
 * The cream is what makes the pair read as one unit — with a white panel the
 * copy would look like it had fallen off the section above.
 */
.block--featured-products .featured-products__grid,
.cat-feature {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
    gap: 1.25rem;
}

.block--featured-products .featured-products__panel {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
    gap: 0;
    border-radius: var(--radius);
    overflow: hidden;
}

.block--featured-products .featured-products__image,
.cat-feature__image {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    border-radius: var(--radius);
    background: var(--color-surface);
}

.block--featured-products .featured-products__body,
.cat-feature__copy {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2.5rem 2rem;
    background: var(--color-cream);
    border-radius: var(--radius);
    text-align: center;
}

.block--featured-products .featured-products__title,
.cat-feature__title {
    margin: 0;
    font-size: var(--fs-section);
    font-weight: 700;
    color: var(--color-text);
}

.cat-feature__text,
.block--featured-products .featured-products__body p {
    margin: 0;
    color: var(--color-text-soft);
}

.cat-feature__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-block-size: var(--control-h);
    margin-block-start: 0.75rem;
    padding-inline: 1.875rem;
    background: var(--color-primary);
    color: var(--color-on-primary);
    border-radius: var(--radius-sm);
    font-size: var(--fs-control);
    text-decoration: none;
}

.cat-feature__cta:hover { background: var(--color-primary-light); }


/* ------------------------------------------------- featured product */

/*
 * One product given the width: artwork on one side, and on the other a stack
 * that reads exactly like the top of a product page — name, was/now price,
 * quantity, one full-width navy action, then a quiet link through to the rest.
 *
 * Left-aligned, not centred: this block is a buying decision, and a centred
 * column of mixed-length lines makes the price harder to find than a flush edge
 * does.
 */
.block--featured-product .featured-product__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: center;
    gap: 3rem;
}

.block--featured-product .featured-product__image {
    inline-size: 100%;
    aspect-ratio: 1 / 1;
    object-fit: contain;
    background: transparent;
}

/* Live mode: the image sits inside a link, over a skeleton that keeps the
   square while the product loads. */
.block--featured-product .featured-product__media {
    display: block;
    position: relative;
}

.block--featured-product .featured-product__placeholder {
    display: block;
    aspect-ratio: 1 / 1;
    border-radius: var(--radius);
    background: var(--color-surface);
}

.block--featured-product .featured-product__placeholder[hidden] { display: none; }

.block--featured-product .featured-product__desc {
    margin: 0;
    color: var(--color-text-soft);
}

.block--featured-product .featured-product__name a {
    color: inherit;
    text-decoration: none;
}

.block--featured-product .featured-product__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    text-align: start;
}

/* The campaign line sits directly over the product name, start-aligned with
   the rest of the column — quiet, so the name below stays the headline. */
.block--featured-product .featured-product__head {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

.block--featured-product .featured-product__eyebrow {
    margin: 0;
    font-size: var(--fs-body);
    font-weight: 500;
    color: var(--color-text-soft);
}

.block--featured-product .featured-product__eyebrow:empty { display: none; }

.block--featured-product .featured-product__tag {
    margin: 0;
    font-size: var(--fs-nav);
    color: var(--color-text-faint);
}

.block--featured-product .featured-product__name {
    margin: 0;
    font-size: var(--fs-block);
    /* Same family as the product cards: semibold, not bold — the spotlight is
       a bigger card, not a different vocabulary, and Plex's 700 overshoots
       what the reference's bold renders at (the Greta substitution note on
       .f-card__title). */
    font-weight: 600;
}

.block--featured-product .featured-product__price {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    margin: 0;
}

.block--featured-product .featured-product__price del {
    font-size: var(--fs-body);
    color: var(--color-text-soft);
}

/* The now-price is the largest thing in the block after the name — on the
   reference it is set well above body size and in red. */
.block--featured-product .featured-product__price span {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--color-sale);
}

.block--featured-product .featured-product__body .btn {
    inline-size: 100%;
    min-block-size: 3.5rem;
    font-size: var(--fs-lead);
}

/*
 * The SDK's add-to-cart renders its host as `display: contents` and puts its
 * own .f-btn inside, so classes on <falak-add-product-button> style nothing —
 * the inner button is the box. Same numbers as the .btn rule above, so the
 * legacy link CTA and the live one are indistinguishable.
 */
.block--featured-product .featured-product__cta .f-add-product__button {
    inline-size: 100%;
    min-block-size: 3.5rem;
    border-radius: var(--radius-sm);
    font-size: var(--fs-lead);
    font-weight: 500;
}


/* --------------------------------------------------------- footer */

/*
 * Four columns: the store's identity (mark, about, socials, VAT) then three
 * link lists. The identity column is wider than the others because it carries
 * a paragraph, and equal columns would set that paragraph in a measure too
 * narrow to read.
 */
.site-footer__grid,
.site-footer__cols {
    display: grid;
    grid-template-columns: 1.6fr 1fr 1fr 1fr;
    gap: 2.5rem;
    align-items: start;
}

.site-footer__about {
    max-inline-size: 34rem;
    color: rgba(255, 255, 255, 0.75);
    /* Justified, as the reference sets it — with a paragraph this size beside
       three ragged link columns, a flush right edge is what stops the block
       looking accidental. */
    text-align: justify;
}

.site-footer__social {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
    margin-block-start: 1.25rem;
}

.site-footer ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* Trust marks (VAT certificate, Saudi Business Centre) keep white grounds —
   they are official artwork and must not be tinted to fit the footer. */
.site-footer__badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-block-start: 1rem;
}

.site-footer__badges img {
    block-size: 4.5rem;
    inline-size: auto;
    background: #fff;
    border-radius: 0.25rem;
}

/* ---- app row ---- */

.site-footer__apps {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1.25rem;
    margin-block-start: 1.875rem;
    padding-block-start: 1.875rem;
    border-block-start: 1px solid rgba(255, 255, 255, 0.08);
}

.site-footer__apps-links {
    display: flex;
    gap: 0.75rem;
}

.site-footer__apps-links img {
    block-size: 3.125rem;
    inline-size: auto;
}

/* ---- payment + legal bar ---- */

.site-footer__payments {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-block-end: 1rem;
}

/* Payment marks are supplied as brand artwork on light grounds, so each sits on
   its own white chip rather than being knocked out against the navy. */
.site-footer__payments img,
.site-footer .f-payments__item {
    block-size: 1.875rem;
    inline-size: auto;
    padding: 0.25rem 0.5rem;
    background: #fff;
    border-radius: 0.375rem;
}

.site-footer__legal {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.25rem 1.25rem;
    font-size: var(--fs-nav);
}

.site-footer__copyright {
    margin: 0.5rem 0 0;
    text-align: center;
    font-size: var(--fs-nav);
    color: rgba(255, 255, 255, 0.6);
}


/* ------------------------------------------------ blocks on phones */

@media (max-width: 767px) {
    /* Every two-up editorial layout stacks. The image leads, because on a phone
       the picture is what identifies the section. */
    .block--featured-products .featured-products__grid,
    .block--featured-products .featured-products__panel,
    .cat-feature,
    .block--featured-product .featured-product__grid,
    .site-footer__grid,
    .site-footer__cols {
        grid-template-columns: 1fr;
        gap: 1.25rem;
    }

    .block--featured-product .featured-product__grid { gap: 1.5rem; }

    .block--featured-products .featured-products__body,
    .cat-feature__copy {
        padding: 1.5rem 1.25rem;
    }

    /* A 2.7:1 hero is a 130px-tall sliver on a phone. The reference serves a
       squarer crop there; without a second asset the next best thing is to let
       the same image stand taller and crop its sides. */
    .hero-slide__img { aspect-ratio: 1.6 / 1; }

    .site-footer__about { text-align: start; }

    .site-footer__apps {
        justify-content: center;
        text-align: center;
    }
}


/* ------------------------------------------------ image with text */

/*
 * A square picture with a cream card of copy overlapping it.
 *
 * Measured off the reference: media 650x650 (exactly half the 1300 container),
 * card 690 wide pulled 40px OVER the picture, both at a 10px radius, card
 * centred against the picture's height.
 *
 * The overlap is the point of the section — without it the two are just tiles
 * sitting beside each other. It is a logical margin, so in Arabic the card
 * lands on the other side and overlaps from the other edge with no second rule.
 */
.iwt {
    display: flex;
    align-items: center;
}

.iwt__media {
    /* half the row, and square */
    flex: 0 0 50%;
    aspect-ratio: 1 / 1;
    border-radius: 0.625rem;
    overflow: hidden;
    background: var(--color-surface);
}

.iwt__media img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

.iwt__panel {
    /* takes the rest of the row, plus the 40px it steals back from the media */
    flex: 1 1 auto;
    /* above the picture, not under it */
    position: relative;
    z-index: 1;
    margin-inline-start: -2.5rem;
    padding: 3.75rem 4.375rem 4.375rem;
    background: var(--color-cream);
    border-radius: 0.625rem;
    text-align: center;
}

/* Flipped: the picture moves to the trailing edge, so the card has to overlap
   from the other side too — otherwise it pulls away from the picture and
   leaves a gap where the overlap should be. */
.iwt--flipped {
    flex-direction: row-reverse;
}

.iwt--flipped .iwt__panel {
    margin-inline-start: 0;
    margin-inline-end: -2.5rem;
}

/* A section with no picture set: the card should not keep half a row of empty
   space beside it, nor overlap something that is not there. */
.iwt:not(:has(.iwt__media)) .iwt__panel {
    margin-inline: 0;
}

.iwt__eyebrow {
    margin: 0;
    font-size: var(--fs-body);
    font-weight: 400;
    color: rgba(16, 22, 49, 0.7);
}

.iwt__title {
    margin: 0;
    font-size: var(--fs-section);
    /* 600 rather than the reference's 700 — same substituted-font reasoning as
       the product card: Plex's bold is heavier than Greta's. */
    font-weight: 600;
    line-height: 1.23;
    color: var(--color-text);
}

.iwt__text {
    margin: 1.25rem 0 0;
    font-size: var(--fs-body);
    color: var(--color-text-soft);
}

.iwt__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 7.5rem;
    min-block-size: var(--control-h);
    margin-block-start: 1.875rem;
    padding-inline: 1.875rem;
    background: var(--color-primary);
    color: var(--color-on-primary);
    border-radius: var(--radius-sm);
    font-size: var(--fs-control);
    font-weight: 500;
    text-decoration: none;
    transition: background var(--transition);
}

.iwt__cta:hover { background: var(--color-primary-light); }

/* On a cream ground the card would vanish, so it inverts to the page's own
   white and keeps its edge. */
.block--bg-cream .iwt__panel {
    background: var(--color-bg);
}

@media (max-width: 900px) {
    /*
     * Stacked, and the overlap turns vertical: the card rides up over the foot
     * of the picture instead of over its side, which keeps the two joined
     * rather than becoming two stacked boxes with a gap.
     */
    .iwt,
    .iwt--flipped {
        flex-direction: column;
    }

    .iwt__media {
        flex: none;
        inline-size: 100%;
    }

    .iwt__panel,
    .iwt--flipped .iwt__panel {
        inline-size: calc(100% - 2rem);
        margin-inline: 0;
        margin-block-start: -2.5rem;
        padding: 2rem 1.5rem 2.25rem;
    }
}


/* ------------------------------------------------------ testimonials */

/*
 * Customer voices, built on <falak-slider> — the SDK's carousel — with the card
 * styled here. The card itself renders <falak-rating-stars> for its rating, so
 * the only thing the theme owns is the look.
 *
 * The reference's card: a quiet framed box, the quote in soft ink, then a rule,
 * then the name with its date beneath. No avatar and no quotation glyph — both
 * pull attention to the frame instead of to what the customer said.
 */
.block--testimonials .testimonials__slider,
.block--testimonials custom-falak-testimonials {
    display: block;
}

.testimonial-card {
    display: flex;
    flex-direction: column;
    /* the rule sits ABOVE the byline, so the byline is pushed to the foot and
       cards of unequal quote length still line their rules up */
    justify-content: space-between;
    block-size: 100%;
    padding: 1.5rem;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    text-align: start;
}

/*
 * No decorative quote mark and no avatar.
 *
 * The card carries both for the theme it was inherited from. The reference has
 * neither — its card is the words and who said them, and a glyph or a circle of
 * initials beside a two-line quote crowds a card this size.
 */
.testimonial-card__quote,
.testimonial-card__avatar {
    display: none;
}

.testimonial-card__text {
    margin: 0 0 1.25rem;
    font-size: var(--fs-nav);
    line-height: 1.9;
    color: var(--color-text-soft);
}

/* The byline sits under a hairline that spans the card. */
.testimonial-card__who {
    display: block;
    padding-block-start: 1rem;
    border-block-start: 1px solid var(--color-border);
}

.testimonial-card__meta {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

.testimonial-card__name {
    font-size: var(--fs-nav);
    font-weight: 600;
    color: var(--color-text);
}

.testimonial-card__date {
    font-size: var(--fs-meta);
    color: var(--color-text-faint);
}

.testimonial-card__stars {
    margin-block-start: 0.25rem;
}

/*
 * Dots: the active one is a PILL, not a bigger circle.
 *
 * The reference widens the current dot rather than recolouring a same-sized
 * one, which reads as position-in-a-row at a glance. Same 10px ring the hero
 * uses, so the two carousels agree.
 */
.block--testimonials .f-slider__dot {
    inline-size: 0.625rem;
    block-size: 0.625rem;
    border: 0;
    border-radius: 999px;
    background: color-mix(in srgb, var(--color-primary) 30%, transparent);
    transition: inline-size var(--transition), background var(--transition);
}

.block--testimonials .f-slider__dot[aria-selected="true"],
.block--testimonials .f-slider__dot.is-active {
    inline-size: 1.75rem;
    background: var(--color-primary);
}

/* The rail carries no arrows in the reference — the dots and a swipe are the
   whole control surface. */
.block--testimonials .f-slider__controls { display: none; }

@media (max-width: 767px) {
    .testimonial-card { padding: 1.125rem; }
}


/* ----------------------------------------------------------- brands */

/*
 * An "Our clients" wall that moves.
 *
 * The reference: a centred title with a short bar in the primary under it,
 * then every mark on its own flat white card with a soft shadow, in straight
 * rows. The cards are the whole device — they turn the wildly different
 * artwork merchants upload (a wide wordmark here, a square roundel there)
 * into one optical grid. The ground is a fixed light grey on every store
 * rather than a merchant option, so the wall looks the same whatever the
 * brand colours are.
 *
 * Motion is a continuous rail (the theme's own marquee — see the template for
 * why not <falak-slider>): a duplicated group translated by exactly one
 * group's width, which loops seamlessly and costs one composited transform
 * per frame. It pauses on hover and focus, runs the other way in RTL, and
 * stands still under prefers-reduced-motion. The still wall is the fallback
 * and the "still rows" choice.
 */
.block--brands {
    position: relative;
    /* a little more air than an ordinary band: the logos are small and the
       rows need room to read as a wall rather than a strip */
    padding-block: 3.25rem;
    /* the rails are full-bleed and clip their own overflow; this is the
       backstop so nothing in here can widen the page */
    overflow: hidden;
    /*
     * A FIXED ground, deliberately outside the token system: this wall is the
     * same light grey on every store, whatever the merchant's colours and in
     * the dark store mode too, so the ink below is literal as well — the
     * tokens would flip to cream text on this grey when the store goes dark.
     */
    background: #f5f5f5;
    color: #1a1a1a;
}

.block--brands .block-head { margin-block-end: 2.25rem; }

.block--brands .block-head__title { color: #1a1a1a; }
.block--brands .block-head__sub { color: #6b6b6b; }

/*
 * The underline.
 *
 * Onyx hides `.block-head__rule` everywhere (the diamond ornament is Nova's),
 * but this wall's reference draws a short solid bar in the primary under its
 * centred title, so the shared markup gets its rule back here as that bar:
 * one flat rectangle, no gradient gap and no diamond. It draws itself in
 * from the centre once the heading has arrived.
 */
.block--brands .block-head__rule {
    display: block;
    inline-size: 9.5rem;
    block-size: 3px;
    margin-block-start: 0.875rem;
    border-radius: 2px;
    background: var(--color-primary);
    transform-origin: center;
}

.block--brands .block-head__rule::before,
.block--brands .block-head__rule::after { content: none; }

.block--brands .block-head__rule span { display: none; }

/* The reveal system fades and lifts the rule like any heading part; this adds
   the draw-in on top. `scale` is its own property, so it stacks with the
   reveal's `translate` instead of fighting it. */
.block--brands .block-head__rule[data-reveal] {
    scale: 0 1;
    transition:
        opacity 0.7s cubic-bezier(0.22, 0.7, 0.3, 1),
        translate 0.95s cubic-bezier(0.22, 0.7, 0.3, 1),
        scale 0.8s cubic-bezier(0.22, 0.7, 0.3, 1);
    transition-delay: var(--reveal-delay, 0ms), var(--reveal-delay, 0ms), calc(var(--reveal-delay, 0ms) + 200ms);
}

.block--brands .block-head__rule[data-reveal].is-revealed { scale: 1 1; }

/*
 * The card: flat white, a small radius, no border, lifted off the ground by a
 * soft spread shadow. Hover lifts it further and lets the mark grow a touch.
 */
.brand {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    min-block-size: 5.75rem;
    padding: 1rem 1.25rem;
    border-radius: 0.5rem;
    background: #fff;
    box-shadow: 0 2px 12px rgba(16, 22, 49, 0.09);
    transition: transform var(--transition), box-shadow var(--transition);
}

.brand:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 28px rgba(16, 22, 49, 0.14);
}

.brand__link {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 100%;
    block-size: 100%;
}

/*
 * One optical size for every mark.
 *
 * Brand artwork arrives at wildly different aspect ratios — a wordmark is wide
 * and short, a roundel is square. Capping HEIGHT and letting width follow keeps
 * them all reading at the same weight, which is what makes a logo row look
 * deliberate rather than pasted together.
 */
.brand__logo {
    max-block-size: 3.25rem;
    max-inline-size: 100%;
    inline-size: auto;
    object-fit: contain;
    transition: transform 320ms cubic-bezier(0.22, 0.7, 0.3, 1);
}

.brand:hover .brand__logo { transform: scale(1.07); }

/*
 * The rails: full-bleed, with their edges faded out.
 *
 * Deliberately outside `.container` — cards that drift in and out of the page
 * edge read as an endless strip, where a loop that starts and stops at the
 * container's gutter reads as a widget. The mask is the piece that sells it:
 * without it the leading card pops into existence at a hard edge.
 *
 * `container-type: inline-size` makes `cqw` below measure this element, which
 * is how a card can be sized from the merchant's "logos in view" with no JS.
 * The block padding is room for the hover lift and the shadow, which the
 * overflow clip would otherwise cut.
 */
.brands-rail {
    --brands-gap: 1.5rem;
    container-type: inline-size;
    overflow: hidden;
    padding-block: 0.75rem;
    mask-image: linear-gradient(to right,
        transparent, #000 7rem, #000 calc(100% - 7rem), transparent);
}

.brands-rail + .brands-rail { margin-block-start: 0.25rem; }

.brands-rail__lane {
    display: flex;
    inline-size: max-content;
}

.brands-rail__group {
    display: flex;
    align-items: stretch;
    flex: 0 0 auto;
    gap: var(--brands-gap);
    /*
     * The gap BETWEEN two groups lives here rather than on the lane.
     *
     * The loop translates by exactly one group's width; a gap on the lane is
     * not part of that width, so every lap would land half a gap short and the
     * row would visibly jump once per cycle.
     */
    padding-inline-end: var(--brands-gap);
}

.brands-rail .brand {
    inline-size: calc(
        (100cqw - var(--brands-per-view, 6) * var(--brands-gap)) / var(--brands-per-view, 6)
    );
    min-inline-size: 8rem;
    max-inline-size: 15rem;
}

/*
 * The drift.
 *
 * Duration comes from the logo COUNT and the merchant's pace (both written
 * inline by the template), so twelve marks travel at the same speed as four
 * rather than three times faster — one group's width always takes
 * count × pace. The shift is one group as a share of the lane: 50% for two
 * groups, 25% for the four the template emits when there are few logos.
 */
.brands--rolling .brands-rail__lane {
    animation: onyx-brands-roll calc(var(--brands-count, 6) * var(--brands-pace, 3.25s)) linear infinite;
}

@keyframes onyx-brands-roll {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(calc(var(--brands-dir, -1) * var(--brands-shift, 50%)), 0, 0); }
}

/* RTL lays the groups out right-to-left, so the lane has to travel the other
   way for the next group to arrive from the empty side. The second of two
   rails runs against its neighbour, in either direction. */
[dir="rtl"] .brands-rail { --brands-dir: 1; }
.brands-rail--reverse { --brands-dir: 1; }
[dir="rtl"] .brands-rail--reverse { --brands-dir: -1; }

/* Stop for anyone who looks: a mark cannot be read, and a link cannot be
   clicked, while it is moving. Focus counts as looking — tabbing through the
   logos would otherwise chase a moving target. */
.brands--rolling .brands-rail:hover .brands-rail__lane,
.brands--rolling .brands-rail:focus-within .brands-rail__lane {
    animation-play-state: paused;
}

/*
 * The still wall.
 *
 * A wrapping flex row rather than a grid, because the reference centres a
 * short last row (seven, then three in the middle) where a grid would park
 * the leftovers at the inline start. Each card takes an equal share of the
 * wall from `--brands-cols` (written inline by the template as
 * min(count, in view)), capped so a short row of wide cards does not stretch
 * across the full 1400px.
 */
.brands-wall {
    --brands-gap: 1.5rem;
    container-type: inline-size;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--brands-gap);
}

.brands-wall .brand {
    inline-size: calc(
        (100cqw - (var(--brands-cols, 6) - 1) * var(--brands-gap)) / var(--brands-cols, 6)
    );
    max-inline-size: 13rem;
}

/*
 * Reduced motion: a plain swipeable strip.
 *
 * Nothing drifts, so the duplicate groups would read as the same logos listed
 * twice — they come out, and the rail scrolls natively instead. No scrollbar:
 * the faded edges already say the row continues.
 */
@media (prefers-reduced-motion: reduce) {
    .brands--rolling .brands-rail__lane { animation: none; }

    .brands-rail {
        overflow-x: auto;
        scrollbar-width: none;
    }

    .brands-rail::-webkit-scrollbar { display: none; }

    .brands-rail__group[aria-hidden="true"] { display: none; }

    .brand__logo { transition: none; }
}

@media (max-width: 1024px) {
    .brands-rail,
    .brands-wall { --brands-gap: 1.25rem; }

    .brands-rail .brand { min-inline-size: 7.5rem; }
}

@media (max-width: 767px) {
    .block--brands { padding-block: 2.5rem; }
    .block--brands .block-head { margin-block-end: 1.5rem; }

    .brands-rail {
        --brands-gap: 0.875rem;
        mask-image: linear-gradient(to right,
            transparent, #000 2rem, #000 calc(100% - 2rem), transparent);
    }

    .brands-wall { --brands-gap: 0.875rem; }

    .brand {
        min-block-size: 4.75rem;
        padding: 0.75rem 0.875rem;
    }

    /*
     * Phones ignore the merchant's "logos in view" — six cards across 375px
     * are illegible whatever the setting says. The rail shows two and a bit,
     * so the next card is half in frame, which is how a phone row says it
     * keeps going; the wall holds three to a row.
     *
     * Set on the card rather than on the rail or wall because the template
     * writes the count inline there, and an inline declaration beats a
     * stylesheet rule on the same element.
     */
    .brands-rail .brand {
        --brands-per-view: 2.4;
        min-inline-size: 6.5rem;
        max-inline-size: 11rem;
    }

    .brands-wall .brand {
        --brands-cols: 3;
        max-inline-size: none;
    }

    .brand__logo { max-block-size: 2.75rem; }
}


/* ----------------------------------------------- rails: no furniture */

/*
 * app.js draws a custom scrollbar rail under any horizontally-scrolling track
 * (.onyx-rail, inherited from the Nova lineage). Under a product row it lands
 * as a hard dark line between the cards and the view-all button, which reads as
 * a section divider in the wrong place.
 *
 * The reference has no such rail — its rows are grids, and on a phone it lets
 * the native scroll do the talking. So it is hidden here rather than removed
 * from app.js, which still draws it for the genuinely scroll-only rails
 * (category strips, thumbnails) where it is useful.
 */
.block--products-slider .onyx-rail,
.block--featured-products .onyx-rail,
.block--category-feature .onyx-rail,
.block--testimonials .onyx-rail,
.block--blog-slider .onyx-rail,
.block--hero .onyx-rail {
    display: none;
}

/* Testimonials and articles: two across on a phone. The merchant's
   slides-per-view (3 by default) is a desktop count and left each card ~98px
   wide at 375px. Re-declared on the track, as for the product rows, because
   the slider writes the count inline on its host. */
@media (max-width: 767px) {
    .block--testimonials .f-slider__track,
    .block--blog-slider .f-slider__track {
        --f-slider-per-view: 2;
        --f-slider-gap: 12px;
        gap: 12px;
    }
    .block--testimonials .testimonial-card { padding: 1rem; }
}

/* ------------------------------------------- card action: label only */

/*
 * The reference's card button is a bare label — "Add to cart", "Choose
 * options", "Sold out" — with no glyph. <falak-product-card> renders an icon
 * beside it; at 15px regular in a 45px full-width button the icon adds nothing
 * and pushes the label off centre.
 */
.f-card__add > svg { display: none; }

/* --------------------------------------- editorial panel, refined */

/*
 * With no image set, the panel must not keep a half-width empty column.
 * :has() lets the same block serve both cases — picture beside copy when there
 * is a picture, copy full width when there is not.
 */
.block--featured-products .featured-products__panel:not(:has(.featured-products__image)) {
    grid-template-columns: 1fr;
}

.cat-feature:not(:has(.cat-feature__image)) .cat-feature__panel {
    grid-template-columns: 1fr;
}

/* Same for the spotlight block: no artwork, no empty half. */
.block--featured-product .featured-product__grid:not(:has(.featured-product__image)) {
    grid-template-columns: 1fr;
    max-inline-size: 34rem;
    margin-inline: auto;
}

/* ------------------------------------------ empty section guard */

/*
 * A products row whose source returns nothing would otherwise render as a
 * title, a gap, and a view-all button — which looks like a broken section
 * rather than an empty one. The component leaves its viewport empty in that
 * case, so the button is pulled up against the head and the block keeps its
 * band without pretending to hold a row.
 */
.block--products-slider:has(.f-slider__track:empty) .block__view-all {
    margin-block-start: 0;
}

/* ------------------------------------- slider track: correct column width */

/*
 * Every multi-slide rail in the theme was overflowing its own viewport.
 *
 * <falak-slider> lays its track out as a grid and sizes the columns with
 * `grid-auto-columns: calc(16.6667% - 13.3333px)` at six across — but that
 * subtracts only part of the gap each column owes. Six columns of 203.33px
 * plus five 32px gaps is 1380px inside a 1300px track, so the last slide sat
 * at x=-10 and the page's overflow guard clipped it. The brands row showed it
 * as "topface" rendering "pface"; the same arithmetic was quietly cropping the
 * testimonials rail too.
 *
 * n columns separated by n-1 gaps must each be (100% - (n-1)·gap) / n. The
 * component publishes both numbers on itself as --f-slider-per-view and
 * --f-slider-gap, so this one rule corrects every rail without any block
 * having to pass its own values through.
 *
 * !important because the component writes grid-auto-columns inline. A slider
 * using slides-per-view="auto" resolves the var to `auto`, which makes the
 * calc invalid — the declaration is dropped and the component's own sizing
 * stands, which is what that mode wants anyway.
 */
.f-slider__track {
    grid-auto-columns: calc(
        (100% - (var(--f-slider-per-view, 1) - 1) * var(--f-slider-gap, 0px))
        / var(--f-slider-per-view, 1)
    ) !important;
}


/* ------------------------------------------- footer: SDK components */

/*
 * The footer's contents are platform components with their own headings and
 * their own layouts, built for a stacked column. The reference lays the same
 * information out differently — socials as a bare row of discs, payment marks
 * as a centred strip — so each is re-laid here rather than re-templated, which
 * keeps the components shared with the other themes.
 */

/* ---- column headings ---- */

/*
 * The heading is a <summary>, so it needs the marker removed as well as the
 * type set — a disclosure triangle beside a footer heading is the giveaway that
 * an accordion was left switched on for desktop.
 */
.site-footer__heading {
    display: block;
    margin-block-end: 0.75rem;
    color: var(--color-cream);
    font-size: var(--fs-card);
    font-weight: 500;
    line-height: 1.23;
    cursor: default;
    list-style: none;
}

.site-footer__heading::-webkit-details-marker { display: none; }
.site-footer__heading::marker { content: ''; }

.site-footer__links {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.site-footer__hours {
    margin: 0;
    /* The setting is a textarea; this is what turns its newlines into lines
       without passing merchant text through an HTML filter. */
    white-space: pre-line;
    color: rgba(255, 255, 255, 0.75);
    font-size: var(--fs-nav);
}

/* ---- social: a row of discs, no heading ---- */

/*
 * <falak-social> prints its own "Follow us" heading and stacks its list. The
 * reference has neither — just the marks in a row under the about paragraph,
 * where they read as part of the brand block rather than as a section of their
 * own.
 */
.site-footer .f-social__title,
.site-footer .f-social__label {
    display: none;
}

/*
 * flex-direction is stated explicitly, not left to the initial value.
 *
 * The shared base already sets these lists to `column` for its own stacked
 * footer. Declaring only `display: flex` here left that column in place — the
 * cascade only replaces the properties a rule actually names — so the discs
 * came out in a vertical stack 44px wide. Same for the host, which shrink-wraps
 * to that stack unless it is told to fill the column.
 */
.site-footer falak-social.f-social {
    display: block;
    inline-size: 100%;
}

.site-footer .f-social__list {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.625rem;
    margin: 1.25rem 0 0;
    padding: 0;
    inline-size: 100%;
    list-style: none;
}

.site-footer .f-social__item { margin: 0; }

.site-footer .f-social__link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--icon-btn);
    block-size: var(--icon-btn);
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    transition: background var(--transition);
}

.site-footer .f-social__link:hover {
    background: rgba(255, 255, 255, 0.3);
    color: #fff;
}

/* ---- payments: one centred strip ---- */

.site-footer .f-payments__title { display: none; }

.site-footer falak-payments.f-payments {
    display: block;
    inline-size: 100%;
}

.site-footer .f-payments__list {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin: 0 0 1rem;
    padding: 0;
    inline-size: 100%;
    list-style: none;
}

/*
 * Each mark keeps a white chip.
 *
 * These are brand assets drawn for light grounds — mada's blue and green and
 * Apple Pay's black mark all disappear against the navy. A chip per mark is
 * what the reference does, and it is also the only treatment that stays correct
 * whichever gateways a merchant enables.
 */
.site-footer .f-payments__item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 3.5rem;
    block-size: 1.875rem;
    padding: 0.25rem 0.5rem;
    background: #fff;
    border: 0;
    border-radius: 0.375rem;
}

.site-footer .f-payments__logo {
    block-size: 100%;
    inline-size: auto;
    object-fit: contain;
}

.site-footer .f-payments__label {
    color: var(--color-primary);
    font-size: var(--fs-caption);
}

/* ---- trust badges ---- */

.site-footer falak-trust-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
    margin-block-start: 1rem;
}

/* ---- app row ---- */

.site-footer__apps-title {
    margin: 0;
    color: var(--color-cream);
    font-size: var(--fs-card);
    font-weight: 500;
}

.site-footer__apps-text {
    margin: 0.25rem 0 0;
    color: rgba(255, 255, 255, 0.75);
    font-size: var(--fs-nav);
}

.site-footer__apps-links {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.site-footer__apps-links img,
.site-footer__apps-links .f-apps__link img {
    block-size: 3.125rem;
    inline-size: auto;
}

/* ---- bottom bar ---- */

.site-footer__bottom {
    margin-block-start: 1.875rem;
    padding-block-start: 1.875rem;
    border-block-start: 1px solid rgba(255, 255, 255, 0.08);
}

.site-footer__bottom-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
}

.site-footer__copyright {
    margin: 0;
    text-align: center;
    font-size: var(--fs-nav);
    color: rgba(255, 255, 255, 0.6);
}

/* ---- phones ---- */

@media (max-width: 767px) {
    /*
     * The accordion comes back: app.js closes each <details> below this
     * breakpoint, which is what the reference does too. The heading therefore
     * becomes a control again and gets its pointer and its marker back.
     */
    .site-footer__heading {
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-block-end: 0;
        padding-block: 0.75rem;
    }

    .site-footer__group[open] .site-footer__heading {
        margin-block-end: 0.5rem;
    }

    .site-footer__group {
        border-block-end: 1px solid rgba(255, 255, 255, 0.08);
    }

    /* The brand column is not an accordion — it has no heading to collapse. */
    .site-footer__col--brand .site-footer__group { border: 0; }

    .site-footer .f-social__list { justify-content: flex-start; }
}

/* ---- newsletter: <falak-newsletter> on the navy band ---- */

/*
 * The SDK component supplies the form, the wiring and the aria-live status
 * line; this is only its Onyx skin. The component's defaults are drawn for a
 * light page, so on the navy footer the field goes translucent-on-dark and the
 * button takes the cream — the same pair every other control on this ground
 * uses.
 */
.site-footer .f-newsletter__input {
    min-block-size: var(--control-h);
    padding-inline: 1rem;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: var(--radius-sm);
    color: #fff;
}

.site-footer .f-newsletter__input::placeholder { color: rgba(255, 255, 255, 0.45); }

.site-footer .f-newsletter__input:focus-visible {
    outline: 2px solid var(--color-cream);
    outline-offset: 1px;
}

.site-footer .f-newsletter__submit {
    min-block-size: var(--control-h);
    padding-inline: 1.5rem;
    background: var(--color-cream);
    color: var(--color-primary);
    border-radius: var(--radius-sm);
    font-size: var(--fs-control);
    font-weight: 500;
    transition: background var(--transition);
}

.site-footer .f-newsletter__submit:hover:not(:disabled) { background: #e8d5bb; }

.site-footer .f-newsletter__status { color: rgba(255, 255, 255, 0.75); }

/* Error red is unreadable on navy at the token's strength, so the failure
   line lightens instead of darkening. */
.site-footer .f-newsletter__status.is-error { color: #ffb3ad; }


/* ------------------------------------------------------------ modals */

/*
 * A dialog never grows past the window.
 *
 * The SDK sizes .f-modal__body by width only — `max-height` is `none` and its
 * overflow is `visible` — so a tall body simply ran off the screen. The size
 * guide showed it worst: a merchant's chart image is whatever pixels they
 * uploaded, so the dialog ran past the bottom of the page with no way to scroll
 * it and no backdrop left to click.
 *
 * Capping the body and letting IT scroll keeps the dialog on screen at any
 * window height, and leaves the wrapper's empty space clickable — which is what
 * dismisses the dialog.
 */
.theme-onyx .f-modal__body {
    max-block-size: calc(100vh - 4rem);
    /* dvh where supported: on mobile browsers the toolbars make 100vh taller
       than the visible area, which would push the dialog's foot off-screen. */
    max-block-size: calc(100dvh - 4rem);
    overflow: auto;
    overscroll-behavior: contain;
}

/*
 * The size chart is merchant-uploaded artwork at unknown dimensions, so it is
 * bounded on BOTH axes and scaled to fit rather than cropped — a size chart
 * with its edge cut off is worse than a small one.
 */
.theme-onyx .f-size-guide__image {
    display: block;
    margin-inline: auto;
    max-inline-size: 100%;
    max-block-size: calc(100vh - 12rem);
    max-block-size: calc(100dvh - 12rem);
    block-size: auto;
    object-fit: contain;
}

/* A long size table scrolls inside the dialog rather than stretching it. */
.theme-onyx .f-size-guide__content {
    overflow-x: auto;
}

.theme-onyx .f-size-guide__content table {
    inline-size: 100%;
    border-collapse: collapse;
}

.theme-onyx .f-size-guide__content th,
.theme-onyx .f-size-guide__content td {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--color-border);
    text-align: start;
}

.theme-onyx .f-size-guide__content th {
    background: var(--color-surface);
    font-weight: 600;
}

/* The wrapper is the clickable backdrop (see modal.js): it must not become a
   scroll container of its own, or the dialog scrolls the page behind it
   instead of scrolling its own body. */
.theme-onyx .f-modal__wrapper {
    padding: 2rem 1rem;
}

/*
 * The login dialog is exempt from the body cap above. Its country picker is a
 * dropdown positioned below the phone row, and a scroll container counts an
 * absolutely-positioned child in its overflow — so the moment the picker
 * opened, the capped body grew a scrollbar beside a form that fits on screen
 * with room to spare. The form itself is a heading and two fields; it never
 * needs the cap, and on a window too short for it the wrapper scrolls, which
 * is the SDK's own behaviour for this dialog.
 */
.theme-onyx #falak-login .f-modal__body {
    max-block-size: none;
    overflow: visible;
}

/* The picker's list gives ground before the window does: past the default cap
   the open menu would run under the bottom edge of a short window and hand the
   wrapper a scrollbar instead. The floor keeps a few rows visible even where
   the subtraction goes negative — the list scrolls internally regardless. */
#falak-login .f-login__dial-list {
    max-block-size: clamp(8rem, 100dvh - 30rem, 15rem);
}


/* ------------------------------------- product rows on phones */

@media (max-width: 767px) {
    /*
     * On a phone the product rows become a two-up GRID, not a carousel.
     *
     * <falak-slider> sizes its slides from `slides-per-view`, which is a
     * desktop number. Left alone on a 390px screen that put roughly one and a
     * half cards in view with the next one sliced off at the edge — the row
     * read as broken rather than as scrollable, and the cut card sat under the
     * viewport edge with no affordance saying it could be dragged.
     *
     * The reference does not scroll these rows on a phone either: it wraps them
     * two across and lets the page scroll. Overriding the track to a grid gives
     * exactly that, and because the slides keep their DOM order and their
     * classes, the component's own logic is untouched — it simply has nothing
     * left to scroll.
     */
    .block--products-slider .f-slider__viewport,
    .block--featured-products .f-slider__viewport,
    .block--category-feature .f-slider__viewport {
        overflow: visible;
    }

    .block--products-slider .f-slider__track,
    .block--featured-products .f-slider__track,
    .block--category-feature .f-slider__track {
        display: grid;
        /*
         * auto-flow AND template-columns both have to be stated.
         *
         * The base lays the track out with `grid-auto-flow: column`, so setting
         * only `grid-template-columns` left the flow intact and the browser kept
         * generating one implicit column per product — eight of them, each
         * 261px, inside a 358px viewport. That is what pushed the cards off both
         * edges. Forcing the flow back to `row` is what makes the two declared
         * columns the ones that are actually used.
         *
         * !important here because the competing declarations come from the
         * generated SDK block copied earlier into this same file, at a
         * specificity this selector cannot outrank without pinning it to the
         * component's internals.
         */
        grid-auto-flow: row !important;
        grid-auto-columns: auto !important;
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        gap: var(--grid-gap);
        /* The track is a scroll container on desktop; as a grid it must not
           keep the snap behaviour, or the page fights the row for the gesture. */
        overflow: visible;
        scroll-snap-type: none;
        transform: none !important;
    }

    /* Slides are sized by the grid now, so their inline width — set by the
       component from slides-per-view — has to go. */
    .block--products-slider .f-slider__slide,
    .block--featured-products .f-slider__slide,
    .block--category-feature .f-slider__slide {
        /* `auto` resolved to 0 while the track still had implicit columns; with
           the flow fixed above, the grid sizes these and the slide only needs to
           stop imposing its own desktop width. */
        inline-size: auto !important;
        min-inline-size: 0 !important;
        max-inline-size: none !important;
        flex: none;
        scroll-snap-align: none;
    }

    /* Nothing to page through, so the arrows would be dead controls. */
    .block--products-slider .f-slider__controls,
    .block--featured-products .f-slider__controls,
    .block--category-feature .f-slider__controls {
        display: none;
    }

    /*
     * The editorial panel's rail is the exception: it is two products beside a
     * picture, and stacked on a phone it becomes the same two-up grid as every
     * other row, which is what it should have been all along.
     */
    .block--featured-products .featured-products__rail {
        inline-size: 100%;
    }
}


/* --------------------------------------------------- products grid */

/*
 * The reference's product band, built on <falak-products-list>.
 *
 * The component already lays its own responsive grid out from the `columns`
 * attribute, so there is almost nothing to do here — which is the point of
 * moving these sections off the carousel. All this section changes is the gap
 * (to the theme's own) and where the grid drops to two columns, so it matches
 * the breakpoint the rest of the theme uses rather than the SDK's default.
 */
.block--products-grid .f-list__grid {
    gap: var(--grid-gap);
}

/* The SDK drops to two columns at 639px; Onyx's card type and gutters change at
   767px, so the grid changes there too — otherwise there is a band of widths
   where three columns are set in phone-sized type. */
@media (max-width: 767px) {
    .block--products-grid .f-list__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/*
 * An empty band keeps its head AND says why it is empty. This used to be
 * `display: none`, on the reasoning that a "no products" line under a section
 * title reads as a fault in the store — but the store IS empty at that point,
 * and hiding the line left the merchant who placed the section staring at a
 * heading over a gap, which reads as a fault in the theme instead.
 *
 * The copy comes from the section's own `empty-message` (product.none_added),
 * so it says "none added yet" rather than the component's default "none found".
 */

.block--products-grid:has(.f-list__message--empty) .block__view-all {
    margin-block-start: 0;
}

/* Loading placeholders take the card's shape, so the band does not jump when
   the real cards land. */
.block--products-grid .f-card--skeleton {
    aspect-ratio: 1 / 1;
    border-radius: var(--radius);
    background: var(--color-surface);
}


/* ------------------------------------------------ blob card variant */

/*
 * The reference's "Oud Oil" band: each photo sits on an irregular organic
 * shape that shifts gently under the pointer.
 *
 * The reference cuts its blob with a ~100-point clip-path polygon and morphs
 * it via `transition: clip-path .5s ease-in-out` (measured off the live
 * card). Ours is built from asymmetric border-radius instead: the same
 * organic read, but it needs no polygon asset, interpolates natively, and
 * mirrors itself in RTL with no second set of coordinates.
 *
 * Three shapes rotate across the row (nth-child), because a row of six
 * IDENTICAL blobs reads as a rounded square that came out wrong — the
 * irregularity only registers when neighbours differ. The reference
 * randomises per card for the same reason.
 *
 * The hover morph rides the global reduced-motion rule: transitions collapse
 * to 0.01ms there, so the shape change becomes an imperceptible snap.
 */
.products-grid--blob .f-card__media {
    border: 0;
    background: var(--color-surface);
    border-radius: 58% 42% 44% 56% / 46% 56% 44% 54%;
    transition: border-radius 600ms ease-in-out;
    /*
     * NOT hidden, unlike the square card. The blob curve cuts deep into the
     * corners, and the hexagon badge lives INSIDE this box in the SDK's
     * markup — clipping to the blob sliced the badge to a sliver. Nothing
     * else needs the clip: the photo sits 8% inside the box and its 1.04
     * hover scale never reaches the edge.
     */
    overflow: visible;
}

.products-grid--blob .f-card:nth-child(3n + 2) .f-card__media {
    border-radius: 44% 56% 58% 42% / 56% 44% 52% 48%;
}

.products-grid--blob .f-card:nth-child(3n) .f-card__media {
    border-radius: 52% 48% 42% 58% / 44% 58% 42% 56%;
}

/* The photo breathes inside the shape — a packshot touching the blob's edge
   gets its corners shaved off by the curve. `border-radius: inherit` clips the
   PHOTO to the same blob: a cut-out packshot is unaffected (its transparency
   already is the shape), but an opaque studio shot becomes a smaller blob
   inside the tinted one instead of a hard rectangle floating on it. The same
   transition keeps the two shapes morphing together on hover. */
/*
 * Absolutely positioned, so the photo cannot SIZE the blob.
 *
 * aspect-ratio only sets a box's preferred height — content taller than that
 * still stretches it (min-height: auto), and a portrait packshot did exactly
 * that: one 200x291 blob in a row of 200x210s, pushing its whole card down.
 * Out of the flow, the box answers to aspect-ratio alone and the photo fits
 * inside whatever square that yields.
 */
.products-grid--blob .f-card__media img {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    box-sizing: border-box;
    padding: 8%;
    object-fit: contain;
    border-radius: inherit;
    transition: border-radius 600ms ease-in-out, transform 400ms ease;
}

.products-grid--blob .f-card__media {
    position: relative;
}

/* ---- the hover morph ---- */

.products-grid--blob .f-card__inner:hover .f-card__media {
    border-radius: 47% 53% 56% 44% / 55% 46% 54% 45%;
}

.products-grid--blob .f-card:nth-child(3n + 2) .f-card__inner:hover .f-card__media {
    border-radius: 56% 44% 46% 54% / 45% 55% 47% 53%;
}

.products-grid--blob .f-card:nth-child(3n) .f-card__inner:hover .f-card__media {
    border-radius: 43% 57% 53% 47% / 56% 44% 55% 45%;
}

/* On the grey band the blob inverts to white, the same trade the image-with-
   text panel makes — a surface-on-surface shape has no edge. */
.block--bg-surface.products-grid--blob .f-card__media {
    background: var(--color-bg);
}

/* Six-up cards are small; the display-size title of the four-up rows wraps
   everything to two lines at this width. The reference drops to ~18px here. */
.products-grid--blob .f-card__title {
    font-size: var(--fs-lead);
}

/* The hexagon rides the blob's upper curve rather than a square's corner —
   flush against the edge it looks like it slid off the shape. */
.products-grid--blob .f-card__badge {
    inset-block-start: 0;
    inset-inline-end: 0.25rem;
}


/* ============================================================ footer v2 */

/*
 * The reference footer, exactly: a newsletter card floating on the navy, five
 * columns under it, then two rules — compliance against payment, and the legal
 * line.
 *
 * Written as one block at the end of the sheet rather than by editing the
 * rules above, because the footer inherits three earlier layers (the 2026
 * base, the shared chrome, and Onyx's own) that each style `.site-footer__*`.
 * Overriding them in place would mean touching all three; landing last means
 * this block is the one that describes the footer that ships.
 *
 * Everything here is written in logical properties: the store runs RTL, and
 * the reference is drawn LTR.
 */

.site-footer {
    /* The legal rule is the page's last edge — its own padding closes the
       footer, so the section padding would only add a dead band under it. */
    padding-block-end: 0;
}

/* ---- 1 · newsletter card ---- */

.site-footer__newsletter {
    /* Was a full-bleed band; the card carries its own ground now. The base
       rule also drew a hairline under the band, which with the padding gone
       sat flush against the card as a second edge. The card has its own
       border, so the line goes rather than being pushed down. */
    background: none;
    /* Block padding only: this element is also the `.container`, and a bare
       `padding: 0` took its side gutter, so the card ran edge to edge. */
    padding-block: 0;
    border-block-end: 0;
    margin-block-end: 3rem;
}

.site-footer__newsletter-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1.5rem 2.5rem;
    padding: 1.75rem 2rem;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: var(--radius-lg, 1rem);
    background: rgba(255, 255, 255, 0.04);
}

.site-footer__newsletter-copy {
    display: flex;
    align-items: center;
    gap: 1rem;
    min-inline-size: 0;
}

.site-footer__newsletter-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border-radius: 0.75rem;
    background: rgba(255, 255, 255, 0.08);
    color: var(--color-cream);
}

.site-footer__newsletter-words {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-inline-size: 0;
}

/* The heading sits inside a card now, so it drops the section-title size the
   generic `.site-footer h2` rule gives it. */
.site-footer .site-footer__newsletter-title {
    margin: 0;
    color: #fff;
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.3;
}

.site-footer__newsletter-text {
    margin: 0;
    color: rgba(255, 255, 255, 0.6);
    font-size: var(--fs-nav);
    line-height: 1.5;
}

/* The SDK stacks label, field and status; on the card the field and its button
   are one row and the label is carried by the placeholder. */
.site-footer .site-footer__newsletter-form {
    flex: 0 1 auto;
    min-inline-size: 0;
}

.site-footer .site-footer__newsletter-form .f-newsletter__label {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.site-footer .site-footer__newsletter-form .f-newsletter__row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.site-footer .site-footer__newsletter-form .f-newsletter__input {
    inline-size: clamp(14rem, 26vw, 19rem);
}

/* ---- 2 · the five columns ---- */

/*
 * No reserved tracks. Five fixed columns left a hole for every column a store
 * did not have — and a new store has two. auto-fit collapses the empty
 * tracks, so whatever columns ARE there share the width: brand keeps its wider
 * measure for the about line, the rest divide the remainder evenly.
 */
.site-footer__grid {
    grid-template-columns: minmax(0, 1.6fr) repeat(auto-fit, minmax(10rem, 1fr));
    gap: 3rem;
}

/* Small, spaced, and quiet: the column heads are labels over their stacks, not
   titles competing with the brand name. */
.site-footer .site-footer__heading {
    margin-block-end: 1.25rem;
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.site-footer__col { gap: 0; }

/* The brand stack inherits align-items:center from the shared chrome, which
   put the mark, the paragraph and the social discs each on its own axis — a
   staggered start edge down the widest column in the footer. All three share
   the column edge instead. */
.site-footer .site-footer__col--brand {
    align-items: flex-start;
    text-align: start;
}

.site-footer__logo {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    margin-block-end: 1.25rem;
}

.site-footer__logo img {
    block-size: 2.75rem;
    inline-size: auto;
    object-fit: contain;
}

.site-footer__brand-name {
    color: #fff;
    font-size: 1.125rem;
    font-weight: 700;
}

.site-footer .site-footer__about {
    margin: 0;
    max-inline-size: 26ch;
    /* Ragged, not justified: at this measure justification opens rivers, and
       the reference sets it flush on the start edge only. */
    text-align: start;
    font-size: var(--fs-nav);
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.6);
}

.site-footer .site-footer__social { margin-block-start: 1.75rem; }

.site-footer .site-footer__links a,
.site-footer .site-footer__legal-links a {
    font-size: var(--fs-nav);
    color: rgba(255, 255, 255, 0.7);
}

.site-footer .site-footer__links { gap: 0.875rem; }

/* "Show more" under a capped categories list — the rows past the cap ship
   hidden and the button reveals them. */
.site-footer__links li[hidden] { display: none; }

.site-footer__more-btn {
    margin-block-start: 0.875rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: var(--fs-nav);
    font-weight: 600;
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    text-align: start;
}
.site-footer__more-btn:hover { color: var(--color-primary-light); }

/* ---- working hours ---- */

.site-footer .site-footer__hours-list {
    display: flex;
    flex-direction: column;
    gap: 1.125rem;
}

.site-footer__hours-row {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
}

.site-footer__hours-icon {
    display: inline-flex;
    flex: 0 0 auto;
    /* Optical, not geometric: the glyph lines up with the x-height of the day
       range beside it rather than with the top of its box. */
    margin-block-start: 0.0625rem;
    color: rgba(255, 255, 255, 0.55);
}

.site-footer__hours-words {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.site-footer__hours-days {
    color: #fff;
    font-size: var(--fs-nav);
    font-weight: 600;
}

.site-footer__hours-time,
.site-footer .site-footer__hours {
    margin: 0;
    color: rgba(255, 255, 255, 0.6);
    font-size: var(--fs-nav);
}

/* The free-text fallback keeps its line breaks. */
.site-footer .site-footer__hours { white-space: pre-line; }

/* ---- the app column ---- */

.site-footer__col--apps .site-footer__apps-text {
    margin: 0 0 1.25rem;
    max-inline-size: 22ch;
    font-size: var(--fs-nav);
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.6);
}

/* The component prints its own "Download our app" heading, which in a column
   that already has one says the same thing twice. */
.site-footer .site-footer__apps-links .f-apps__title { display: none; }

/* Stacked, not side by side: in a column this width two badges in a row would
   each be too small to read the store name on. */
.site-footer .site-footer__apps-links .f-apps__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
    max-inline-size: 12.5rem;
}

.site-footer .site-footer__apps-links .f-apps__item {
    justify-content: flex-start;
    padding: 0.625rem 0.875rem;
    border-color: rgba(255, 255, 255, 0.14);
    border-radius: 0.625rem;
    background: rgba(255, 255, 255, 0.03);
    color: #fff;
}

.site-footer .site-footer__apps-links .f-apps__item:hover {
    border-color: rgba(255, 255, 255, 0.35);
    transform: none;
}

.site-footer .site-footer__apps-links .f-apps__sub { opacity: 0.6; }

/* ---- 3 · compliance against payment ---- */

.site-footer__bottom {
    margin-block-start: 3rem;
    padding-block-start: 0;
    border-block-start: 1px solid rgba(255, 255, 255, 0.08);
}

.site-footer .site-footer__bottom-inner {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem 1.5rem;
    padding-block: 1.5rem;
}

.site-footer__marks {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* The component stacks its certificates in a column for a sidebar; on this
   rule they run as a row of chips. */
.site-footer .site-footer__marks falak-trust-badges { margin-block-start: 0; }

.site-footer .site-footer__marks .f-trust__list {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.site-footer .site-footer__marks .f-trust__item {
    margin: 0;
    padding: 0.5rem 0.875rem;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 0.625rem;
    background: rgba(255, 255, 255, 0.03);
}

/* The official mark beside each certificate. A white tile, because the marks
   are designed for paper and their greens and golds vanish straight onto the
   footer's navy; `contain` because the three are different shapes. */
.site-footer .site-footer__marks .f-trust__logo {
    flex: none;
    inline-size: 2.5rem;
    block-size: 2.5rem;
    padding: 0.2rem;
    border-radius: 0.5rem;
    background: #fff;
    object-fit: contain;
}

/* The preview-only "add your numbers" prompt stands in for the badges only
   while there are none: the component hides itself when it has nothing to
   show, and that is the signal. */
.site-footer .site-footer__marks falak-trust-badges:not([hidden]) ~ .site-footer__add--docs {
    display: none;
}

.site-footer .site-footer__payments { margin: 0; }

.site-footer .site-footer__payments .f-payments__list {
    justify-content: flex-end;
    gap: 0.5rem;
}

/* Same row as the certificate badges. The footer-wide rule above makes
   <falak-payments> block-level and full-width (right for the column layout it
   was written for); in the bottom band that forced the marks onto a line of
   their own. Here the badges take the slack and the marks sit at the end. */
.site-footer .site-footer__bottom-inner .site-footer__marks {
    flex: 1 1 auto;
    min-inline-size: 0;
}

.site-footer .site-footer__bottom-inner falak-payments.f-payments {
    inline-size: auto;
    flex: 0 1 auto;
}

.site-footer .site-footer__bottom-inner .f-payments__list {
    inline-size: auto;
    margin: 0;
}

/* ---- 4 · the legal line ---- */

.site-footer__legal {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem 1.5rem;
    padding-block: 1.25rem;
    border-block-start: 1px solid rgba(255, 255, 255, 0.08);
}

.site-footer .site-footer__copyright,
.site-footer__powered {
    /* width/border/padding are reset, not just overridden: the base sheet sets
       the copyright to a full-width rule of its own, which in this row ate the
       whole line and pushed the credit under it. */
    margin: 0;
    padding: 0;
    border: 0;
    inline-size: auto;
    text-align: start;
    font-size: 0.8125rem;
    color: rgba(255, 255, 255, 0.5);
}

.site-footer .site-footer__legal-links {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 1.5rem;
}

.site-footer .site-footer__legal-links a { font-size: 0.8125rem; }

/* ---- phones ---- */

@media (max-width: 767px) {
    .site-footer__newsletter { margin-block-end: 2rem; }

    .site-footer__newsletter-card {
        padding: 1.25rem;
        gap: 1.25rem;
    }

    /* The field and its button stop sharing a line: at this width a row leaves
       the field too narrow to show a whole address. */
    .site-footer .site-footer__newsletter-form,
    .site-footer .site-footer__newsletter-form .f-newsletter__row {
        inline-size: 100%;
    }

    .site-footer .site-footer__newsletter-form .f-newsletter__row {
        flex-direction: column;
        align-items: stretch;
    }

    /* <falak-newsletter> is a flex box, so its <form> shrank to its content
       and left the field short of the card's start edge. */
    .site-footer .site-footer__newsletter-form .f-newsletter__form { inline-size: 100%; }

    .site-footer .site-footer__newsletter-form .f-newsletter__input { inline-size: 100%; }

    .site-footer__grid {
        grid-template-columns: 1fr;
        gap: 0;
    }

    /* Every stack shares the start edge. The older phone rules above centred
       the columns, their links and their heads for a footer that no longer
       ships. */
    .site-footer .site-footer__col { align-items: stretch; text-align: start; }
    .site-footer .site-footer__links { align-items: flex-start; }

    /* The brand block closes with a hairline, like each accordion row under it. */
    .site-footer .site-footer__col--brand {
        padding-block-end: 1.5rem;
        border-block-end: 1px solid rgba(255, 255, 255, 0.08);
    }

    .site-footer .site-footer__social-wrap { inline-size: 100%; }
    .site-footer .site-footer__social { margin-block-start: 1.25rem; }
    .site-footer .site-footer__social .f-social__list { margin-block-start: 0; }

    /* Column heads are accordion rows: label on the start edge, chevron on the
       end edge, the whole row the tap target. */
    .site-footer .site-footer__group > summary.site-footer__heading {
        justify-content: space-between;
        margin-block-end: 0;
        padding-block: 1.125rem;
        color: #fff;
        font-size: 0.8125rem;
        font-weight: 700;
        letter-spacing: 0.1em;
    }

    .site-footer .site-footer__group[open] > summary.site-footer__heading { margin-block-end: 0.25rem; }
    .site-footer .site-footer__group[open] { padding-block-end: 1.25rem; }

    /* The app row is always open, so its head is a label, not a control. */
    .site-footer .site-footer__col--apps .site-footer__group { border-block-end: 0; }
    .site-footer .site-footer__col--apps .site-footer__group > summary { pointer-events: none; }
    .site-footer .site-footer__col--apps .site-footer__group > summary::after { display: none; }

    /* Side by side across the full row: the stacked pair is a desktop-column
       answer to a narrow track, and a phone has the width for both. */
    .site-footer .site-footer__apps-links,
    .site-footer .site-footer__apps-links .f-apps__list { inline-size: 100%; }

    .site-footer .site-footer__apps-links .f-apps__list {
        flex-direction: row;
        max-inline-size: none;
    }

    .site-footer .site-footer__col--apps .site-footer__group[open] { padding-block-end: 0; }

    .site-footer .site-footer__apps-links .f-apps__item {
        flex: 1 1 0;
        min-inline-size: 0;
        justify-content: center;
        padding-inline: 0.625rem;
        white-space: nowrap;
    }

    .site-footer__bottom { margin-block-start: 1.5rem; }

    .site-footer .site-footer__about { max-inline-size: none; }

    .site-footer .site-footer__bottom-inner,
    .site-footer__legal {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }

    .site-footer .site-footer__copyright,
    .site-footer__powered { text-align: center; }

    .site-footer .site-footer__marks .f-trust__list,
    .site-footer .site-footer__payments .f-payments__list { justify-content: center; }

    .site-footer .site-footer__legal-links { justify-content: center; }
}


/* ================================================== split collections */

/*
 * A list of collection names on one side, the picture of whichever one the
 * pointer is on beside it.
 *
 * Two behaviours, one set of markup. Above 1024px the cards are stacked on top
 * of each other and crossfaded; below it the same cards become a scroll-snapped
 * rail, because two halves side by side is the one thing a phone cannot do.
 * The desktop half is what needs the JS; the rail is CSS only and works with
 * scripting off.
 */

.block--collection-split {
    /* The tint the JS writes as the pointer moves, falling back to the base the
       merchant chose and then to the theme's own surface. Transitioned here so
       every change — hover, leave, the rail scrolling on a phone — eases. */
    background-color: var(--split-tint, var(--split-base-tint, var(--color-surface)));
    transition: background-color 0.8s cubic-bezier(0.25, 1, 0.5, 1);
}

.collection-split__eyebrow {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    margin: 0;
    font-size: var(--fs-caption);
    font-weight: 600;
    letter-spacing: 0.25em;
    color: var(--color-text-soft);
}

.collection-split__eyebrow-rule {
    inline-size: 2rem;
    block-size: 1px;
    background: currentColor;
    opacity: 0.3;
}

.collection-split__title {
    margin: 0;
    font-size: var(--fs-hero);
    font-weight: 800;
    line-height: 1.15;
    text-align: center;
}

.collection-split__stage-wrap {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 3.5rem;
    align-items: center;
    margin-block-start: 3rem;
}

/* ---- the list ---- */

.collection-split__nav {
    display: flex;
    flex-direction: column;
}

.collection-split__row {
    display: flex;
    align-items: baseline;
    gap: 1.5rem;
    padding: 1.25rem 1.5rem;
    border-radius: var(--radius);
    border-block-end: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
    color: var(--color-text);
    text-decoration: none;
    transition: background-color var(--transition), color var(--transition);
}

.collection-split__row:last-child { border-block-end: 0; }

/* The row the stage is currently showing. Driven by a class rather than
   :hover so the keyboard reaches the same state, and so the first row is
   already in it before anything is pointed at. */
.collection-split__row.is-active {
    background: color-mix(in srgb, var(--color-text) 4%, transparent);
    border-block-end-color: transparent;
}

.collection-split__num {
    flex: none;
    font-size: var(--fs-caption);
    letter-spacing: 0.15em;
    color: var(--color-text-faint);
    font-variant-numeric: tabular-nums;

    /* An index is a number, not prose: isolated so "01 /" keeps that order in
       an RTL page instead of being re-ordered to "/ 01". */
    direction: ltr;
    unicode-bidi: isolate;
}

.collection-split__row-name {
    flex: 1 1 auto;
    min-inline-size: 0;
    font-size: clamp(1.5rem, 2.6vw, 2.25rem);
    font-weight: 700;
    line-height: 1.2;
}

.collection-split__row-arrow {
    flex: none;
    display: inline-flex;
    align-self: center;
    color: var(--color-text-soft);
    opacity: 0.55;
    /* The arrow points the way the text runs, so it mirrors with the page. */
    transform: scaleX(1);
    transition: transform var(--transition), opacity var(--transition);
}

[dir="ltr"] .collection-split__row-arrow { transform: scaleX(-1); }

.collection-split__row.is-active .collection-split__row-arrow,
.collection-split__row:hover .collection-split__row-arrow {
    opacity: 1;
    transform: translateX(-0.35rem) scaleX(1);
}

[dir="ltr"] .collection-split__row.is-active .collection-split__row-arrow,
[dir="ltr"] .collection-split__row:hover .collection-split__row-arrow {
    transform: translateX(0.35rem) scaleX(-1);
}

/* ---- the stage ---- */

.collection-split__stage {
    position: relative;
    aspect-ratio: 3 / 4;
    inline-size: 100%;
    max-inline-size: 28rem;
    margin-inline: auto;
}

.collection-split__card {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: 2rem;
    border: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
    background: color-mix(in srgb, var(--color-text) 5%, transparent);
    box-shadow: 0 1.5rem 3rem color-mix(in srgb, var(--color-text) 18%, transparent);

    /* Out: slightly larger and invisible, so the one coming in appears to
       settle rather than cut. The easing matches the tint's. */
    opacity: 0;
    transform: scale(1.05);
    pointer-events: none;
    transition: opacity 0.7s cubic-bezier(0.25, 1, 0.5, 1),
                transform 0.7s cubic-bezier(0.25, 1, 0.5, 1);
}

.collection-split__card.is-active {
    opacity: 1;
    transform: scale(1);
    pointer-events: auto;
}

.collection-split__image {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    transition: transform 1s ease-out;
}

.collection-split__card.is-active .collection-split__image { transform: scale(1.03); }

.collection-split__scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(
        to top,
        rgba(0, 0, 0, 0.9) 0%,
        rgba(0, 0, 0, 0.3) 45%,
        rgba(0, 0, 0, 0) 100%
    );
}

.collection-split__card-body {
    position: absolute;
    inset-block-end: 0;
    inset-inline: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1.25rem;
    padding: 2.25rem;
    z-index: 1;
}

.collection-split__card-title {
    margin: 0;
    color: #fff;
    font-size: var(--fs-block);
    font-weight: 700;
    line-height: 1.3;
}

.collection-split__cta {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    border-radius: 999px;
    background: var(--color-bg);
    color: var(--color-text);
    font-size: var(--fs-control);
    font-weight: 600;
    text-decoration: none;
    transition: background var(--transition), transform var(--transition);
}

.collection-split__cta:hover {
    background: var(--color-cream, var(--color-bg));
    transform: translateY(-2px);
}

.collection-split__cta-arrow { display: inline-flex; }

[dir="ltr"] .collection-split__cta-arrow { transform: scaleX(-1); }

/* ---- phones: the same cards, as a rail ---- */

@media (max-width: 1023px) {
    .collection-split__stage-wrap {
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
        margin-block-start: 2rem;
    }

    /* The list is the desktop affordance. On a phone the cards themselves are
       the list, and a duplicate of the same names above them is just height. */
    .collection-split__nav { display: none; }

    .collection-split__stage {
        display: flex;
        gap: 0.75rem;
        aspect-ratio: auto;
        max-inline-size: none;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        /* The cards carry a shadow; without room for it the rail clips it. */
        padding-block-end: 1rem;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .collection-split__stage::-webkit-scrollbar { display: none; }

    .collection-split__card {
        position: relative;
        inset: auto;
        flex: 0 0 min(78%, 20rem);
        aspect-ratio: 3 / 4;
        scroll-snap-align: center;

        /* Every card is present on a rail — the stacked-and-faded behaviour is
           the desktop one. */
        opacity: 1;
        transform: none;
        pointer-events: auto;
    }

    .collection-split__card.is-active .collection-split__image { transform: none; }

    .collection-split__card-body { padding: 1.5rem; gap: 1rem; }
}

/* The crossfade and the tint are both decoration; the section reads the same
   without them, and a merchant's colour choice still applies. */
@media (prefers-reduced-motion: reduce) {
    .block--collection-split,
    .collection-split__card,
    .collection-split__image,
    .collection-split__row-arrow {
        transition-duration: 0.01ms;
    }

    .collection-split__card.is-active .collection-split__image { transform: none; }
}


/* ============================================== FAQ: the split layout */

/*
 * Heading and pictures in one column, numbered questions in the other.
 *
 * The stacked layout above is untouched — everything here hangs off
 * .block--faq-split, so a store that never picks the layout renders exactly the
 * CSS it did before.
 */

.faq-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 2.5rem;
    align-items: start;
}

.faq-split__head { margin-block-end: 2rem; }

.faq-split__title {
    margin: 0 0 0.75rem;
    font-size: var(--fs-section);
    font-weight: 700;
    line-height: 1.2;
}

.faq-split__sub {
    margin: 0;
    max-inline-size: 42ch;
    color: var(--color-text-soft);
    font-size: var(--fs-lead);
    line-height: 1.7;
}

/* ---- the overlapping pair ---- */

/*
 * A fixed frame the two pictures are positioned inside. Its aspect ratio is
 * what reserves the space, so the column does not jump when the images load —
 * and the percentages below are of the frame, not of each other, which is what
 * keeps the overlap identical at every width.
 */
.faq-split__figures {
    position: relative;
    aspect-ratio: 4 / 3.2;
    inline-size: 100%;
}

.faq-split__figure {
    position: absolute;
    overflow: hidden;
    border-radius: var(--radius-lg, 1rem);
}

.faq-split__figure img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

.faq-split__figure--back {
    inset-block-start: 0;
    inset-inline-start: 0;
    inline-size: 68%;
    block-size: 60%;
    z-index: 1;
    box-shadow: 0 0.5rem 1.5rem color-mix(in srgb, var(--color-text) 14%, transparent);
}

.faq-split__figure--front {
    inset-block-end: 0;
    inset-inline-end: 0;
    inline-size: 62%;
    block-size: 58%;
    z-index: 2;
    box-shadow: 0 1rem 2.5rem color-mix(in srgb, var(--color-text) 22%, transparent);
}

/* One picture has nothing to overlap, so it fills the frame instead of
   sitting in the corner of an empty box. */
.faq-split__figures.is-single { aspect-ratio: 4 / 3; }

.faq-split__figures.is-single .faq-split__figure--back {
    position: relative;
    inline-size: 100%;
    block-size: 100%;
}

/* ---- the numbered list ---- */

.faq-split__list {
    display: flex;
    flex-direction: column;
}

/*
 * The component ships as a card — a surface fill and a radius — because most
 * places that use an accordion want one. This layout wants rules, so the card
 * is undone here rather than in the component, which every other theme shares.
 */
.faq-split__item {
    background: none;
    border-radius: 0;
    border-block-end: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
}

.block--faq-split .f-accordion__head {
    padding-inline: 0;
}

.faq-split__item:last-child { border-block-end: 0; }

/*
 * The head is the SDK's button; only its layout is set here so the component
 * keeps its own keyboard handling and aria state.
 */
.block--faq-split falak-accordion-head {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding-block: 1.25rem;
    font-size: var(--fs-lead);
    font-weight: 600;
}

.faq-split__num {
    flex: none;
    font-size: var(--fs-caption);
    font-weight: 700;
    color: var(--color-text-faint);
    font-variant-numeric: tabular-nums;

    /* An index is a number, not prose: isolated so it is not re-ordered
       against the question in an RTL page. */
    direction: ltr;
    unicode-bidi: isolate;
}

.faq-split__question {
    flex: 1 1 auto;
    min-inline-size: 0;
}

.block--faq-split falak-accordion-body {
    display: block;
    padding-block-end: 1.25rem;
    padding-inline-start: 2.5rem;
    color: var(--color-text-soft);
    line-height: 1.8;
}

/* The component publishes its state as data-collapsed on all three elements —
   what collapsed looks like is the theme's call, which is this. */
.block--faq-split falak-accordion-body[data-collapsed="true"] { display: none; }

@media (max-width: 900px) {
    .faq-split {
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
    }

    .faq-split__head { margin-block-end: 1.5rem; }

    .block--faq-split falak-accordion-body { padding-inline-start: 0; }
}

/* ========================================================================
   Customizer style hooks
   ========================================================================
   The theme's half of the per-section styling contract, mirroring
   falak-theme-raed. Two jobs:

   1. "Element alignment" moves a box with auto margins, and an inline box
      ignores those. Every styleable button below is inline-flex, or a bare
      inline <a>, so it is made block-level with a fit-content width —
      visually identical, since each already sits on its own line — which
      gives those margins something to push against.

   2. SDK components render their own markup, so the theme cannot tag a
      node inside them. Those roles are declared with no element at all and
      reach their target through the custom properties the platform
      publishes on the section root. Each fallback below is the value that
      rule had before, so a control the merchant has not touched changes
      nothing.
   ======================================================================== */
.banner-products__cta,
.banner__content .btn,
.block__view-all > a,
.branch__map,
.cat-feature__cta,
.collection-split__cta,
.compact-slide__content .btn,
.featured-product__body .btn,
.featured-products__body .btn,
.fixed-banner__content .btn,
.hero-slide__content .btn,
.iwt__cta,
.offer-band__cta,
.promo-countdown__body .btn,
.store-story .btn,
.style-banner__cta,
.video-card__link {
    display: flex;
    inline-size: fit-content;
}

/* contact — <falak-contact-form> is an unknown element, so it is inline and
   has no box of its own. The `form` role's padding, ground and alignment
   need a block-level frame before any of them can land. */
.contact__form { min-inline-size: 0; }
.contact__form falak-contact-form { display: block; }

/* products rails — the cards are <falak-product-card>, styled by the
   platform's falak-components.css, so the `card` role carries no element. */
.block--banner-products .f-card__inner,
.block--best-sellers .f-card__inner,
.block--latest-duo .f-card__inner,
.block--product-tabs .f-card__inner,
.block--products-grid .f-card__inner,
.block--products-slider .f-card__inner {
    border-radius: var(--falak-el-card-radius, var(--f-radius));
    background-color: var(--falak-el-card-bg, var(--f-surface));
}

/* --------------------------------------- header: language + currency */

/*
 * Language and currency are ONE segmented control: a single grey pill with a
 * hairline down the middle. Two adjoining pills read as two unrelated
 * buttons; one with a divider reads as "your locale". The join is done with
 * logical radii and a negative start margin equal to the row's gap, so it
 * holds in RTL, and only when the currency control is actually rendered —
 * a one-currency store keeps the language pill whole.
 */
.site-header .site-header__bar-inner falak-language:has(+ falak-currency:not([hidden])) .f-locale__trigger {
    border-start-end-radius: 0;
    border-end-end-radius: 0;
    padding-inline-end: 0.75rem;
}

/* Must equal .site-header__start's gap exactly (0.5rem — the header rewrite's
   value, which supersedes the older 1.1rem). It was still -1.1rem, so the
   currency segment slid 10px over the language one and the overlap showed as
   a dark band across the language caret. */
.site-header .site-header__bar-inner falak-language + falak-currency:not([hidden]) {
    margin-inline-start: -0.5rem;
}

.site-header .site-header__bar-inner falak-language + falak-currency:not([hidden]) .f-currency__field {
    border-start-start-radius: 0;
    border-end-start-radius: 0;
    padding-inline-start: 0.75rem;
    border-inline-start: 1px solid rgba(16, 22, 49, 0.14);
}

.site-header .site-header__bar-inner .f-currency__field,
.site-header .site-header__bar-inner .f-locale__trigger { font-weight: 600; letter-spacing: 0.02em; }
.site-header .site-header__bar-inner .f-currency__current { font-variant-numeric: tabular-nums; }
.site-header .site-header__bar-inner .f-currency__chevron { opacity: 0.5; }


/*
 * The preferences sheet lives inside the sticky header, so it is stacked in
 * the header's own context (z-index 50) — and a hero layer above 50 would
 * paint over it. While a sheet is open, the header rises above everything.
 */
.site-header:has(.f-modal[data-visible="true"]) { z-index: 1200; }

/* ---------------------------------------- phones: locale lives in the drawer */

/*
 * Below 768px the bar is hamburger | logo | currency | cart and the language
 * pill is gone — but the sheet it owns must survive, because the drawer's
 * preferences entry (menu.twig) is what opens it on a phone. So the host
 * stays as display: contents and only its trigger is hidden.
 */

@media (max-width: 767px) {
    /* The drawer nav is a flex ROW on desktop (menu items across the strip);
       in the drawer it must stack, or the preferences entry sits beside the
       list instead of under it. */
    .site-header .main-menu { flex-direction: column; align-items: stretch; justify-content: flex-start; }

    /* The theme hid the language pill here and had nowhere else to switch
       language on a phone. It stays, joined to the currency pill as on
       desktop — hamburger | logo | QAR·العربية | cart fits a 360px bar. */
    .site-header .site-header__bar-inner falak-language.locale-trigger { display: inline-flex; }
    /* …as a globe segment: the word "العربية" plus "QAR" plus the hamburger
       outgrew the end column and ran into the centred logo at 360px. */
    .site-header .site-header__bar-inner .f-locale__globe { display: inline-flex; }
    .site-header .site-header__bar-inner .f-locale__current { display: none; }
    .site-header .site-header__bar-inner .f-locale__trigger { padding-inline: 0.7rem 0.6rem; }
    /* And the currency segment loses its chevron and some padding, so the
       whole pill clears the centred logo with room to spare. */
    .site-header .site-header__bar-inner .f-currency__chevron { display: none; }
    .site-header .site-header__bar-inner .f-currency__field { padding-inline: 0.65rem 0.6rem; }

    /* Even compacted, hamburger + locale pill measured ~160px against a
       ~140px start column at 375px and ran under the logo. Tighter cluster
       gap (the join's negative margin follows it), and the side columns may
       not shrink below their content: the logo column gives way instead, so
       on a narrow phone or with a wide logo the mark shrinks — it never
       sits under the pills. */
    .site-header .site-header__bar-inner {
        grid-template-columns: minmax(max-content, 1fr) minmax(0, auto) minmax(max-content, 1fr);
    }
    .site-header .site-header__start { gap: 0.375rem; }
    .site-header .site-header__bar-inner falak-language + falak-currency:not([hidden]) {
        margin-inline-start: -0.375rem;
    }
    .site-header .site-header__bar-inner .site-header__logo { min-width: 0; }
    .site-header .site-header__bar-inner .site-header__logo-img { max-width: 100%; }
    /* The globe alone says "language" — its caret is what kept the cluster
       wider than its column at 375px and the logo off centre. */
    .site-header .site-header__bar-inner .f-locale__chevron { display: none; }
    .site-header .site-header__bar-inner .f-locale__trigger { padding-inline: 0.65rem 0.55rem; }
    .site-header .site-header__bar-inner .f-currency__field { padding-inline: 0.5rem 0.55rem; }
    /* The sheet's host is an empty flex item in the cluster, and cost a
       second gap between the hamburger and the pill. */
    .site-header .site-header__start > falak-localization-modal { margin-inline-end: -0.375rem; }
}


/* ------------------------------------------------ order page (theme look) */
/* The SDK draws the order with neutral greys; these tune it to the theme's
   surfaces, radius and primary colour. Overrides match the copied rules'
   specificity (two classes), so they win on source order. */
.account-order .f-order { gap: 1rem; }
.account-order .f-order__card,
.account-order .f-payment-status__card {
    padding: 1.25rem 1.35rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg, 1rem);
    background: var(--color-bg, #fff);
    box-shadow: none;
}
.account-order .f-order__card-title { font-size: 1rem; letter-spacing: 0.01em; }
.account-order .f-order__card-title .f-order__icon { color: var(--color-primary); }
.account-order .f-order__head { padding: 1.35rem; }
.account-order .f-order__title { font-size: 1.25rem; }
.account-order .f-order__meta { color: var(--color-text-soft); }

/* Rows: a hairline instead of a nested grey box. */
.account-order .f-order__item,
.account-order .f-order__file,
.account-order .f-order__pay-row,
.account-order .f-order__kv {
    background: transparent;
    border-radius: 0;
    padding-inline: 0;
}
.account-order .f-order__item { padding-block: 0.85rem; border-block-start: 1px solid var(--color-border); }
.account-order .f-order__item:first-child { border-block-start: 0; padding-block-start: 0; }
.account-order .f-order__item:last-child { padding-block-end: 0; }
.account-order .f-order__item-image { inline-size: 4rem; block-size: 4rem; border: 1px solid var(--color-border); background: var(--color-surface); }
.account-order .f-order__item-name { font-size: 0.95rem; }
.account-order .f-order__items { gap: 0; }
.account-order .f-order__pay-rows { gap: 0; }
.account-order .f-order__pay-row { padding-block: 0.75rem; border-block-end: 1px solid var(--color-border); }
.account-order .f-order__pay-row-icon { color: var(--color-primary); }
/* The SDK chips the currency row with the payment gateway (TAP) — that names
   the processor, not the currency, and read as a mislabel. The method row
   already says how the order was paid; the reference chip there is a <code>. */
.f-order__pay-row > span.f-order__badge { display: none; }
.account-order .f-order__kvs { gap: 0; }
.account-order .f-order__kv { padding-block: 0.6rem; border-block-end: 1px solid var(--color-border); font-size: 0.86rem; }
.account-order .f-order__kv:last-child { border-block-end: 0; }
.account-order .f-order__kv-label { color: var(--color-text-soft); }
.account-order .f-order__totals { padding-block-start: 0.85rem; }
.account-order .f-order__row--total { border-color: var(--color-border); }

/* Tags and pills take the theme's surface rather than flat grey. */
.account-order .f-order__tag { background: var(--color-surface); }
.account-order .f-order__badge { background: var(--color-surface); border: 1px solid var(--color-border); }

/* Progress: the primary colour marks the way travelled. */
.account-order .f-order__step.is-done .f-order__step-dot,
.account-order .f-order__step-line.is-done { background: var(--color-primary); border-color: var(--color-primary); }
.account-order .f-order__step.is-done .f-order__step-dot { color: var(--color-on-primary, #fff); }
.account-order .f-order__step.is-current .f-order__step-dot { border-color: var(--color-primary); box-shadow: inset 0 0 0 3px var(--color-bg, #fff), inset 0 0 0 8px var(--color-primary); }
.account-order .f-order__step-title { font-size: 0.82rem; }

/* Locked boxes and banners sit on the theme surface. */
.account-order .f-order__locked,
.account-order .f-order__locked--inline { background: var(--color-surface); border-color: var(--color-border); }

/* Sidebar actions: full-width theme buttons with even spacing. */
.account-order .f-order__action-list { gap: 0.5rem; }
.account-order .f-order__cancel { color: var(--color-text-soft); }
.account-order .f-order__cancel:hover { color: #b91c1c; border-color: #fecaca; }

@media (min-width: 900px) {
    .account-order .f-order__grid { grid-template-columns: minmax(0, 1fr) 20rem; gap: 1rem; }
}


/* ------------------------------------------------ thank-you page (theme look) */
/* A hero card, then the order beside what the shopper needs to know next.
   Written after the base .thank-you rules so these win on source order. */
.thank-you { display: flex; flex-direction: column; align-items: stretch; gap: 1.25rem; max-inline-size: 60rem; margin-inline: auto; padding-block: 1.5rem 3rem; text-align: center; }
.thank-you > * { margin-block: 0; }
.thank-you__hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 2.25rem 1.5rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg, 1rem);
    background: var(--color-bg, #fff);
}
.thank-you__hero > * { margin: 0; }
.thank-you__mark,
.thank-you__icon {
    display: grid;
    place-items: center;
    inline-size: 64px;
    block-size: 64px;
    margin: 0;
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-primary) 16%, var(--color-bg, #fff));
    color: var(--color-primary);
    font-size: 1.75rem;
}
.thank-you__title,
.thank-you__hero h1 { margin: 0; font-size: clamp(1.35rem, 2.4vw, 1.9rem); font-weight: 700; }
.thank-you__message,
.thank-you__hero > p { color: var(--color-text-soft); }
.thank-you__order { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.75rem; }
.thank-you__pill {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem 0.35rem 0.85rem;
    border: 1px solid var(--color-border);
    border-radius: 0.6rem;
    background: var(--color-surface);
    font-size: 0.9rem;
}
.thank-you__pill-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-soft); }
.thank-you__copy {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border: 0;
    border-radius: 0.4rem;
    background: transparent;
    color: var(--color-text-soft);
    cursor: pointer;
}
.thank-you__copy:hover { background: var(--color-border); color: var(--color-text); }
.thank-you__copied {
    position: absolute;
    inset-block-end: calc(100% + 0.35rem);
    inset-inline-start: 50%;
    transform: translateX(-50%);
    padding: 0.2rem 0.5rem;
    border-radius: 0.35rem;
    background: var(--color-text);
    color: var(--color-bg, #fff);
    font-size: 0.7rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s;
}
[dir="rtl"] .thank-you__copied { transform: translateX(50%); }
.thank-you__copy.is-copied .thank-you__copied { opacity: 1; }
.thank-you__total { font-size: 1.05rem; font-weight: 700; margin: 0; }
.thank-you__sent { font-size: 0.875rem; color: var(--color-text-soft); }
.thank-you__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; text-align: start; }
@media (min-width: 820px) {
    .thank-you__grid { grid-template-columns: minmax(0, 1fr) 20rem; align-items: start; }
}
.thank-you__aside { display: flex; flex-direction: column; gap: 1rem; min-inline-size: 0; }
.thank-you__card {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1.25rem 1.35rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg, 1rem);
    background: var(--color-bg, #fff);
}
.thank-you__card-title { margin: 0; font-size: 1rem; font-weight: 700; }
.thank-you__card-text { margin: 0; font-size: 0.9rem; line-height: 1.6; }
.thank-you__card-text--soft { font-size: 0.8rem; color: var(--color-text-soft); }
.thank-you__facts { display: flex; flex-direction: column; gap: 0.5rem; margin: 0; }
.thank-you__facts > div { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding-block: 0.45rem; border-block-end: 1px solid var(--color-border); font-size: 0.88rem; }
.thank-you__facts > div:last-child { border-block-end: 0; }
.thank-you__facts dt { color: var(--color-text-soft); }
.thank-you__facts dd { margin: 0; font-weight: 600; }
.thank-you__status { display: inline-block; padding: 0.15rem 0.6rem; border-radius: 999px; font-size: 0.75rem; font-weight: 600; background: var(--color-surface); }
.thank-you__status--paid, .thank-you__status--completed { background: #dcfce7; color: #166534; }
.thank-you__status--pending, .thank-you__status--unpaid { background: #fef3c7; color: #92400e; }
.thank-you__status--failed { background: #fee2e2; color: #991b1b; }
.thank-you__steps { margin: 0; padding-inline-start: 1.25rem; display: flex; flex-direction: column; gap: 0.4rem; font-size: 0.88rem; color: var(--color-text-soft); }
.thank-you__steps li::marker { color: var(--color-primary); font-weight: 700; }
.thank-you__summary { display: block; inline-size: 100%; margin: 0; }
.thank-you__card .thank-you__items { max-width: none; margin: 0; }
.thank-you__card .f-order__totals { padding: 1rem 0 0; background: none; border-radius: 0; border-block-start: 1px solid var(--color-border); }
.thank-you__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem; margin-block-start: 0.25rem; }

/* ------------------------------------------------------------------
   Drawer (under 860px): the sheet a phone shopper opens from the hamburger.

   Everything marked .main-menu__drawer-only is display:none on desktop,
   where .main-menu is the horizontal bar and only the merchant's menu
   items belong in it. Below the breakpoint the same nav becomes the
   drawer and these parts appear around those items: name + close, the
   welcome card, search, Shop / Categories / Pages sections, the
   customer's own pages.
   ------------------------------------------------------------------ */
/* !important on purpose: the bar's own list rules (.site-header__nav .main-menu ul …)
   outrank one class, and the Categories and Pages lists leaked into the desktop bar
   without it. */
.main-menu__drawer-only { display: none !important; }

@media (max-width: 860px) {
    .site-header .main-menu {
        display: flex;
        flex-direction: column;
        padding: 0;
        width: min(21rem, 88vw);
        background: var(--color-bg);
    }
    .main-menu__drawer-only { display: block !important; }

    /* The bar centres its items (.site-header__nav .main-menu, align-items:
       center) — in the drawer every row spans the sheet and reads from the
       start edge. */
    .site-header__nav .site-header .main-menu,
    .site-header .main-menu { align-items: stretch; justify-content: flex-start; text-align: start; }
    .main-menu ul, .main-menu__list { inline-size: auto; }
    .site-header .main-menu ul,
    .site-header .main-menu .main-menu__list { align-items: stretch; justify-content: flex-start; }
    .site-header__nav .main-menu ul,
    .site-header__nav .main-menu .main-menu__list { margin: 0 1.1rem 0.9rem !important; padding: 0 !important; gap: 0 !important; }
    .site-header__nav .main-menu .main-menu__submenu { margin: 0 !important; padding: 0 0 0.4rem !important; }
    .site-header .main-menu ul > li,
    .site-header .main-menu .main-menu__list > li {
        display: block;
        inline-size: 100%;
        max-inline-size: none;
        margin: 0;
        text-align: start;
    }
    /* The desktop caret is a 4px triangle drawn from borders; the drawer
       draws a chevron instead, so the triangle's borders and nudges go. */
    .main-menu .main-menu__item.has-children > a::after,
    .main-menu .main-menu__item.has-children.is-open > a::after {
        border: 0;
        border-inline-end: 1.6px solid currentColor;
        border-block-end: 1.6px solid currentColor;
        translate: 0 0;
        rotate: 0deg;
    }
    .main-menu__drawer-only[hidden] { display: none !important; }
    .main-menu__head.main-menu__drawer-only,
    .main-menu__welcome.main-menu__drawer-only,
    .main-menu__search.main-menu__drawer-only { display: flex !important; }
    .main-menu__welcome.main-menu__drawer-only[hidden] { display: none !important; }
    .main-menu__icon { inline-size: 1.15rem; block-size: 1.15rem; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

    /* head */
    .main-menu__head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.75rem;
        padding: 1rem 1.1rem 0.75rem;
    }
    .main-menu__brand { font-size: 1.2rem; font-weight: 700; color: var(--color-text); text-decoration: none; }
    .main-menu__close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 2.1rem;
        block-size: 2.1rem;
        border: 0;
        border-radius: 50%;
        background: var(--color-surface-2, rgba(0, 0, 0, 0.06));
        color: var(--color-text);
        cursor: pointer;
    }

    /* welcome card */
    .main-menu__welcome {
        display: flex;
        align-items: center;
        gap: 0.7rem;
        margin: 0 1.1rem 0.9rem;
        padding: 0.8rem 0.9rem;
        border-radius: var(--radius-lg, 14px);
        background: var(--color-footer-bg, #1f1a16);
        color: #fff;
    }
    .main-menu__welcome[hidden] { display: none; }
    .main-menu__avatar {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex: none;
        inline-size: 2.4rem;
        block-size: 2.4rem;
        border-radius: 50%;
        background: rgba(255, 255, 255, 0.18);
        color: #fff;
        font-weight: 700;
        font-size: 1rem;
    }
    .main-menu__welcome-text { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; line-height: 1.25; }
    .main-menu__welcome-text small { font-size: 0.72rem; opacity: 0.75; }
    .main-menu__welcome-text strong { font-size: 0.95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .main-menu__pill {
        flex: none;
        padding: 0.45rem 0.85rem;
        border: 0;
        border-radius: 999px;
        background: rgba(255, 255, 255, 0.14);
        color: #fff;
        font: inherit;
        font-size: 0.78rem;
        font-weight: 600;
        text-decoration: none;
        cursor: pointer;
    }

    /* search */
    .main-menu__search {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin: 0 1.1rem 1rem;
        padding: 0 0.8rem;
        border-radius: 999px;
        background: var(--color-surface-2, rgba(0, 0, 0, 0.05));
        color: var(--color-muted, #6b7280);
    }
    .main-menu__search input {
        flex: 1 1 auto;
        min-inline-size: 0;
        padding: 0.65rem 0;
        border: 0;
        background: none;
        color: var(--color-text);
        font: inherit;
        font-size: 0.9rem;
        outline: none;
    }

    /* sections + rows */
    .main-menu__section {
        margin: 0.25rem 1.1rem 0.2rem;
        font-size: 0.7rem;
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--color-muted, #6b7280);
    }
    .main-menu ul,
    .main-menu__list { margin: 0 1.1rem 0.9rem; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0; }
    .main-menu ul .main-menu__item > a,
    .main-menu__list .main-menu__item > a,
    .main-menu__logout {
        display: flex;
        align-items: center;
        gap: 0.7rem;
        inline-size: 100%;
        padding: 0.75rem 0.1rem;
        border: 0;
        border-block-end: 1px solid var(--color-border);
        background: none;
        color: var(--color-text);
        font: inherit;
        font-size: 0.95rem;
        font-weight: 500;
        text-decoration: none;
        text-align: start;
        cursor: pointer;
    }
    .main-menu .main-menu__item:last-child > a,
    .main-menu .main-menu__item:last-child > .main-menu__logout { border-block-end: 0; }
    .main-menu .main-menu__item.has-children > a::after {
        content: '';
        margin-inline-start: auto;
        inline-size: 0.5rem;
        block-size: 0.5rem;
        border-inline-end: 1.6px solid currentColor;
        border-block-end: 1.6px solid currentColor;
        transform: rotate(45deg);
        opacity: 0.6;
        transition: transform 0.15s ease;
    }
    .main-menu .main-menu__item.has-children.is-open > a::after { transform: rotate(-135deg); }
    .main-menu .main-menu__submenu { margin: 0; padding: 0 0 0.4rem 0; }
    .main-menu .main-menu__submenu a { display: block; padding: 0.55rem 0 0.55rem 1.85rem; font-size: 0.9rem; color: var(--color-text); text-decoration: none; opacity: 0.85; }
    [dir="rtl"] .main-menu .main-menu__submenu a { padding: 0.55rem 1.85rem 0.55rem 0; }
    .main-menu__logout { color: var(--color-danger, #b3261e); }

    /* A long label wraps instead of widening the sheet. The desktop bar sets
       white-space: nowrap on .site-header__nav .main-menu__item > a and the
       drawer rules above never undid it, so a long product or category name
       pushed the list past the panel edge and overflow-y: auto on .main-menu
       turned that into a horizontal scroll. overflow-wrap: anywhere keeps an
       unbroken token (a URL, a long Arabic compound) inside the row too, and
       the chevron keeps its own width as the text takes the rest. */
    .site-header .main-menu { overflow-x: hidden; }
    .site-header .main-menu ul .main-menu__item > a,
    .site-header .main-menu .main-menu__list .main-menu__item > a,
    .site-header .main-menu .main-menu__submenu a,
    .site-header .main-menu .main-menu__logout {
        white-space: normal;
        overflow-wrap: anywhere;
        min-inline-size: 0;
    }
    .site-header .main-menu .main-menu__item > a > span { flex: 1 1 auto; min-inline-size: 0; }
    .site-header .main-menu .main-menu__item.has-children > a::after { flex: none; }

}

/* ===== full-screen hero + transparent navbar (2026-10-14) ===================
   The hero stopped being the first card on the page and became the page's
   opening screen: full-bleed, viewport-tall, with the header floating over it
   in white. These rules come last so they replace the contained, rounded,
   2.7:1 hero above rather than sit beside it.

   `block--flush` strips the section padding; the container moved from around
   the slider to the slide copy only, so the media runs edge to edge. */
.block--hero.block--flush { padding: 0; margin: 0; }
.block--hero .hero-slider { display: block; position: relative; }
.block--hero .hero-slide,
.block--hero .hero-slide__img { border-radius: 0; }
.block--hero .hero-slide__picture { display: block; }

/* A slide can carry media for only one viewport — a desktop still with a
   phone-only video, or a desktop video with a phone still. The template then
   renders both a <video> and a <picture> with complementary modifiers, and
   these rules show exactly one per viewport. Same breakpoint as the
   <source media> and the isPhone check in app.js. */
@media (max-width: 767px) {
    .block--hero .hero-slide__video--desktop-only,
    .block--hero .hero-slide__picture--desktop-only { display: none; }
}
@media (min-width: 768px) {
    .block--hero .hero-slide__video--mobile-only,
    .block--hero .hero-slide__picture--mobile-only { display: none; }
}

/* svh, not vh: on a phone 100vh is taller than the visible area while the
   browser chrome is showing, which pushes the slide copy under the toolbar. */
.block--hero .hero-slide__img {
    display: block;
    width: 100%;
    inline-size: 100%;
    height: 100vh;
    height: 100svh;
    min-height: 30rem;
    aspect-ratio: auto;
    object-fit: cover;
}
@media (max-width: 639px) {
    .block--hero .hero-slide__img { height: 100svh; aspect-ratio: auto; }
}
/* Where the fixed bottom bar shows, the hero stops above it — otherwise the
   bar covers the slide's foot and the first screen scrolls. min-height off:
   30rem is taller than what's left on a short phone. */
@media (max-width: 860px) {
    .block--hero .hero-slide__img {
        height: calc(100svh - var(--bottom-nav-height, 0px));
        min-height: 0;
    }
    /* The SDK track's 4px bottom padding would push the hero past the bar. */
    .block--hero .hero-slider .f-slider__track { padding-block-end: 0; }
}

@media (max-width: 767px) {
    /* Smaller arrows hugging the edges, see-through, so they stop covering
       the slide's copy on a narrow screen. */
    /* The disc paints at 28px, but the button is 44px: the transparent
       border is tap area, and background-clip keeps the white inside it. At
       28px of actual button a thumb kept landing beside it, on the slide. */
    .block--hero .hero-slider .f-slider__controls { padding-inline: 0; }
    .block--hero .hero-slider .f-slider__arrow {
        box-sizing: border-box;
        inline-size: 2.75rem;
        block-size: 2.75rem;
        border: 0.5rem solid transparent;
        background: rgba(255, 255, 255, 0.7);
        background-clip: padding-box;
    }
    .block--hero .hero-slider .f-slider__arrow::before { inline-size: 0.45rem; block-size: 0.45rem; }
}

/* A second wash at the foot of the slide for the copy and the dots; the top
   wash under the header already exists above. */
.block--hero .hero-slide::before {
    content: '';
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 45%;
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0));
    pointer-events: none;
    z-index: 1;
    /* Off unless the merchant sets Background dimming in the customizer. */
    opacity: var(--falak-overlay, 0%);
}
.block--hero .hero-slide__content {
    z-index: 2;
    inset-block-end: clamp(4rem, 12vh, 8rem);
}

/* Dots on the picture rather than in a strip below it — a strip below a
   100svh slide is a white band the shopper has to scroll past. */
.block--hero .hero-slider .f-slider__dots {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 1.5rem;
    margin: 0;
    z-index: 3;
}
.block--hero .hero-slider .f-slider__dots button,
.block--hero .hero-slider .f-slider__dots [role="tab"] {
    background: rgba(255, 255, 255, 0.45);
}
.block--hero .hero-slider .f-slider__dots .is-active,
.block--hero .hero-slider .f-slider__dots [aria-selected="true"] {
    background: #fff;
}

/* ---- navbar over the hero -----------------------------------------------
   Airy, borderless, white ink. Row borders go, the main bar gets more room,
   the menu reads as spaced small caps and the icon buttons sit in frosted
   discs so they stay visible on a light frame of the video. All of it is
   scoped to the transparent state; the scrolled bar keeps the solid design
   defined earlier in the file. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__utility,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__nav {
    border-color: transparent;
}
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__utility {
    font-size: 0.82rem;
    color: rgba(255, 255, 255, 0.82);
}
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__bar-inner {
    min-height: 5.5rem;
}
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__logo img {
    max-height: 3.5rem;
}
@media (min-width: 861px) {
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__nav .main-menu > ul > li > a,
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__nav .main-menu > .main-menu__list > .main-menu__item > a {
        color: #fff;
        font-size: 0.8rem;
        font-weight: 600;
        letter-spacing: 0.12em;
        text-transform: uppercase;
        opacity: 0.92;
    }
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__nav .main-menu > ul > li > a:hover,
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__nav .main-menu > .main-menu__list > .main-menu__item > a:hover {
        opacity: 1;
        text-decoration: underline;
        text-underline-offset: 0.45em;
    }
}
/* Icon controls: frosted discs. Every trigger in the two side clusters is a
   button or a link rendered by an SDK component, so the disc goes on the
   host rather than on the component's own markup. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__start > *,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__end > * {
    color: #fff;
}
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .menu-toggle span {
    background: #fff;
}
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .cart-link {
    /* The host is square; the round disc is the link inside it. Boxing the
       host drew a rectangle around the disc, so only the colour is set. */
    color: #fff;
}
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .search-link .f-search__trigger,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .wishlist-link .f-wishlist-drawer__trigger {
    border-color: rgba(255, 255, 255, 0.35);
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}

/* ---- the discs do NOT frost over the hero -------------------------------
   One treatment for the icon controls in every header state: the #f8f8f8
   plate with the glyph in the brand colour, over the video exactly as on the
   solid bar. The frosted rule above, and this state's white ink, are undone
   here rather than deleted up there - the ink rules also serve the menu, the
   utility links and the logo, which DO stay white on the hero.

   Same prefix as the rules it overrides plus :not([data-scrolled]), so it wins
   on specificity and not merely on being last. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .search-link .f-search__trigger,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .wishlist-link .f-wishlist-drawer__trigger,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .f-cart-summary__link,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .f-user__trigger,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .theme-toggle,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .menu-toggle {
    background: var(--color-icon-disc);
    border-color: transparent;
    color: var(--color-primary);
    box-shadow: var(--shadow-icon-disc-hero);
}

/* The pills, which are not in the disc rule above and would otherwise sit on
   the hero wearing the flat bar's shadow. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .f-locale__trigger,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .f-currency__field {
    box-shadow: var(--shadow-icon-disc-hero);
}

/* Hover, stated inside this state as well. Every selector here carries the
   state's long prefix, so the resting rules above outrank the solid bar's
   own :hover rule - without this the disc would scale under the pointer and
   its shadow would sit still. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .search-link .f-search__trigger:hover,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .wishlist-link .f-wishlist-drawer__trigger:hover,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .f-cart-summary__link:hover,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .f-user__trigger:hover,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .theme-toggle:hover,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .menu-toggle:hover,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .f-locale__trigger:hover,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .f-currency__field:hover {
    box-shadow: var(--shadow-icon-disc-hero-hover);
}

/* The drop-shadow halo goes with the frosting. It was drawn to hold a white
   glyph together against a bright frame of the video; an opaque disc does that
   job itself, and the filter reached only three of the five controls, so the
   row read with two different edges. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .cart-link,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .search-link .f-search__trigger,
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .wishlist-link .f-wishlist-drawer__trigger {
    filter: none;
}

/* The hamburger's bars are <span>s painted white for this state. They only
   need that where the toggle has no disc - below 768px it does, and white on
   #f8f8f8 is an empty circle. */
@media (max-width: 767px) {
    .header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .menu-toggle span {
        background: var(--color-primary);
    }
}

/* The control row carries its own ground (.site-header__bar, above) so the
   header's `background: transparent` never reached it: the bar stayed white
   over the hero while the nav row beneath it went clear. Same scope as the
   rest of the transparent state. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"]:not([data-scrolled]) .site-header__bar {
    background: transparent;
}

/* A deeper top wash than the band version carried: the nav row now sits on
   whatever the slide's brightest frame happens to be, in white. */
.block--hero .hero-slide::after {
    height: 17rem;
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.58), rgba(0, 0, 0, 0));
}

/* ---- one logo, categories in the bar ------------------------------------
   Onyx carries ONE logo, the store's own, shown as uploaded on every ground.
   The brightness(0) fallback above flattened a coloured mark to black the
   moment the header went solid; with no second logo to switch to, it goes. */
.header-is-transparent .app-inner:has(> main > .block--hero:first-child) .site-header[data-transparent="1"][data-scrolled] .site-header__logo img {
    filter: var(--logo-shadow);
}

/* Counterpart of .main-menu__drawer-only: the categories rendered into the
   desktop bar vanish inside the drawer, where their own section lives. */
@media (max-width: 860px) {
    .main-menu__desktop-only { display: none !important; }
}

/* ===== onyx card: the panel design =====
   One card for the whole theme (custom-falak-product-card, panel mode),
   measured off the reference storefront's .v3-product-card:

     card      #f7f7f8, radius 20, hover lifts 4px with a 12/24 shadow
     photo     square, radius 14, full width of the card
     discs     30px white, 10px from the photo's physical left, at 10 and 48
     panel     #e8e8e8, radius 16, 1rem margin and padding
     category  13px, primary        name 1.2rem / 700, two lines
     pills     26px, 1px white border, radius 6; chosen = primary + tint
     price     15px / 700
     button    outlined pill, 1.5px primary, 14px / 600, label then bag glyph

   Scoped to .vp-card--panel, which app.js sets on every card except the
   video-commerce wall's, so the lead / row / clip variants keep their own
   look. Last in the file on purpose: the vp-card rules above were written for
   the hover-overlay card and each of them has to be undone here, at a higher
   specificity, rather than edited; they still serve those other variants.

   The grey panel is body + foot together (the button is a sibling of the
   body in the markup), seamed by matching background and complementary radii. */
.vp-card.vp-card--panel {
    gap: 0;
    padding: 0;
    min-height: 420px;
    background: #f7f7f8;
    border: 1px solid transparent;
    border-radius: 20px;
    transition: transform 0.3s, box-shadow 0.3s;
}
.vp-card.vp-card--panel:hover {
    transform: translateY(-4px);
    border-color: transparent;
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12);
}

/* Doubled class on media and body: several sections (products-slider,
   product-tabs, category-feature, best-sellers) size the hover card with
   `.block--x custom-falak-product-card .vp-card__media`, which would otherwise
   outrank these and give the same panel card a different photo ratio per
   section. */
.vp-card.vp-card--panel .vp-card__media {
    flex: 0 0 auto;
    min-block-size: auto;
    aspect-ratio: 1 / 1;
    border-radius: 14px;
    background: #fff;
}
.vp-card--panel .vp-card__video { width: 100%; height: 100%; object-fit: cover; }
/* The video-commerce wall: same panel card, but the clip keeps its portrait
   frame — it is shot for a phone, and a square crop cuts the product out. */
.vp-card.vp-card--panel.vp-card--clip .vp-card__media { aspect-ratio: 9 / 16; }

/* The disc pair: always on, top-left of the photo, stacked 8px apart (30 + 8
   is the reference's 48px for the second). Physical left, as the reference. */
.vp-card--panel .vp-card__actions {
    inset-block: 10px auto;
    inset-inline: auto;
    left: 10px;
    right: auto;
    flex-direction: column;
    justify-content: flex-start;
    gap: 8px;
}
.vp-card--panel .vp-card__control {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s;
}
.vp-card--panel .vp-card__control[data-title]::before { content: none; }
.vp-card--panel .vp-card__icon {
    width: 30px;
    height: 30px;
    flex-basis: 30px;
    color: #9ca3af;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}
.vp-card--panel .vp-card__icon .f-wishlist__icon,
.vp-card--panel .vp-card__icon svg,
.vp-card--panel .vp-card__icon-glyph { width: 16px; height: 16px; }

.vp-card.vp-card--panel .vp-card__body {
    flex: 1 1 auto;
    justify-items: stretch;
    align-content: start;
    gap: 4px;
    margin: 0.625rem 0.625rem 0;
    padding: 0.75rem 0.75rem 0;
    background: #e8e8e8;
    border-radius: 16px 16px 0 0;
    text-align: start;
    /* One column capped at the panel: an `auto` track grows to its widest
       row's min-content, and a nowrap "Size [Choose size]" row is ~165px —
       on a 166px phone card that pushed the name, category and options past
       the card edge, where they were clipped. */
    grid-template-columns: minmax(0, 1fr);
}
.vp-card.vp-card--panel .vp-card__body > * { min-width: 0; }
.vp-card--panel .vp-card__category {
    margin: 0;
    color: var(--color-primary);
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.vp-card--panel .vp-card__name {
    font-size: 15px;
    font-weight: 700;
    line-height: 1.4;
}
.vp-card--panel .vp-card__stars { justify-content: flex-start; }
.vp-card--panel .vp-card__price {
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 8px;
    margin-block: 2px 4px;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.4;
}
.vp-card--panel .vp-card__price del { font-size: 12px; font-weight: 400; }

/* Variants: the label, then outlined chips. */
.vp-card--panel .vp-card__variants .f-options__group {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    margin: 0;
}
.vp-card--panel .vp-card__variants .f-options__label {
    margin: 0;
    color: var(--color-text-secondary, #6b7280);
    font-size: 12px;
    font-weight: 600;
}
.vp-card--panel .vp-card__variants .f-options__pills { justify-content: flex-start; gap: 6px; }
.vp-card--panel .vp-card__variants .f-options__pill {
    min-width: 26px;
    min-height: 26px;
    height: 26px;
    padding: 0 8px;
    border: 1px solid #fff;
    border-radius: 6px;
    background: transparent;
    box-shadow: none;
    color: var(--color-text);
    font-size: 12px;
    line-height: 1;
    transition: all 0.15s;
}
.vp-card--panel .vp-card__variants .f-options__pill.is-selected,
.vp-card--panel .vp-card__variants .f-options__pill[aria-checked="true"] {
    border-color: var(--color-primary);
    background: color-mix(in srgb, var(--color-primary) 10%, white 85%);
    color: var(--color-primary);
    font-weight: 700;
}
.vp-card--panel .vp-card__variants .f-options__pill:disabled { opacity: 0.4; text-decoration: line-through; }

/* The foot: the rest of the grey panel, holding the button. */
.vp-card--panel .vp-card__addcart--foot {
    position: static;
    inset: auto;
    margin: 0 0.625rem 0.625rem;
    padding: 8px 0.75rem 0.75rem;
    opacity: 1;
    visibility: visible;
    transform: none;
    background: #e8e8e8;
    border-radius: 0 0 16px 16px;
}

/* The button's HOST is a .vp-card__cart too, and the overlay-bar rules give it
   a dark wash, square corners and white text, so the pill is drawn on the host
   and the inner button is made transparent to sit inside it. */
.vp-card--panel .vp-card__addcart--foot .vp-card__cart {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: auto;
    line-height: 1.2;
    border: 1.5px solid var(--color-primary);
    border-radius: 999px;
    background: transparent;
    color: var(--color-primary);
    box-shadow: none;
    overflow: hidden;
    transition: all 0.2s;
}
.vp-card--panel .vp-card__addcart--foot .vp-card__cart::before { content: none; }
.vp-card--panel .vp-card__addcart--foot .vp-card__cart:hover {
    background: var(--color-primary);
    color: var(--color-on-primary);
}
.vp-card--panel .vp-card__addcart--foot .vp-card__cart .f-add-product__button,
.vp-card--panel .vp-card__addcart--foot .vp-card__cart .f-btn,
.vp-card--panel .vp-card__addcart--foot .vp-card__cart button {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    height: auto;
    padding: 10px 16px;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: inherit;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
}
.vp-card--panel .vp-card__addcart--foot .vp-card__cart button::before { content: none; }
.vp-card--panel .vp-card__addcart--foot .vp-card__cart button:hover:not(:disabled) {
    background: transparent;
    color: inherit;
}
.vp-card--panel .vp-card__addcart--foot .vp-card__cart svg { flex-shrink: 0; width: 16px; height: 16px; }
.vp-card--panel .vp-card__addcart--foot .vp-card__cart:has(button:disabled) { opacity: 0.7; cursor: not-allowed; }

@media (max-width: 480px) {
    .vp-card.vp-card--panel { border-radius: 16px; }
    .vp-card--panel .vp-card__media { border-radius: 12px; }
    .vp-card.vp-card--panel .vp-card__body { margin: 0.5rem 0.5rem 0; padding: 0.625rem 0.625rem 0; }
    .vp-card--panel .vp-card__addcart--foot { margin: 0 0.5rem 0.5rem; padding: 6px 0.625rem 0.625rem; }
    .vp-card--panel .vp-card__icon { width: 26px; height: 26px; flex-basis: 26px; }
    .vp-card--panel .vp-card__actions { gap: 6px; }
    .vp-card--panel .vp-card__name { font-size: 12px; }
    .vp-card--panel .vp-card__price { font-size: 14px; }
    .vp-card--panel .vp-card__addcart--foot .vp-card__cart button { padding: 8px 12px; font-size: 13px; }
}

/* ---- panel card: variants, as the reference lays them out ----
   Each group is one wrapping row: the label, then its chips. When the chips do
   not fit beside the label they drop to their own line as a block, which is
   how the long "light" names sit under their caption in the reference. The
   SDK's own extras — the colon, the bold chosen value and the "choose an
   option" hint — are not part of that design, so they are hidden here. */
.vp-card--panel .vp-card__variants .f-options { gap: 6px; }
.vp-card--panel .vp-card__variants .f-options__label { display: contents; }
.vp-card--panel .vp-card__variants .f-options__name {
    color: var(--color-text-secondary, #6b7280);
    font-size: 12px;
    font-weight: 600;
}
.vp-card--panel .vp-card__variants .f-options__name::after,
.vp-card--panel .vp-card__variants .f-options__chosen,
.vp-card--panel .vp-card__variants .f-options__hint { display: none; content: none; }
/* The error stays: it is the only explanation when an add is refused. */
.vp-card--panel .vp-card__variants .f-options__error:not([hidden]) { display: block; font-size: 12px; }
.vp-card--panel .vp-card__variants .f-options__pills { flex: 0 1 auto; min-width: 0; }

/* Dropdown groups (size, volume…) stay on the label's row: the select takes
   whatever width is left instead of wrapping to a full-width line of its own,
   and is cut to chip height so the row is no taller than a chip row. */
.vp-card--panel .vp-card__variants .f-options__group:not(:has(.f-options__error:not([hidden]))) { flex-wrap: nowrap; }
.vp-card--panel .vp-card__variants .f-options__name { flex: none; white-space: nowrap; }

/* Chips that outgrow the row scroll sideways rather than wrap. The 4px pad
   (taken back by the negative margin) keeps the chosen swatch's ring from
   being clipped by the scroll box. */
.vp-card--panel .vp-card__variants .f-options__pills {
    flex-wrap: nowrap;
    margin: -4px;
    padding: 4px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}
.vp-card--panel .vp-card__variants .f-options__pills::-webkit-scrollbar { display: none; }
.vp-card--panel .vp-card__variants .f-options__pill { flex: none; }
.vp-card--panel .vp-card__variants .f-options__select {
    flex: 1 1 0;
    min-width: 0;
    width: auto;
    height: 28px;
    min-height: 0;
    padding: 0 6px;
    border-radius: 6px;
    font-size: 12px;
    line-height: 1;
}

/* Colour swatches: a 15px dot; the chosen one gets a white gap, a primary ring
   and a tick that inverts against whatever colour it sits on. The generic chip
   rule above would otherwise square them to 26px. */
.vp-card--panel .vp-card__variants .f-options__pill--swatch {
    width: 15px;
    min-width: 0;
    height: 15px;
    min-height: 0;
    padding: 0;
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 50%;
    background: transparent;
    justify-content: center;
}
.vp-card--panel .vp-card__variants .f-options__pill--swatch.is-selected,
.vp-card--panel .vp-card__variants .f-options__pill--swatch[aria-checked="true"] {
    background: transparent;
    border-color: rgba(0, 0, 0, 0.08);
    box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px var(--color-primary);
}
.vp-card--panel .vp-card__variants .f-options__pill--swatch .f-options__swatch {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    box-shadow: none;
}
.vp-card--panel .vp-card__variants .f-options__pill--swatch.is-selected .f-options__swatch::after {
    content: "";
    position: absolute;
    inset-block-start: 2px;
    inset-inline-start: 4.5px;
    width: 3px;
    height: 7px;
    border: solid #fff;
    border-width: 0 1.5px 1.5px 0;
    transform: rotate(45deg);
    mix-blend-mode: difference;
}

/* ---- panel card: chips answer the pointer ----
   Two small motions. Hovering the CARD wakes the row: each chip's white
   hairline tints toward the primary one after another, 40ms apart, on the
   way in only (leaving snaps back together). Hovering a CHIP lifts it 2px
   with a slight swell and a soft shadow, and a click presses it back. A
   swatch dot swells in place instead of lifting and takes a faint primary
   ring, weaker than the chosen dot's own ring so that one still reads as
   chosen. Every excursion fits in the 4px pad the scroll box above keeps,
   so nothing is clipped. The property order below is what the per-property
   delays index into. */
.vp-card--panel .vp-card__variants .f-options__pill {
    transition-property: border-color, transform, box-shadow, background-color, color;
    transition-duration: 0.2s;
    transition-timing-function: ease, cubic-bezier(0.34, 1.56, 0.64, 1), ease, ease, ease;
    transition-delay: 0s;
}
.vp-card--panel:hover .vp-card__variants .f-options__pill:not(:disabled):not(.is-selected):not([aria-checked="true"]):not(.f-options__pill--swatch) {
    border-color: color-mix(in srgb, var(--color-primary) 35%, #fff);
}
.vp-card--panel:hover .vp-card__variants .f-options__pill:nth-child(2) { transition-delay: 40ms, 0s, 0s, 0s, 0s; }
.vp-card--panel:hover .vp-card__variants .f-options__pill:nth-child(3) { transition-delay: 80ms, 0s, 0s, 0s, 0s; }
.vp-card--panel:hover .vp-card__variants .f-options__pill:nth-child(4) { transition-delay: 120ms, 0s, 0s, 0s, 0s; }
.vp-card--panel:hover .vp-card__variants .f-options__pill:nth-child(5) { transition-delay: 160ms, 0s, 0s, 0s, 0s; }
.vp-card--panel:hover .vp-card__variants .f-options__pill:nth-child(n+6) { transition-delay: 200ms, 0s, 0s, 0s, 0s; }

.vp-card--panel .vp-card__variants .f-options__pill:not(.f-options__pill--swatch):hover:not(:disabled),
.vp-card--panel .vp-card__variants .f-options__pill:not(.f-options__pill--swatch):focus-visible {
    transform: translateY(-2px) scale(1.05);
    border-color: var(--color-primary);
    background: color-mix(in srgb, var(--color-primary) 6%, #fff);
    color: var(--color-primary);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    transition-delay: 0s;
}
/* The chosen chip lifts too, but keeps its own stronger fill. */
.vp-card--panel .vp-card__variants .f-options__pill.is-selected:not(.f-options__pill--swatch):hover:not(:disabled),
.vp-card--panel .vp-card__variants .f-options__pill[aria-checked="true"]:not(.f-options__pill--swatch):hover:not(:disabled) {
    background: color-mix(in srgb, var(--color-primary) 14%, #fff);
}
.vp-card--panel .vp-card__variants .f-options__pill:not(.f-options__pill--swatch):active:not(:disabled) {
    transform: translateY(0) scale(0.96);
    box-shadow: none;
    transition-duration: 0.08s;
}

.vp-card--panel .vp-card__variants .f-options__pill--swatch .f-options__swatch {
    transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.vp-card--panel .vp-card__variants .f-options__pill--swatch:hover:not(:disabled) .f-options__swatch,
.vp-card--panel .vp-card__variants .f-options__pill--swatch:focus-visible .f-options__swatch {
    transform: scale(1.15);
}
.vp-card--panel .vp-card__variants .f-options__pill--swatch:hover:not(:disabled):not(.is-selected):not([aria-checked="true"]) {
    box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px color-mix(in srgb, var(--color-primary) 45%, transparent);
}

@media (prefers-reduced-motion: reduce) {
    .vp-card--panel .vp-card__variants .f-options__pill,
    .vp-card--panel .vp-card__variants .f-options__pill .f-options__swatch {
        transition: none;
        transform: none !important;
    }
}

/* ---- panel card: the disc pair, heart first ----
   The markup puts quick view first (other card variants rely on that order);
   the reference stacks the heart on top. The heart's host and its SDK button
   both carry sizes from the touch block (34px), so all three are pinned. */
.vp-card--panel .vp-card__actions .vp-card__control:nth-child(2) { order: -1; }
.vp-card--panel .vp-card__actions falak-wishlist-button.vp-card__icon,
.vp-card--panel .vp-card__actions .vp-card__icon .f-wishlist__button {
    width: 30px;
    height: 30px;
    min-width: 0;
    min-height: 0;
    flex-basis: 30px;
}
.vp-card--panel .vp-card__actions falak-wishlist-button.vp-card__icon {
    color: #9ca3af;
    background: #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}
.vp-card--panel .vp-card__icon:hover,
.vp-card--panel .vp-card__actions falak-wishlist-button.vp-card__icon:hover {
    background: #fff;
    color: var(--color-primary);
}

/* ---- panel card: sold out ----
   The button is disabled by the SDK (product-status="out") and says "out of
   stock"; it keeps the pill but drops to the muted ink, and never fills on
   hover, so it cannot read as something to press. */
.vp-card--panel .vp-card__addcart--foot .vp-card__cart:has(button:disabled),
.vp-card--panel .vp-card__addcart--foot .vp-card__cart:has(button:disabled):hover {
    opacity: 1;
    border-color: var(--color-border);
    background: transparent;
    color: var(--color-text-faint);
    cursor: not-allowed;
}
.vp-card--panel .vp-card__addcart--foot .vp-card__cart button:disabled { opacity: 1; cursor: not-allowed; }
.vp-card--panel.vp-card--out-of-stock .vp-card__media img,
.vp-card--panel.vp-card--out-of-stock .vp-card__media video { opacity: 0.6; }

/* ---- hero: copy in the middle of the frame ----
   The copy was pinned 4–8rem above the slide's foot. On a viewport-tall hero
   that put the title, text and button on the bottom edge, crowding the dots.
   It now sits in the vertical middle of the area BELOW the floating header
   (--header-h is the header's own height), so it reads as the slide's
   headline rather than a caption.

   Still display:block, still the full container width, so the customizer's
   text-alignment control keeps working; only the box's vertical position
   changes. A slide whose copy is empty keeps its artwork untouched. */
.block--hero .hero-slide__content {
    inset-block-start: calc(50% + var(--header-h, 0px) / 2);
    inset-block-end: auto;
    transform: translateY(-50%);
    /* Clear of the prev/next arrows, which sit on the slide edges. */
    padding-inline: clamp(3.5rem, 6vw, 5.5rem);
}
/* No ch caps on the title or text: a capped box stays at the start while
   centred words move, which is the half-centred look the note above the
   original block describes. Size and rhythm only. */
.block--hero .hero-slide__title {
    line-height: 1.15;
    font-size: clamp(2rem, 4.2vw, 3.75rem);
}
.block--hero .hero-slide__text {
    font-size: clamp(1rem, 1.4vw, 1.25rem);
    line-height: 1.6;
    opacity: 0.92;
}

/* Copy in the middle needs a wash in the middle: the foot-only gradient left
   white text on whatever bright frame the picture had there. Only on slides
   that actually carry copy, so finished artwork is not dimmed. */
.block--hero .hero-slide:has(.hero-slide__title:not(:empty))::before,
.block--hero .hero-slide:has(.hero-slide__content .btn)::before {
    height: 100%;
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.25) 55%, rgba(0, 0, 0, 0.15) 100%);
}

@media (max-width: 639px) {
    .block--hero .hero-slide__content { inset-block-start: calc(50% + var(--header-h, 0px) / 3); }
}

/* ---- panel card: marks opposite the discs ----
   The heart and eye are pinned to the photo's physical left, but the sale,
   "hot" and offer marks sit at the inline START — the left on an English
   page — so they slid underneath the discs. On the panel card every mark
   takes the physical right instead, stacked top-down so a product carrying
   several never piles them on one spot; free shipping keeps the foot. */
.vp-card--panel .vp-card__sale,
.vp-card--panel .vp-card__hot,
.vp-card--panel .vp-card__offer,
.vp-card--panel .vp-card__badge,
.vp-card--panel .vp-card__ship {
    inset-inline: auto;
    left: auto;
    right: 10px;
    z-index: 3;
}
.vp-card--panel .vp-card__sale  { top: 10px; }
.vp-card--panel .vp-card__hot   { top: 38px; }
.vp-card--panel .vp-card__offer { top: 10px; max-inline-size: calc(100% - 60px); }
/* Sale and offer both claim the top; when both are present the offer steps
   below the sale (and below "hot" when that is there too). */
.vp-card--panel .vp-card__sale ~ .vp-card__offer,
.vp-card--panel .vp-card__offer:has(~ .vp-card__sale) { top: 38px; }
.vp-card--panel .vp-card__offer:has(~ .vp-card__hot) { top: 66px; }
.vp-card--panel .vp-card__ship  { top: auto; bottom: 10px; }

/* ---------------------------------------------------------- custom html */
/* Merchant markup is unknown — keep its media inside the column. */
.custom-html__body {
    overflow-wrap: anywhere;
}

.custom-html__body :where(img, video, iframe) {
    max-width: 100%;
}

.custom-html__body :where(img, video) {
    height: auto;
}
