/* css/main/bottom-nav.css — part 15/30 of the app styles (was css/main.css; loaded in this order by index.html). */
      /* Bottom navigation — in the body's flow (which is flex column).
         We don't use position:fixed so that .content shrinks
         automatically without needing artificial paddings that
         create empty scrollable areas. Body has a centered max-width
         of 480px, so the bottom-nav ends up where it should without having to
         calculate safe-areas manually. */
      /* ⛔ The body of a notice MUST be able to scroll. Without this, a
         four-paragraph message on an iPhone gets cut off and what overflows
         doesn't exist for the user: no bar, no hint. Santi spent a whole afternoon
         unable to read the line that explained why a
         recovery failed, because it was at the end of the text (2026-08-10). It affects
         ALL the long notices in the app, not just that one. */
      .modal .confirm-msg {
        max-height: 52vh;
        overflow-y: auto;
        overscroll-behavior: contain;
      }

      /* Wait spinner. The app had none: long processes showed
         nothing and looked like a hang (recovering the identity takes
         several seconds of derivation). Respects prefers-reduced-motion. */
      .tl-spin {
        width: 30px; height: 30px; border-radius: 50%;
        border: 3px solid var(--border);
        border-top-color: var(--accent);
        animation: tl-spin 0.9s linear infinite;
      }
      @keyframes tl-spin { to { transform: rotate(360deg); } }
      @media (prefers-reduced-motion: reduce) {
        .tl-spin { animation-duration: 3s; }
      }

      /* ── Keyboard open: what isn't the form collapses ─────────────────────
         ⛔ It only kicks in on iOS. The class is set by `_applyAppH`
         (js/app.js) MEASURING how much the keyboard covers; on Android the layout already
         shrinks by itself and that measure gives 0, so none of this applies there.

         The problem: the competition wizard is a column with a shortcut bar to
         catalogs, a step header and the app's button bar. With the
         keyboard taking half the screen, the field you were filling in was left
         with a one-centimeter strip and you had to drag around
         blindly to know which field you were in (iPhone, 2026-08-10).

         What is NOT needed while typing is hidden: the app's navigation and the
         shortcuts to catalogs. ⛔ The wizard's own button bar
         (Back / Next / Save) is NOT touched: hiding it would leave the
         user locked in the form with no way to advance or leave. */
      body.tl-teclado .bottom-nav { display: none; }
      body.tl-teclado #view-wizard-cv > .filter-bar { display: none; }

      .bottom-nav {
        flex-shrink: 0;
        /* ⛔ `min-height` AND NOT `height`, even though today it changes NOTHING here.
           ⚠️ CORRECTION the same day: it was added believing the iPhone
           home indicator gap was being deducted from inside. It was NOT
           so — this app doesn't carry `viewport-fit=cover`, so iOS
           places it inside the safe area on its own and `env(safe-area-inset-bottom)`
           is ZERO. The bar measures 60 px and reaches the edge, which is exactly what
           Santi saw and I denied.
           It is kept because it is the safe way: with a fixed `height` and
           `box-sizing: border-box` —global in this sheet—, the day someone
           adds `viewport-fit=cover` to the app the buttons would silently narrow
           down to 26 px, below the touch minimum. With `min-height`,
           that day the bar grows instead of eating its content. */
        min-height: 60px;
        background: var(--surface);
        border-top: 1px solid var(--border);
        display: flex;
        z-index: 19;
        padding-bottom: env(safe-area-inset-bottom, 0);
        /* With the UI size enlarged the buttons grow and may not fit
           across: we allow horizontal scroll (at 1× they fill with flex:1
           and no bar appears). */
        overflow-x: auto;
      }
      /* Profile lock: with no profile created we hide the bottom button bar and
         the header hamburger. Only the My Data screen stays operational
         until the user creates their profile. */
      body.tl-profile-locked .bottom-nav,
      body.tl-profile-locked #hdrMenuBtn { display: none !important; }
      /* ⛔ 6.3 (Santi, 2026-09-16): a MINOR has no chat, and the option isn't shown.
         The class is set by `_tlSetIdentityFromSelf` (js/app.js); the bottom bar
         filters it when painting. Hiding it is courtesy: the server and
         the database rules close it. */
      body.tl-chat-menor .drawer-item[data-go="chat"] { display: none !important; }
      /* ⛔ INSIDE A CONVERSATION THERE IS NO BUTTON BAR. Santi, 2026-08-28:
         "when we're inside a chat the bottom button bar gets in the way, it should
         be removed so the chat takes up the whole screen". That is 60 px of the
         only screen where the space IS the product, and there that navigation isn't
         used: you leave a conversation through «back».
         ⛔ The class is removed by the chat itself from ALL the screens that aren't
         the conversation —the tree, the loading and the errors—, not just from
         «back»: a navigation bar that disappears and doesn't return leaves the app
         with no exit, and that gives no error, it looks like it hung. */
      body.tl-chat-dentro .bottom-nav { display: none !important; }
      /* ...except BACKUP, which stays reachable on purpose: it is the only way to
         recover a profile after reinstalling or changing device. There its
         notice card is shown with the back button, and what makes
         no sense without a profile is hidden — you can't back up what isn't there,
         nor export an identity that doesn't exist yet. */
      #backupRestoreGate { display: none; }
      body.tl-profile-locked #backupRestoreGate { display: block; }
      body.tl-profile-locked #backupStartBtn,
      body.tl-profile-locked #backupTargetHint,
      body.tl-profile-locked #backupNoneBanner,
      body.tl-profile-locked #idExportBtn { display: none !important; }
      /* During Tiro Rápido practice the button bar is removed entirely.
         The practice screen covers it with its z-index, but on iOS the footer with
         the Cancel button ended up behind it anyway (2026-08-06): if
         the button bar doesn't exist, there is nothing that can cover it. Also during
         the series you can't navigate anywhere, so nothing is lost
         and screen is gained. */
      body.tr-practice-open .bottom-nav { display: none !important; }
      /* And in Help, for the same reason: there the keyboard is open almost the whole
         time and between the two they hide the typing field. It is governed by
         `goTo`, the only place that knows which screen is showing. */
      body.tl-sin-botonera .bottom-nav { display: none !important; }
      .bottom-nav-btn {
        flex: 1;
        background: none;
        border: none;
        color: var(--muted);
        font-family: "Inter", sans-serif;
        font-size: 10px;
        font-weight: 600;
        letter-spacing: 0.4px;
        text-transform: uppercase;
        cursor: pointer;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        padding: 6px 4px;
        transition: color 0.15s;
      }
      .bottom-nav-btn svg {
        width: 22px;
        height: 22px;
        display: block;
      }
      /* «Unread» badge on the bottom bar's icon. It is the one seen WITHOUT opening the drawer,
         which was precisely the objection: if they don't open the
         menu, they don't find out.
         ⛔ It carries a NUMBER, not a dot: color can't be the only indicator
         (UX norm §2). And `position:absolute` over the button, which therefore becomes
         `relative` — floating over the icon is the only thing that doesn't shift the
         icon + label column nor push the neighbor. */
      .bottom-nav-btn { position: relative; }
      .bottom-nav-btn .bn-badge {
        position: absolute;
        top: 2px;
        left: 50%;
        margin-left: 4px;
        min-width: 16px;
        height: 16px;
        padding: 0 4px;
        box-sizing: border-box;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        border-radius: 999px;
        background: var(--badge);
        color: #fff;
        font-family: "Oswald", sans-serif;
        font-size: 10px;
        font-weight: 600;
        line-height: 1;
        letter-spacing: 0;
        pointer-events: none;
      }
      .bottom-nav-btn.active {
        color: var(--accent);
        box-shadow: inset 0 3px 0 0 var(--accent);
      }
      /* Cluster with 6 buttons (cluster A · training): tightens
         typography and side padding so "MODALIDADES" /
         "CALENDARIO" / "TIRO RAPIDO" fit in 80px of width. */
      /* ⛔ THE LABEL CAN'T BREAK THE BAR, and today it could. Measured on
         2026-08-22 on a 360 px phone: with SIX buttons each has 52 px
         of usable space, and at 9 px in caps «Seguridad» measures 56, «Vinculados»
         62 and «Aktualisieren» 76. Without `nowrap` the text wrapped onto two lines
         —22 for the icon + 3 + 24 = 49 plus padding, i.e. MORE than the bar's 60 px
         height— and, since the automatic minimum of a flex item is its
         content, what didn't fit pushed the bar to scroll.

         ⚠️ And it's NOT from the new block: the ORGANIZATION cluster has painted six
         since 2026-08-16 with «Vinculados» inside, so it had been there since
         then. It wasn't seen because on tablet —where it was tested— there is plenty of
         room.

         The safety net trims with an ellipsis rather than break the layout. In
         Spanish it doesn't kick in with five buttons; with six it eats a letter
         of «Seguridad» on the narrowest phones. It is the lesser evil: splitting
         the word onto two lines throws off the whole bar. */
      .bottom-nav-btn { min-width: 0; }
      .bottom-nav-btn span {
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .bottom-nav.bottom-nav--6 .bottom-nav-btn {
        font-size: 9px;
        letter-spacing: 0;
        padding: 6px 1px;
      }
      .bottom-nav-btn:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: -4px;
      }
      .topbar-hamb:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 2px;
        border-radius: 6px;
      }

      /* Respects the system's reduced-motion preference. */
      @media (prefers-reduced-motion: reduce) {
        .drawer,
        .drawer-backdrop,
        .drawer-item,
        .bottom-nav-btn {
          transition: none !important;
        }
      }

      /* Artificial padding-bottom removed. Since the bottom-nav now lives
         in the body's flow (flex-column), .content and the views
         adjust automatically without covering content or creating
         empty areas. */

