/* ==========================================================================
   3Bee base primitives (PHASE 24 → P9). Loaded after tokens.css, before
   dashboard.css / auth.css. Zero-specificity defaults + opt-in utilities.
   ========================================================================== */

/* 1. Focus: one brand ring wherever a component has not styled its own. */
:where(a[href], button, [role="button"], [role="tab"], summary,
       input, select, textarea, [tabindex]:not([tabindex="-1"])):focus-visible {
  outline: var(--bee-focus-ring);
  /* Re-read per element so a scoped --bee-focus-color override applies
     (--bee-focus-ring is resolved once at :root). */
  outline-color: var(--bee-focus-color);
  outline-offset: var(--bee-focus-offset);
}
/* Firefox: the Tailwind preflight :-moz-focusring { outline: auto } (0,1,0)
   beats the zero-specificity ring above, so restate the brand ring at the
   same specificity (base.css loads after tailwind.css, so it wins). Component
   :focus-visible rules (0,2,0) still win. */
:-moz-focusring {
  outline: var(--bee-focus-ring);
  outline-color: var(--bee-focus-color);
  outline-offset: var(--bee-focus-offset);
}
/* Dark surfaces (navy toasts, the consoles): gold-ink is under 3:1 there,
   so the ring switches to honey gold (D2 dark-surface exception). */
:where(.billing-toast, .deploy-console-container, .manager-console-box,
       .pay-toast, .profile-toast, .settings-toast, .manager-toast, .popup-toast) {
  --bee-focus-color: var(--bee-focus-color-on-dark);
}
:where(button, [role="button"]):disabled,
:where([aria-disabled="true"]) { cursor: not-allowed; }

/* Field pattern: gold-ink border (5.8:1 on cloud, the 3:1 indicator) +
   decorative gold halo; a transparent outline keeps the indicator in
   forced-colors mode. Apply the same declarations to
   existing field selectors (settings-input, profile-input, pg-*,
   .input-container), or add the class. Wrapper fields use :focus-within. */
.bee-field {
  border: 1px solid var(--bee-line-strong);
  border-radius: var(--bee-r-sm);
  background: var(--bee-surface-2);
  transition: border-color var(--bee-dur-2) var(--bee-ease-out),
              box-shadow var(--bee-dur-2) var(--bee-ease-out);
}
.bee-field:focus-visible,
.bee-field:focus-within {
  border-color: var(--bee-gold-ink);
  box-shadow: var(--bee-focus-halo);
  outline: 2px solid transparent;
  outline-offset: 2px;
}
.bee-field[aria-invalid="true"],
.has-error .bee-field { border-color: var(--bee-danger); }
.bee-field[aria-invalid="true"]:focus-within,
.has-error .bee-field:focus-within {
  box-shadow: var(--bee-focus-halo-danger), 0 0 0 1px var(--bee-danger);
}

/* 2. Hover lift: ONLY for a real hovering pointer (no sticky hover on
   touch). Gold glow variant for gold-themed interactive cards. */
.bee-lift {
  transition: transform var(--bee-dur-2) var(--bee-ease-out),
              box-shadow var(--bee-dur-2) var(--bee-ease-out),
              border-color var(--bee-dur-2) var(--bee-ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .bee-lift:hover { transform: translateY(var(--bee-lift)); box-shadow: var(--bee-e2); }
  .bee-lift--gold:hover { box-shadow: var(--bee-e2), var(--bee-glow-gold); }
}

/* 3. Press: opt-in (a global :active transform would break elements that
   are positioned with transform, such as the password toggle and switch knobs). */
.bee-press { transition: transform var(--bee-dur-1) var(--bee-ease-out); }
.bee-press:not(:disabled):not([aria-disabled="true"]):active {
  transform: translateY(0) scale(var(--bee-press-scale));
}

/* 4. Touch hit-area expander: grows the hit box to 44px without changing
   the drawn size. The host must not use ::after or overflow:hidden. */
.bee-hit { position: relative; }
.bee-hit::after {
  content: "";
  position: absolute;
  inset: min(0px, calc((100% - var(--bee-touch)) / 2));
}

/* 5. Skeleton shimmer */
.bee-skel {
  color: transparent !important;
  pointer-events: none;
  border-radius: var(--bee-r-sm);
  background: linear-gradient(90deg, var(--bee-skel-base) 25%, var(--bee-skel-hi) 50%,
              var(--bee-skel-base) 75%) 0 0 / 200% 100%;
  animation: bee-shimmer 1.2s ease-in-out infinite;
}
/* Text that is filled by JS: <h1 class="... bee-skel-text"></h1> */
.bee-skel-text:empty::before {
  content: "";
  display: inline-block;
  width: var(--bee-skel-w, 10ch);
  height: 0.8em;
  vertical-align: middle;
  border-radius: var(--bee-r-sm);
  background: linear-gradient(90deg, var(--bee-skel-base) 25%, var(--bee-skel-hi) 50%,
              var(--bee-skel-base) 75%) 0 0 / 200% 100%;
  animation: bee-shimmer 1.2s ease-in-out infinite;
}
@keyframes bee-shimmer {
  from { background-position: 150% 0; }
  to   { background-position: -50% 0; }
}
/* High contrast: forced colours can repaint the transparent placeholder
   copy (fake status and usage values), so keep it hidden and draw the
   skeleton as a plain system-grey block instead. */
@media (forced-colors: active) {
  .bee-skel {
    forced-color-adjust: none;
    color: transparent !important;
    background: GrayText;
  }
}

/* 6. Shared spinner + entrance keyframes (replace managerSpin,
   settingsSpin, pagelockSpin, profileSpin; bee-rise is the shell entrance). */
.bee-spinner {
  width: 16px; height: 16px;
  border: 2px solid rgba(15, 23, 42, 0.2);
  border-top-color: var(--bee-ink);
  border-radius: 50%;
  animation: bee-spin 0.7s linear infinite;
}
@keyframes bee-spin { to { transform: rotate(360deg); } }
@keyframes bee-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* 7. Reduced motion: neutralises EVERY animation and transition, including
   the shell entrance (.dashboard-fade-in / bee-rise) and the dashboard
   sequence, which are pinned to their final state. Essential progress
   indicators keep spinning, slowed. Durations are 1ms rather than "none"
   so JS waiting on transitionend/animationend still resolves. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  /* Only the elements the golden settle animates (dashboard.css §10): a
     blanket descendant selector would also force opacity 1 on the dashboard's
     own states, such as the busy retry button's 0.6 fade. */
  .dashboard-fade-in,
  .dash-seq .hero-banner,
  .dash-seq .quick-access,
  .dash-seq .usage-cards,
  .dash-seq .qa-card,
  .dash-seq .dash-package-section {
    animation: none !important;
    opacity: 1 !important;
  }
  .dashboard-fade-in { transform: none !important; }
  .bee-skel,
  .bee-skel-text:empty::before { animation: none !important; }
  .bee-lift:hover,
  .bee-press:active,
  .hero-banner__card.is-tilting { transform: none !important; }
  /* Every page hover lift and press scale reads these tokens
     (translateY(var(--bee-lift)), scale(var(--bee-press-scale))), so zeroing
     them here stops the 2px jump and the 2% snap on every page at once.
     base.css loads after tokens.css, so this :root wins. */
  :root { --bee-lift: 0px; --bee-press-scale: 1; }
  /* Essential progress: keep, slowed */
  .bee-spinner, .spinner, .pagelock-spinner,
  .is-spinning svg, .is-pending::after, .btn-loading .spinner,
  .builder-row--deleting .col-action::after,
  .manager-refresh-btn.is-spinning .mm-refresh-icon,
  .manager-action-btn.is-loading .mm-action-icon,
  .manager-action-btn.is-loading svg {
    animation-duration: 1.6s !important;
    animation-iteration-count: infinite !important;
  }
}
