  /* =========================================================================
     responsive.css — mobile / narrow-viewport layer (P0).
     Loaded LAST in index.html so these equal-specificity rules win the cascade
     over the per-component sheets. Additive only: no desktop rule above the
     breakpoints is changed, so behaviour ≥641px is identical to before.
     Breakpoints: 640px (shell rail → top bar), 560px (tile grids / key-value).
     ========================================================================= */

  /* Modals never touch the screen edge on narrow viewports. min() leaves the
     480px desktop cap intact (viewport ≥504px) and adds 12px side gutters below
     that. Intentionally-wide modals use a more specific selector and still win.
     .fs-picker is NOT a .modal (own .fs-picker-back), so it is unaffected. */
  .modal { max-width: min(480px, calc(100vw - 24px)); }

  /* Mobile nav trigger (hamburger) — hidden on desktop; phones show it below. */
  .nav-trigger { display: none; }

  /* Phones — portrait (≤640px) AND landscape (short viewport, any width, since a
     phone rotated to landscape is wide but very short). Both get the compact top
     bar + dropdown menu so the nav never eats horizontal/vertical space. */
  @media (max-width: 640px), (orientation: landscape) and (max-height: 520px) {
    /* The 156px sidebar rail collapses into a sticky top header: logo on its
       own line (top-left), then the menu buttons as one full-width row. */
    /* APP-SHELL: на мобиле портал — это фиксированный кадр в 100dvh, БЕЗ общей
       прокрутки body. Скроллится только контент (.main) и собственные панели.
       Так контент не «вылезает» за экран целиком — он помещается, а длинное
       листается ВНУТРИ .main. (Не скрываем скролл — его просто нет на body.) */
    html, body { height: 100%; overflow: hidden; }
    .app {
      grid-template-columns: minmax(0, 1fr);  /* min:0 — колонка НЕ растёт до min-content детей (иначе cover-SVG раздувает .main/.side шире экрана) */
      grid-template-rows: auto 1fr;   /* строка1 = top-bar (.side), строка2 = .main */
      height: 100dvh; min-height: 0;
    }
    /* .main — единственный вертикальный скролл-контейнер на мобиле. */
    .main {
      overflow-y: auto; overflow-x: hidden;
      -webkit-overflow-scrolling: touch;
      min-height: 0; min-width: 0; max-width: 100%;
    }
    /* The 156px sidebar rail collapses into a sticky top header (flex column):
       row 1 = logo + plus balance (.brand-row), row 2 = the full-width nav. */
    .side {
      position: sticky; top: 0; z-index: 60;
      width: 100%; height: auto; min-width: 0; max-width: 100%; box-sizing: border-box;
      flex-direction: column; align-items: stretch; gap: 8px;
      /* Respect the notch / status bar in standalone PWA mode (env() is 0 on
         non-notched devices, so max() keeps the normal 8/12px otherwise). */
      padding: max(6px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right))
               6px max(12px, env(safe-area-inset-left));
      border-right: 0; border-bottom: 1px solid var(--border);
      overflow: visible;   /* let the .nav dropdown panel spill below the bar (base shell.css clips it) */
    }
    /* Logo (left) + plus balance (right) share one row. .brand-row is
       display:contents on desktop (see shell.css), so this only kicks in here. */
    .side .brand-row {
      display: flex; align-items: center; justify-content: space-between;
      gap: 10px; width: 100%;
    }
    .side .brand-row .brand { padding: 0; margin: 0 auto 0 0; }  /* push balance+burger to the right */
    /* Hide the «WF Platform» wordmark on phones — keep just the logo mark — so the
       category dropdown + hamburger fit on the one compact row without overflow. */
    .side .brand-row .brand .brand-name { display: none; }
    .side .brand-row .brand-balance { margin: 0; flex: 0 0 auto; }
    /* Compact hamburger trigger — lives in the brand row (right of logo+balance),
       icon-only so the bar stays ONE row (saves vertical space, esp. landscape). */
    .side .nav-trigger {
      display: flex; align-items: center; justify-content: center;
      flex: 0 0 auto;
      width: 40px; height: 40px;
      padding: 0;
      background: transparent;
      border: 1px solid var(--border-2, var(--border));
      border-radius: var(--r-md, 10px);
      color: var(--text);
      cursor: pointer;
    }
    .side .nav-trigger-ic { display: flex; }
    .side.nav-open .nav-trigger { border-color: rgba(110, 150, 135, 0.6); }

    /* Catalog category dropdown lifted into the brand row (catalog.js moves the
       node here on phones) — a compact pill next to the burger; its menu drops
       below the bar (.side has overflow:visible). Overrides the in-.main sticky
       layout from catalog.css. */
    .side .brand-row .cat-select {
      position: relative; top: auto; z-index: auto;
      display: block; margin: 0;
      flex: 0 1 auto; min-width: 0; max-width: 150px;
    }
    .side .brand-row .cat-select-trigger {
      min-height: 34px; padding: 0 24px 0 10px;
      font-size: 13px; font-weight: 600;
    }
    .side .brand-row .cat-select-label {
      text-align: left;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .side .brand-row .cat-select-chev { right: 9px; }
    .side .brand-row .cat-select-menu {
      left: 0; right: auto; min-width: 200px; max-width: 80vw;
      z-index: 80;
    }

    /* The nav itself becomes a vertical dropdown panel anchored under the bar,
       hidden until the trigger opens it. max-height + scroll so it always fits —
       critical in landscape where the viewport is short (≈13 items). */
    .side .nav {
      grid-column: 1 / -1;
      position: absolute;
      top: calc(100% + 6px);
      left: max(12px, env(safe-area-inset-left));
      right: max(12px, env(safe-area-inset-right));
      display: none;            /* shown only when .side.nav-open */
      grid-auto-flow: row;
      grid-template-columns: 1fr;
      gap: 2px;
      padding: 6px;
      background: var(--surface-2, #1c2128);
      border: 1px solid var(--border-2, var(--border));
      border-radius: var(--r-md, 10px);
      box-shadow: var(--shadow-card, 0 12px 30px rgba(0, 0, 0, 0.5));
      max-height: 70vh; overflow-y: auto;
      -webkit-overflow-scrolling: touch;
      z-index: 70;
    }
    .side.nav-open .nav { display: grid; }
    /* Dropdown rows: icon + label, left-aligned, comfortable tap target. */
    .side .nav .icon-btn {
      aspect-ratio: auto;
      display: flex; align-items: center; justify-content: flex-start;
      gap: 12px;
      width: 100%; min-height: 44px;
      padding: 0 12px;
      text-align: left;
    }
    .side .nav .icon-btn > svg { margin: 0; display: block; flex: 0 0 auto; }
    .side .nav-label { display: none; }                  /* brand-balance «плюсиков» и т.п. */
    .side .nav .icon-btn .nav-label { display: inline; } /* but DO show the item labels in the dropdown */
    .side .side-toggle { display: none; }
    /* The anon-nudge block does not fit the compact bar — hidden on mobile;
       the same prompt still lives in Settings → Profile. */
    .side .anon-nudge-badge { display: none; }
    /* Reclaim horizontal space lost to the desktop 36px gutters; add the
       bottom/side safe-area insets (home indicator, landscape notch). */
    .main {
      padding: 16px max(14px, env(safe-area-inset-right))
               calc(48px + env(safe-area-inset-bottom)) max(14px, env(safe-area-inset-left));
    }
  }

  /* Tablet (641–768px, tall enough to NOT be a landscape phone): sidebar goes
     icon-only. min-height:521 excludes landscape phones — those use the dropdown
     from the phones block above (which must win the cascade at these widths). */
  @media (min-width: 641px) and (max-width: 768px) and (min-height: 521px) {
    .side .nav-label { display: none; }
    .side .anon-nudge-badge { display: none; }
    .app.nav-collapsed .side .nav,
    .side .nav {
      grid-template-columns: none;
      grid-auto-flow: column;
      grid-auto-columns: minmax(0, 1fr);
    }
    .side .nav .icon-btn {
      aspect-ratio: 1 / 1;
      display: grid;
      place-items: center;
      gap: 0;
      padding: 0;
    }
    .side .side-toggle { display: none; }
  }

  @media (max-width: 560px) {
    /* Tile grids: 240/280px min-cells overflow a 360px screen → shrink so two
       tiles fit side by side. Also helps the .my-grid fullscreen ad picker. */
    .grid-games, .my-grid {
      grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
      gap: 12px;
    }
    /* `1fr`/`auto` tracks honour a child's min-content and can push a grid wider
       than its container (→ horizontal overflow, clipped off the right). Letting
       the tiles shrink below their content min guarantees the row never overflows
       the viewport on phones. */
    .grid-games > *, .my-grid > *, .cat-row-grid > * { min-width: 0; }
    /* Catalog: one game per row on narrow screens (my-games stays 2-up). */
    .my-grid[data-cat-grid] { grid-template-columns: 1fr; }
    /* Game-detail key/value: the fixed 200px label column collapses to stacked
       rows so values stop getting crushed on a phone. */
    .kv { grid-template-columns: 1fr; gap: 2px 0; }
    .kv .k { margin-top: 6px; }

    /* "New game" create row: 180px paste/drop tiles + the 240px engine tile sit
       in a flex row that overflows a phone — wrap and let each go full width. */
    .paste-screen-top { flex-wrap: wrap; gap: 12px; min-height: 0; }
    .huge-paste, .drop-zone { width: 100%; height: 140px; }
    .game-new-engine-tile { width: 100%; min-width: 0; max-width: none; height: auto; min-height: 96px; }
  }

  /* =========================================================================
     Touch devices (no real hover). Fixes two P1 problems:
       1) Tile/card controls are opacity:0 until :hover on desktop, so on touch
          they are invisible/unreachable — reveal them permanently.
       2) A tap can leave the desktop :hover lift (translateY) stuck — neutralize
          it. Also bump the main tile controls to a 44px touch target.
     (trash stays gated behind body.ctrl-on — an intentional desktop power mode.)
     ========================================================================= */
  @media (hover: none) {
    .my-tile .frame .play-fs,
    .my-tile .frame .tile-admin-btn,
    .my-tile .frame .game-act-btn,
    .game-card .game-act-btn,
    .inv-card .sell-btn { opacity: 1; }

    .my-tile:hover, .game-card:hover, .inv-card:hover { transform: none; }

    .my-tile .frame .play-fs,
    .my-tile .frame .tile-admin-btn,
    .my-tile .frame .game-act-btn,
    .game-card .game-act-btn { width: 44px; height: 44px; }
  }

  /* Phones (portrait): ONE game card per row — for the main pool grid AND the
     curated featured rows (cat-row--1/2/3), so the whole catalog is single-column.
     Landscape phones get 2 — see the landscape block below (later → wins). The
     cat-row selectors match catalog.css's specificity; responsive.css loads last. */
  @media (max-width: 640px) {
    .grid-games,
    .cat-row--1 .cat-row-grid,
    .cat-row--2 .cat-row-grid,
    .cat-row--3 .cat-row-grid { grid-template-columns: 1fr; }
  }

  /* (Removed) The old horizontally-scrolling icon bar at ≤640px — replaced by the
     hamburger + vertical dropdown panel in the phones block above. */

  /* Landscape phones: trim the top bar further — vertical space is scarce here,
     so shave the padding and shrink the burger a touch (comes AFTER the phones
     block so it overrides the 6px padding / 40px trigger). */
  @media (orientation: landscape) and (max-height: 520px) {
    .side {
      padding-top: max(4px, env(safe-area-inset-top));
      padding-bottom: 4px;
      gap: 4px;
    }
    .side .nav-trigger { width: 34px; height: 34px; }
    /* Landscape phones: TWO game cards per row (portrait is 1) — pool + featured. */
    .grid-games,
    .cat-row--1 .cat-row-grid,
    .cat-row--2 .cat-row-grid,
    .cat-row--3 .cat-row-grid { grid-template-columns: repeat(2, 1fr); }
  }

  /* P0 MUST stay last — iOS Safari zoom fix: inputs at <16px trigger auto-zoom.
     Placed at the end of the cascade so no per-component rule can override it. */
  @media (max-width: 768px) {
    input, textarea, select { font-size: 16px; }
  }
