/* ============================================================================
   RESPONSIVE — mobile & tablet shell
   Desktop keeps the fixed 244px sidebar. Below the shell breakpoint (900px,
   covering phones and iPad-portrait) the sidebar turns into an off-canvas drawer
   toggled by a topbar hamburger, windows fill the screen, and spacing tightens.
   The per-component breakpoints elsewhere in this file (grids, forms, search
   panes, hero) stay as-is; this block only handles the shell + windows.
   ========================================================================== */

/* Hamburger + drawer scrim live in the DOM always, shown only on mobile. */
.nav-toggle { display: none; }
.topbar-left { display: flex; align-items: center; gap: 12px; min-width: 0; }
.nav-scrim { display: none; }

@media (max-width: 900px) {
  /* ── Topbar ─────────────────────────────────────────────────────────────
     Sticks to the top so the hamburger stays reachable while the page scrolls.
     Opaque fill (not the desktop veil gradient) so content can't bleed through. */
  .topbar {
    position: sticky; top: 0; z-index: 90;
    padding: 11px 16px; gap: 10px;
    background: var(--bg-2); border-bottom: 1px solid var(--border);
  }
  .topbar h1 {
    font-size: 18px; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .topbar-right { gap: 10px; }
  .content { padding: 18px 16px 40px; }

  /* The hamburger reuses `.icon-btn` for its look (see base.html); here it just
     becomes visible and, like the other topbar buttons, grows to a 40px target. */
  .nav-toggle { display: inline-flex; }
  .icon-btn, .nav-toggle { width: 40px; height: 40px; }
  /* The scope dropdown sits in the same row — match the 40px touch target so the
     header buttons line up (it keeps its label + width, only the height grows). */
  .scope-btn { height: 40px; }

  /* Topbar action buttons collapse to icon-only squares once the shell goes to
     the hamburger layout — on a tablet the title + a run of full-text buttons
     (e.g. «Редагувати» + «Локація» + «До списку») otherwise crush each other.
     The label hides and the leading glyph carries the meaning; `title` gives the
     name. `:has(.btn-ico)` guards it so a label-less button keeps its text. */
  .topbar-right .btn:has(.btn-ico) {
    width: 40px; min-width: 40px; height: 40px;
    padding: 0; gap: 0; justify-content: center;
  }
  .topbar-right .btn:has(.btn-ico) .btn-lbl { display: none; }
  .topbar-right .btn-ico { font-size: 19px; line-height: 1; }
  .topbar-right .btn:has(.btn-ico) svg { width: 18px; height: 18px; }

  /* ── Sidebar → off-canvas drawer ─────────────────────────────────────────
     Fixed, parked off the left edge; `html.nav-open` slides it in. It keeps its
     own scroll (nav + user footer) since it's now full-height over the content. */
  .sidebar {
    position: fixed; top: 0; left: 0; z-index: 200;
    width: 280px; max-width: 84vw; height: 100vh; height: 100dvh;
    transform: translateX(-100%);
    box-shadow: var(--shadow); overflow-y: auto;
  }
  /* A shorter brand block, so the drawer spends its height on the sections instead of
     on the mark. On a desktop the sidebar is 100vh of a tall screen and 130px of logo
     costs nothing; in a drawer it was two of the fourteen nav rows. */
  .brand { padding: 14px 18px 12px; }
  .brand-logo { height: 46px; }
  .brand::before { top: 14px; bottom: 12px; }

  /* The drawer scrolls as one column — brand, sections, account card — instead of
     pinning the account card and scrolling the nav inside it. Two reasons, and the
     first is that the desktop arrangement does not survive the move: on a desktop the
     sidebar is a column of a page and the card at its foot is the page's own furniture,
     while in a 844px drawer that card is 146px of *pinned* height and the nav under it
     became a nested scroller — a scrollbar inside a scrollbar, showing no affordance,
     which simply cut the last three sections off. They were «Користувачі», «Ролі та
     права» and «Групи доступу»: the bottom of the «Система» group, i.e. exactly the
     administrative half of the app, unreachable on a phone unless you guessed that the
     strip between the brand and the card could be dragged.
     The card ends up below the last section, which is where the one gesture that
     reveals the sections also lands. */
  .nav { flex: none; overflow: visible; }
  .sidebar .user { margin-top: auto; }
  html.nav-open .sidebar { transform: none; }
  html.nav-open { overflow: hidden; }

  .nav-scrim {
    display: block; position: fixed; inset: 0; z-index: 150;
    background: var(--backdrop);
    opacity: 0; pointer-events: none; transition: opacity .22s ease;
  }
  html.nav-open .nav-scrim { opacity: 1; pointer-events: auto; }

  /* ── Windows go full-screen so everything fits on a small viewport ───────── */
  .modal-backdrop { padding: 0; align-items: stretch; }
  .modal {
    max-height: none; height: 100vh; height: 100dvh;
    border-radius: 0; border-left: 0; border-right: 0;
  }
  .win-full { padding: 0; }
  .win-full .modal,
  .win-lg .modal, .win-md .modal, .win-sm .modal, .win-xs .modal,
  .search-modal,
  .modal-backdrop > .modal.sub-picker,
  .modal-backdrop > .modal.win-picker,
  .win-screen {
    max-width: none; width: 100%; height: 100dvh; max-height: none; align-self: stretch;
  }
  .search-modal { padding: 16px; }

  /* Tighter table cells so more columns fit before the wrap needs scrolling. */
  th, td { padding: 9px 11px; }
}

/* Person list: below this width the 10-column table degrades (endless horizontal
   scroll), so swap it for the stacked card view and drop the desktop-only bulk
   toolbar entirely — its checkboxes live in the now-hidden table. */
@media (max-width: 720px) {
  .person-cards, .list-cards { display: flex; }
  .table-wrap.has-card-fallback { display: none; }
  .bulk-bar { display: none !important; }
}

/* Phones: the title used to give way always, which on the pages that carry one or no
   action (a form, an editor, «Мій обліковий запис») left a topbar holding a hamburger,
   a search glyph and nothing that said where you were — the drawer marks the current
   *section*, and «Новий обліковий запис» is not a section. What makes keeping it safe
   is that a crowded row now *truncates* the heading instead of shoving the buttons
   around: `.topbar-right { flex: none }` (`layout/shell.css`) plus the h1's ellipsis in
   the ≤900 block above. So a busy page shows «Військовослуж…» rather than nothing.
     One control is still too wide to share the row at all — the 190px scope picker —
   and it is named outright. Deliberately *not* «does this topbar look crowded»,
   which CSS can only ask by counting `.topbar-right`'s children: every action in every
   `{% block topbar_actions %}` sits behind an `{% if %}`, so that count is a fact about
   the viewer's permissions and about the row's data, not about the page. It made the
   access-group editor's own title appear when the group had holders (no «Видалити»
   button) and vanish when it had none — one screen, one user, chrome flipping on a
   query. */
@media (max-width: 560px) {
  .topbar:has(.scope-btn) h1 { display: none; }
  .scope-btn { max-width: 190px; }

  /* Filter-toolbar controls take the row rather than their desktop max-widths, so
     each is comfortably tappable — except the narrow ones, which pair up: a select
     reading «Всі дії» does not need 358px, and the journal's six filters as six full
     rows pushed the first entry off the screen entirely. A 40% basis is what makes
     them pair: two fit a row and grow to exact halves, three cannot, for any gap this
     toolbar might carry — where `calc(50% - <half the gap>)` would have to be edited
     in step with the `gap` a line above it. */
  .toolbar { gap: 10px; }
  .toolbar > .w-search,
  .toolbar > .w-filter-lg,
  .toolbar > .range-inputs { flex: 1 1 100%; max-width: none; }
  .toolbar > .w-filter { flex: 1 1 40%; max-width: none; }
  /* The от/до pair takes a row and splits it, rather than each date pairing with
     whatever select happened to precede it. `.range-inputs input { flex: 1 }` already
     halves it; only the desktop 150px cap has to go. */
  .range-inputs > .w-date { max-width: none; }
  .actions { flex-wrap: wrap; }
  .actions .btn { flex: 1 1 auto; justify-content: center; }

  /* Tighter still than the ≤900 step. What is left on screen at this width is only
     the tables carrying no `has-card-fallback` — every wide one is swapped for cards by
     the ≤720 block above — and there are three: the subdivision card's «Локації» and
     «Дочірні підрозділи» (three columns that miss fitting by a dozen pixels and hand
     back a horizontal scrollbar for a header cut at «ЗАРАЗ ТУ|Т») and the import
     report's skipped rows. 3 cells × 4px is what they were short of. Everything wider
     than that has cards instead: a table that needs more than a padding step needs the
     `has-card-fallback` opt-in, which is the call the muster report's «Підрозділи»
     roll-up had been missing. */
  th, td { padding: 8px 9px; }
}
