@layer utilities {
  /* Programmatic visibility toggle. Prefer .is-hidden over inline
   * `style.display = "none"` — class mutations batch better in the
   * style recalc pipeline than inline-style writes (one rule resolution
   * vs one full inline style serialization per element). */
  .is-hidden {
    display: none !important;
  }

  /* Zona táctil de 44px en un control que se VE más bajo (--control-compact).
   * Un pseudo-elemento centrado de --touch-target de alto recibe el toque sin
   * ocupar sitio en el layout: la casilla adelgaza, el dedo no lo nota. Centrado
   * con transform, no con `inset` negativo, para no depender del grosor del borde.
   * Condición: entre filas de estos controles, hueco ≥ 8px — si no, las zonas
   * extendidas se solapan y la fila de abajo se come los toques de la de arriba. */
  .tap-target {
    position: relative;
  }

  .tap-target::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 50%;
    height: var(--touch-target);
    transform: translateY(-50%);
  }

  /* Cuotas que viven en HTML de servidor sin gate de JS propio (la tabla de casas
   * y la cuota media de Pronósticos): se esconden cuando el visitante no puede
   * verlas. `data-odds-hidden` lo pone en <html> el arranque de base.html.twig
   * (sin +18 o apagadas en Ajustes — mismo criterio que canShowOdds()). La tarjeta
   * y la pestaña de Cuotas no lo necesitan: tienen su propio gate. */
  :root[data-odds-hidden] [data-odds-surface] {
    display: none !important;
  }

  /* Viewport-class visibility guards — mobile-only / desktop-only.
   * Threshold matches the desktop shell MQ in layout.css (1200px).
   * Use sparingly: prefer responsive components that adapt, not parallel
   * mobile + desktop markup. Reserved for shell-level chrome (e.g. nav
   * primary that appears in topbar on desktop vs drawer on mobile). */
  .is-mobile-only {
    display: revert;
  }

  .is-desktop-only {
    display: none;
  }

  @media (width >= 1200px) {
    .is-mobile-only {
      display: none;
    }

    .is-desktop-only {
      display: revert;
    }
  }

  /* Logo brightness backdrop — applied by logo_brightness_controller.js.
   * The controller tags the element with `.logo--dark` when the crest has
   * LOW perceptual luminance (e.g. Premier League, Bundesliga), and with
   * `.logo--light` when the crest has HIGH luminance (white stars on white
   * bg, etc). CSS paints a contrasting backdrop per theme so both families
   * remain legible on any surface. */

  /* Dark logos on dark themes → white backdrop */
  :root[data-theme^="dark"] .logo--dark,
  :root[data-theme^="dark"] img.logo--dark {
    background: rgb(255 255 255 / 92%);
    border-radius: 6px;
    padding: 2px;
  }

  /* Light logos on light themes → subtle dark backdrop */
  :root[data-theme^="light"] .logo--light,
  :root[data-theme^="light"] img.logo--light {
    background: rgb(15 23 42 / 10%);
    border-radius: 6px;
    padding: 2px;
  }
}
