/* css/main/toggles-footer-and-view-scroll.css — part 12/30 of the app styles (was css/main.css; loaded in this order by index.html). */
      .star-row {
        display: flex;
        gap: 8px;
        justify-content: center;
        margin: 6px 0;
      }
      .star-contact {
        font-size: 28px;
        cursor: pointer;
        transition: transform 0.1s;
        color: var(--muted);
      }
      .star-contact.on {
        color: #f1c40f;
      }
      .star-contact:active {
        transform: scale(1.3);
      }
      .type-toggle {
        display: flex;
        gap: 8px;
        margin-bottom: 12px;
      }
      .type-opt {
        display: flex;
        align-items: center;
        gap: 8px;
        cursor: pointer;
        background: var(--card);
        border: 1.5px solid var(--border);
        border-radius: 6px;
        padding: 10px 14px;
        flex: 1;
        font-size: 13px;
        font-weight: 600;
        transition:
          border-color 0.15s,
          color 0.15s;
        user-select: none;
      }
      .type-opt input[type="radio"] {
        width: 16px;
        height: 16px;
        accent-color: var(--accent);
        cursor: pointer;
        flex-shrink: 0;
      }
      .type-opt:has(input:checked) {
        border-color: var(--accent);
        color: var(--accent);
      }
      .page-footer {
        border-top: 1px solid var(--border);
        padding: 8px 16px;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        flex-shrink: 0;
        position: relative;
      }
      .footer-ver {
        position: absolute;
        right: 16px;
        font-size: 10px;
        color: var(--muted);
        letter-spacing: 0.5px;
      }
      .footer-priv {
        position: absolute;
        left: 16px;
        font-size: 10px;
        color: var(--muted);
        letter-spacing: 0.5px;
        background: none;
        border: none;
        cursor: pointer;
        padding: 0;
        font-family: "Inter", sans-serif;
        text-transform: uppercase;
      }
      .footer-priv:active {
        color: var(--accent);
      }
      .footer-txt {
        font-size: 10px;
        color: var(--muted);
        letter-spacing: 1.5px;
        text-transform: uppercase;
      }
      .footer-avatar {
        width: 22px;
        height: 22px;
        border-radius: 50%;
        object-fit: cover;
        border: 1.5px solid var(--border);
        flex-shrink: 0;
      }
      /* Privacy: normal view with an iframe that fills all the space */
      .privacy-frame {
        flex: 1;
        border: none;
        width: 100%;
        background: var(--bg);
      }
      /* ⛔ THE TRIO: whoever enters here MUST ALSO enter the
         `.content:has(...)` below, or its inner area doesn't scroll and the
         end of the list can't be reached. Guard: `unit-vista-scroll-trio`.
         «Mis clubes» (My clubs) entered on 2026-08-25 with its floating button (card #121). */
      #view-registrar.active,
      #view-modalidades.active,
      #view-historial.active,
      #view-compras.active,
      #view-notas.active,
      #view-comp-vivo.active,
      #view-org-ficha.active,
      #view-mis-organizadores.active,
      #view-mis-campos.active,
      #view-mis-plantillas.active,
      #view-mis-clubes.active,
      #view-chat.active,
      #view-wizard-cv.active {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-height: 0;
      }
      #view-registrar .reg-scroll,
      #view-modalidades .mod-scroll,
      #view-historial .hist-scroll,
      #view-compras .hist-scroll,
      #view-notas .mod-scroll,
      /* ⛔ WITHOUT THESE THREE RULES, `.cv-scroll` IS NOT A SCROLLER AND `sticky`
         DOES NOT STICK. The public record carried them inline (`flex:1;overflow-y:
         auto;min-height:0`) and they did nothing: `flex` does nothing inside
         a parent that isn't flex, so the area grew whole and what
         scrolled was `.content`, one level up. A `position: sticky`
         anchors to its NEAREST scroller —`.cv-scroll`, which never
         moved—, so the Save bar went away with the text even though its CSS
         said `top: 0`. Measured in the browser on 2026-08-21: scrolling all the way down
         the button ended up at `top: -845`.
         The three ALWAYS go together: `.content` as a column, the view as a column
         with `flex:1`, and the inner area with `flex:1; overflow-y:auto`. */
      #view-comp-vivo .cv-scroll,
      #view-org-ficha .cv-scroll {
        flex: 1;
        overflow-y: auto;
        min-height: 0;
        overscroll-behavior-y: none;
      }
      /* ⚠️ THE AIR AT THE BOTTOM IS RESTORED HERE. While the record scrolled with
         `.content`, the last field had 36 px below it: the 24 of
         `.content` plus the 12 of `.section`. When the scrolling moved to this
         box, the `.content:has(...)` rule sets that padding to zero and 12 were
         left — «Provincia / Región» (Province / Region) stuck to the edge, right above the button bar,
         which reads as if the screen were cut off. The neighbors in that
         list don't notice because the ones with «+» bring `.cv-scroll-fab` with
         88 px; this one doesn't. */
      #view-org-ficha .cv-scroll {
        padding-bottom: 24px;
      }
      /* Extra space at the end of the lists with a floating FAB so the
         + button (56px + 16px of air) doesn't cover the last element when
         scrolling to the end. Applies to the views with a jade FAB. */
      #view-modalidades .mod-scroll,
      #view-notas .mod-scroll,
      #view-compras .hist-scroll,
      #view-historial .hist-scroll,
      /* ⛔ The ones that debuted «+» on 2026-08-20 when the create slab was removed.
         Without this cushion the button covers the last element of the list, which is
         exactly the one just added. */
      .cv-scroll-fab {
        padding-bottom: 88px;
      }
      /* ⛔ In History and in Purchases there are TWO floating buttons stacked (the «+» and the
         report), so their lists need more cushion than the others: without
         it the last entry ends up under the report button.
         16 + 56 + 12 + 48 + 16 = 148. */
      #view-historial .hist-scroll,
      #view-compras .hist-scroll {
        padding-bottom: 148px;
      }
      /* The competition history has ONE floating button (the report, shooter
         only): without a cushion it covers the arrow of the last card and the tap
         opens the report instead of the competition (review, 2026-09-24). */
      #view-dir-historico {
        padding-bottom: 88px;
      }
      .cv-panel { flex:1; overflow:hidden; display:flex; flex-direction:column; min-height:0; }
      .cv-panel-scroll { flex:1; overflow-y:auto; min-height:0; overscroll-behavior-y:none; }
      /* Quick Shot manages its own scroll: the list of cards inside
         and the start button fixed at the bottom. If .content could also
         scroll, the LOG bar would go up out of the
         screen at the slightest overflow (2026-08-06). */
      .content:has(#view-tiro-rapido.active),
      .content:has(#view-registrar.active),
      .content:has(#view-modalidades.active),
      .content:has(#view-historial.active),
      .content:has(#view-compras.active),
      .content:has(#view-notas.active),
      .content:has(#view-comp-vivo.active),
      .content:has(#view-org-ficha.active),
      .content:has(#view-mis-organizadores.active),
      .content:has(#view-mis-campos.active),
      .content:has(#view-mis-plantillas.active),
      .content:has(#view-mis-clubes.active),
      .content:has(#view-chat.active),
      .content:has(#view-wizard-cv.active) {
        overflow-y: hidden;
        padding-bottom: 0;
        display: flex;
        flex-direction: column;
      }
      /* ⛔ THE CHAT STARTS STUCK TO THE APP HEADER. Santi, 2026-08-28:
         "the title that appears at the top… is separated from what the app
         header is by a few pixels, it doesn't look very good, it should be joined
         so it's all one". And that was exactly it: the 5 px of `--content-pt`,
         which exist so that what sticks to the top doesn't leave a gap — but
         here nothing sticks, the channel header is fixed. With the padding at
         zero, the two share `--surface` and read as a single piece.
         ⚠️ The channel tree doesn't lose its air: `.tlch-arbol` provides it. */
      .content:has(#view-chat.active) { padding-top: 0; }

