/* ============================================================================
   SOLA ITSM responsive layer (v4.4.0: responsive-mobile, platform-responsive-mobile)

   Loaded last, after styles.css. Part 1 is the contract every screen builds on
   (breakpoints and reusable primitives); parts 2–5 apply it to the shell, the
   shared components and the views. Each correction names the defect it fixes,
   as measured by e2e-tests/tests/responsive-platform-audit.spec.ts at 15 widths
   (320–1920 px) in English and Arabic.

   Rules for new CSS (CLAUDE.md, "Responsive by default"):
   - Use only the breakpoints below. Desktop-first: `@media (max-width: …)`.
   - Use logical properties (margin-inline-start, inset-inline-end,
     text-align: start) so one rule serves English and Arabic.
   - Prefer the primitives in part 1 to a new media query.
   - Never hide overflow to make a screen "fit": find the element and fix it.
   ========================================================================== */

/* ── Part 1 — Contract ─────────────────────────────────────────────────────

   Breakpoints (max-width, desktop-first):
     xs   480px   narrow phones (320–480): icon-only top-bar action, full-width
                  toolbar controls
     sm   640px   phones: one-column grids and forms, near-full-screen dialogs,
                  stacked tables (`table.responsive-stack`)
     md   768px   tablets in portrait and below: the sidebar becomes a drawer,
                  tables scroll inside their card, tab strips scroll
     lg  1024px   small laptops and landscape tablets: wide two-column layouts
                  become one column
     xl  1280px   desktop: dense report grids relax from 4 to 2 columns
   Same values as tokens.css --bp-* where they overlap (768); JavaScript reads
   the drawer breakpoint through App.isDrawerMode(), never window.innerWidth.

   Primitives (use these in new views instead of writing media queries):
     .sola-page-header  title block + actions; wraps; actions drop below the
                        title when they no longer fit
     .sola-actions      a row of buttons; wraps; on phones each button grows to
                        share the row (primary action stays visible)
     .sola-toolbar      filters/search/sort; wraps; controls grow to fill and
                        go full width under 480px
     .sola-table-wrap   a wide table scrolls inside its own box (alias of
                        .table-container); or put `responsive-stack` on the
                        table to show each row as a card under 640px
     .sola-form-grid    form fields in as many 240px+ columns as fit, one on
                        phones; `.sola-span-all` makes a field span the row
     .sola-auto-grid    cards/stat tiles in as many columns as fit
                        (--sola-grid-min, default 220px), never wider than
                        the screen
     .sola-tabs-scroll  a tab strip that scrolls sideways instead of wrapping
     .sola-truncate / .sola-break   long names, e-mails, URLs and ids
     .sola-split        a main column and a side panel (detail pages); the
                        panel drops under the main column when the CONTENT
                        AREA (not the window) is narrower than 760px, so it
                        works whatever the sidebar state

   Container: .content-area is a size container named `content`. Layouts that
   depend on the space next to the sidebar use `@container content (…)`
   rather than a viewport media query.
   ------------------------------------------------------------------------ */

.content-area { container: content / inline-size; }

.sola-split {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 20px;
}
@container content (max-width: 760px) {
    .sola-split { grid-template-columns: minmax(0, 1fr); }
}

.sola-page-header {
    flex-wrap: wrap;
    row-gap: var(--space-3, 12px);
}
.sola-page-header > :first-child { min-width: 0; flex: 1 1 240px; }

.sola-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

.sola-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 12px;
    align-items: center;
}
.sola-toolbar > * { min-width: 0; }
.sola-toolbar > input,
.sola-toolbar > select,
.sola-toolbar > .form-control,
.sola-toolbar > .form-select,
.sola-toolbar > .sola-select--inline { flex: 1 1 160px; max-width: 100%; }

.sola-table-wrap {
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.sola-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
    gap: 12px 16px;
}
.sola-form-grid > .sola-span-all { grid-column: 1 / -1; }

.sola-auto-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--sola-grid-min, 220px)), 1fr));
    gap: 16px;
}

.sola-tabs-scroll {
    display: flex;
    flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: thin;
}
.sola-tabs-scroll > * { flex-shrink: 0; white-space: nowrap; }

.sola-truncate { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sola-break { min-width: 0; overflow-wrap: anywhere; }

@media (max-width: 640px) {
    .sola-actions > .btn { flex: 1 1 auto; justify-content: center; }
    .sola-page-header > .sola-actions,
    .sola-page-header > :last-child:not(:first-child) { flex: 1 1 100%; }
}
@media (max-width: 480px) {
    .sola-toolbar > input,
    .sola-toolbar > select,
    .sola-toolbar > .form-control,
    .sola-toolbar > .form-select,
    .sola-toolbar > .sola-select--inline,
    .sola-toolbar > .btn { flex: 1 1 100%; }
}

/* The existing header, action and toolbar classes of the views follow the same
   contract, so none of them can push buttons past the screen edge (measured at
   320 px: ticket, asset, CMDB and Settings headers clipped their buttons). */
.page-header, .ticket-header, .asset-header, .card-header, .reports-header,
.webhook-header, .rule-header, .request-header, .release-notes-header,
.my-maintenance-header, .kb-detail-header, .cmdb-type-designer-header,
.cmdb-detail-header, .cmdb-section-header, .assets-page-header,
.cmdb-toolbar, .cmdb-section-toolbar, .toolbar, .filters-bar, .workflow-filters,
.asset-drilldown-toolbar, .chart-header, .mention-card-header {
    flex-wrap: wrap;
    row-gap: 8px;
}
.webhook-actions, .rule-actions, .request-actions, .my-maint-actions,
.mention-card-actions, .cmdb-type-card-actions, .cmdb-toolbar-left,
.cmdb-toolbar-right, .cmdb-tree-actions, .sr-ownership-actions,
.sr-detail-banner-actions, .sr-approval-actions, .cmdb-detail-header-right,
.ticket-actions, .detail-actions {
    flex-wrap: wrap;
    gap: 8px;
}
.page-header > *, .ticket-header > *, .asset-header > *, .card-header > *,
.cmdb-detail-header > *, .assets-page-header > * { min-width: 0; }

/* Inline-styled flex rows that hold buttons (about 150 template literals) wrap
   instead of running off the screen. Rows that must not wrap say so inline
   (`flex-wrap: nowrap`), which wins over this rule. */
.content-area [style*="display:flex"]:has(> .btn, > button),
.content-area [style*="display: flex"]:has(> .btn, > button),
.modal [style*="display:flex"]:has(> .btn, > button),
.modal [style*="display: flex"]:has(> .btn, > button) {
    flex-wrap: wrap;
}

/* Filter rows (the toolbar family): the views' filter bars and inline-styled
   rows of fields follow .sola-toolbar. On phones the controls shared a row at
   whatever width their inline max-width allowed (Team Tasks, Settings › Users);
   they now fill the row, one per line under 480px. */
.kanban-filters, .filters-bar, .workflow-filters, .assets-filters,
.mission-filters, .reports-filters {
    flex-wrap: wrap;
}
/* v4.6.0: the asset filters (now six, with Source and AD status) sit beside the search and wrap
   only when the row is full, instead of pushing the page sideways at tablet widths. The search takes
   the free space (grow 999); when the filters need a line of their own, they fill it. */
.assets-search { flex: 999 1 240px; }
.assets-filter-group { flex: 1 1 auto; flex-wrap: wrap; min-width: 0; justify-content: flex-end; }
@media (max-width: 640px) {
    .kanban-filters > select, .kanban-filters > input, .kanban-filters > .sola-select--inline,
    .content-area [style*="flex"]:has(> select.form-control, > input.form-control) > .form-control,
    .content-area [style*="flex"]:has(> select.form-control, > input.form-control) > select,
    .content-area [style*="flex"]:has(> select.form-control, > input.form-control) > .sola-select--inline {
        flex: 1 1 160px;
        min-width: 0 !important;
        max-width: 100% !important;
    }
}
@media (max-width: 480px) {
    .kanban-filters > select, .kanban-filters > input, .kanban-filters > .sola-select--inline,
    .content-area [style*="flex"]:has(> select.form-control, > input.form-control) > .form-control,
    .content-area [style*="flex"]:has(> select.form-control, > input.form-control) > select,
    .content-area [style*="flex"]:has(> select.form-control, > input.form-control) > .sola-select--inline {
        flex-basis: 100%;
    }
}

/* Collapsible filter bars (js/components/filter-panel.js): on phones only the
   search field and a "Filters" button show until the user opens the panel. */
.sola-filter-toggle { display: none; }
.sola-filter-count { background: var(--primary-color); color: #fff; margin-inline-start: 4px; }
@media (max-width: 640px) {
    .sola-filter-panel > .sola-filter-toggle { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; min-height: 40px; }
    .sola-filter-panel:not(.is-open) > :not(.sola-filter-toggle):not([data-filter-keep]) { display: none !important; }
    .sola-filter-panel > [data-filter-keep] { flex: 1 1 140px !important; min-width: 0 !important; max-width: 100% !important; }
    /* Collapsed: the button and the search share one row (the ≤480px rule in
       styles.css stacks .filters-bar children full width), without the
       search field's visible label. */
    .sola-filter-panel:not(.is-open) { flex-direction: row; flex-wrap: nowrap; align-items: center; }
    .sola-filter-panel:not(.is-open) > * { width: auto; }
    .sola-filter-panel:not(.is-open) [data-filter-keep] > label { display: none; }
    .sola-filter-panel.is-open > .sola-filter-toggle { align-self: flex-start; }
}

/* Long unbroken values (ticket subjects, asset tags, e-mail addresses, URLs,
   test names) wrap inside their box instead of widening the page. */
.content-area h1, .content-area h2, .content-area h3, .content-area h4,
.content-area h5, .content-area p, .content-area dd,
.content-area li, .modal-body p, .modal-body label {
    overflow-wrap: anywhere;
}
/* Table cells use break-word: `anywhere` would also shrink a column's minimum
   width to one letter and squeeze the table instead of letting it scroll. */
.content-area td, .modal-body td { overflow-wrap: break-word; }

/* ── Part 2 — Application shell ───────────────────────────────────────── */

/* .main-content hid everything wider than itself (`overflow-x: hidden`), which
   concealed clipped buttons and let a tab click slide the whole page sideways
   (asset detail at 320 px). As a flex child it now shrinks properly instead,
   and anything still too wide shows up in the audit. */
.main-content { min-width: 0; overflow-x: visible; }
.content-area { max-width: 100%; }

/* The collapsed icon rail is 70px wide but the content was only moved 60px, so
   10px of every page sat under the rail. */
.sidebar.collapsed + .main-content { margin-left: var(--sidebar-width-collapsed); }
[dir="rtl"] .sidebar.collapsed + .main-content { margin-left: 0; margin-right: var(--sidebar-width-collapsed); }

/* The sidebar must scroll its own menu when it grows longer than the screen,
   keeping the language, profile and sign-out controls reachable. */
.sidebar { left: 0; right: auto; height: 100vh; height: 100dvh; }
[dir="rtl"] .sidebar { left: auto; right: 0; }
.sidebar-nav { min-height: 0; overscroll-behavior: contain; }
.sidebar-footer { flex-shrink: 0; }
.nav-item span { min-width: 0; overflow-wrap: anywhere; }

@media (max-width: 768px) {
    /* The sidebar starts collapsed, and the collapsed-state margin outranked the
       mobile "no margin" rule, leaving 60px empty beside the drawer. */
    .sidebar.collapsed + .main-content,
    [dir="rtl"] .sidebar.collapsed + .main-content,
    .main-content,
    [dir="rtl"] .main-content {
        margin-left: 0;
        margin-right: 0;
    }
    /* Drawer: full labels, at most 85% of the screen, and out of the keyboard
       order while closed (it used to be tabbable off-screen). */
    .sidebar { max-width: 85vw; visibility: hidden; transition: transform .25s ease, visibility 0s linear .25s; }
    .sidebar.open { visibility: visible; transition: transform .25s ease, visibility 0s; }
    .sidebar .nav-item { min-height: 44px; }
    body.drawer-open { overflow: hidden; }
}

.content-area { min-height: calc(100dvh - var(--topbar-height)); }
.login-screen { min-height: 100dvh; padding: 16px; }
/* Keep the 420px card from styles.css; only cap it to the screen on small widths. */
.login-container { max-width: min(420px, 100%); }

@media (max-width: 480px) {
    .login-container { padding: 32px 20px; }
}

/* Top bar: page actions sit at the far end in both directions. */
.topbar-page-actions { margin-left: 0; margin-inline-start: auto; }
#notification-badge { right: auto; inset-inline-end: 0; }
.topbar-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

@media (max-width: 768px) {
    .top-bar { gap: 8px; padding-inline: 12px; }
    /* A flex child will not shrink below its content without this, which is
       what pushed the refresh button off the screen. */
    .search-box { min-width: 0; flex: 1 1 0; }
    .top-bar-actions { gap: 6px; flex-shrink: 0; }
    .topbar-page-actions { flex-shrink: 0; }
    /* The page title competes with search on tablets; the active menu entry
       and the page heading already say where the user is. */
    .topbar-title { flex: 0 1 auto; max-width: 30vw; font-size: 16px; }
}

@media (max-width: 640px) {
    .topbar-title { display: none; }
}

@media (max-width: 480px) {
    .top-bar { padding: 0 8px; gap: 6px; }
    .btn-icon, .btn-toggle-sidebar { padding: 8px 10px; min-width: 40px; min-height: 40px; }
    /* Icon-only page action (e.g. "New ticket") on the narrowest phones; the
       label stays available to assistive technology (aria-label set in app.js). */
    .topbar-page-actions .btn { font-size: 0; padding: 8px 10px; min-width: 40px; min-height: 40px; }
    .topbar-page-actions .btn i { font-size: 15px; margin: 0; }
    .search-box input { padding-inline-start: 34px; padding-inline-end: 8px; }
    .search-box i { left: 12px; }
    [dir="rtl"] .search-box i { left: auto; right: 12px; }
}

/* Unread counts on the collapsed rail sit in the corner nearest the content. */
[dir="rtl"] .sidebar.collapsed .nav-badge { right: auto; left: 4px; }

/* Mentions dropdown: never wider than the screen, anchored to the correct edge. */
.mentions-menu { max-width: calc(100vw - 16px); }
[dir="rtl"] .mentions-menu { right: auto; left: 0; }
@media (max-width: 480px) {
    .mentions-menu { position: fixed; top: calc(var(--topbar-height) - 4px); left: 8px; right: 8px; width: auto; max-height: calc(100dvh - var(--topbar-height) - 16px); overflow-y: auto; }
    [dir="rtl"] .mentions-menu { left: 8px; right: 8px; }
}

/* ── Part 3 — Shared components ───────────────────────────────────────── */

/* Toasts. Bootstrap's `.toast:not(.show) { display: none }` outranks
   styles.css's `.toast`, and the app never adds `.show`. */
.toast-container .toast { display: flex; }

.toast-container { right: auto; inset-inline-end: 20px; max-width: calc(100vw - 24px); }
[dir="rtl"] .toast-container { left: auto; right: auto; inset-inline-end: 20px; }
.toast-container .toast { min-width: 0; width: 350px; max-width: 100%; }
.toast-content { min-width: 0; overflow-wrap: anywhere; }
.toast.success, .toast.error, .toast.warning, .toast.info { border-left: none; }
.toast.success { border-inline-start: 4px solid var(--success-color); }
.toast.error { border-inline-start: 4px solid var(--danger-color); }
.toast.warning { border-inline-start: 4px solid var(--warning-color); }
.toast.info { border-inline-start: 4px solid var(--info-color); }

[dir="rtl"] .toast-container .toast { animation-name: slideInRtl; }
@keyframes slideInRtl {
    from { transform: translateX(-100%); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}

@media (max-width: 480px) {
    /* On phones toasts sit at the bottom, clear of the top bar's menu, search
       and action buttons they used to cover (Bootstrap's `width: max-content`
       ignored both insets). */
    .toast-container {
        top: auto;
        bottom: calc(12px + env(safe-area-inset-bottom, 0px));
        inset-inline-end: 12px; inset-inline-start: 12px; width: auto; max-width: none;
    }
    [dir="rtl"] .toast-container { left: 12px; right: 12px; }
    .toast-container .toast { width: auto; }
}

/* Dialog. One shared component, so these rules cover every dialog. */
.modal { max-width: calc(100vw - 32px); max-height: 90dvh; }
.modal.modal-fullwidth { max-height: calc(100dvh - 40px); height: calc(100dvh - 40px); }
.modal-header { gap: 12px; }
.modal-header h3 { min-width: 0; overflow-wrap: anywhere; }
.modal-footer { flex-wrap: wrap; }
.modal-body { min-height: 0; min-width: 0; overscroll-behavior: contain; }
/* Wide tables inside a dialog scroll inside the dialog body's own box. */
.modal-body .table-container,
.modal-body .table-responsive { max-width: 100%; overflow-x: auto; }
#btn-close-modal { min-width: 40px; min-height: 40px; display: inline-flex; align-items: center; justify-content: center; }

@media (max-width: 640px) {
    .modal,
    .modal.modal-large,
    .modal.modal-small,
    .modal.modal-fullwidth {
        width: calc(100vw - 16px);
        max-width: calc(100vw - 16px);
        max-height: calc(100dvh - 16px);
    }
    .modal.modal-fullwidth { height: calc(100dvh - 16px); }
    .modal-header { padding: 14px 16px; }
    .modal-body { padding: 16px; }
    .modal-footer { padding: 12px 16px; gap: 8px; }
    .modal-footer .btn { flex: 1 1 auto; }
    /* Two-column form rows inside dialogs stack. */
    .modal .form-row,
    .modal .row > [class*="col-"] { flex-basis: 100%; max-width: 100%; }
}

/* Form controls: 16px text on touch screens stops iOS Safari zooming the page
   when a field is focused; fields never overflow their column. */
.form-control, .form-select, input, select, textarea { max-width: 100%; }
@media (max-width: 768px) and (pointer: coarse) {
    .form-control, .form-select,
    input[type="text"], input[type="email"], input[type="password"], input[type="search"],
    input[type="number"], input[type="tel"], input[type="url"], input[type="date"],
    input[type="datetime-local"], input[type="time"], select, textarea { font-size: 16px; }
}
input[type="file"] { max-width: 100%; min-width: 0; }

/* Tables. */
th, td { text-align: start; }

/* Tables rendered without a scroll wrapper: up to tablet-landscape width (the
   report tables overflowed at 820px) the table itself scrolls sideways inside
   its card instead of being clipped. Tables already in
   a wrapper, and the stacked-card tables, are left alone. */
@media (max-width: 1024px) {
    .content-area table:not(.responsive-stack):not(.table-container table):not(.cmdb-table-wrap table):not(.table-responsive table):not(.sola-table-wrap table),
    .modal-body table:not(.responsive-stack):not(.table-container table):not(.table-responsive table):not(.sola-table-wrap table) {
        display: block;
        max-width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}
.table-container, .table-responsive, .cmdb-table-wrap { max-width: 100%; }

/* Card tables (table.responsive-stack, labelled by js/components/responsive-ui.js).
   The base card layout is in styles.css; this adds the title line, the action
   row and optional cells. Ids such as INC-2026-04225561 never break mid-way. */
.cell-id, .cell-id * { white-space: nowrap; }
@media (max-width: 640px) {
    table.responsive-stack tr { display: flex; flex-direction: column; background: var(--bg-card); }
    table.responsive-stack td > * { min-width: 0; }
    table.responsive-stack td.cell-primary { order: -1; display: block; text-align: start; font-weight: 600; padding-block: 2px 6px; overflow-wrap: anywhere; }
    table.responsive-stack td.cell-primary::before,
    table.responsive-stack td.cell-actions::before { content: none; }
    table.responsive-stack td.cell-actions { justify-content: flex-end; padding-block-start: 8px; margin-block-start: 4px; border-block-start: 1px solid var(--border-color); }
    table.responsive-stack td.cell-actions .btn { min-width: 40px; min-height: 40px; }
    table.responsive-stack td.cell-optional { display: none; }
    /* Bootstrap tables shade cells for hover and stripes; a card is one surface. */
    table.responsive-stack.table > :not(caption) > * > * { box-shadow: none; background-color: transparent; }
    table.responsive-stack td:not([data-label])::before { content: none; }
    table.responsive-stack td.cell-span { display: block; text-align: center; }
    table.responsive-stack .cell-primary { unicode-bidi: plaintext; }
}

/* Pagination rows wrap and keep their buttons tappable. */
.pagination, .cmdb-pagination, .pager, .pagination-controls { flex-wrap: wrap; row-gap: 8px; }
@media (pointer: coarse) {
    .pagination .btn, .pagination button, .pager button { min-width: 40px; min-height: 40px; }
}

/* Grids. The ≤1024px two-column rule for these grids came later in styles.css
   than the ≤768px one-column rule, so phones kept two columns. */
@media (max-width: 640px) {
    .reports-stats-grid,
    .sla-overview,
    .agent-stats,
    .ticket-meta { grid-template-columns: minmax(0, 1fr); }
}

/* A `1fr` track cannot shrink below the widest unbreakable thing inside it (a
   tab strip, a long id), so the stacked detail layouts were 740px wide on a
   320px phone. `minmax(0, 1fr)` lets the column fit the screen and the wide
   part scroll or wrap inside it. */
/* Ticket and asset detail follow the .sola-split contract: at 820px (tablet
   landscape, collapsed rail) their side panel was pushed 130px off screen. */
.ticket-detail, .asset-detail { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
@container content (max-width: 760px) {
    .ticket-detail, .asset-detail { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 768px) {
    .ticket-detail, .asset-detail, .sr-detail-columns, .cmdb-overview-grid,
    .cmdb-attributes-grid, .kb-articles-grid, .service-grid, .services-grid,
    .assets-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 1024px) {
    .kb-detail { grid-template-columns: minmax(0, 1fr); }
}
.ticket-main, .ticket-sidebar, .asset-main, .asset-sidebar, .kb-detail > *,
.sr-detail-columns > *, .cmdb-content-panel, .cmdb-layout > * { min-width: 0; }

/* Grids laid out in inline styles (25 in the views: dashboard 2fr/1fr panels,
   form rows, `minmax(360px, 1fr)` cards in Teams Progress …) stack on phones.
   None of them is a calendar-like grid that must keep its columns. */
@media (max-width: 640px) {
    [style*="grid-template-columns"] { grid-template-columns: minmax(0, 1fr) !important; }
    .charts-grid,
    .agents-grid,
    .asset-warnings,
    .webhooks-grid { grid-template-columns: minmax(0, 1fr); }
}
.chart-card, .report-stat-card, .card, .stat-card, .stat-info { min-width: 0; }

/* Stat tiles: one per row on phones made four numbers fill two screens. Two
   compact tiles per row from 360px; one on the narrowest phones. */
@media (max-width: 768px) {
    .stats-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); gap: 12px; }
}
/* A tile's icon, number and label share one row; the label wraps instead of
   pushing the tile wider than its column (asset dashboard at 600px). */
.stat-card > * { min-width: 0; }
.stat-card .stat-label, .stat-info p { overflow-wrap: anywhere; }
@media (max-width: 480px) {
    .stat-card { padding: 14px; gap: 10px; }
    .stat-card .stat-icon { width: 40px; height: 40px; font-size: 18px; flex-shrink: 0; }
    .stat-card .stat-value, .stat-card h3 { font-size: 22px; }
}
.chart-card canvas, .card canvas { max-width: 100%; }

/* Inline minimum widths on filter controls (reports, missions, CMDB, settings)
   and the shared combobox. */
@media (max-width: 640px) {
    select[style*="min-width"],
    input[style*="min-width"],
    div[style*="min-width"],
    .sola-combobox,
    .kanban-filters select,
    .kanban-filters input {
        min-width: 0 !important;
        max-width: 100%;
    }
    .filter-group { flex-wrap: wrap; min-width: 0; max-width: 100%; }
    .filter-group select,
    .filter-group input,
    .filter-group > .sola-select--inline { min-width: 0; max-width: 100%; flex: 1 1 140px; }
    .kb-filters .filter-label,
    .kb-filters select { max-width: 100%; }
}
/* Inline fixed widths on controls (e.g. `width:220px` selects in the mission
   filters, `width:420px` pickers) never exceed the screen. */
.content-area select[style*="width"], .content-area input[style*="width"],
.modal select[style*="width"], .modal input[style*="width"] { max-width: 100%; }

/* Tab strips scroll sideways rather than overflow the page. */
@media (max-width: 768px) {
    .assets-page-tabs,
    .tabs,
    .nav-tabs,
    .settings-tabs,
    .cmdb-tabs,
    .asset-detail-tabs,
    .reports-tabs {
        max-width: 100%;
        overflow-x: auto;
        flex-wrap: nowrap;
        scrollbar-width: thin;
    }
    .assets-page-tabs > *,
    .tabs > *,
    .cmdb-tabs > *,
    .asset-detail-tabs > *,
    .reports-tabs > * { flex-shrink: 0; white-space: nowrap; }
}

/* Kanban: columns keep a readable width and the board scrolls. */
@media (max-width: 480px) {
    .kanban-column { min-width: 260px; flex: 0 0 260px; }
}

/* ── Part 4 — Views (only what the primitives above cannot express) ────── */

/* Asset list filters: three fixed 140px selects in a row that would not wrap. */
@media (max-width: 640px) {
    .assets-filters { flex-wrap: wrap; }
    .assets-filter-group { flex-shrink: 1; flex-wrap: wrap; width: 100%; min-width: 0; }
    .assets-filter-group .form-control,
    .assets-filter-group > .sola-select--inline { width: auto; flex: 1 1 120px; min-width: 0; }
    .cmdb-pagination { flex-wrap: wrap; justify-content: center; }
    /* CMDB detail: Back sat beside a three-line title; it goes above it. */
    .cmdb-detail-header-left { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* ── Part 5 — Touch and accessibility ─────────────────────────────────── */

.btn, .btn-icon, .nav-item, .tab-btn { touch-action: manipulation; }
@media (pointer: coarse) {
    /* Approximately 44px targets on touch screens, without inflating the dense
       desktop layout used with a mouse. */
    .btn-icon, .btn-sm, .tab-btn, .assets-tab, .cmdb-tab { min-height: 40px; }
    .btn-icon { min-width: 40px; }
    .content-area input[type="checkbox"], .modal input[type="checkbox"],
    .content-area input[type="radio"], .modal input[type="radio"] { min-width: 20px; min-height: 20px; }
}
.modal:focus { outline: none; }
.btn-toggle-sidebar:focus-visible, .btn-icon:focus-visible, #btn-close-modal:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
#btn-close-modal:focus-visible { outline-color: var(--primary-color); }


/* ── Server-side lists (feature server-side-lists, js/components/server-list.js) ── */
.sola-list-search { position: relative; flex: 1 1 14rem; min-width: 0; }
.sola-list-search > i { position: absolute; inset-inline-start: 12px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); pointer-events: none; }
.sola-list-search > input { padding-inline-start: 36px; }
.sola-sort-btn { display: inline-flex; align-items: center; gap: 6px; padding: 0; border: 0; background: none; font: inherit; font-weight: inherit; color: inherit; cursor: pointer; text-align: start; }
.sola-sort-btn > i { color: var(--text-light); font-size: .85em; }
.sola-sort-btn.is-active > i { color: var(--primary-color); }
.sola-sort-btn:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; border-radius: 4px; }
.sola-list-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; padding-block: 12px; padding-inline: 16px; }
@media (max-width: 640px) {
    .sola-list-footer { justify-content: center; text-align: center; }
    .sola-sort-btn { min-height: 40px; }
}
