/* Shared filter controls (Rebel.Shared.UI). Canonical .app-* contracts.
   Applications adopt these class names; product-prefixed variants are retired.
   Per-application sheet breakpoints stay in app stylesheets (768px unified). */

/* ── Search field with icon, mode selector, and clear action ─────────────── */

.app-search {
    position: relative;
    display: flex;
    align-items: center;
    min-width: 0;
    width: 100%;
    min-height: 48px;
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
    background: var(--app-surface);
}

.app-search:focus-within {
    border-color: var(--app-primary);
}

.app-search__icon {
    position: absolute;
    left: 0.75rem;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--app-text-muted);
    font-size: 1.1rem;
    pointer-events: none;
}

.app-search input[type="search"],
.app-search input[type="text"] {
    width: 100%;
    min-width: 0;
    min-height: 46px;
    padding: 0.55rem 0.75rem 0.55rem 2.5rem;
    border: 0;
    border-radius: var(--app-radius-control);
    color: var(--app-text);
    background: transparent;
    font-size: 0.95rem;
}

.app-search input::placeholder {
    color: var(--app-text-muted);
    opacity: 0.82;
}

.app-search input:focus {
    outline: none;
    background: none;
}

.app-search:focus-within .app-search__icon {
    color: var(--app-primary);
}

.app-search__clear {
    flex: 0 0 auto;
    min-width: 44px;
    min-height: 44px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: var(--app-text-muted);
    font-size: 1.2rem;
    cursor: pointer;
}

.app-search__clear[hidden] {
    display: none;
}

.app-search-modes {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.2rem;
    min-height: 48px;
    margin: 0;
    padding: 3px;
    border: 0;
    border-radius: 11px;
    background: rgba(var(--app-primary-rgb), 0.065);
}

.app-search-mode-segment {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
    min-height: 40px;
    padding: 0.3rem 0.55rem;
    border: 1px solid rgba(var(--app-primary-rgb), 0.14);
    border-radius: 9px;
    color: var(--app-text-muted);
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    cursor: pointer;
    user-select: none;
}

.app-search-mode-segment input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.app-search-mode-segment span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: normal;
    overflow-wrap: anywhere;
}

.app-search-mode-segment--active,
.app-search-mode-segment:has(input:checked) {
    border-color: var(--app-primary);
    background: color-mix(in srgb, var(--app-focus-accent) 14%, transparent);
    color: var(--app-primary);
}

.app-search-mode-segment:hover {
    color: var(--app-text);
    background: var(--app-hover-bg);
}

.app-search-mode-segment:has(input:focus-visible) {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

/* ── Segmented choices: one semantic fieldset, pill options ──────────────── */

.app-segmented {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;
    margin: 0 0 12px;
    padding: 0;
    border: 0;
}

.app-segmented legend,
.app-segmented__legend {
    padding: 0;
    margin-bottom: 8px;
    color: var(--app-text);
    font-size: 14px;
    font-weight: 600;
}

.app-segmented__option {
    display: flex;
    position: relative;
    min-width: 0;
}

.app-segmented__option input {
    position: absolute;
    inset: 0;
    opacity: 0;
    margin: 0;
    cursor: pointer;
}

.app-segmented__label {
    display: inline-flex;
    width: 100%;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    padding: 8px 14px;
    border: 1px solid var(--app-control-border);
    border-radius: 12px;
    background: var(--app-surface);
    color: var(--app-text-muted);
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
    white-space: normal;
    text-align: center;
    cursor: pointer;
    overflow-wrap: anywhere;
}

.app-segmented__label .app-svg-icon {
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
}

.app-segmented__option input:checked + .app-segmented__label {
    border-color: var(--app-primary);
    background: var(--app-accent-soft);
    color: var(--app-accent-text);
}

.app-segmented__option input:focus-visible + .app-segmented__label {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

/* Native choice states stay visible even when labels fill the rail. */
.app-segmented__option:hover .app-segmented__label {
    border-color: var(--app-primary);
}

.app-segmented__option:has(input:disabled) {
    opacity: 0.5;
}

.app-segmented__option input:disabled,
.app-segmented__option input:disabled + .app-segmented__label {
    cursor: not-allowed;
}

/* Optional full-width distribution for choices outside a scrolling rail. */
.app-segmented--distributed > .app-segmented__option {
    flex: 1 1 max-content;
}

/* ── Choice rail: full-width distribution on desktop, contained scroll on mobile ──
   The track holds the option labels; the outer wrapper is only a frame.
   Desktop distributes options across the available width. Mobile keeps a
   touch-sized scrolling rail via the tier below. */

.app-choice-rail {
    display: flex;
    align-items: stretch;
    min-width: 0;
    width: 100%;
    gap: 6px;
}

.app-choice-rail__nav {
    display: none;
}

.app-choice-rail__track {
    display: flex;
    flex: 1 1 auto;
    flex-wrap: wrap;
    min-width: 0;
    width: 100%;
    margin: 0;
    padding: 2px;
    border: 0;
    gap: 8px;
    scroll-margin: 0;
}

.app-choice-rail__track > input[type="hidden"] {
    display: none;
}

.app-choice-rail__track > .app-segmented__option {
    flex: 1 1 max-content;
    min-width: 0;
}

.app-choice-rail__track > .app-segmented__option > .app-segmented__label {
    width: 100%;
    min-width: 0;
}

/* ── Filter field: label above a single control outline + paired ranges ─── */

.app-filter-field {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    gap: 6px;
}

.app-filter-field__label {
    display: flex;
    align-items: center;
    min-width: 0;
    gap: 0.4rem;
    color: var(--app-text-muted);
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.3;
}

.app-filter-field__label .app-icon {
    flex: 0 0 auto;
    color: var(--app-primary);
    font-size: 1rem;
}

.app-filter-field select,
.app-filter-field input {
    width: 100%;
    min-width: 0;
    min-height: 48px;
    border: 1px solid var(--app-control-border);
    border-radius: var(--app-radius-control);
    background: var(--app-surface);
    color: var(--app-text);
    font-size: 0.95rem;
    padding: 0 0.75rem;
    box-shadow: none;
}

.app-filter-field select:focus,
.app-filter-field input:focus {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
    border-color: var(--app-primary);
    box-shadow: none;
}

.app-filter-field input::placeholder {
    color: var(--app-text-muted);
    opacity: 0.9;
}

.app-filter-field input:disabled,
.app-filter-field select:disabled {
    cursor: not-allowed;
    opacity: 0.62;
}

.app-filter-field--disabled {
    opacity: 0.58;
}

.app-filter-field--range .app-filter-range-pair,
.app-filter-range-pair {
    display: flex;
    align-items: center;
    min-width: 0;
    gap: 8px;
}

.app-filter-field--range input,
.app-filter-range-pair input {
    flex: 1 1 0;
    min-width: 0;
}

.app-filter-range-sep,
.app-filter-range-pair > em {
    flex: 0 0 auto;
    color: var(--app-text-muted);
    font-style: normal;
}

/* TomSelect closed control: the single intentional outline for enhanced
   dropdowns. The body-level listbox anatomy follows below. */
.app-filter-field .ts-wrapper {
    width: 100%;
    min-width: 0;
}

.app-filter-field .ts-wrapper.multi .ts-control,
.app-filter-field .ts-wrapper.single .ts-control {
    min-height: 46px;
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
    background: var(--app-surface);
    color: var(--app-text);
    padding: 5px 8px;
    gap: 6px;
    font-size: 0.9rem;
    box-shadow: none;
}

.app-filter-field .ts-wrapper.focus .ts-control,
.app-filter-field .ts-wrapper .ts-control:focus-within {
    border-color: var(--app-primary);
    box-shadow: none;
}

.app-filter-field .ts-wrapper.multi .ts-control {
    max-height: 96px;
    overflow-y: auto;
    overscroll-behavior: contain;
    align-content: flex-start;
}

.app-filter-field .ts-wrapper.multi .ts-control > .item,
.app-filter-field .ts-wrapper.plugin-remove_button .item {
    display: inline-flex;
    align-items: center;
    max-width: 100%;
    min-height: 1.6rem;
    margin: 2px 2px 2px 0;
    padding: 0.18rem 0.55rem;
    border: 1px solid var(--ts-color-item-bg);
    border-radius: 999px;
    background: var(--ts-color-item-bg);
    color: var(--ts-color-item-text);
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-filter-field .ts-wrapper.multi .ts-control > .item.active {
    background: var(--ts-color-item-active-bg);
    color: var(--app-text);
}

.app-filter-field .ts-wrapper .item .remove,
.app-filter-field .ts-wrapper.plugin-remove_button .item .remove {
    margin-left: 0.3rem;
    border-left: 1px solid var(--ts-color-border);
    color: currentColor;
    opacity: 0.7;
}

.app-filter-field .ts-wrapper .item .remove:hover,
.app-filter-field .ts-wrapper.plugin-remove_button .item .remove:hover {
    opacity: 1;
}

.app-filter-field .ts-wrapper .ts-control > input {
    flex: 1 1 4rem;
    min-width: 4rem;
    max-width: 100%;
    min-height: 2rem;
    border: 0;
    padding: 0 0.25rem;
    background: transparent;
    color: var(--app-text);
    font-size: 0.9rem;
}

.app-filter-field .ts-wrapper .ts-control > input::placeholder {
    color: var(--app-text-muted);
    opacity: 0.9;
}

.app-filter-field .ts-wrapper.disabled .ts-control {
    cursor: not-allowed;
    opacity: 0.62;
}

/* TomSelect listbox: TomSelect appends it to <body>, so this global (not
   scoped) anatomy is the only styling that can reach the open dropdown. */
.ts-dropdown {
    overflow: hidden;
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
    background: var(--ts-color-dropdown-bg);
    color: var(--app-text);
    box-shadow: var(--app-shadow-soft);
    z-index: 1600;
}

/* The vendor renders a separate content node. Only it scrolls, so the
   option list has one bounded scroller even when appended to body. */
.ts-dropdown-content {
    max-height: min(18rem, 40dvh);
    overflow: hidden auto;
    overscroll-behavior: contain;
}

body > .ts-dropdown {
    z-index: 1600;
}

.ts-dropdown .option,
.ts-dropdown .create,
.ts-dropdown .no-results {
    min-height: 44px;
    display: flex;
    align-items: center;
    padding: 0.55rem 0.75rem;
    color: var(--app-text);
    font-size: 0.9rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ts-dropdown .no-results {
    color: var(--app-text-muted);
}

.ts-dropdown .option:hover,
.ts-dropdown .option.active {
    background: var(--ts-color-option-active-bg);
    color: var(--app-text);
}

.ts-dropdown .option.selected {
    background: var(--ts-color-option-active-bg);
    color: var(--ts-color-item-text);
    font-weight: 600;
}

.ts-dropdown .highlight {
    border-radius: 4px;
    background: var(--ts-color-highlight-bg);
    color: inherit;
}

@media (max-width: 768px) {
    .app-search input[type="search"],
    .app-search input[type="text"],
    .app-filter-field select,
    .app-filter-field input,
    .app-filter-field .ts-wrapper .ts-control > input {
        font-size: 16px;
    }

    /* Mobile multiselect: let the selected-value area grow with the sheet
       instead of trapping vertical gestures in a small nested scroller.
       The open option list (.ts-dropdown) keeps its own bounded scrolling. */
    .app-filter-field .ts-wrapper.multi .ts-control {
        max-height: none;
        overflow: visible;
        overscroll-behavior: auto;
    }
}

.app-filter-field--wide {
    grid-column: 1 / -1;
}

/* ── Filter trigger with count badge ─────────────────────────────────────── */

.app-filter-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.48rem;
    min-height: 48px;
    padding: 0.6rem 0.9rem;
    border: 1px solid var(--app-border-strong);
    border-radius: 12px;
    color: var(--app-text);
    background: var(--app-surface);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

.app-filter-trigger:hover {
    border-color: var(--app-primary);
    background: var(--app-hover-bg);
}

.app-filter-trigger:focus-visible {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

.app-filter-trigger__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.4rem;
    border-radius: 999px;
    background: var(--app-primary);
    color: var(--app-on-primary);
    font-size: 0.68rem;
    font-weight: 700;
}

.app-filter-trigger__count[hidden] {
    display: none;
}

/* ── Applied-filter chips ────────────────────────────────────────────────── */

.app-filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;
    margin: 0;
    padding: 0;
    list-style: none;
}

.app-filter-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--app-space-2);
    min-height: var(--app-touch-target);
    min-width: 0;
    max-width: 100%;
    padding: 0.3rem 0.35rem 0.3rem 0.6rem;
    border-radius: 9px;
    border: 1px solid rgba(var(--app-primary-rgb), 0.42);
    background: rgba(var(--app-primary-rgb), 0.10);
    color: var(--app-text);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
}

.app-filter-chip:hover {
    background: var(--app-hover-bg);
    border-color: var(--app-primary);
}

.app-filter-chip:focus-visible {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

.app-filter-chip__text {
    min-width: 0;
    max-width: min(18rem, 70vw);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-filter-chip .app-svg-icon {
    width: 1rem;
    height: 1rem;
    flex: 0 0 auto;
    font-size: 0.85rem;
    opacity: 0.75;
}

.app-filter-chip__remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 36px;
    min-height: 36px;
    margin: -0.3rem -0.6rem -0.3rem 0;
    padding: 0 0.6rem;
    border: 0;
    background: transparent;
    color: inherit;
    font-size: 1rem;
    cursor: pointer;
}

.app-filters-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    min-height: 36px;
    padding: 0.3rem 0.65rem;
    border: 1px solid var(--app-border-strong);
    border-radius: 10px;
    color: var(--app-primary);
    background: transparent;
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.app-filters-clear:hover {
    border-color: var(--app-primary);
    background: var(--app-hover-bg);
}

/* ── Filter sheet frame ──────────────────────────────────────────────────── */

.app-filter-sheet__header,
.app-filter-sheet__actions {
    display: none;
}

.app-filter-sheet__scroll {
    display: contents;
}

.app-filter-sheet__header-handle {
    position: absolute;
    top: 8px;
    left: 50%;
    width: 44px;
    height: 5px;
    transform: translateX(-50%);
    border-radius: 10px;
    background: var(--app-border);
}

.app-filter-sheet__title {
    flex: 1 1 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    font-size: 1.1rem;
    font-weight: 700;
}

.app-filter-sheet__count {
    color: var(--app-text-muted);
    font-size: 0.85rem;
    font-weight: 700;
}

.app-filter-sheet__close {
    flex: 0 0 44px;
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 1px solid var(--app-border);
    border-radius: 10px;
    background: var(--app-surface);
    color: var(--app-text);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
}

.app-filter-sheet__close:hover {
    border-color: var(--app-primary);
    background: var(--app-hover-bg);
}

.app-filter-sheet__backdrop {
    position: fixed;
    inset: 0;
    z-index: 1190;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    padding: 0;
    border: 0;
    background: rgba(8, 6, 9, 0.45);
    cursor: pointer;
}

.app-filter-sheet__backdrop[hidden] {
    display: none;
}

/* Unified mobile sheet tier: the owning form becomes a bottom sheet. */
@media (max-width: 768px) {
    form[data-filter-sheet]:not(.app-filter-sheet--open) .app-filter-sheet__primary,
    form[data-filter-sheet]:not(.app-filter-sheet--open) .app-filter-sheet__advanced {
        display: none;
    }

    form[data-filter-sheet].app-filter-sheet--open {
        position: fixed;
        z-index: 1200;
        inset: max(12px, env(safe-area-inset-top, 0px)) 0 0;
        width: 100%;
        height: auto;
        max-height: calc(100vh - 12px);
        margin: 0;
        padding: 0;
        border: 1px solid var(--app-border);
        border-bottom: 0;
        border-radius: 20px 20px 0 0;
        background: var(--app-surface);
        box-shadow: var(--app-shadow-strong);
        display: flex;
        flex-direction: column;
        gap: 0;
        overflow: hidden;
        animation: appFilterSheetRise 180ms ease-out;
    }

    @supports (max-height: 100dvh) {
        form[data-filter-sheet].app-filter-sheet--open {
            max-height: calc(100dvh - 12px);
        }
    }

    form[data-filter-sheet].app-filter-sheet--open .app-filter-sheet__header {
        flex: 0 0 auto;
        display: flex;
        align-items: center;
        gap: 0.7rem;
        min-height: 72px;
        padding: 1rem 0.85rem 0.75rem;
        padding-top: max(1rem, env(safe-area-inset-top, 0px));
        border-bottom: 1px solid var(--app-divider);
        position: relative;
    }

    form[data-filter-sheet].app-filter-sheet--open .app-filter-sheet__scroll {
        display: block;
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding: 0.85rem 0.85rem 1.25rem;
    }

    form[data-filter-sheet].app-filter-sheet--open .app-filter-sheet__scroll > * {
        margin-bottom: 0.85rem;
    }

    form[data-filter-sheet].app-filter-sheet--open .app-filter-sheet__scroll > :last-child {
        margin-bottom: 0;
    }

    form[data-filter-sheet].app-filter-sheet--open .app-filter-sheet__actions {
        flex: 0 0 auto;
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.65rem;
        padding: 0.75rem 0.85rem calc(0.75rem + env(safe-area-inset-bottom, 0px));
        border-top: 1px solid var(--app-divider);
        background: var(--app-surface);
    }

    form[data-filter-sheet].app-filter-sheet--open .app-filter-sheet__actions > * {
        min-height: 48px;
    }

    /* Explicit full-width hooks for long fields inside sheet grids. */
    form[data-filter-sheet].app-filter-sheet--open [data-sheet-full] {
        grid-column: 1 / -1;
    }

    /* Mobile rail treatment for canonical choice rails. */
    .app-choice-rail {
        display: flex;
        align-items: stretch;
        min-width: 0;
        gap: 6px;
    }

    .app-choice-rail__nav {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex: 0 0 44px;
        width: 44px;
        min-height: 44px;
        align-self: center;
        padding: 0;
        border: 1px solid var(--app-border);
        border-radius: 10px;
        background: var(--app-surface);
        color: var(--app-text-muted);
        font-size: 1.2rem;
        cursor: pointer;
        touch-action: manipulation;
    }

    .app-choice-rail__nav[hidden] {
        display: none;
    }

    .app-choice-rail__nav:disabled {
        opacity: 0.35;
        cursor: default;
    }

    .app-choice-rail__nav:not(:disabled):hover {
        border-color: var(--app-primary);
        color: var(--app-text);
        background: var(--app-hover-bg);
    }

    .app-choice-rail__track {
        display: flex;
        flex: 1 1 auto;
        flex-wrap: nowrap;
        min-width: 0;
        gap: 6px;
        margin: 0;
        padding: 2px;
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        scroll-behavior: smooth;
        border: 0;
    }

    .app-choice-rail__track::-webkit-scrollbar {
        display: none;
    }

    .app-choice-rail__track > .app-segmented__option {
        flex: 1 0 max-content;
    }

    .app-choice-rail__track > .app-segmented__option > .app-segmented__label {
        white-space: nowrap;
        overflow-wrap: normal;
    }

    .app-choice-rail--can-scroll-right .app-choice-rail__track {
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
        mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    }

    .app-choice-rail--can-scroll-left .app-choice-rail__track {
        -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent);
        mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent);
    }

    .app-choice-rail--can-scroll-left.app-choice-rail--can-scroll-right .app-choice-rail__track {
        -webkit-mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent);
        mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent);
    }
}

/* ── Open filter composition contract ───────────────────────────────────────
   Opt-in. The page provides the background; an interactive control may carry a
   surface, but a layout wrapper does not gain one merely because it groups
   controls. Add [data-open-filters] to the owning discovery form and mark the
   surface-free wrappers inside it with .app-filter-layout or .app-filter-group.

   Scoped to [data-open-filters] so unrelated forms and cards keep their
   surfaces, and it owns row rhythm so local rules do not stack a parent gap, a
   child margin, and nested padding for the same spacing. Controls
   (.app-search, .app-search-modes, .app-filter-field, .app-filter-chip,
   .app-filter-trigger, .app-segmented__label, the sheet) keep their surfaces. */

[data-open-filters] {
    margin: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    padding: 0;
    display: grid;
    align-content: start;
    gap: 12px;
}

/* Surface-free wrapper: card body, search row, collapsible advanced panel. */
.app-filter-layout {
    margin: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    padding: 0;
}

/* Advanced sections use a heading and one thin divider, not nested panels. */
.app-filter-group {
    min-width: 0;
    margin: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    padding: 0;
}

.app-filter-group + .app-filter-group {
    border-top: 1px solid var(--app-divider);
    padding-top: 12px;
}

.app-filter-group__header {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin: 0 0 10px;
}

.app-filter-group__title {
    margin: 0;
    color: var(--app-text);
    font-size: 0.9rem;
    font-weight: 600;
}

.app-filter-group__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
}

/* First row: search plus matching mode plus the additional-filters trigger.
   The row fills its available width: search takes the largest share, modes
   take a balanced middle share, and the trigger fills the remaining track. */
.app-search-row {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 3fr) minmax(min-content, 2fr);
    align-items: stretch;
    gap: 12px;
    width: 100%;
    min-width: 0;
}

.app-search-row > * {
    min-width: 0;
}

.app-search-row .app-filter-trigger {
    width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
}

@media (max-width: 1023px) {
    .app-search-row {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 8px;
    }

    .app-search-row > .app-search {
        grid-column: 1;
        grid-row: 1;
    }

    .app-search-row > .app-filter-trigger {
        grid-column: 2;
        grid-row: 1;
    }

    .app-search-row > .app-search-modes {
        grid-column: 1 / -1;
        grid-row: 2;
    }
}

@media (max-width: 480px) {
    .app-search-row {
        grid-template-columns: minmax(0, 1fr);
    }

    .app-search-row > .app-filter-trigger {
        grid-column: 1;
        grid-row: 3;
    }
}

/* In the modal all fields stay in the one surrounding sheet scroller. */
@media (max-width: 768px) {
    form[data-filter-sheet].app-filter-sheet--open .app-search-row {
        grid-template-columns: minmax(0, 1fr);
    }

    form[data-filter-sheet].app-filter-sheet--open .app-search-row > .app-filter-trigger {
        display: none;
    }
}

@media (max-width: 1023px) {
    .app-filter-group__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 480px) {
    .app-filter-group__grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ── Unified button system ─────────────────────────────────────────────────
   One appearance for primary, secondary, quiet, icon-only, and destructive
   actions. Primary uses the neutral button tokens; the accent is reserved
   for selected controls, focus, badges, and supporting emphasis. */
.app-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--app-space-2);
    min-height: var(--app-touch-target);
    min-width: 0;
    padding: var(--app-space-2) var(--app-space-4);
    border: 1px solid transparent;
    border-radius: var(--app-radius-control);
    font: inherit;
    font-size: 0.92rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease;
}

.app-button__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}

.app-button--primary {
    border-color: var(--app-primary);
    color: var(--app-on-primary);
    background: var(--app-primary);
}

.app-button--primary:hover {
    background: var(--app-primary-dark);
    border-color: var(--app-primary-dark);
    color: var(--app-on-primary);
}

.app-button--secondary {
    border-color: var(--app-border);
    color: var(--app-text);
    background: var(--app-surface);
}

.app-button--secondary:hover {
    border-color: var(--app-primary);
    color: var(--app-text);
    background: var(--app-hover-bg);
}

.app-button--quiet {
    border-color: var(--app-border-strong);
    color: var(--app-text-muted);
    background: transparent;
}

.app-button--quiet:hover {
    border-color: var(--app-primary);
    color: var(--app-text);
    background: var(--app-hover-bg);
}

.app-button--danger {
    border-color: color-mix(in srgb, var(--app-danger) 45%, var(--app-border));
    color: var(--app-danger);
    background: transparent;
}

.app-button--danger:hover {
    border-color: var(--app-danger);
    background: color-mix(in srgb, var(--app-danger) 10%, transparent);
}

.app-button--icon {
    padding: 0;
    width: var(--app-touch-target);
    flex: 0 0 var(--app-touch-target);
}

.app-button--small {
    min-height: 36px;
    padding: var(--app-space-1) var(--app-space-3);
    font-size: 0.82rem;
}

@media (max-width: 768px) {
    .app-button--small {
        min-height: 44px;
    }
}

.app-button[hidden] {
    display: none;
}

.app-button:disabled,
.app-button.disabled,
.app-button[aria-disabled="true"] {
    opacity: 0.45;
    cursor: default;
    pointer-events: none;
}

.app-button:focus-visible {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

.app-button[aria-pressed="true"],
.app-button[aria-expanded="true"] {
    border-color: var(--app-primary);
    color: var(--app-accent-text);
    background: var(--app-accent-soft);
}

/* ── Page gutters: full-width composition (Option A) ───────────────────────
   Main discovery and home content always occupies the available viewport
   width. Only individual text blocks and controls take a local readable
   width; the composition itself is never constrained by a fixed max-width. */
:root {
    --app-gutter: var(--app-page-padding-inline);
}

/* ── Shared hero composition ───────────────────────────────────────────────
   One homepage hero across all six applications. Compact introduction with
   copy on one side and product plus contact actions on the other. */
.app-hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    gap: 16px;
    width: 100%;
    min-width: 0;
    margin: 0 0 16px;
    padding: 16px;
    border: 1px solid var(--app-border);
    border-radius: 20px;
    background: linear-gradient(115deg, #FFFFFF, #F0F0FC);
    box-shadow: none;
}

[data-theme="dark"] .app-hero {
    background: linear-gradient(115deg, #1D1F22, #262638);
}

.app-hero__copy {
    min-width: 0;
    display: grid;
    gap: 8px;
    align-content: start;
}

.app-hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--app-accent-text);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.app-hero__title {
    margin: 0;
    max-width: 34ch;
    font-size: 28px;
    line-height: 1.16;
    letter-spacing: -0.01em;
    overflow-wrap: break-word;
}

.app-hero__description {
    max-width: 64ch;
    margin: 0;
    color: var(--app-text-muted);
    font-size: 16px;
    line-height: 1.55;
}

.app-hero__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    min-width: 0;
    max-width: 480px;
}

.app-hero__actions > * {
    min-width: 0;
}

@media (min-width: 641px) and (max-width: 1023px) {
    .app-hero {
        padding: 20px;
    }

    .app-hero__title {
        font-size: 34px;
    }
}

@media (min-width: 1024px) {
    .app-hero {
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
        gap: 24px;
        margin-bottom: 24px;
        padding: 24px;
    }

    .app-hero__title {
        font-size: 40px;
    }

    .app-hero__actions {
        justify-content: flex-end;
    }
}

@media (max-width: 480px) {
    .app-hero__actions {
        display: grid;
        grid-template-columns: 1fr 1fr;
        width: 100%;
        max-width: none;
    }

    .app-hero__actions > :nth-child(3):last-child {
        grid-column: 1 / -1;
    }
}

/* ── Shared admin contact dialog ──────────────────────────────────────────
   One dialog surface for every application. URLs and labels arrive as
   parameters so the shared library never sees product option types. */
.app-contact-dialog {
    width: min(30rem, calc(100vw - 2rem));
    max-width: 100%;
    padding: 0;
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-card);
    color: var(--app-text);
    background: var(--app-surface);
    box-shadow: var(--app-shadow-strong);
}

.app-contact-dialog::backdrop {
    background: rgba(8, 6, 9, 0.45);
}

.app-contact-dialog__panel {
    display: grid;
    gap: var(--app-space-4);
    padding: var(--app-space-4);
}

.app-contact-dialog__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--app-space-3);
}

.app-contact-dialog__copy {
    min-width: 0;
    display: grid;
    gap: var(--app-space-1);
}

.app-contact-dialog__title {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.25;
}

.app-contact-dialog__description {
    margin: 0;
    color: var(--app-text-muted);
    font-size: 0.9rem;
    line-height: 1.5;
}

.app-contact-dialog__close {
    flex: 0 0 var(--app-touch-target);
    display: grid;
    place-items: center;
    width: var(--app-touch-target);
    height: var(--app-touch-target);
    padding: 0;
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
    color: var(--app-text);
    background: var(--app-surface);
    cursor: pointer;
}

.app-contact-dialog__close:hover {
    border-color: var(--app-primary);
    color: var(--app-text);
    background: var(--app-hover-bg);
}

.app-contact-dialog__methods {
    display: grid;
    gap: var(--app-space-2);
}

.app-contact-dialog__method {
    display: flex;
    align-items: center;
    gap: var(--app-space-3);
    min-height: var(--app-touch-target);
    padding: var(--app-space-2) var(--app-space-3);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
    color: var(--app-text);
    background: var(--app-surface);
    font-weight: 600;
    text-decoration: none;
}

.app-contact-dialog__method:hover {
    border-color: var(--app-primary);
    background: var(--app-hover-bg);
}

.app-contact-dialog__method-icon {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 10px;
    color: var(--app-primary);
    background: rgba(var(--app-primary-rgb), 0.12);
}

.app-contact-dialog__method-label {
    min-width: 0;
    overflow-wrap: anywhere;
}

.app-contact-dialog__fallback {
    display: grid;
    gap: var(--app-space-1);
    color: var(--app-text-muted);
    font-size: 0.85rem;
}

/* ── Single-line results toolbar ──────────────────────────────────────────
   Metadata (counts, sorting) stays on the left where present. The layout
   selector and column stepper form one compact group at the right edge,
   with or without metadata. */
.app-results-toolbar {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--app-space-2);
    width: 100%;
    min-width: 0;
}

.app-results-toolbar__group {
    display: flex;
    align-items: center;
    gap: var(--app-space-1);
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

.app-results-toolbar__layout {
    display: flex;
    align-items: center;
    gap: var(--app-space-1);
    min-width: 0;
}

.app-results-toolbar__layout-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--app-space-1);
    flex: 0 0 auto;
    min-width: var(--app-touch-target);
    min-height: var(--app-touch-target);
    padding: var(--app-space-1) var(--app-space-3);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
    color: var(--app-text-muted);
    background: var(--app-surface);
    font: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

.app-results-toolbar__layout-button[aria-pressed="true"] {
    border-color: var(--app-primary);
    color: var(--app-accent-text);
    background: var(--app-accent-soft);
}

.app-results-toolbar__layout-button:focus-visible {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

.app-results-toolbar__columns {
    display: flex;
    align-items: center;
    gap: var(--app-space-1);
    min-width: 0;
}

.app-results-toolbar__step {
    display: grid;
    place-items: center;
    flex: 0 0 var(--app-touch-target);
    width: var(--app-touch-target);
    height: var(--app-touch-target);
    padding: 0;
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
    color: var(--app-text);
    background: var(--app-surface);
    font: inherit;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}

.app-results-toolbar__step:hover:not(:disabled) {
    border-color: var(--app-primary);
    background: var(--app-hover-bg);
}

.app-results-toolbar__step:disabled {
    opacity: 0.4;
    cursor: default;
}

.app-results-toolbar__count {
    flex: 0 0 auto;
    min-width: 2.5ch;
    padding-inline: var(--app-space-1);
    color: var(--app-text-muted);
    font-size: 0.82rem;
    font-weight: 600;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.app-results-toolbar__meta {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    flex: 1 1 auto;
    flex-wrap: wrap;
    gap: var(--app-space-2) var(--app-space-3);
    min-width: 0;
    margin: 0;
}

.app-results-toolbar__controls {
    display: flex;
    align-items: center;
    gap: var(--app-space-2);
    flex: 0 0 auto;
    min-width: 0;
    margin-inline-start: auto;
}

@media (max-width: 640px) {
    .app-results-toolbar {
        flex-wrap: wrap;
    }

    .app-results-toolbar__meta {
        flex: 1 1 100%;
        justify-content: flex-start;
    }

    .app-results-toolbar__controls {
        flex: 0 0 auto;
        margin-inline-start: auto;
    }
}

@media (max-width: 520px) {
    .app-results-toolbar__layout-button {
        padding-inline: 0;
        min-width: var(--app-touch-target);
    }

    .app-results-toolbar__layout-label {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}

/* ── Bounded active-filter summary ────────────────────────────────────────
   A coherent compact section: subtle theme-aware surface, restrained border,
   comfortable internal spacing, and clear hierarchy between heading, chips,
   and Clear all. Collapsed preview clips to about two chip rows. The
   expanded region is a bounded scroller; disclosure controls sit outside it
   so no clipped chip is ever left in the keyboard tab order. */
.app-active-filters {
    min-width: 0;
    display: grid;
    gap: var(--app-space-2);
    padding: var(--app-space-3);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
    background: color-mix(in srgb, var(--app-primary) 5%, var(--app-surface));
}

.app-active-filters[hidden] {
    display: none;
}

.app-active-filters__heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-2);
    min-width: 0;
}

.app-active-filters__heading strong {
    min-width: 0;
    color: var(--app-text);
    font-size: 0.9rem;
    font-weight: 700;
    overflow-wrap: break-word;
}

.app-active-filters__preview {
    position: relative;
    max-height: calc(var(--app-touch-target) * 2 + var(--app-space-2));
    overflow: hidden;
    min-width: 0;
}

.app-active-filters__preview .app-filter-chips {
    align-content: flex-start;
}

.app-active-filters__list {
    min-width: 0;
}

.app-active-filters__expander {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-2);
    min-width: 0;
}

.app-active-filters__expander[hidden] {
    display: none;
}

.app-active-filters__toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--app-space-1);
    min-height: var(--app-touch-target);
    padding: var(--app-space-1) var(--app-space-3);
    border: 1px solid var(--app-border-strong);
    border-radius: var(--app-radius-control);
    color: var(--app-primary);
    background: transparent;
    font: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
}

.app-active-filters__toggle:hover {
    border-color: var(--app-primary);
    background: var(--app-hover-bg);
}

.app-active-filters__toggle:focus-visible {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

.app-active-filters__expanded {
    max-height: 240px;
    overflow-y: auto;
    overscroll-behavior: contain;
    min-width: 0;
    padding: var(--app-space-2);
    border: 1px solid var(--app-border);
    border-radius: var(--app-radius-control);
}

.app-active-filters__expanded[hidden] {
    display: none;
}

.app-active-filters__expanded .app-filter-chip__text {
    max-width: none;
    white-space: normal;
    overflow-wrap: anywhere;
}

.app-active-filters__expanded .app-filter-chip__remove {
    min-width: 36px;
    min-height: 36px;
}

@media (max-width: 768px) {
    .app-active-filters__expanded {
        max-height: min(40vh, 320px);
    }
}

/* ── Filter sheet pinned actions ───────────────────────────────────────────
   Presentation for the sheet footer and disclosure controls. The desktop tier
   hides the pinned regions; the mobile tier promotes them. */
.app-filter-sheet__clear,
.app-filter-sheet__done {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--app-space-1);
    min-height: var(--app-touch-target);
    padding: var(--app-space-2) var(--app-space-4);
    border-radius: var(--app-radius-control);
    font: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
}

.app-filter-sheet__clear {
    border: 1px solid var(--app-border-strong);
    color: var(--app-text-muted);
    background: var(--app-surface);
}

.app-filter-sheet__clear:hover {
    border-color: var(--app-primary);
    color: var(--app-text);
    background: var(--app-hover-bg);
}

.app-filter-sheet__done {
    border: 1px solid var(--app-button-primary-bg);
    color: var(--app-button-primary-text);
    background: var(--app-button-primary-bg);
}

.app-filter-sheet__done:hover {
    filter: brightness(1.08);
}

.app-filter-sheet__clear:focus-visible,
.app-filter-sheet__done:focus-visible {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

/* Additional-filter disclosure triggers use the same quiet control. */
.app-filter-disclosure {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--app-space-2);
    min-height: var(--app-touch-target);
    width: 100%;
    padding: var(--app-space-2) var(--app-space-4);
    border: 1px solid var(--app-border-strong);
    border-radius: var(--app-radius-control);
    color: var(--app-text);
    background: var(--app-surface);
    font: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
}

.app-filter-disclosure:hover {
    border-color: var(--app-primary);
    background: var(--app-hover-bg);
}

.app-filter-disclosure:focus-visible {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
}

.app-filter-disclosure[aria-expanded="true"] .app-filter-disclosure__chevron {
    transform: rotate(180deg);
}

.app-filter-disclosure__chevron {
    transition: transform 0.16s ease;
}

/* ── Results grid: Cards and Rows ─────────────────────────────────────────
   Column count arrives from the shared policy script as
   --app-results-columns. Both orientations are predictable grids, so no
   masonry measurement is involved. */
.app-results {
    display: grid;
    gap: var(--app-space-4);
    min-width: 0;
    align-items: start;
}

.app-results[data-layout="cards"] {
    grid-template-columns: repeat(var(--app-results-columns, 4), minmax(0, 1fr));
}

.app-results[data-layout="rows"] {
    grid-template-columns: repeat(var(--app-results-columns, 2), minmax(0, 1fr));
}

/* First-paint column defaults per viewport tier. The shared results engine
   refines --app-results-columns after measuring and applying the stored
   preference; these rules only govern the pre-script paint so it agrees
   with the engine. Product stylesheets must not define competing counts. */
.app-results[data-layout="cards"] { --app-results-columns: 2; }
.app-results[data-layout="rows"] { --app-results-columns: 1; }

@media (max-width: 359px) {
    .app-results[data-layout="cards"] { --app-results-columns: 1; }
}

@media (min-width: 768px) {
    .app-results[data-layout="cards"] { --app-results-columns: 3; }
}

@media (min-width: 1024px) {
    .app-results[data-layout="cards"] { --app-results-columns: 4; }
    .app-results[data-layout="rows"] { --app-results-columns: 2; }
}

@media (min-width: 1600px) {
    .app-results[data-layout="cards"] { --app-results-columns: 6; }
    .app-results[data-layout="rows"] { --app-results-columns: 3; }
}

.app-results__item {
    min-width: 0;
}

.app-results__item[hidden] {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .app-filter-disclosure__chevron {
        transition: none;
    }
}

@keyframes appFilterSheetRise {    from {
        transform: translateY(24px);
        opacity: 0.98;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

html.app-filter-sheet-active,
html.app-filter-sheet-active body {
    overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
    form[data-filter-sheet].app-filter-sheet--open {
        animation: none;
    }

    .app-choice-rail__track {
        scroll-behavior: auto;
    }
}

/* ── Shared presentation primitives ─────────────────────────────────────
   Canonical hooks owned by Rebel.Shared.UI. Applications migrate existing
   markup to these primitives instead of defining local equivalents. */
.app-page-heading {
    margin: 0 0 16px;
    font-size: 30px;
    font-weight: 700;
    line-height: 1.2;
}

@media (max-width: 1023px) {
    .app-page-heading {
        font-size: 26px;
    }
}

.app-panel {
    background: var(--app-surface);
    border: 1px solid var(--app-border);
    border-radius: 16px;
    box-shadow: var(--app-shadow-soft);
    padding: 16px;
}

@media (min-width: 1024px) {
    .app-panel {
        padding: 20px;
    }
}

.app-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.app-field__label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--app-text);
}

.app-input,
.app-select,
.app-textarea {
    width: 100%;
    min-height: 48px;
    padding: 0 12px;
    border: 1px solid var(--app-control-border);
    border-radius: 12px;
    background: var(--app-surface);
    color: var(--app-text);
    font-size: 15px;
    box-shadow: none;
}

.app-textarea {
    min-height: 120px;
    padding: 12px;
    resize: vertical;
}

.app-input:focus,
.app-select:focus,
.app-textarea:focus {
    outline: 2px solid var(--app-primary);
    outline-offset: 2px;
    border-color: var(--app-primary);
}

.app-input[aria-invalid="true"],
.app-select[aria-invalid="true"],
.app-textarea[aria-invalid="true"] {
    border-color: var(--app-danger);
}

.app-field__help,
.app-field__error {
    font-size: 13px;
    line-height: 1.45;
}

.app-field__help {
    color: var(--app-text-muted);
}

.app-field__error {
    color: var(--app-danger);
}

.app-choice-card {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 48px;
    padding: 8px 12px;
    border: 1px solid var(--app-control-border);
    border-radius: 12px;
    background: var(--app-surface);
    font-size: 15px;
    font-weight: 600;
}

.app-choice-card[aria-pressed="true"],
.app-choice-card:has(input:checked) {
    border-color: var(--app-primary);
    background: var(--app-accent-soft);
    color: var(--app-accent-text);
}

.app-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    border-radius: 8px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
    background: var(--app-surface-soft);
    color: var(--app-text-soft);
    border: 1px solid var(--app-border);
}

.app-badge--success {
    background: var(--app-success-soft);
    color: var(--app-success);
}

.app-badge--warning {
    background: var(--app-warning-soft);
    color: var(--app-warning);
}

.app-badge--danger {
    background: var(--app-danger-soft);
    color: var(--app-danger);
}

.app-badge--info {
    background: var(--app-info-soft);
    color: var(--app-info);
}

.app-alert {
    display: grid;
    gap: 4px;
    padding: 12px 16px;
    border: 1px solid var(--app-border);
    border-radius: 16px;
    background: var(--app-surface);
    font-size: 14px;
}

.app-alert--success {
    border-color: var(--app-success);
    background: var(--app-success-soft);
}

.app-alert--warning {
    border-color: var(--app-warning);
    background: var(--app-warning-soft);
}

.app-alert--danger {
    border-color: var(--app-danger);
    background: var(--app-danger-soft);
}

.app-alert--info {
    border-color: var(--app-info);
    background: var(--app-info-soft);
}

.app-empty-state {
    display: grid;
    justify-items: center;
    gap: 12px;
    padding: 32px 24px;
    border: 1px solid var(--app-border);
    border-radius: 16px;
    background: var(--app-surface);
    text-align: center;
}

.app-empty-state__icon {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
}

.app-empty-state__title {
    margin: 0;
    font-size: 24px;
    font-weight: 700;
}

.app-empty-state__description {
    margin: 0;
    max-width: 52ch;
    font-size: 14px;
    color: var(--app-text-muted);
}

.app-sticky-actions {
    position: sticky;
    bottom: 0;
    display: flex;
    gap: 8px;
    padding: 12px;
    background: var(--app-surface);
    border-top: 1px solid var(--app-border);
    z-index: 10;
}

.app-sticky-actions .app-button {
    min-height: 48px;
}

.app-sticky-actions__hint {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    margin-right: auto;
    color: var(--app-text-muted);
    font-size: 13px;
    line-height: 1.45;
}

@media (max-width: 1024px) {
    .app-sticky-actions {
        bottom: var(--app-mobile-nav-clearance);
    }
}

.app-body--no-bottom-nav .app-sticky-actions {
    bottom: 0;
}

.app-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--app-border);
    border-radius: 16px;
    background: var(--app-surface);
}

.app-table-wrap table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.app-result-card {
    background: var(--app-surface);
    border: 1px solid var(--app-border);
    border-radius: 16px;
    box-shadow: var(--app-shadow-soft);
    overflow: hidden;
}

.app-result-card:hover {
    border-color: var(--app-border-strong);
    box-shadow: var(--app-shadow-strong);
}

.app-result-card__body {
    padding: 12px;
}

.app-result-card__title {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
}

.app-result-card__meta {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--app-text-muted);
}

/* Filter field grid policy. */
.app-filter-grid {
    display: grid;
    gap: 12px;
}

@media (min-width: 1280px) {
    .app-filter-grid--escort {
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }

    .app-filter-grid--dating,
    .app-filter-grid--auto {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) and (max-width: 1279px) {
    .app-filter-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 769px) and (max-width: 1023px) {
    .app-filter-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 768px) {
    .app-filter-grid {
        grid-template-columns: 1fr 1fr;
    }
}

@media (max-width: 480px) {
    .app-filter-grid {
        grid-template-columns: 1fr;
    }
}

/* Results toolbar groups: layout group plus columns group. */
.app-results-toolbar {
    gap: var(--app-space-2);
}

/* Shared results gap. */
.app-results {
    gap: 16px;
}

/* Neutral media frame: images and missing-image content cannot contribute
   intrinsic size. Product CSS supplies the Cards aspect ratio and focal point.
   Rows use the same responsive block size; content can grow independently. */
.app-card-media {
    position: relative;
    min-width: 0;
    overflow: hidden;
}

.app-card-media__fill,
.app-card-media img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    min-height: 0;
}

.app-card-media img {
    display: block;
    object-fit: cover;
}

.app-results[data-layout="rows"] .app-card-media {
    block-size: clamp(9rem, 18vw, 14rem);
    aspect-ratio: auto;
    align-self: start;
}
