* { box-sizing: border-box; }
body { margin: 0; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--slate-50); color: var(--slate-900); }
.container { max-width: 1400px; margin: 0 auto; padding: 30px; border-radius: 12px; background: white; box-shadow: 0 4px 6px rgb(0 0 0 / 10%); }
header { padding-bottom: 20px; border-bottom: 1px solid var(--slate-200); display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
h1 { margin: 0; font-size: 1.6rem; }
.subtitle, .loading, .empty { color: var(--slate-500); }
.subtitle { margin: 12px 0 24px; }
.btn { padding: 10px 18px; border: 0; border-radius: 8px; background: var(--blue-600); color: white; font-weight: 600; cursor: pointer; text-decoration: none; display: inline-block; }
.btn-secondary { background: var(--slate-200); color: var(--slate-900); }
/* `.btn { display: inline-block }` above is an author rule and so
   overrides the UA stylesheet's unqualified `[hidden] { display: none }`
   regardless of specificity -- any .btn element toggled via the `hidden`
   attribute (e.g. #confirm-modal-ok in the delete-blocked confirmation
   dialog) would otherwise stay visually clickable despite `hidden` being
   correctly set. Same root cause as the already-fixed
   air_curtains_project_hub.css:#delete-project-btn issue (F3) -- found in
   independent review to be a same-file, same-bug-class gap that the F3
   fix's own commit had already named this file for without checking it. */
.btn[hidden] { display: none; }
.form-error { margin-top: 8px; color: var(--red-800); }
.form-error:empty { display: none; }
.loading, .empty { padding: 24px 0; text-align: center; }
.empty { display: none; }

/* ---- Toolbar: search + filters + sort + view ---- */
.registry-toolbar { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; margin: 18px 0; }
.registry-toolbar .field { display: grid; gap: 4px; font-size: .82rem; color: var(--slate-600); }
.registry-toolbar input, .registry-toolbar select { padding: 7px 9px; border: 1px solid var(--slate-300); border-radius: 6px; font: inherit; }
#registry-search { min-width: 240px; }
.registry-toolbar .checkbox-field { flex-direction: row; align-items: center; gap: 6px; font-size: .82rem; }
.registry-toolbar .checkbox-field input { width: auto; }

/* "Фильтры" collapse (F4, item 3). Two real-browser behaviours drove this
   design, both confirmed by hand against actual Chromium (not assumed
   from the CSS/HTML spec text):
   1) Content inside a *closed* <details> is reported not-visible/
      not-interactable (checkVisibility(), and so Playwright's own
      actionability checks) regardless of any `display` override on the
      content -- so the desktop-always-usable requirement is met by
      genuinely keeping this <details> `open` (see the matching
      `filtersDesktopQuery`/`syncFiltersDetailsToViewport()` JS in
      templates/air_curtains_projects.html), not by fighting the closed
      state with CSS.
   2) `display: contents` on <details>/<summary> does NOT reliably
      flatten their children into an ancestor flex container -- fields
      rendered out of source order and stacked one-per-row instead of
      wrapping, confirmed by hand. So instead of unwrapping <details>
      into .registry-toolbar's own flex row, the search field keeps its
      own row (first, always visible per the task) and .filters-details
      is a second flex item that always starts a fresh row of its own
      (flex-basis: 100%), with .filters-fields reproducing the identical
      wrap/gap/align rules as its own independent flex row underneath. */
.registry-toolbar .filters-toggle { display: none; }
@media (min-width: 821px) {
    .registry-toolbar .filters-details { display: block; flex: 1 1 100%; }
    .registry-toolbar .filters-fields { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
}

/* Status filter checkbox-dropdown (F4, item 2): same .row-menu/
   .row-menu-toggle/.row-menu-items[hidden] component as the per-row
   action menu (see "Table" section above) -- these rules only add the
   bits specific to hosting it in the toolbar instead of a table cell. */
.registry-toolbar .status-filter-menu { margin-left: 0; }
.registry-toolbar .status-filter-toggle { display: inline-flex; align-items: center; gap: 4px; padding: 7px 9px; }
/* The row-menu component this reuses defaults to `right: 0` (opens
   leftward), which makes sense in its original home -- the rightmost
   "Действия" table column, with room to spare on the left. Here the
   toggle sits near the toolbar's own LEFT edge, so `right: 0` pushed the
   190px-wide panel off the left edge of the viewport entirely (confirmed
   by a real screenshot -- the checkbox labels were visibly clipped).
   `left: 0` opens it rightward instead, which fits. */
.status-filter-items { left: 0; right: auto; display: flex; flex-direction: column; gap: 2px; min-width: 190px; }
.status-filter-items .status-filter-item { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px; cursor: pointer; font-size: .86rem; font-weight: 400; }
.status-filter-items .status-filter-item:hover { background: var(--slate-100); }
.status-filter-items .status-filter-item input { width: auto; }

/* ---- Table ---- */
.data-table th[data-sort-key] { cursor: pointer; user-select: none; }
.data-table td.name-cell { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.data-table tr.registry-row { cursor: pointer; }
.data-table tr.registry-row.missing-required { box-shadow: inset 3px 0 0 var(--amber-500, #f59e0b); }
.missing-badge { display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 999px; background: var(--amber-100, #fef3c7); color: var(--amber-800, #92400e); font-size: .72rem; }
.status-badge { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: .78rem; font-weight: 600; background: var(--slate-200); color: var(--slate-700); }
.status-badge[data-status="ARCHIVED"] { background: var(--slate-300); color: var(--slate-600); }
.status-badge[data-status="IN_PROGRESS"] { background: var(--blue-100, #dbeafe); color: var(--blue-800, #1e40af); }
.status-badge[data-status="DONE"] { background: var(--green-100, #dcfce7); color: var(--green-800, #166534); }
.incoming-cell .incoming-more { color: var(--slate-500); margin-left: 4px; }
.actions-cell { white-space: nowrap; }
.row-menu { position: relative; display: inline-block; margin-left: 6px; }
.row-menu-toggle { cursor: pointer; padding: 4px 8px; border: 1px solid var(--slate-300); border-radius: 6px; background: white; font: inherit; }
.row-menu-toggle[aria-expanded="true"] { background: var(--slate-100); }
.row-menu-items { position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; background: white; border: 1px solid var(--slate-200); border-radius: 8px; box-shadow: 0 8px 20px rgb(0 0 0 / 12%); min-width: 170px; padding: 4px; }
.row-menu-items[hidden] { display: none; }
.row-menu-items button { display: block; width: 100%; text-align: left; padding: 8px 10px; border: 0; background: none; cursor: pointer; border-radius: 6px; font: inherit; }
.row-menu-items button:hover { background: var(--slate-100); }

/* ---- Expand row ---- */
tr.expand-row td { background: var(--slate-50); padding: 14px 18px; }
.expand-requests-table { width: 100%; border-collapse: collapse; }
.expand-requests-table th, .expand-requests-table td { padding: 6px 8px; text-align: left; border-bottom: 1px solid var(--slate-200); font-size: .88rem; }

/* ---- Modal (repurposed .modal/.modal-content scaffold) ---- */
.modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 1000; overflow-y: auto; }
.modal.open { display: block; }
.modal-content { background: white; margin: 60px auto; padding: 24px; border-radius: 12px; max-width: 90%; width: 480px; box-shadow: 0 10px 25px rgb(0 0 0 / 20%); position: relative; }
.modal-content h2 { margin-top: 0; }
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
.close-modal { position: absolute; top: 14px; right: 16px; font-size: 22px; cursor: pointer; color: var(--slate-500); background: none; border: 0; }

/* ---- Create-project panel ---- */
.mini-form { margin: 18px 0 28px; padding: 18px; border: 1px solid var(--slate-200); border-radius: 10px; }
.mini-form h2 { margin: 0 0 14px; font-size: 1.1rem; }
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 14px; }
.form-grid label { display: grid; gap: 4px; color: var(--slate-700); font-size: .88rem; }
.form-grid .full { grid-column: 1 / -1; }
input, textarea, select { font: inherit; }
.mini-form input, .mini-form textarea { width: 100%; padding: 8px 10px; border: 1px solid var(--slate-300); border-radius: 6px; }
.mini-form textarea { min-height: 64px; resize: vertical; }
.form-hint { color: var(--amber-800, #92400e); font-size: .85rem; }

.project-card:focus-visible, .btn:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible, summary:focus-visible {
    outline: 2px solid var(--blue-600); outline-offset: 2px;
}
.form-error[tabindex] { outline: 2px solid var(--red-800); outline-offset: 2px; }

/* ---- Adaptive cards below the nav-collapse breakpoint ---- */
@media (max-width: 820px) {
    .container { padding: 14px; }
    .registry-toolbar { flex-direction: column; align-items: stretch; }

    /* F4 item 3: filter fields (everything except search, which stays
       outside .filters-details and so is unaffected) collapse behind a
       "Фильтры" toggle, closed by default, so the first screen on a phone
       shows the search box + table instead of a wall of filter fields.
       .filters-fields' own display (none while closed, flex/column while
       [open]) is what actually hides/shows it here -- see the base-rule
       comment above (before this @media block) for the real-Chromium
       reason `display: contents` is not used anywhere in this file. */
    .registry-toolbar .filters-details { display: block; width: 100%; }
    .registry-toolbar .filters-toggle {
        display: inline-flex; align-items: center; gap: 6px; width: fit-content;
        margin: 4px 0 0; padding: 8px 14px; border: 1px solid var(--slate-300); border-radius: 6px;
        background: white; font: inherit; font-size: .86rem; font-weight: 600; color: var(--slate-700);
        cursor: pointer; list-style: none; user-select: none;
    }
    .registry-toolbar .filters-toggle::-webkit-details-marker { display: none; }
    .registry-toolbar .filters-toggle::after { content: "\25be"; margin-left: 2px; display: inline-block; transition: transform .15s ease; }
    .registry-toolbar .filters-details[open] .filters-toggle::after { transform: rotate(180deg); }
    .registry-toolbar .filters-details[open] .filters-toggle { background: var(--slate-100); }
    .registry-toolbar .filters-fields {
        display: none; flex-direction: column; align-items: stretch; gap: 10px; width: 100%; margin-top: 8px;
    }
    .registry-toolbar .filters-details[open] .filters-fields { display: flex; }

    .table-container { overflow-x: visible; }
    #registry-table thead { display: none; }
    #registry-table, #registry-table tbody, #registry-table tr, #registry-table td { display: block; width: 100%; }
    #registry-table tr.registry-row {
        border: 1px solid var(--slate-200); border-radius: 10px; margin-bottom: 10px; padding: 10px 12px;
    }
    #registry-table td { border: 0; padding: 4px 0; }
    #registry-table td[data-col="object_name"], #registry-table td[data-col="customer"],
    #registry-table td[data-col="requests"], #registry-table td[data-col="incoming"],
    #registry-table td[data-col="responsible"], #registry-table td[data-col="updated_at"] { display: none; }
    #registry-table td.name-cell { white-space: normal; max-width: none; font-weight: 600; }
    /* Must out-specificity the "#registry-table ... tr { display: block }"
       rule above (ID beats a bare class): a plain "tr.expand-row {display:
       none}" here loses to it, which also defeats the [hidden] attribute's
       own native hiding for the SAME reason (author rules override the UA
       stylesheet's unqualified `[hidden] { display: none }` regardless of
       specificity) -- an expand-row's placeholder "Загрузка…" content was
       visibly rendered below every card at narrow widths until this was
       qualified with #registry-table too. */
    #registry-table tr.expand-row { display: none; }
}
