/* ==========================================================================
   bb-polish.css — additive, low-risk overrides for the BBLABU frontend
   --------------------------------------------------------------------------
   LOAD ORDER: must come AFTER /static/css/index.*.css
     <link rel="stylesheet" href="/bb-polish.css">

   Ground rules followed in this file
   - Additive only: no colours, layout, branding or visibility are changed.
   - Nothing is hidden (no display:none / visibility / opacity:0 rules).
   - !important appears ONLY inside the reduced-motion / data-saver queries.
   - Every class / attribute selector below was grepped in index.pretty.css
     (line numbers given per rule). No speculative selectors.
   - Normal-motion look of the home "orbit" scene is untouched.

   Why some rules sit in `@layer base`:
   the main stylesheet is layered (properties, theme, base, components,
   utilities — index.pretty.css:5431-6533). Unlayered CSS beats every layer,
   so a plain rule here would override Tailwind utilities such as
   `.touch-none` or `.outline-hidden`. Appending to the existing `base` layer
   keeps these rules true *fallbacks*: components, utilities and all
   unlayered site CSS still win.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Fallbacks (lowest priority: existing `base` layer + :where() = 0 spec.)
   -------------------------------------------------------------------------- */
@layer base {

  /* Preflight only sets the -webkit- prefixed property (index.pretty.css:5808).
     Add the unprefixed one so Firefox Android / future engines also keep text
     from being auto-inflated in landscape. Same value, no visual change. */
  html {
    text-size-adjust: 100%;
  }

  /* -webkit-tap-highlight-color: intentionally NOT re-declared. It is already
     `transparent` on html (index.pretty.css:5814) and the property inherits,
     so every element is covered. */

  /* Removes the double-tap-to-zoom wait on tap targets (iOS Safari still
     applies it even with width=device-width). Pan and pinch-zoom stay enabled.
     Being in `base`, it never overrides `.touch-none` (9436), the pan-y/pan-x
     carousels (38433, 38901) or any other explicit touch-action.
     Selectors verified: [role=button], [role=tab], [role=checkbox]. */
  :where(a, button, summary, label, select,
         [role=button], [role=tab], [role=checkbox]) {
    touch-action: manipulation;
  }

  /* Keyboard-focus fallback. The site styles focus per component
     (58 focus-visible rules) and `.orbit-ui :is(a,button,input,textarea,
     summary):focus-visible` (36848) only sets colour + offset, relying on the
     UA default outline. This guarantees a visible 2px ring in the existing
     brand token (--ring) wherever no component rule supplies one.
     Any utility (`.outline-hidden`, focus-visible:ring-*) or unlayered rule
     still wins, so designed focus rings are unchanged.
     [tabindex] is deliberately excluded: dialogs/containers focused
     programmatically must not gain an outline. */
  :where(a, button, input, select, textarea, summary,
         [role=button], [role=tab], [role=checkbox]):focus-visible {
    outline: 2px solid var(--ring, currentColor);
    outline-offset: 2px;
  }

  /* Stop scroll chaining from overlays into the page behind them. Needed
     because `body[data-scroll-locked] { overflow: unset !important }`
     (index.pretty.css:6101) disables the library scroll lock, so reaching the
     end of a dialog/sheet/menu scrolls the page underneath.
     Only has an effect on elements that are scroll containers; a no-op
     otherwise. Selectors verified: all five data-slot values exist. */
  :where([data-slot=dialog-content],
         [data-slot=sheet-content],
         [data-slot=popover-content],
         [data-slot=dropdown-menu-content],
         [data-slot=select-content]) {
    overscroll-behavior: contain;
  }
}


/* --------------------------------------------------------------------------
   2. Mobile: cap the two largest backdrop blurs
   --------------------------------------------------------------------------
   `.backdrop-blur-xl` = 24px and `.backdrop-blur-2xl` = 40px
   (index.pretty.css:16849, 16873; tokens at 5768-5774). Large-radius backdrop
   blur is the most expensive paint effect on phone GPUs and the difference
   above ~16px is barely perceptible on a small screen. Cap both to the
   existing `lg` token (16px). Only the blur radius variable is overridden;
   the utility's own `backdrop-filter` declaration keeps composing it, so
   saturate/brightness/etc. are untouched. sm/md/lg are left as designed.
   Unlayered on purpose: it must beat the utility layer (no !important). */
@media (max-width: 768px) {
  .backdrop-blur-xl,
  .backdrop-blur-2xl {
    --tw-backdrop-blur: blur(var(--blur-lg, 16px));
  }
}


/* --------------------------------------------------------------------------
   3. Reduced motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {

  /* Stop the decorative infinite loops that have no reduced-motion rule of
     their own: .pulse-glow, .sakura-petal, .dark .pixel-particle,
     .dark .neon-scan-line, .anime-petal, .anime-mascot svg,
     .animate-caret-blink. Targeted on purpose (NOT a blanket
     `* {animation-duration:0}`) so spinners, dialogs and toasts keep working.
     Each element simply rests in its own base style. */
  .pulse-glow,
  .sakura-petal,
  .dark .pixel-particle,
  .dark .neon-scan-line,
  .anime-petal,
  .anime-mascot svg,
  .animate-caret-blink {
    animation: none !important;
  }

  /* will-change cleanup. These elements keep a permanent compositor layer
     (will-change at 30726, 30743, 28736, 27830, 27835, 36451) even though
     their animation is switched off in this mode, which only wastes GPU
     memory (14 motes + 7 providers). Reset the hint while motion is reduced.
     Normal-motion rendering is not touched. */
  .flower-mote,
  .flower-kenburns,
  .anime-petal,
  .animate-scroll-up,
  .animate-scroll-down,
  .orbit-ui .orbit-provider {
    will-change: auto !important;
  }
}

/* Source-order bug fix. The site lowers the material blur tokens to
   10/14/16px for reduced-motion and slow-refresh displays
   (index.pretty.css:31843), but the phone block that follows (31854) sets
   12/18/22px and wins by order — so on phones the lighter values never apply.
   Re-assert the site's own values for that intersection. No !important
   needed: same selector, later in the cascade. */
@media (max-width: 640px) and (prefers-reduced-motion: reduce),
       (max-width: 640px) and (update: slow) {
  :root,
  .dark {
    --material-blur-sm: 10px;
    --material-blur-md: 14px;
    --material-blur-lg: 16px;
  }
}


/* --------------------------------------------------------------------------
   4. Data saver
   --------------------------------------------------------------------------
   The bundle already treats data-saver like reduced motion for the heavy
   parts (background video off, WebGL earth paused — index-entry:31919-31921,
   6197), but the stylesheet has no prefers-reduced-data rule at all, so the
   decorative background loops keep running. Mirror the site's own
   reduced-motion rule for them (index.pretty.css:31029). Elements stay
   visible, only the looping stops.
   Note: this media feature is not yet shipped by default in browsers; the
   block is inert until it is, and harmless either way. */
@media (prefers-reduced-data: reduce) {
  .flower-mote,
  .flower-kenburns {
    animation: none !important;
    will-change: auto !important;
  }
}
