/**
 * BPMB UI — the app kit (handle: `bpmb-ui-helpers`).
 *
 * Buttons, the modal (bpmbModal), confirm (bpmbConfirm), skeleton / busy
 * states, badges, avatars and the empty / error / success
 * states. Pairs with public/js/bpmb-ui.js: these are the pieces a script puts
 * on the page or that only an interactive surface (dashboard, editor, admin,
 * load-more, the logged-in engagement buttons) renders.
 *
 * Declares no tokens. It depends on `bpmb-front` (bpmb-front.css), which
 * carries every `--bpmb-*` token and the reader components, so enqueueing
 * `bpmb-ui-helpers` still yields the complete design system - the handle means
 * what it always meant. A reading page that needs no script enqueues only
 * `bpmb-front`.
 *
 * @package BuddyPress_Member_Blog
 * @since   3.4.2
 * @since   4.3.0 Tokens and reader components moved to bpmb-front.css.
 */

body.bpmb-modal-open {
    overflow: hidden;
}

/*--------------------------------------------------------------
# Button
--------------------------------------------------------------*/
.bpmb-btn {
    --bpmb-btn-pad-y: 8px;
    --bpmb-btn-pad-x: 16px;
    --bpmb-btn-radius: 8px;
    --bpmb-btn-bg: var(--bpmb-bg-secondary, #f1f5f9);
    --bpmb-btn-fg: var(--bpmb-text-primary, #111827);
    --bpmb-btn-border: var(--bpmb-border-color, #e2e8f0);

    /*
     * BORDER-BOX, or the tap target below is only honoured on half the elements.
     *
     * `<button>` is `border-box` in the UA stylesheet, `<a>` is `content-box`. Without this,
     * `min-height: 40px` reads as 40px TOTAL on a button and 40px of CONTENT on a link, which then
     * adds 16px of padding and 2px of border - so the same class rendered 40px and 58px side by
     * side. The admin sheet carried the identical bug and it is what "the buttons are too big"
     * turned out to be.
     */
    box-sizing: border-box;

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;

    /* 40px minimum tap target (spec 09 §4). */
    min-height: 40px;
    padding-block: var(--bpmb-btn-pad-y);
    padding-inline: var(--bpmb-btn-pad-x);

    font-size: 14px;
    font-weight: 500;
    line-height: 1.25;
    text-decoration: none;

    color: var(--bpmb-btn-fg);
    background-color: var(--bpmb-btn-bg);
    border: 1px solid var(--bpmb-btn-border);
    border-radius: var(--bpmb-btn-radius);

    cursor: pointer;
    transition: background-color .2s cubic-bezier(.4, 0, .2, 1),
                border-color .2s cubic-bezier(.4, 0, .2, 1),
                color .2s cubic-bezier(.4, 0, .2, 1);
}

.bpmb-btn:hover {
    filter: brightness(.96);
}

.bpmb-btn:focus-visible {
    outline: 2px solid transparent;
    outline-offset: 2px;
    box-shadow: 0 0 0 3px rgba(37, 99, 235, .35);
}

.bpmb-btn[disabled],
.bpmb-btn[aria-disabled="true"] {
    opacity: .6;
    cursor: not-allowed;
}

.bpmb-btn--primary {
    --bpmb-btn-bg: var(--bpmb-primary, #2563eb);
    --bpmb-btn-fg: #fff;
    --bpmb-btn-border: var(--bpmb-primary, #2563eb);
}

.bpmb-btn--secondary {
    --bpmb-btn-bg: transparent;
    --bpmb-btn-fg: var(--bpmb-text-primary, #111827);
    --bpmb-btn-border: var(--bpmb-border-color, #e2e8f0);
}

.bpmb-btn--danger {
    --bpmb-btn-bg: var(--bpmb-danger, #dc2626);
    --bpmb-btn-fg: #fff;
    --bpmb-btn-border: var(--bpmb-danger, #dc2626);
}

.bpmb-btn--ghost {
    --bpmb-btn-bg: transparent;
    --bpmb-btn-border: transparent;
}

/*--------------------------------------------------------------
# Modal — the generic dialog (bpmbModal)
#
# `.bpmb-modal` is owned EXCLUSIVELY by bpmbModal() in bpmb-ui.js, which builds
# the element and adds `.is-active` to reveal it. It is hidden by default here
# (opacity + visibility), so any static markup that borrows this class is
# invisible forever: jQuery .show()/.fadeIn() set `display` and `opacity`, and
# neither can touch `visibility`.
#
# That is exactly how the composer's preview dialog was lost — it was declared
# `class="bpmb-modal"` in the template and opened with .show(). Static dialog
# markup gets its OWN root class (see `.bpmb-preview-modal`).
--------------------------------------------------------------*/
.bpmb-modal {
    --bpmb-modal-width: 520px;
    --bpmb-modal-pad: 20px;
    --bpmb-modal-radius: 12px;
    --bpmb-modal-accent: var(--bpmb-primary, #2563eb);

    position: fixed;
    inset: 0;
    z-index: 100000;

    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;

    opacity: 0;
    visibility: hidden;

    /*
     * Transition opacity ONLY. `visibility` must flip synchronously with
     * .is-active: if it is transitioned it stays `hidden` for the duration of
     * the transition, and a browser refuses to move focus into an invisible
     * element — so the dialog would open with focus stranded on <body>.
     */
    transition: opacity .2s cubic-bezier(.4, 0, .2, 1);
}

.bpmb-modal.is-active {
    opacity: 1;
    visibility: visible;
}

.bpmb-modal--sm { --bpmb-modal-width: 420px; }
.bpmb-modal--lg { --bpmb-modal-width: 720px; }

.bpmb-modal--danger  { --bpmb-modal-accent: var(--bpmb-danger, #dc2626); }
.bpmb-modal--warning { --bpmb-modal-accent: var(--bpmb-warning, #d97706); }
.bpmb-modal--info    { --bpmb-modal-accent: var(--bpmb-info, #2563eb); }

.bpmb-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, .55);
}

.bpmb-modal__panel {
    position: relative;
    z-index: 1;

    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: var(--bpmb-modal-width);
    max-height: calc(100vh - 32px);
    overflow: hidden;

    background: var(--bpmb-bg-primary, #fff);
    color: var(--bpmb-text-primary, #111827);
    border-radius: var(--bpmb-modal-radius);
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, .18), 0 8px 10px -6px rgba(0, 0, 0, .12);

    transform: translateY(8px) scale(.98);
    transition: transform .2s cubic-bezier(.4, 0, .2, 1);
}

.bpmb-modal.is-active .bpmb-modal__panel {
    transform: translateY(0) scale(1);
}

.bpmb-modal__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;

    padding: var(--bpmb-modal-pad);
    padding-block-end: 0;
}

.bpmb-modal__title {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    line-height: 1.25;
    color: inherit;
}

/* An empty title still needs the close button to sit correctly. */
.bpmb-modal__title:empty {
    display: none;
}

.bpmb-modal__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;

    /* Icon-only control: keep the 40px target even though the glyph is 18px. */
    width: 40px;
    height: 40px;
    margin-block-start: -8px;
    margin-inline-end: -8px;

    color: var(--bpmb-text-secondary, #6b7280);
    background: none;
    border: 0;
    border-radius: 8px;
    cursor: pointer;
}

.bpmb-modal__close:hover {
    background: var(--bpmb-bg-hover, rgba(0, 0, 0, .05));
    color: var(--bpmb-text-primary, #111827);
}

.bpmb-modal__close:focus-visible {
    outline: 2px solid var(--bpmb-modal-accent);
    outline-offset: 2px;
}

.bpmb-modal__body {
    padding: var(--bpmb-modal-pad);
    overflow-y: auto;
    font-size: 14px;
    line-height: 1.5;
}

.bpmb-modal__message {
    margin: 0;
    color: var(--bpmb-text-secondary, #6b7280);
}

.bpmb-modal__foot {
    display: flex;
    justify-content: flex-end;
    gap: 8px;

    padding: var(--bpmb-modal-pad);
    padding-block-start: 0;
}

/*--------------------------------------------------------------
# Confirm — a destructive-action gate rendered inside a modal
--------------------------------------------------------------*/
.bpmb-confirm {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    text-align: center;
}

.bpmb-confirm__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;

    width: 64px;
    height: 64px;
    border-radius: 9999px;

    color: var(--bpmb-modal-accent, #dc2626);
    /* Tint of the accent, with a hex fallback for browsers without color-mix. */
    background: var(--bpmb-danger-light, #fee2e2);
    background: color-mix(in srgb, var(--bpmb-modal-accent, #dc2626) 12%, transparent);
}

.bpmb-confirm__message {
    margin: 0;
    font-size: 15px;
    line-height: 1.5;
    color: var(--bpmb-text-secondary, #6b7280);
}

/*--------------------------------------------------------------
# Skeleton — the LOADING state (spec 09 §3 four-state contract)
--------------------------------------------------------------*/
.bpmb-skeleton-group {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.bpmb-skeleton {
    background: var(--bpmb-skeleton-base, #e9edf2);
    background-image: linear-gradient(
        90deg,
        var(--bpmb-skeleton-base, #e9edf2) 0%,
        var(--bpmb-skeleton-sheen, #f4f6f9) 50%,
        var(--bpmb-skeleton-base, #e9edf2) 100%
    );
    background-size: 200% 100%;
    border-radius: 6px;
    animation: bpmb-skeleton-sheen 1.4s ease-in-out infinite;
}

.bpmb-skeleton--thumb  { width: 100%; aspect-ratio: 16 / 9; border-radius: 10px; }
.bpmb-skeleton--title  { width: 70%;  height: 18px; }
.bpmb-skeleton--meta   { width: 40%;  height: 12px; }
.bpmb-skeleton--text   { width: 100%; height: 12px; }
.bpmb-skeleton--short  { width: 55%; }
.bpmb-skeleton--avatar { width: 40px; height: 40px; border-radius: 9999px; flex: 0 0 auto; }

.bpmb-skeleton-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/*--------------------------------------------------------------
# Busy state
#
# `.bpmb-loading` is applied by ~13 call sites across both plugins while a request
# is in flight, but until now it only existed as a layout rule in the EDITOR
# stylesheet - `display: inline-flex` and a gap, no visual feedback at all, and not
# loaded on any other screen. So on most surfaces the class was applied, the user
# saw nothing change, and the button still looked clickable.
#
# Defining it here, in the shared sheet every surface already depends on, is what
# makes those existing call sites mean something. Works on a button or a container:
# the element dims, stops taking pointer events, and grows a spinner.
--------------------------------------------------------------*/

/*
 * THE busy state. State only - dim, inert, and a progress cursor. It deliberately
 * paints NO spinner, because this codebase already has a spinner primitive
 * (`.bpmb-spinner`, below) that six call sites inject into the markup themselves.
 * A glyph on the base class collided with those and painted two spinners at once.
 *
 * Want a glyph without touching markup? Add `.bpmb-loading--spinner` as well.
 */
.bpmb-loading {
    opacity: 0.6;
    pointer-events: none;
    cursor: progress;
}

/*
 * Opt-in trailing glyph, for callers that have no `.bpmb-spinner` of their own.
 * Sits after the label rather than replacing it: swapping the text out would change
 * the button's width mid-click and shift whatever is beside it.
 */
.bpmb-loading--spinner::after {
    content: "";
    display: inline-block;
    width: 1em;
    height: 1em;
    /*
     * `flex: 0 0 auto` is load-bearing, not defensive. Most of the buttons this lands on are
     * `inline-flex` (.bpmb-btn, .add-bpmb-category), which makes the pseudo-element a flex ITEM -
     * and a flex item shrinks by default. Measured without it: a spinner 4px wide and 13px tall,
     * i.e. a squashed line rather than a circle.
     */
    flex: 0 0 auto;
    margin-inline-start: 0.5em;
    vertical-align: -0.125em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: bpmb-spin 0.7s linear infinite;
}

/*
 * Honour reduced-motion: keep the affordance, drop the spin. A pulse still says
 * "working" without animating a rotating element for someone who asked us not to.
 */
@media (prefers-reduced-motion: reduce) {
    .bpmb-loading--spinner::after {
        animation: bpmb-busy-pulse 1.2s ease-in-out infinite;
        border-top-color: currentColor;
    }

    @keyframes bpmb-busy-pulse {
        50% { opacity: 0.25; }
    }
}

/*
 * The ONE rotate keyframe for the whole design system. It used to be copy-pasted six
 * times (twice in buddypress-member-blog-public.css alone, plus the editor, admin,
 * Pro co-authors and Pro analytics stylesheets). Every one of those stylesheets
 * depends on `bpmb-ui-helpers` - Pro's reach it transitively through the virtual
 * `bpmbp-frontend-tokens` handle - so they all resolve this definition.
 */
@keyframes bpmb-spin {
    to { transform: rotate(360deg); }
}

.bpmb-skeleton-card__body {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.bpmb-skeleton-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.bpmb-skeleton-row .bpmb-skeleton--text {
    flex: 1 1 auto;
}

@keyframes bpmb-skeleton-sheen {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/*--------------------------------------------------------------
# Badge
--------------------------------------------------------------*/
.bpmb-badge {
    --bpmb-badge-fg: var(--bpmb-text-secondary, #6b7280);
    --bpmb-badge-bg: var(--bpmb-bg-secondary, #f1f5f9);

    display: inline-flex;
    align-items: center;
    gap: 4px;

    padding: 2px 8px;

    font-size: 12px;
    font-weight: 500;
    line-height: 1.5;
    white-space: nowrap;

    color: var(--bpmb-badge-fg);
    background: var(--bpmb-badge-bg);
    border-radius: 6px;
}

.bpmb-badge--success   { --bpmb-badge-fg: var(--bpmb-success, #16a34a); --bpmb-badge-bg: var(--bpmb-success-light, #dcfce7); }
.bpmb-badge--danger    { --bpmb-badge-fg: var(--bpmb-danger, #dc2626);  --bpmb-badge-bg: var(--bpmb-danger-light, #fee2e2); }
.bpmb-badge--warning   { --bpmb-badge-fg: var(--bpmb-warning, #d97706); --bpmb-badge-bg: var(--bpmb-warning-light, #fef3c7); }
.bpmb-badge--info      { --bpmb-badge-fg: var(--bpmb-info, #2563eb);    --bpmb-badge-bg: var(--bpmb-info-light, #dbeafe); }
.bpmb-badge--featured  { --bpmb-badge-fg: #92400e; --bpmb-badge-bg: #fef3c7; }

/*--------------------------------------------------------------
# Avatar
--------------------------------------------------------------*/
.bpmb-avatar {
    --bpmb-avatar-size: 32px;

    display: inline-block;
    flex: 0 0 auto;
    width: var(--bpmb-avatar-size);
    height: var(--bpmb-avatar-size);
    overflow: hidden;
    border-radius: 9999px;
}

.bpmb-avatar img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
}

.bpmb-avatar--sm { --bpmb-avatar-size: 24px; }
.bpmb-avatar--lg { --bpmb-avatar-size: 48px; }

/* Stacked group (co-authors). */
.bpmb-avatar-group {
    display: inline-flex;
    align-items: center;
}

.bpmb-avatar-group .bpmb-avatar + .bpmb-avatar {
    margin-inline-start: -8px;
    box-shadow: 0 0 0 2px var(--bpmb-bg-primary, #fff);
}

/*--------------------------------------------------------------
# States — EMPTY / ERROR / SUCCESS (the other three of the four)
--------------------------------------------------------------*/
.bpmb-empty,
.bpmb-error-state,
.bpmb-success-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;

    padding: 40px 20px;
    text-align: center;

    color: var(--bpmb-text-secondary, #6b7280);
    background: var(--bpmb-bg-secondary, #f8fafc);
    border: 1px solid var(--bpmb-border-color, #e2e8f0);
    border-radius: 12px;
}

.bpmb-empty__icon,
.bpmb-error-state__icon,
.bpmb-success-state__icon {
    color: var(--bpmb-text-muted, #9ca3af);
}

/*
 * `--bpmb-danger-text`, not `--bpmb-danger`.
 *
 * `--bpmb-danger` is the SIGNAL colour - for borders, icons and filled buttons, where
 * it sits against a light surface. As body text on the state's own dark surface it
 * measured 3.13:1, under the 4.5:1 AA floor. `--bpmb-danger-text` is the token that
 * flips per mode for exactly this (#721c24 light, #fca5a5 dark).
 */
.bpmb-error-state   { color: var(--bpmb-danger-text, #721c24); }
.bpmb-success-state { color: var(--bpmb-success, #16a34a); }

.bpmb-error-state__icon   { color: currentColor; }
.bpmb-success-state__icon { color: currentColor; }

.bpmb-empty__title,
.bpmb-error-state__title,
.bpmb-success-state__title {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: var(--bpmb-text-primary, #111827);
}

.bpmb-empty__text,
.bpmb-error-state__text,
.bpmb-success-state__text {
    margin: 0;
    font-size: 14px;
    line-height: 1.5;
}

/* The next step: one primary action, optionally one quieter one beside it. */
.bpmb-empty__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-block-start: 8px;
}

/*
 * A shortcode that has nothing to list (see BP_Member_Blog_Shortcodes_Loader::empty_state()).
 * The same state as everywhere else, given room from whatever heading the owner put above it.
 */
.bpmb-shortcode-empty-state {
    margin-block: var(--bpmb-space-md, 16px) var(--bpmb-space-lg, 24px);
}

/* The setup note only a site admin sees, under or above a list that is empty because of how it
 * was placed. Warning-tinted so it cannot be mistaken for content. */
.bpmb-admin-hint {
    margin-block: var(--bpmb-space-sm, 8px) var(--bpmb-space-md, 16px);
    padding: var(--bpmb-space-sm, 8px) var(--bpmb-space-md, 16px);
    font-size: var(--bpmb-font-size-sm, 13px);
    line-height: 1.5;
    color: var(--bpmb-warning-text, #92400e);
    background: var(--bpmb-warning-bg, #fef3c7);
    border-inline-start: 3px solid var(--bpmb-warning, #d97706);
    border-radius: var(--bpmb-radius-md, 6px);
}

.bpmb-admin-hint a {
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
}

/*--------------------------------------------------------------
# Responsive — spec 09 §4: stack under 480px, full-bleed dialogs
--------------------------------------------------------------*/
@media (max-width: 480px) {
    .bpmb-modal {
        padding: 0;
        align-items: flex-end;
    }

    .bpmb-modal__panel {
        max-width: none;
        max-height: 90vh;
        border-start-start-radius: var(--bpmb-modal-radius);
        border-start-end-radius: var(--bpmb-modal-radius);
        border-end-start-radius: 0;
        border-end-end-radius: 0;
    }

    .bpmb-modal__foot {
        flex-direction: column-reverse;
    }

    .bpmb-modal__foot .bpmb-btn {
        width: 100%;
    }
}

/*--------------------------------------------------------------
# Reduced motion
--------------------------------------------------------------*/
@media (prefers-reduced-motion: reduce) {
    .bpmb-modal,
    .bpmb-modal__panel,
    .bpmb-btn {
        transition: none;
    }

    .bpmb-skeleton {
        animation: none;
    }
}
