:root {
    --droply-primary: 28 177 201;
    --droply-primary-dark: 23 154 175;
    --droply-orange: 249 115 22;
    --droply-violet: 139 92 246;
    --droply-success: 22 163 74;
    --droply-text-main: 15 23 42;
    --droply-text-sub: 100 116 139;
    --droply-border: 226 232 240;
    --droply-surface: 255 255 255;
    --droply-surface-soft: 248 250 252;
    --droply-page: 244 247 251;
    --droply-shadow-soft: 0 22px 55px -28px rgba(28, 177, 201, 0.22);
    --droply-shadow-card: 0 28px 80px -32px rgba(15, 23, 42, 0.18);
    --droply-shadow-glass: 0 20px 50px -35px rgba(15, 23, 42, 0.28);
    --droply-radius-xl: 1.5rem;
    --droply-radius-2xl: 2rem;
    --droply-radius-3xl: 2.5rem;
}

html,
body {
    font-family: 'Manrope', 'Segoe UI', Tahoma, Arial, sans-serif;
    background:
        radial-gradient(circle at top right, rgba(var(--droply-primary), 0.12), transparent 28%),
        radial-gradient(circle at bottom left, rgba(var(--droply-orange), 0.08), transparent 26%),
        rgb(var(--droply-page));
    color: rgb(var(--droply-text-main));
}

body {
    min-height: 100vh;
}

a,
.btn-link {
    color: rgb(var(--droply-primary));
}

.btn-primary {
    color: #fff;
    background-color: rgb(var(--droply-primary));
    border-color: rgb(var(--droply-primary-dark));
}

.droply-shell {
    position: relative;
    isolation: isolate;
}

.droply-shell::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background:
        radial-gradient(circle at 12% 12%, rgba(var(--droply-primary), 0.07), transparent 18%),
        radial-gradient(circle at 88% 18%, rgba(var(--droply-violet), 0.06), transparent 20%),
        radial-gradient(circle at 82% 84%, rgba(var(--droply-orange), 0.07), transparent 18%);
    z-index: -1;
}

.droply-page {
    max-width: 1440px;
    margin-inline: auto;
    padding-inline: 1.5rem;
}

.droply-surface-card {
    background: rgba(var(--droply-surface), 0.88);
    border: 1px solid rgba(var(--droply-border), 0.9);
    border-radius: var(--droply-radius-2xl);
    box-shadow: var(--droply-shadow-soft);
    backdrop-filter: blur(14px);
}

.droply-surface-card-strong {
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.95));
    border: 1px solid rgba(var(--droply-border), 0.9);
    border-radius: var(--droply-radius-3xl);
    box-shadow: var(--droply-shadow-card);
}

.droply-glass-nav {
    background: rgba(255, 255, 255, 0.76);
    border-bottom: 1px solid rgba(255, 255, 255, 0.7);
    box-shadow: var(--droply-shadow-glass);
    backdrop-filter: blur(18px);
}

.droply-button-primary {
    background: linear-gradient(135deg, rgb(var(--droply-primary)), rgb(var(--droply-primary-dark)));
    color: #fff;
    box-shadow: 0 20px 45px -24px rgba(var(--droply-primary), 0.7);
}

.droply-button-secondary {
    background: rgba(255, 255, 255, 0.9);
    color: rgb(var(--droply-text-main));
    border: 1px solid rgba(var(--droply-border), 0.9);
    box-shadow: 0 18px 36px -28px rgba(15, 23, 42, 0.18);
}

.droply-button-primary,
.droply-button-secondary {
    transition: transform 180ms ease, box-shadow 180ms ease, background-color 180ms ease;
}

.droply-button-primary:hover,
.droply-button-secondary:hover {
    transform: translateY(-1px);
}

.droply-muted {
    color: rgb(var(--droply-text-sub));
}

.droply-text-gradient {
    background: linear-gradient(135deg, rgb(var(--droply-primary)), rgb(var(--droply-violet)));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.text-gradient {
    background: linear-gradient(135deg, rgb(var(--droply-primary)), rgb(var(--droply-violet)));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

/* ─── intl-tel-input wrapper ─────────────────────────────────────────────
   Shared styling for the phone-number widget across the app. Used by
   PartnerRegistration's owner-phone field AND the Manual Order panels
   (Add + Edit). Anything that wraps an intl-tel-input <input> in a
   `<div class="intl-tel-input-wrapper">` picks these rules up.
   Keeps the widget the full width of its container, hides the default
   country-flag chrome's background so it inherits the input's bg, and
   forces LTR rendering of the dialled number even when the page is RTL
   (phone numbers always read left-to-right). */
.intl-tel-input-wrapper .iti { width: 100%; }
[dir="ltr"] .intl-tel-input-wrapper .iti__flag-container { left: 0; right: auto; padding-left: 12px; padding-right: 0; }
[dir="ltr"] .intl-tel-input-wrapper .iti__selected-flag { background: transparent !important; border-radius: 12px 0 0 12px; }
[dir="rtl"] .intl-tel-input-wrapper .iti__flag-container { left: auto; right: 0; padding-left: 0; padding-right: 12px; }
[dir="rtl"] .intl-tel-input-wrapper .iti__selected-flag { background: transparent !important; border-radius: 0 12px 12px 0; }
[dir="rtl"] .intl-tel-input-wrapper .iti { direction: ltr; }
[dir="rtl"] .intl-tel-input-wrapper input { direction: ltr; text-align: right; }
.intl-tel-input-wrapper .iti__country-list { border-radius: 12px; box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.15); max-height: 250px; }
[dir="rtl"] .intl-tel-input-wrapper .iti__country-list { text-align: right; }
.intl-tel-input-wrapper .iti--separate-dial-code .iti__selected-dial-code { font-weight: 500; }

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

[dir="rtl"] body {
    font-family: 'Segoe UI', Tahoma, Arial, sans-serif;
}

/* ── Dashboard panel / dialog animations ── */

@keyframes droply-overlay-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes droply-overlay-out {
    from { opacity: 1; }
    to   { opacity: 0; }
}

@keyframes droply-slide-in-right {
    from { transform: translateX(100%); }
    to   { transform: translateX(0); }
}

@keyframes droply-slide-out-right {
    from { transform: translateX(0); }
    to   { transform: translateX(100%); }
}

@keyframes droply-dialog-in {
    from { opacity: 0; transform: scale(0.95) translateY(4px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes droply-dialog-out {
    from { opacity: 1; transform: scale(1) translateY(0); }
    to   { opacity: 0; transform: scale(0.95) translateY(4px); }
}

.droply-overlay-enter {
    animation: droply-overlay-in 300ms ease-out both;
}

.droply-panel-enter {
    animation: droply-slide-in-right 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* "Preparing" state — panel/overlay are in the DOM but visually hidden
   and NOT animating. Used for the brief window where we need to run JS
   interop on a child element (e.g. populate intl-tel-input with the
   saved phone number on the Edit panel) BEFORE the slide-in animation
   makes the panel visible. Without this, the user would see the panel
   slide in with an empty phone input, then watch the number "pop" in a
   moment later — visually jumpy. With it, the slide-in starts only
   after the widget is fully populated, so the user sees a clean entry.

   The preparing classes use !important to override any stale animation
   class that might still be on the element (e.g. left over from a
   previous render). transform: translateX matches the from-state of
   the slide-in keyframes so when we swap classes, the element doesn't
   visibly jump position. */
.droply-panel-preparing {
    transform: translateX(100%) !important;
    opacity: 0 !important;
    animation: none !important;
}

[dir="rtl"] .droply-panel-preparing {
    transform: translateX(-100%) !important;
}

.droply-overlay-preparing {
    opacity: 0 !important;
    animation: none !important;
}

.droply-dialog-enter {
    animation: droply-dialog-in 200ms ease-out both;
}

/* Exit classes — applied by droplyClosePanel() before Blazor removes the DOM */
.droply-overlay-exit {
    animation: droply-overlay-out 250ms ease-in both !important;
    pointer-events: none;
}

.droply-panel-exit {
    animation: droply-slide-out-right 300ms ease-in both !important;
}

.droply-dialog-exit {
    animation: droply-dialog-out 150ms ease-in both !important;
}

/* Panel shake — used when clicking outside a dirty edit panel */
@keyframes droply-shake {
    0%, 100% { transform: translateX(0); }
    15%      { transform: translateX(6px); }
    30%      { transform: translateX(-5px); }
    45%      { transform: translateX(4px); }
    60%      { transform: translateX(-3px); }
    75%      { transform: translateX(2px); }
}

.droply-panel-shake {
    animation: droply-shake 400ms ease-out;
}

/* ── Account-menu dropdown enter animation ──────────────────────
   Used by the topbar account menu (DashboardLayout.razor). Per
   ui-ux-pro-max: duration 140ms (in the 150–300ms micro-interaction
   band), ease-out, transform/opacity only (no layout shift),
   modal-motion style (anchored to trigger via origin-top-right).
   `prefers-reduced-motion` falls back to a snap-open so reduced-
   motion users still see the menu but without the slide. */
@keyframes droply-menu-in {
    0%   { opacity: 0; transform: translateY(-4px) scale(0.97); }
    100% { opacity: 1; transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    @keyframes droply-menu-in {
        0%, 100% { opacity: 1; transform: none; }
    }
}

/* ── Deep-link focus highlight ─────────────────────────────────
   Applied by droply-focus-field.js when the owner arrives on a
   page via a `?focus=X` deep link from the launch checklist.
   Wraps the target field in a soft amber halo that pulses once
   and decays. Tuned for "you've landed where you should act" —
   not a permanent state. Honors prefers-reduced-motion by
   collapsing to a simple solid outline. */
@keyframes droply-focus-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.55), 0 0 0 0 rgba(245, 158, 11, 0.25); }
    35%  { box-shadow: 0 0 0 6px rgba(245, 158, 11, 0.20), 0 0 0 14px rgba(245, 158, 11, 0.08); }
    100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0), 0 0 0 0 rgba(245, 158, 11, 0); }
}

.droply-focus-highlight {
    border-radius: 0.75rem;
    animation: droply-focus-pulse 1500ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
    .droply-focus-highlight {
        animation: none;
        outline: 2px solid rgba(245, 158, 11, 0.55);
        outline-offset: 4px;
    }
}

/* ── Inline limit message (manual order qty stepper) ──────────
   Styled to match the dashboard's existing inline validation messages
   (e.g. card-number error: <p class="text-[0.7rem] text-[#dc2626]">),
   so this looks like every other field-validation line in a panel.
   Tiny red text, no icon, no card. Smooth fade-in is preserved so the
   message doesn't pop without warning. */
@keyframes droply-limit-in {
    from { opacity: 0; transform: translateY(-2px); }
    to   { opacity: 1; transform: translateY(0); }
}
.droply-limit-msg {
    font-size: 0.7rem;
    line-height: 1.35;
    color: #dc2626;
    animation: droply-limit-in 200ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

/* ── Manual order line — expand/collapse ─────────────────────
   Used by the Items section in the Add/Edit Order panels. The
   body content (variant dropdowns, qty stepper, limit message)
   stays in the DOM at all times; we transition max-height +
   opacity + margin for a smooth slide-down/up rather than a
   pop-on/pop-off. overflow-hidden makes the slide work cleanly
   without scrollbars at intermediate heights. pointer-events on
   the collapsed state stops mouse interactions with hidden form
   controls; aria-hidden on the wrapper keeps screen readers
   aligned with what's visible. */
.droply-line-collapsible {
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    margin-top: 0;
    pointer-events: none;
    transition:
        max-height 280ms cubic-bezier(0.2, 0.8, 0.2, 1),
        opacity   200ms ease-out,
        margin-top 280ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.droply-line-collapsible--open {
    max-height: 60rem; /* generous; covers max ~3 options + qty + msg */
    opacity: 1;
    margin-top: 0.5rem;
    pointer-events: auto;
}

/* ──────────────────────────────────────────────────────────
   Admin "Extend / Renew subscription" modal.
   Shared by the DashboardHome admin store cards AND the
   SettingsPage Stores table + View panel — both fire the
   same modal so admins see one consistent UX.
   ────────────────────────────────────────────────────────── */
.droply-extend-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.5);
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 60;
    animation: droplyExtendFadeIn 180ms ease-out;
}
@keyframes droplyExtendFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.droply-extend-modal {
    background: white;
    border-radius: 1rem;
    padding: 1.5rem;
    width: 100%;
    max-width: 28rem;
    box-shadow: 0 25px 60px -12px rgba(15, 23, 42, 0.35);
    animation: droplyExtendSlideIn 220ms cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes droplyExtendSlideIn {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.droply-extend-modal__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.65rem;
}
.droply-extend-modal__eyebrow {
    font-size: 0.7rem;
    font-weight: 600;
    color: rgb(180, 83, 9);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.droply-extend-modal__title {
    font-size: 1.05rem;
    font-weight: 700;
    color: #131b2e;
    margin-top: 0.15rem;
}
.droply-extend-modal__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 0.5rem;
    background: transparent;
    color: #74808f;
    border: 0;
    cursor: pointer;
}
.droply-extend-modal__close:hover { background: rgba(19, 27, 46, 0.06); color: #131b2e; }
.droply-extend-modal__sub {
    font-size: 0.78rem;
    color: #64748b;
    line-height: 1.5;
    margin-bottom: 0.85rem;
}
.droply-extend-modal__owner {
    font-size: 0.85rem;
    font-weight: 600;
    color: #131b2e;
    padding: 0.6rem 0.8rem;
    background: rgba(19, 27, 46, 0.04);
    border-radius: 0.6rem;
    margin-bottom: 1rem;
}
.droply-extend-modal__chips {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.85rem;
    flex-wrap: wrap;
}
.droply-extend-modal__chip {
    flex: 1;
    min-width: 5rem;
    padding: 0.55rem 0.85rem;
    border-radius: 0.6rem;
    background: rgba(19, 27, 46, 0.04);
    border: 1px solid rgba(19, 27, 46, 0.08);
    font-size: 0.85rem;
    font-weight: 600;
    color: #131b2e;
    cursor: pointer;
    transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease;
}
.droply-extend-modal__chip:hover { background: rgba(180, 83, 9, 0.06); border-color: rgba(180, 83, 9, 0.25); }
.droply-extend-modal__chip--active {
    background: rgba(180, 83, 9, 0.12);
    border-color: rgba(180, 83, 9, 0.5);
    color: rgb(146, 64, 14);
}
.droply-extend-modal__custom {
    margin-bottom: 1.25rem;
}
.droply-extend-modal__label {
    display: block;
    font-size: 0.72rem;
    font-weight: 600;
    color: #74808f;
    margin-bottom: 0.35rem;
}
.droply-extend-modal__input {
    width: 100%;
    padding: 0.55rem 0.75rem;
    border-radius: 0.55rem;
    border: 1px solid rgba(19, 27, 46, 0.12);
    font-size: 0.9rem;
    font-weight: 600;
    color: #131b2e;
    outline: none;
}
.droply-extend-modal__input:focus { border-color: rgba(180, 83, 9, 0.55); box-shadow: 0 0 0 3px rgba(180, 83, 9, 0.12); }
.droply-extend-modal__actions {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
}
.droply-extend-modal__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.55rem 1rem;
    border-radius: 0.55rem;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    border: 1px solid transparent;
    transition: background-color 160ms ease, border-color 160ms ease;
}
.droply-extend-modal__btn:disabled { opacity: 0.6; cursor: not-allowed; }
.droply-extend-modal__btn--secondary {
    background: transparent;
    color: #131b2e;
    border-color: rgba(19, 27, 46, 0.15);
}
.droply-extend-modal__btn--secondary:hover:not(:disabled) { background: rgba(19, 27, 46, 0.04); }
.droply-extend-modal__btn--primary {
    background: rgb(180, 83, 9);
    color: white;
    border-color: rgb(180, 83, 9);
}
.droply-extend-modal__btn--primary:hover:not(:disabled) { background: rgb(146, 64, 14); border-color: rgb(146, 64, 14); }

/* ──────────────────────────────────────────────────────────
   Frozen-subscription write affordances.
   When <main data-frozen="true"> is rendered (owner whose
   subscription is Expired/Cancelled), all write buttons fade
   to a non-interactive look. The hard block is server-side via
   SubscriptionGuard — this is the visual cue + click swallow
   so the owner can't even try the action.

   What's covered:
     • .droply-fab — every Add/Create floating action button.
     • Any element with the explicit .droply-frozen-disable
       opt-in class (use for in-form Save buttons, etc).
   What's NOT covered (intentional):
     • .droply-expiry-banner__cta — these are the renewal CTAs;
       they MUST stay clickable so the owner can renew.
   ────────────────────────────────────────────────────────── */
[data-frozen="true"] .droply-fab,
[data-frozen="true"] .droply-button-primary,
[data-frozen="true"] .droply-frozen-disable,
/* Row Edit / Delete icon buttons across all dashboard tables.
   Title-attribute selectors cover both English and Arabic so the
   buttons fade out for frozen owners regardless of UI culture. */
[data-frozen="true"] button[title="Edit"],
[data-frozen="true"] button[title="تعديل"],
[data-frozen="true"] button[title="Delete"],
[data-frozen="true"] button[title="حذف"],
[data-frozen="true"] button[title="Remove"],
[data-frozen="true"] button[title="إزالة"] {
    opacity: 0.45;
    cursor: not-allowed;
    filter: grayscale(0.4);
}
/* Inner spans (icons, labels) inherit pointer-events from the parent
   so the not-allowed cursor sticks even when hovering the icon. The
   JS interceptor in droply-frozen-guard.js blocks the click; CSS
   provides the visual cue only. */
[data-frozen="true"] .droply-fab *,
[data-frozen="true"] .droply-button-primary *,
[data-frozen="true"] .droply-frozen-disable *,
[data-frozen="true"] button[title="Edit"] *,
[data-frozen="true"] button[title="تعديل"] *,
[data-frozen="true"] button[title="Delete"] *,
[data-frozen="true"] button[title="حذف"] *,
[data-frozen="true"] button[title="Remove"] *,
[data-frozen="true"] button[title="إزالة"] * {
    cursor: not-allowed;
}
/* Re-enable any explicitly opt-out children (e.g. links to /plans). */
[data-frozen="true"] .droply-frozen-keep {
    opacity: 1;
    cursor: pointer;
    pointer-events: auto;
    filter: none;
}

/* ──────────────────────────────────────────────────────────
   Frozen-subscription banner.
   Shown to owners whose plan has expired or been cancelled.
   Visual: amber warning panel sitting above the dashboard
   content with two CTAs ("Renew plan" + "See plans") that
   both deep-link to /plans. Amber (not red) — feels
   recoverable rather than punitive.
   ────────────────────────────────────────────────────────── */
.droply-expiry-banner {
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
    padding: 0.875rem 1rem;
    background: linear-gradient(135deg, #fff8eb 0%, #fff3d7 100%);
    border: 1px solid rgba(217, 119, 6, 0.25);
    border-radius: 0.75rem;
    box-shadow: 0 1px 2px rgba(217, 119, 6, 0.06);
}
.droply-expiry-banner__icon {
    color: #b45309;
    font-size: 1.5rem;
    /* Material Symbols look better filled for status icons. */
    font-variation-settings: 'FILL' 1;
    flex-shrink: 0;
    margin-top: 0.05rem;
}
.droply-expiry-banner__text {
    flex: 1;
    min-width: 0;
}
.droply-expiry-banner__title {
    color: #78350f;
    font-weight: 600;
    font-size: 0.95rem;
    line-height: 1.3;
}
.droply-expiry-banner__sub {
    color: #92400e;
    font-size: 0.8rem;
    margin-top: 0.2rem;
    line-height: 1.45;
}
/* Subscription chip row sitting between the banner title and the
   bullets — surfaces plan / date / status / time-hint at a glance.
   Tinted to fit the amber banner palette rather than introducing
   a competing color. */
.droply-expiry-banner__strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.45rem;
    margin: 0.4rem 0 0.1rem 0;
}
.droply-expiry-banner__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.6rem;
    border-radius: 9999px;
    background: rgba(180, 83, 9, 0.10);
    color: #78350f;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.1;
}
.droply-expiry-banner__chip .material-symbols-outlined {
    font-size: 0.9rem;
    color: rgb(180, 83, 9);
}
.droply-expiry-banner__chip--date {
    background: rgba(180, 83, 9, 0.08);
}
.droply-expiry-banner__chip--status {
    background: rgba(217, 119, 6, 0.18);
    color: rgb(120, 53, 15);
    font-weight: 700;
}
.droply-expiry-banner__chip-dot {
    display: inline-block;
    width: 0.4rem;
    height: 0.4rem;
    border-radius: 9999px;
    background: rgb(180, 83, 9);
}
.droply-expiry-banner__hint {
    font-size: 0.72rem;
    font-weight: 500;
    color: #92400e;
}

/* Bullet list inside the banner — three concise status lines so the
   owner knows exactly what's view-only, what's disabled, and what's
   hidden from customers. Icons are tiny and amber-tinted to match
   the banner palette without competing with the title. */
.droply-expiry-banner__points {
    list-style: none;
    padding: 0;
    margin: 0.5rem 0 0 0;
    display: grid;
    gap: 0.25rem;
}
.droply-expiry-banner__points li {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    color: #78350f;
    font-size: 0.78rem;
    line-height: 1.4;
}
.droply-expiry-banner__points li .material-symbols-outlined {
    font-size: 0.95rem;
    color: #b45309;
    flex-shrink: 0;
}
.droply-expiry-banner__actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
}
.droply-expiry-banner__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.45rem 0.95rem;
    border-radius: 0.5rem;
    font-size: 0.825rem;
    font-weight: 600;
    text-decoration: none;
    transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease;
    white-space: nowrap;
}
.droply-expiry-banner__cta--primary {
    background-color: #b45309;
    color: #fff;
    border: 1px solid #b45309;
}
.droply-expiry-banner__cta--primary:hover {
    background-color: #92400e;
    border-color: #92400e;
}
.droply-expiry-banner__cta--secondary {
    background-color: transparent;
    color: #78350f;
    border: 1px solid rgba(180, 83, 9, 0.4);
}
.droply-expiry-banner__cta--secondary:hover {
    background-color: rgba(180, 83, 9, 0.08);
    border-color: rgba(180, 83, 9, 0.65);
}
@media (max-width: 640px) {
    .droply-expiry-banner {
        flex-wrap: wrap;
    }
    .droply-expiry-banner__actions {
        flex-basis: 100%;
        margin-top: 0.25rem;
    }
}

/* ──────────────────────────────────────────────────────────
   Manual-order line "already on the order" highlight.
   Triggered by HighlightLineAsync in OrdersPage / AdminOrdersPage
   when the owner picks a variant that's already on another line
   (or re-adds the same simple product). Premium polish: a soft
   primary-tinted ring + barely-visible background wash that fade
   in, hold, and fade out smoothly — no pulse, no harsh jump.
   ────────────────────────────────────────────────────────── */
.droply-line-highlight {
    /* 2.8s total: ~14% (390ms) ease-in, hold to ~78% (1.79s),
       ~22% (615ms) ease-out. cubic-bezier(0.4, 0, 0.2, 1) is the
       Material "standard" curve — smooth without being mushy. */
    animation: dpLineHighlight 2.8s cubic-bezier(0.4, 0, 0.2, 1);
    /* Scope position so the ring's box-shadow renders cleanly above
       sibling cards even when stacked tight. */
    position: relative;
    z-index: 1;
}
@keyframes dpLineHighlight {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(99, 102, 241, 0),
                    0 0 0 0 rgba(99, 102, 241, 0);
        background-color: transparent;
        border-color: rgba(19, 27, 46, 0.08);
    }
    14%, 78% {
        /* Soft 2px ring + a wide diffused glow underneath. Low
           alpha values (0.22 / 0.18 / 0.04) keep it premium —
           visible but not shouty. */
        box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.22),
                    0 10px 32px -12px rgba(99, 102, 241, 0.18);
        background-color: rgba(99, 102, 241, 0.04);
        border-color: rgba(99, 102, 241, 0.28);
    }
}

/* ══════════════════════════════════════════════════════════
   PANEL HEADERS — Stunning titles for View/Edit/Create panels
   Usage:
     <div class="droply-panel-head droply-panel-head--{view|edit|create}">
       <div class="droply-panel-head-icon droply-panel-head-icon--{view|edit|create}">
         <span class="material-symbols-outlined">icon</span>
       </div>
       <div class="min-w-0 flex-1">
         <p class="droply-panel-eyebrow">View/Edit/Add Thing</p>
         <h2 class="droply-panel-title">Actual item name</h2>
       </div>
       <button class="droply-panel-close">...</button>
     </div>
   ══════════════════════════════════════════════════════════ */
.droply-panel-head {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid rgba(19, 27, 46, 0.06);
    position: relative;
    flex-shrink: 0;
}
.droply-panel-head::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
}
.droply-panel-head--view::before {
    background: linear-gradient(90deg, rgb(28, 177, 201) 0%, rgba(28, 177, 201, 0) 100%);
}
.droply-panel-head--edit::before {
    background: linear-gradient(90deg, rgb(249, 115, 22) 0%, rgba(249, 115, 22, 0) 100%);
}
.droply-panel-head--create::before {
    background: linear-gradient(90deg, rgb(22, 163, 74) 0%, rgba(22, 163, 74, 0) 100%);
}

.droply-panel-head-icon {
    display: flex;
    height: 2.5rem;
    width: 2.5rem;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    border-radius: 0.75rem;
}
.droply-panel-head-icon--view {
    background: linear-gradient(135deg, rgba(28, 177, 201, 0.2), rgba(28, 177, 201, 0.06));
    color: rgb(28, 177, 201);
    box-shadow: 0 6px 16px -4px rgba(28, 177, 201, 0.35);
}
.droply-panel-head-icon--edit {
    background: linear-gradient(135deg, rgba(249, 115, 22, 0.2), rgba(249, 115, 22, 0.06));
    color: rgb(249, 115, 22);
    box-shadow: 0 6px 16px -4px rgba(249, 115, 22, 0.35);
}
.droply-panel-head-icon--create {
    background: linear-gradient(135deg, rgba(22, 163, 74, 0.2), rgba(22, 163, 74, 0.06));
    color: rgb(22, 163, 74);
    box-shadow: 0 6px 16px -4px rgba(22, 163, 74, 0.35);
}

.droply-panel-eyebrow {
    font-size: 0.68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    line-height: 1;
    margin: 0;
}
.droply-panel-head--view .droply-panel-eyebrow { color: rgb(28, 177, 201); }
.droply-panel-head--edit .droply-panel-eyebrow { color: rgb(249, 115, 22); }
.droply-panel-head--create .droply-panel-eyebrow { color: rgb(22, 163, 74); }

.droply-panel-title {
    font-size: 1.0625rem;
    font-weight: 800;
    color: #0f172a;
    letter-spacing: -0.015em;
    margin: 0.3rem 0 0;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.droply-panel-close {
    display: flex;
    height: 2.25rem;
    width: 2.25rem;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    border-radius: 0.7rem;
    background: transparent;
    border: 1px solid transparent;
    color: #64748b;
    cursor: pointer;
    transition: all 0.18s;
}
.droply-panel-close:hover {
    background: rgba(19, 27, 46, 0.06);
    border-color: rgba(19, 27, 46, 0.08);
    color: #0f172a;
}

/* ══════════════════════════════════════════════════════════
   VARIANT IMAGE SELECTOR TILES
   Used in the product-edit popover to link product images to
   a variant. Selected tiles show an order number (1, 2, 3…)
   in the order the user picked them — the marketplace
   displays variant images in exactly this order on save.
   ══════════════════════════════════════════════════════════ */
.dp-var-tile {
    position: relative;
    height: 3.5rem;
    width: 3.5rem;
    border-radius: 0.55rem;
    border: 2px solid rgba(19, 27, 46, 0.10);
    transition: all 0.18s;
    overflow: visible;
}
.dp-var-tile:hover {
    border-color: rgba(139, 92, 246, 0.4);
    transform: translateY(-1px);
}
.dp-var-tile--pending {
    border-style: dashed;
    border-color: rgba(139, 92, 246, 0.4);
}
.dp-var-tile--pending:hover {
    border-color: rgba(139, 92, 246, 0.65);
}
.dp-var-tile--linked {
    border-color: rgb(139, 92, 246);
    box-shadow: 0 4px 14px -3px rgba(139, 92, 246, 0.45);
}
.dp-var-tile-img {
    height: 100%;
    width: 100%;
    border-radius: 0.4rem;
    object-fit: cover;
    cursor: pointer;
}
/* Violet tint overlay on selected tiles — makes the selection state pop */
.dp-var-tile-overlay {
    position: absolute;
    inset: 0;
    border-radius: 0.4rem;
    background: rgba(139, 92, 246, 0.18);
    pointer-events: auto;
    cursor: pointer;
}
/* The order badge — e.g. 1, 2, 3 — in the center of the tile */
.dp-var-tile-order {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    font-weight: 900;
    color: #fff;
    text-shadow: 0 2px 6px rgba(0, 0, 0, 0.55);
    pointer-events: none;
    letter-spacing: -0.01em;
}
/* "New" strip for pending uploads */
.dp-var-tile-new {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.1rem 0;
    border-radius: 0 0 0.4rem 0.4rem;
    background: rgba(19, 27, 46, 0.72);
    color: #fff;
    font-size: 7px;
    font-weight: 700;
    text-align: center;
    pointer-events: none;
}
/* Primary star toggle — top-left corner */
.dp-var-tile-star {
    position: absolute;
    top: -0.375rem;
    left: -0.375rem;
    display: flex;
    height: 1.25rem;
    width: 1.25rem;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    background: #fff;
    color: #cbd5e1;
    border: none;
    cursor: pointer;
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
    box-shadow: 0 0 0 2px #fff, 0 3px 8px rgba(0, 0, 0, 0.15);
    transition: all 0.18s;
    z-index: 3;
}
[dir="rtl"] .dp-var-tile-star {
    left: auto;
    right: -0.375rem;
}
.dp-var-tile-star:hover {
    background: rgb(251, 191, 36);
    color: #fff;
}
.dp-var-tile-star--on {
    background: rgb(251, 191, 36);
    color: #fff;
}
/* Remove button for pending uploads — top-right corner */
.dp-var-tile-remove {
    position: absolute;
    top: -0.375rem;
    right: -0.375rem;
    display: flex;
    height: 1.25rem;
    width: 1.25rem;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    background: rgb(185, 28, 28);
    color: #fff;
    border: none;
    cursor: pointer;
    box-shadow: 0 0 0 2px #fff, 0 3px 8px rgba(0, 0, 0, 0.15);
    z-index: 3;
}
[dir="rtl"] .dp-var-tile-remove {
    right: auto;
    left: -0.375rem;
}
.dp-var-tile-remove:hover {
    background: rgb(153, 27, 27);
}

/* ── Floating Action Button ── */

.droply-fab {
    position: fixed;
    bottom: 2rem;
    right: 1.75rem;
    z-index: 30;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 3.25rem;
    width: 3.25rem;
    border-radius: 9999px;
    background: linear-gradient(135deg, #1cb1c9, #17a0b3);
    color: #fff;
    box-shadow: 0 4px 20px rgba(28, 177, 201, 0.35);
    cursor: pointer;
    border: none;
    overflow: hidden;
    transition: width 0.3s cubic-bezier(0.16, 1, 0.3, 1),
                box-shadow 0.3s ease,
                transform 0.15s ease;
}

/* Arabic / RTL mode: pin the FAB to the bottom-left so it sits on the
   natural reading end of the viewport. */
[dir="rtl"] .droply-fab {
    right: auto;
    left: 1.75rem;
}

.droply-fab:hover {
    width: auto;
    padding-left: 1.1rem;
    padding-right: 1.25rem;
    box-shadow: 0 6px 28px rgba(28, 177, 201, 0.45);
}

.droply-fab:active {
    transform: scale(0.95);
}

.droply-fab .droply-fab-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.droply-fab:hover .droply-fab-icon {
    transform: rotate(90deg);
}

.droply-fab .droply-fab-label {
    max-width: 0;
    opacity: 0;
    white-space: nowrap;
    overflow: hidden;
    font-size: 0.8125rem;
    font-weight: 600;
    margin-inline-start: 0;
    /* COLLAPSE direction (unhover): fade label out FAST and FIRST,
       then let the width/margin collapse after the text is gone.
       This prevents the trailing-edge clipping artifact where the
       container shrinks while the text is still partly visible. */
    transition: max-width 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0.08s,
                opacity 0.1s ease 0s,
                margin-inline-start 0.28s ease 0.08s;
}

.droply-fab:hover .droply-fab-label {
    max-width: 12rem;
    opacity: 1;
    margin-inline-start: 0.5rem;
    /* EXPAND direction (hover): grow width first, then fade label in
       once there's enough room — matches the opening "reveal" feel. */
    transition: max-width 0.3s cubic-bezier(0.16, 1, 0.3, 1),
                opacity 0.18s ease 0.12s,
                margin-inline-start 0.3s ease;
}

@keyframes droply-fab-pulse {
    0%, 100% { box-shadow: 0 4px 20px rgba(28, 177, 201, 0.35); }
    50%      { box-shadow: 0 4px 28px rgba(28, 177, 201, 0.55); }
}

.droply-fab {
    animation: droply-fab-pulse 3s ease-in-out infinite;
}

/* ── Back FAB modifier ──
   Used by the Plans page when the owner arrives from
   /dashboard/billing. Inherits the FULL visual + animation
   treatment of the standard .droply-fab (cyan gradient, white
   icon, pulse, expand-on-hover, collapse-on-unhover, press
   feedback) — only the horizontal corner is swapped so it doesn't
   collide with the primary Add FAB if both ever co-exist.

   Position: BOTTOM-LEFT in LTR (bottom-right in RTL). The Add
   FAB sits at bottom-right (LTR) for "primary action / create";
   the back FAB sits on the opposite horizontal side at the same
   vertical anchor — same height off the viewport floor, mirrored
   across. Stays visible while scrolling via the inherited
   position: fixed. */
.droply-fab--back {
    /* Inherit bottom: 2rem from .droply-fab; just swap the
       horizontal anchor from right → left. */
    left: 1.75rem;
    right: auto;
}
[dir="rtl"] .droply-fab--back {
    /* RTL: swap horizontal anchor from left → right. */
    right: 1.75rem;
    left: auto;
}

/* Reverse the rotate-on-hover behavior — the Add FAB's `add` icon
   rotates 90° to suggest "opening." A back arrow shouldn't rotate
   (it would briefly point up/down mid-animation, which reads as
   confused). Override the rotation back to 0°. */
.droply-fab--back:hover .droply-fab-icon {
    transform: none;
}

/* In RTL, the back arrow needs to point right (which IS "back" in
   RTL reading order). The icon glyph itself is locale-aware in the
   markup (arrow_back rotated via classes), so no transform needed
   here — but a future-proofing safety to ensure RTL doesn't mirror
   it unintentionally. */
[dir="rtl"] .droply-fab--back .droply-fab-icon {
    transform: none;
}

/* ─────────────────────────────────────────────────────────────
   Legacy .droply-plans-back-fab styles — kept below for reference
   but no longer applied. The Back FAB now uses .droply-fab + the
   modifier above for visual parity with the Add FABs.
   ───────────────────────────────────────────────────────────── */
.droply-plans-back-fab {
    position: fixed;
    z-index: 30;
    bottom: 2rem;
    left: 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Slightly larger than the Add FAB (3.25rem vs 3rem) so the
       icon medallion inside has room to breathe + the whole
       control has more visual weight. */
    height: 3.25rem;
    width: 3.25rem;
    /* Explicit padding on the default state so the transition has
       a starting value to interpolate from on EXIT (hover → default).
       Without this, padding snaps from hover values to "browser
       default", which is the choppy collapse the user saw. */
    padding-inline-start: 0;
    padding-inline-end: 0;
    border-radius: 9999px;
    background: linear-gradient(135deg, #ffffff 0%, rgba(28, 177, 201, 0.06) 100%);
    color: #131b2e;
    border: 1px solid rgba(28, 177, 201, 0.22);
    /* Two-layer shadow: top primary-tinted "glow" (brand presence),
       second layer neutral-dark "lift" (separates from background). */
    box-shadow:
        0 4px 16px -2px rgba(28, 177, 201, 0.25),
        0 8px 24px -8px rgba(15, 23, 42, 0.12);
    cursor: pointer;
    overflow: hidden;
    text-decoration: none;
    /* EXIT transition (hover → default).
       Includes padding so the collapse is smooth on every property
       at once — no property snaps. ease-in on width/padding makes
       the collapse start gentle and finish fast, mirroring how the
       label fades out (also fast at the start of the exit). */
    transition: width 0.28s cubic-bezier(0.4, 0, 0.2, 1),
                padding 0.28s cubic-bezier(0.4, 0, 0.2, 1),
                box-shadow 0.35s ease,
                border-color 0.25s ease,
                transform 0.2s ease;
    /* Subtle pulse on the colored shadow draws first-arrival
       attention without being demanding. Slower cadence (4s) than
       the Add FAB's 3s so the two don't compete. */
    animation: droply-plans-back-fab-breathe 4s ease-in-out infinite;
}

[dir="rtl"] .droply-plans-back-fab {
    left: auto;
    right: 1.5rem;
}

/* Desktop + tablet: lift to the top-left side gutter so it sits
   beside the plans grid rather than at the bottom corner. */
@media (min-width: 1024px) {
    .droply-plans-back-fab {
        top: 7rem;
        bottom: auto;
    }
}

.droply-plans-back-fab:hover {
    /* Fixed hover width — NOT "auto". Browsers can't reliably
       transition from a pixel value to "auto"; the reverse-direction
       collapse was snapping. Logical padding so the layout is correct
       in LTR + RTL without separate rules.

       padding-inline-start: 0 — icon medallion sits flush against the
       pill's left edge, nesting inside the rounded left cap.

       justify-content: flex-start overrides the base rule's
       justify-content: center. The base "center" rule exists so the
       single icon in the COLLAPSED state sits in the middle of the
       3.25rem circle. But once expanded to 14rem with icon + label,
       "center" wedges empty space on BOTH sides of the icon+label
       group (because the natural content is narrower than 14rem).
       Switching to flex-start pins the icon to the left and any
       extra width falls at the END of the pill, after the label —
       same shape the Add Plan FAB uses. */
    width: 14rem;
    padding-inline-start: 0;
    padding-inline-end: 1.25rem;
    justify-content: flex-start;
    border-color: rgba(28, 177, 201, 0.5);
    /* Stronger primary glow on hover — the brand color leans in. */
    box-shadow:
        0 12px 32px -4px rgba(28, 177, 201, 0.38),
        0 16px 40px -8px rgba(15, 23, 42, 0.16);
    transform: translateY(-2px);
    /* ENTER transition (default → hover).
       Same property set as the EXIT transition above but with a
       smoother out-back easing (cubic-bezier(0.16, 1, 0.3, 1)) so
       the expansion feels confident and "settled" at the end. */
    transition: width 0.32s cubic-bezier(0.16, 1, 0.3, 1),
                padding 0.32s cubic-bezier(0.16, 1, 0.3, 1),
                box-shadow 0.35s ease,
                border-color 0.25s ease,
                transform 0.2s ease;
    /* Pause the breathing animation while hovered so the lift +
       expand transitions read cleanly without competing pulses. */
    animation-play-state: paused;
}

.droply-plans-back-fab:active {
    transform: translateY(0) scale(0.96);
}

.droply-plans-back-fab .droply-plans-back-fab-icon {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Bigger medallion with primary gradient fill — the focal
       point of the collapsed FAB. Inner highlight + subtle outer
       shadow give it a glossy, premium feel. */
    height: 1.9rem;
    width: 1.9rem;
    border-radius: 9999px;
    background: linear-gradient(135deg, #1cb1c9, #17a0b3);
    color: #fff;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.25),
        0 2px 6px rgba(28, 177, 201, 0.35);
    transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Subtle icon nudge on hover — the arrow "leans" toward the
   direction it'll take you (locale-aware via the markup's rotate
   class). Reinforces "click me to go back" without being kinetic. */
.droply-plans-back-fab:hover .droply-plans-back-fab-icon {
    transform: translateX(-2px);
}

[dir="rtl"] .droply-plans-back-fab:hover .droply-plans-back-fab-icon {
    transform: translateX(2px);
}

.droply-plans-back-fab .droply-plans-back-fab-label {
    max-width: 0;
    opacity: 0;
    white-space: nowrap;
    overflow: hidden;
    /* Typography matched to .droply-fab-label (the Add Plan FAB) so
       the two controls read as siblings — same size, weight, gap.
       Color is #131b2e instead of inherited white because the Back
       FAB body is white, unlike the Add FAB's primary-gradient body. */
    font-size: 0.8125rem;
    font-weight: 600;
    color: #131b2e;
    margin-inline-start: 0;
    /* EXIT transition (hover → default).
       Opacity drops FAST (0.12s) so the text fades out BEFORE the
       max-width starts clipping it from the right edge — no visible
       text-cutoff during collapse. max-width and margin transition
       slightly faster than the enter so the collapse feels crisp. */
    transition: max-width 0.25s cubic-bezier(0.4, 0, 0.2, 1),
                opacity 0.12s ease-out,
                margin-inline-start 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

.droply-plans-back-fab:hover .droply-plans-back-fab-label {
    max-width: 14rem;
    opacity: 1;
    /* Gap matched to Add Plan FAB (0.5rem between icon and label). */
    margin-inline-start: 0.5rem;
    /* ENTER transition (default → hover).
       Opacity gets a 0.08s delay so max-width has already opened
       enough room before the text starts appearing — text never
       fades in while its container is still too narrow. Slightly
       longer max-width (0.32s with out-back ease) gives the
       expansion a confident, settled finish. */
    transition: max-width 0.32s cubic-bezier(0.16, 1, 0.3, 1),
                opacity 0.22s ease 0.08s,
                margin-inline-start 0.32s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes droply-plans-back-fab-breathe {
    0%, 100% {
        box-shadow:
            0 4px 16px -2px rgba(28, 177, 201, 0.25),
            0 8px 24px -8px rgba(15, 23, 42, 0.12);
    }
    50% {
        box-shadow:
            0 6px 22px -2px rgba(28, 177, 201, 0.38),
            0 10px 28px -8px rgba(15, 23, 42, 0.14);
    }
}

/* Respect user's reduced-motion preference — disables the breathe
   pulse + the hover lift, keeps the FAB fully functional and
   color-distinct without animations. */
@media (prefers-reduced-motion: reduce) {
    .droply-plans-back-fab {
        animation: none;
    }
    .droply-plans-back-fab:hover {
        transform: none;
    }
}

.droply-fab:hover {
    animation: none;
}

/* ── Store Selector Dropdown ── */

.droply-store-selector {
    position: relative;
}

.droply-store-selector .droply-store-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 10;
    margin-top: 0.25rem;
    max-height: 12rem;
    overflow-y: auto;
    border-radius: 0.5rem;
    border: 1px solid rgba(19, 27, 46, 0.10);
    background: #fff;
    box-shadow: 0 8px 24px rgba(19, 27, 46, 0.12);
}

.droply-store-dropdown .droply-store-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    font-size: 0.8125rem;
    color: #131b2e;
    cursor: pointer;
    transition: background 0.1s;
}

.droply-store-dropdown .droply-store-option:hover {
    background: rgba(19, 27, 46, 0.04);
}

.droply-store-dropdown .droply-store-option.active {
    background: rgba(28, 177, 201, 0.08);
    color: #1cb1c9;
    font-weight: 600;
}

/* ============================================
   Dashboard Toast Notifications
   ============================================ */
.dp-dash-toast-container {
    position: fixed;
    top: 1.25rem;
    right: 1.25rem;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    pointer-events: none;
    max-width: calc(100vw - 2.5rem);
}

[dir="rtl"] .dp-dash-toast-container {
    right: auto;
    left: 1.25rem;
}

.dp-dash-toast {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    min-width: 280px;
    max-width: 420px;
    padding: 0.75rem 2.25rem 0.75rem 0.875rem;
    border-radius: 0.875rem;
    background: #ffffff;
    color: #131b2e;
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.35;
    box-shadow: 0 12px 32px -12px rgba(15, 23, 42, 0.22), 0 2px 6px -2px rgba(15, 23, 42, 0.08);
    border: 1px solid rgba(19, 27, 46, 0.06);
    overflow: hidden;
    transform: translateX(120%);
    opacity: 0;
    transition: transform 0.32s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.32s ease;
    pointer-events: auto;
}

[dir="rtl"] .dp-dash-toast {
    padding: 0.75rem 0.875rem 0.75rem 2.25rem;
    transform: translateX(-120%);
}

.dp-dash-toast--visible {
    transform: translateX(0);
    opacity: 1;
}

/* RTL sibling must match specificity of `[dir="rtl"] .dp-dash-toast` — otherwise
   the off-screen `translateX(-120%)` from the base RTL rule wins and the toast
   never animates into view when the UI is Arabic. */
[dir="rtl"] .dp-dash-toast--visible {
    transform: translateX(0);
    opacity: 1;
}

.dp-dash-toast--leaving {
    transform: translateX(120%);
    opacity: 0;
}

[dir="rtl"] .dp-dash-toast--leaving {
    transform: translateX(-120%);
    opacity: 0;
}

.dp-dash-toast__icon {
    flex-shrink: 0;
    font-size: 1.25rem !important;
    font-variation-settings: 'FILL' 1, 'wght' 500, 'GRAD' 0, 'opsz' 24;
    line-height: 1;
}

.dp-dash-toast__msg {
    flex: 1 1 auto;
    word-break: break-word;
}

/* Optional action button rendered inside the toast — set via the
   `actionLabel` + `actionUrl` args to droplyToast.show. Used by the
   launch-checklist save flow ("Logo saved · ← Back to setup"). Sits
   between the message and the close button. Subtle styling so the
   close affordance still reads as the primary dismiss. */
.dp-dash-toast__action {
    flex: 0 0 auto;
    background: rgba(255, 255, 255, 0.92);
    color: #131b2e;
    border: 1px solid rgba(19, 27, 46, 0.10);
    padding: 0.25rem 0.6rem;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1.2;
    border-radius: 0.5rem;
    cursor: pointer;
    margin-inline-end: 1.5rem; /* keep clear of the absolute-positioned close button */
    white-space: nowrap;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.dp-dash-toast__action:hover {
    background: #ffffff;
    border-color: rgba(19, 27, 46, 0.20);
}

.dp-dash-toast__close {
    position: absolute;
    top: 0.375rem;
    right: 0.5rem;
    width: 1.25rem;
    height: 1.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    padding: 0;
    font-size: 1.15rem;
    line-height: 1;
    color: #74808f;
    border-radius: 999px;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

[dir="rtl"] .dp-dash-toast__close {
    right: auto;
    left: 0.5rem;
}

.dp-dash-toast__close:hover {
    background: rgba(19, 27, 46, 0.06);
    color: #131b2e;
}

.dp-dash-toast__progress {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 3px;
    width: 100%;
    transform-origin: left center;
    animation: dpDashToastProgress linear forwards;
    opacity: 0.85;
}

[dir="rtl"] .dp-dash-toast__progress {
    transform-origin: right center;
}

@keyframes dpDashToastProgress {
    from { transform: scaleX(1); }
    to   { transform: scaleX(0); }
}

.dp-dash-toast--success .dp-dash-toast__icon { color: #059669; }
.dp-dash-toast--success .dp-dash-toast__progress { background: linear-gradient(90deg, #10b981, #2bb6a8); }
.dp-dash-toast--success::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(90deg, rgba(16, 185, 129, 0.10), rgba(16, 185, 129, 0) 55%);
}

.dp-dash-toast--error .dp-dash-toast__icon { color: #dc2626; }
.dp-dash-toast--error .dp-dash-toast__progress { background: linear-gradient(90deg, #ef4444, #f97316); }
.dp-dash-toast--error::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(90deg, rgba(239, 68, 68, 0.10), rgba(239, 68, 68, 0) 55%);
}

.dp-dash-toast--warning .dp-dash-toast__icon { color: #d97706; }
.dp-dash-toast--warning .dp-dash-toast__progress { background: linear-gradient(90deg, #f59e0b, #fb923c); }
.dp-dash-toast--warning::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(90deg, rgba(245, 158, 11, 0.10), rgba(245, 158, 11, 0) 55%);
}

.dp-dash-toast--info .dp-dash-toast__icon { color: #1cb1c9; }
.dp-dash-toast--info .dp-dash-toast__progress { background: linear-gradient(90deg, #1cb1c9, #8b5cf6); }
.dp-dash-toast--info::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(90deg, rgba(28, 177, 201, 0.10), rgba(28, 177, 201, 0) 55%);
}

/* ============================================
   Cart Toast Container (marketplace)
   Same look as dashboard toasts (.dp-dash-toast), but pinned to the
   BOTTOM-right so the "added to cart!" message pops up near the cart
   icon rather than over the page header. droply-cart.js's showToast()
   renders .dp-dash-toast--<type> children into this container.
   flex-direction: column-reverse keeps newer toasts visually above
   older ones when several stack — same UX as the dashboard top-right
   container, mirrored vertically.
   ============================================ */
.dp-cart-toast-container {
    position: fixed;
    bottom: 1.25rem;
    right: 1.25rem;
    /* Sit ABOVE the QuickAdd modal (which is at z-index 10000) so a
       quantity-limit toast fired from inside the modal isn't hidden
       under the backdrop. Conflict modal is 9998, regular cart drawer
       sits below — 10001 wins over everything we render. */
    z-index: 10001;
    display: flex;
    flex-direction: column-reverse;
    gap: 0.625rem;
    pointer-events: none;
    max-width: calc(100vw - 2.5rem);
}

[dir="rtl"] .dp-cart-toast-container {
    right: auto;
    left: 1.25rem;
}

/* ============================================
   Global RTL adjustments
   One set of rules so every dashboard/admin table auto-flips in Arabic
   without per-page markup changes. Specificity is bumped (table + class)
   so we win over bare Tailwind `text-left` / `text-right` utilities.
   ============================================ */
[dir="rtl"] table th.text-left,
[dir="rtl"] table td.text-left { text-align: right; }

[dir="rtl"] table th.text-right,
[dir="rtl"] table td.text-right { text-align: left; }

/* Floating Action Buttons (create-product / create-collection / etc.).
   Any element with the .dp-fab class pinned to the bottom-right in LTR
   automatically mirrors to the bottom-left in RTL. Pages can still opt
   out by omitting the class. */
.dp-fab {
    position: fixed;
    bottom: 1.5rem;
    right: 1.5rem;
    z-index: 30;
}
[dir="rtl"] .dp-fab {
    right: auto;
    left: 1.5rem;
}

/* ============================================
   Dashboard Edit Panel — Tabs
   Used by the Product edit/create panel to group
   Variants · Collections · Related Products.
   ============================================ */
.dp-tabs { display: block; }

.dp-tabs-strip {
    display: flex;
    gap: 0.25rem;
    border-bottom: 1px solid rgba(19, 27, 46, 0.08);
    margin-bottom: 0.875rem;
    overflow-x: auto;
    scrollbar-width: none;
}
.dp-tabs-strip::-webkit-scrollbar { display: none; }

.dp-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.625rem 0.9rem;
    border: none;
    background: transparent;
    color: #74808f;
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: color 0.2s ease;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px; /* overlap the strip border so active line is flush */
}
.dp-tab:hover { color: #131b2e; }

.dp-tab--active {
    color: rgb(28, 177, 201);
    border-bottom-color: rgb(28, 177, 201);
}

.dp-tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: rgba(19, 27, 46, 0.08);
    color: #64748b;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 1;
    transition: background-color 0.2s ease, color 0.2s ease;
}
.dp-tab--active .dp-tab-count {
    background: rgba(28, 177, 201, 0.15);
    color: rgb(23, 154, 175);
}

/* Each pane is rendered; only the active one is visible (hidden attr).
   Native `hidden` avoids layout thrash — no mount/unmount on tab switch. */
.dp-tab-pane[hidden] { display: none !important; }
.dp-tab-pane { min-height: 3rem; }

/* ============================================
   Related Products — selected card rows
   ============================================ */
.dp-related-card {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.625rem 0.75rem;
    border-radius: 0.75rem;
    border: 1px solid rgba(28, 177, 201, 0.22);
    background: linear-gradient(180deg, rgba(28, 177, 201, 0.04), #ffffff 80%);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.dp-related-card:hover {
    border-color: rgba(28, 177, 201, 0.45);
    box-shadow: 0 4px 14px -6px rgba(28, 177, 201, 0.35);
}
.dp-related-index {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    border-radius: 999px;
    background: rgb(28, 177, 201);
    color: #ffffff;
    font-size: 0.65rem;
    font-weight: 800;
    line-height: 1;
}
.dp-related-img {
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.5rem;
    object-fit: cover;
    background: #f1f5f9;
}
.dp-related-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.65rem;
    height: 1.65rem;
    border-radius: 0.4rem;
    border: none;
    background: transparent;
    color: #74808f;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.dp-related-btn:hover { background: rgba(19, 27, 46, 0.06); color: #131b2e; }
.dp-related-btn:disabled { opacity: 0.3; pointer-events: none; }
.dp-related-btn--danger { color: #b91c1c; }
.dp-related-btn--danger:hover { background: rgba(220, 38, 38, 0.10); color: #b91c1c; }

/* ============================================
   Dashboard Modal (used by Related Products picker)
   ============================================ */
.dp-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 60;
    background: rgba(15, 23, 42, 0.45);
    backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    animation: dpModalOverlayIn 0.18s ease-out;
}
.dp-modal-card {
    width: 100%;
    max-width: 28rem;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    background: #ffffff;
    border-radius: 1rem;
    box-shadow: 0 24px 60px -18px rgba(15, 23, 42, 0.35), 0 4px 16px -4px rgba(15, 23, 42, 0.12);
    overflow: hidden;
    animation: dpModalCardIn 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.dp-modal-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 1rem 1rem 0.75rem;
    border-bottom: 1px solid rgba(19, 27, 46, 0.06);
}
.dp-modal-search {
    position: relative;
    padding: 0.75rem 1rem 0.5rem;
}
.dp-modal-list {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 0 0.5rem 0.75rem;
}
.dp-modal-footer {
    display: flex;
    justify-content: flex-end;
    padding: 0.75rem 1rem;
    border-top: 1px solid rgba(19, 27, 46, 0.06);
    background: rgba(19, 27, 46, 0.02);
}
@keyframes dpModalOverlayIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes dpModalCardIn {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0)   scale(1); }
}

/* ============================================
   Stock / Variant Availability
   Used by:
   - Marketplace + StorePage + StoreProductsPage product cards
     (sold-out card overlay + disabled cart CTA)
   - QuickAdd modal variant chips (faded + diagonal slash)
   - Manual order picker variant chips (same as QuickAdd)
   See the Stock UX Phase plan in CLAUDE.md / session notes for the
   intended state machine.
   ============================================ */

/* Card-level sold-out treatment.
   Image is dimmed + desaturated so the customer sees there's
   still a real product (vs an empty placeholder), but it visually
   recedes. The :hover scale animation is suppressed because hover
   would imply interactivity that no longer applies to the cart
   CTA — the card itself stays clickable through to the PDP. */
.mp-product-card--sold-out .mp-product-img {
    filter: grayscale(0.7) brightness(0.92);
    opacity: 0.7;
}
.mp-product-card--sold-out:hover .mp-product-img {
    transform: none;
}

/* Sold-out variant of the inline cart button. Uses the same base
   .dp-card-cart-inline shape but locks the appearance into a
   neutral, non-interactive state. The container (anchor) above
   stays clickable so customers can navigate to the PDP — only
   the cart click is disabled. */
.dp-card-cart-inline--soldout {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* Variant unavailable — shared between QuickAdd modal chips and
   the manual order picker chips. The chip stays clickable (per
   product spec: clicking an unavailable option keeps it visible
   and surfaces the "Unavailable" CTA below) but is visually
   marked with a faded background + a diagonal slash drawn from
   bottom-left to top-right. The slash is a pseudo-element so it
   sits above content without affecting layout, and pointer-events
   on the slash itself are disabled so the chip's click handler
   continues to receive events.

   Chips that use this class MUST establish a positioning context
   (position: relative) for the ::after slash to anchor against. */
.dp-variant-unavailable {
    position: relative;             /* anchor for ::after slash */
    opacity: 0.55;
    color: #74808f !important;
    background: rgba(19, 27, 46, 0.04);
}
.dp-variant-unavailable::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    border-radius: inherit;
    background: linear-gradient(
        to top right,
        transparent calc(50% - 1px),
        currentColor calc(50% - 1px),
        currentColor calc(50% + 1px),
        transparent calc(50% + 1px)
    );
}
