/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE FOUNDATION — the shared surfaces (header, menus, modals, Home,
   Create Table, La Esquina, Rules, footers).

   Loaded LAST on every player-facing page, so it can adjust the pages above it
   on source order alone. There is no `!important` in this file and no new
   dependency; it is ordinary CSS that happens to be read after everything else.

   ── ONE breakpoint vocabulary ────────────────────────────────────────────────
   Capicúa had accumulated ten different widths (460, 480, 520, 560, 600, 620,
   640, 720, 760, 860). This file does not add an eleventh set: it reuses the two
   that already carry most of the weight and names what they mean, and everything
   new is expressed in terms of them.

     --bp-narrow : 430px   a small phone held in one hand (320…430)
     --bp-phone  : 620px   a phone, any phone — the width the app already uses
     --bp-wide   : 900px   below this the GAME uses its own mobile canvas
                           (see css/game-mobile.css + js/viewport-scale.js)

   Custom properties cannot be used inside a media query, so the numbers are
   written out at each @media; the variables exist so the intent is stated once
   and so JS can read the same number rather than hard-coding its own copy.

   ── Safe areas ───────────────────────────────────────────────────────────────
   env(safe-area-inset-*) resolves to 0px on every device that has no notch, home
   indicator or rounded corner, so these tokens are free on ordinary screens and
   never add padding where none is needed. The fallback keeps them valid in any
   browser that does not know env() at all.
   ══════════════════════════════════════════════════════════════════════════ */
:root {
  --bp-narrow: 430px;
  --bp-phone: 620px;
  --bp-wide: 900px;

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);

  /* The comfortable minimum for a primary control. Not a rule about dominoes —
     a domino keeps its own proportions (see the rack in game-mobile.css); this
     is for the chrome a finger has to hit: burgers, closes, tabs, send. */
  --tap: 44px;
}

/* ═══ SHARED: the persistent site header ═══════════════════════════════════
   The same markup serves Home (inline in index.html) and the pages built by
   js/siteHeader.js, so one set of rules covers both. Sizes only — colour,
   typography and the menu's slide-in behaviour are untouched. */
@media (max-width: 620px), (max-height: 560px) {
  #siteNav .nav-burger,
  #siteNav .side-close {
    min-width: var(--tap); min-height: var(--tap);
    display: inline-flex; align-items: center; justify-content: center;
  }
  #siteNav .nav-lang,
  #siteNav .nav-login,
  #siteNav .nav-link { min-height: var(--tap); }
  #siteNav .nav-link { display: inline-flex; align-items: center; }
  /* The menu is a list of destinations a thumb has to land on; 39px was under
     the comfortable minimum for every one of them. */
  #siteNav .side-item { min-height: 48px; }

  /* The drawer itself: clear of the notch at the top and the home indicator at
     the bottom, and clear of a curved left edge. */
  #siteNav .side-menu {
    padding-top: calc(12px + var(--safe-t));
    padding-bottom: calc(12px + var(--safe-b));
    padding-left: calc(10px + var(--safe-l));
  }
  /* A sticky header sits under the status bar on a notched phone. */
  #siteNav .top-nav { padding-top: var(--safe-t); }
}

/* ═══ SHARED: footers ══════════════════════════════════════════════════════ */
@media (max-width: 620px) {
  .foot-link {
    display: inline-flex; align-items: center; min-height: 40px; padding: 4px 10px;
  }
  .home-footer, .es-foot { padding-bottom: calc(14px + var(--safe-b)); }
}

/* ═══ HOME ═════════════════════════════════════════════════════════════════
   The update banner was the one element on the homepage that pushed the page
   wider than the phone: at 320px its chips and the 52px corner it reserves for
   the close button together needed 323px, which is a horizontal page scroll for
   three pixels. The banner already stacks at 640px; this only lets its contents
   wrap instead of insisting on their own minimum width. */
@media (max-width: 620px) {
  .update-banner { padding: 0 12px; }
  .ub-inner { padding-right: 46px; }
  .ub-main, .ub-body, .ub-list { min-width: 0; max-width: 100%; }
  .ub-list > span, .ub-title, .ub-label,
  .ub-badge { overflow-wrap: anywhere; white-space: normal; }
  .ub-btn { min-height: var(--tap); display: inline-flex; align-items: center; justify-content: center; }
}
/* The atmosphere layer is `position: fixed; inset: 0`, so it is sized by the
   initial containing block — which a browser grows to the widest content on the
   page. It therefore REPORTS an overflow it did not cause and, worse, keeps one
   alive once anything else has caused one. Pinning it to the viewport breaks
   that feedback loop; it is a decorative, pointer-events:none wash either way. */
.home-atmos { width: 100vw; max-width: 100%; }

@media (max-width: 620px) {
  /* Home's job on a phone is: say what this is, then Play. Excess vertical air
     between those two pushed the primary action under the fold. */
  .home-hero { padding-top: 22px; padding-bottom: 18px; }
  .home-cta { gap: 10px; }
  .home-btn { min-height: 52px; }
}

/* ═══ CREATE TABLE (the setup dock) ════════════════════════════════════════
   The dock is already a full-screen page below 860px (sala.css). What it lacked
   was thumb-sized controls and room for the on-screen keyboard. */
@media (max-width: 860px) {
  .setup-panel {
    padding-top: calc(22px + var(--safe-t));
    padding-bottom: calc(22px + var(--safe-b));
    /* The panel is `position: fixed; inset: 0` — without its own scroll the
       bottom of a long form (CREAR MESA included) is simply unreachable once
       the keyboard opens. */
    overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  }
  .setup-tab { min-height: var(--tap); }
  .setup-close {
    min-width: var(--tap); min-height: var(--tap);
    display: inline-flex; align-items: center; justify-content: center;
  }
  /* Segmented choices (opponents, privacy, turn time, bot difficulty, spectators,
     +20 bonus) and the solo difficulty row. `.seg` wraps rather than squeezing
     four labels — "Experto"/"Expert" and "+20 puntos"/"+20 points" are the two
     that clipped first, and they clip at different widths in each language. */
  .seg { flex-wrap: wrap; }
  .seg-btn, .diff { min-height: var(--tap); }
  .setup-field input, .setup-field select { min-height: var(--tap); font-size: 16px; }
  .code-field { min-height: var(--tap); font-size: 16px; }
  .setup-primary, .setup-secondary, .setup-ghost { min-height: 48px; }
  .mesa-share-btn { min-height: var(--tap); }
}
/* 16px is not a type choice — it is the threshold below which iOS Safari zooms
   the page when a field takes focus, which leaves the player looking at a
   magnified form they then have to pinch back out of. */

/* ═══ LA ESQUINA ═══════════════════════════════════════════════════════════ */
@media (max-width: 620px) {
  .es-chip, .es-status-btn, .es-cta-primary, .es-cta-secondary, .esp-action {
    min-height: var(--tap);
  }
  /* The ⓘ that opens a table's details is the ONLY way to see them on touch
     (hover and focus-within, the other two paths, need a pointer or a keyboard),
     so it is the last control on the page that should be hard to hit. */
  .esp-info { width: var(--tap); height: var(--tap); font-size: 15px; }
  .es-foot { padding-bottom: calc(16px + var(--safe-b)); }
  .es-nav { padding-top: var(--safe-t); }
}

/* ═══ RULES ════════════════════════════════════════════════════════════════
   The page is already responsive at 720/520. What it needs on a phone is a
   contents strip a thumb can use and examples that wrap instead of overflowing. */
@media (max-width: 620px) {
  /* The contents strip is a row of jump links — the page's only navigation. */
  .rule-jump { min-height: var(--tap); display: inline-flex; align-items: center; }
  .rules-main { padding-bottom: calc(40px + var(--safe-b)); }
  /* Worked examples are the one place the Rules page sets its own measure. */
  .rule-example { max-width: 100%; overflow-wrap: anywhere; }
}

/* ═══ SHARED MODALS AND PANELS ═════════════════════════════════════════════
   Three overlays carry every dialog in the product — .modal-overlay (login /
   register and the online-play gate), .player-modal (the player card) and
   .ph-modal (the Profile Hub: profile, achievements, avatar picker, badges).
   They are adapted together rather than copied: no mobile-only modal is
   introduced anywhere, and each keeps its own identity.

   All three are `position: fixed; inset: 0; display: flex`, so it is the same
   three changes each time: let the card use the full width, cap it to the
   VISIBLE viewport (dvh tracks the browser's collapsing toolbar, which vh does
   not), and scroll inside the card instead of taking the page along. */
@media (max-width: 620px) {
  .modal-overlay, .player-modal, .ph-modal {
    align-items: flex-start;
    padding: calc(14px + var(--safe-t)) 10px calc(14px + var(--safe-b));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .modal-card, .player-modal-card, .ph-panel {
    width: 100%;
    max-width: 100%;
    max-height: calc(100dvh - var(--safe-t) - var(--safe-b) - 28px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  /* The player card is authored at 340px and then magnified 1.35x so it reads
     across a desktop table. On a 390px phone that asks for 459px of width — a
     horizontal page scroll produced by a single element. The card is already
     full-width here, so the magnifier has nothing left to do; dropping it costs
     the phone nothing and leaves the desktop scale-up exactly as it is. */
  .player-modal-card { transform: none; width: 100%; }

  /* Close controls. All three are absolutely positioned inside a card that now
     scrolls, so scrolling down carried the close out of reach — on the one screen
     size where there is nowhere else to tap. Fixing them to the viewport puts
     them back over the card's top-right corner (the card is full-width and starts
     at the overlay's top padding here, so that corner is a known place) and keeps
     them there for the whole scroll. */
  .modal-close, .pm-close, .ph-close {
    position: fixed;
    top: calc(var(--safe-t) + 22px);
    right: calc(var(--safe-r) + 20px);
    z-index: 5;
    width: var(--tap); height: var(--tap); padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
  }

  .modal-card input, .modal-card select, .auth-input { min-height: var(--tap); font-size: 16px; }
  .modal-card button.primary, .auth-panel button, .auth-tab { min-height: var(--tap); }
}

/* The avatar picker's caption was the one hover-only reveal left in the product.
   Every cell is a real <button>, so a tap focuses it — `:focus-within` is
   therefore the touch path as well as the keyboard one, with no JS and no second
   interaction model to maintain. Desktop hover is untouched. */
.ph-avatar-cell.earned:focus-within .ph-avatar-tip { display: flex; }

/* ═══ REDUCED MOTION ═══════════════════════════════════════════════════════
   The one transition this pass introduces — the game's info drawer — declares
   its own reduced-motion path beside it in game-mobile.css. This is the backstop
   for the sliding panels that were already here. */
@media (prefers-reduced-motion: reduce) {
  .side-menu, .player-panel { transition: none; }
}
