/* ============================================================================
 * frega-loading.css — the canonical Frega loading primitive.
 *
 * Pairs with /js/frega-loading.js. Together they replace four separate legacy
 * mechanisms that had grown up independently across the 7 brand masters:
 *
 *   ShowBusyFloat/HideBusyFloat  (94 shows / 216 hides — see js header)
 *   ShowBusy/HideBusy            (13 sites, 8 of them pointed at a container
 *                                 that never existed)
 *   #progressbar                 (~280 lines / 24 files, neon lime, and
 *                                 unstyled entirely on 2 of its 4 masters)
 *   #preloader                   (besorted + FregaWorks first-paint veil)
 *
 * PORTABILITY — this file is the contract that travels to the sister products
 * (frega.co.uk, GrowthPoints). It is deliberately:
 *   - framework-agnostic: no jQuery, no Bootstrap, no MudBlazor selectors;
 *   - flat (unscoped): class names are namespaced `frega-load-*` instead, so
 *     there is nothing to collide with and no ancestor required. (The legacy
 *     `.s2t-progress` needed BOTH `#EchoMainContent` AND `.s2t-profile` to be
 *     present, which is why it silently failed outside the SPA shell.)
 *   - token-driven with HARD FALLBACKS: every var() carries the MASTER.md
 *     value inline, so the file is correct standalone on a surface that never
 *     loads a Frega token block.
 *
 * Palette is MASTER.md brand green only (--brand #4A8A68 / --brand-strong
 * #136242). Red is reserved for destructive actions and never appears here.
 * ==========================================================================*/

/* ---------------------------------------------------------------------------
 * Tokens — local aliases so a host that already defines --brand wins, and a
 * host that defines nothing still gets the correct Frega greens.
 * ------------------------------------------------------------------------ */
.frega-load-root,
.frega-load-bar,
.frega-load-veil,
#progressbar {
  --_fl-brand: var(--brand, var(--s2t-brand, #4A8A68));
  --_fl-brand-strong: var(--brand-strong, var(--s2t-brand-strong, #136242));
  --_fl-card-bg: rgba(255, 255, 255, 0.92);
  --_fl-scrim: rgba(20, 30, 25, 0.18);
  /* Clears the hub/weblet sticky header (9000); stays under SweetAlert2 (10050)
     so a confirm dialog is never dimmed by a load behind it.
     Deliberately its OWN token, not --s2t-z-modal. Both legacy copies read
     `var(--s2t-z-modal, 10000)`, which looked fine but wasn't: s2t-theme.css
     defines --s2t-z-modal: 300 (the MASTER §7 named modal layer), so on S2T
     main the overlay actually resolved to 300 and rendered UNDERNEATH the site
     nav (s2t-nav.css:103, z-index 1040). The 10000 fallback only ever applied
     on the 6 brands that never load the theme. Override --frega-load-z per
     host if a surface genuinely stacks higher. */
  --_fl-z: var(--frega-load-z, 10000);
}

/* ---------------------------------------------------------------------------
 * Dual-arc spinner — the canonical Frega mark, shared with GrowthPoints.
 * ------------------------------------------------------------------------ */
.frega-load-spinner { position: relative; width: 88px; height: 88px; }
.frega-load-spinner--sm { width: 56px; height: 56px; }
.frega-load-spinner--lg { width: 140px; height: 140px; }
/* --xs is button/field scale: sits on a text baseline without shifting it. */
.frega-load-spinner--xs { width: 18px; height: 18px; }

.frega-load-arc {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  fill: none; stroke-linecap: round;
}
.frega-load-arc--outer { animation: frega-load-cw 1.1s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
.frega-load-arc--outer circle {
  stroke: var(--_fl-brand-strong, #136242); stroke-width: 6; stroke-dasharray: 80 170;
}
.frega-load-arc--inner { animation: frega-load-ccw 0.85s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
.frega-load-arc--inner circle {
  stroke: var(--_fl-brand, #4A8A68); stroke-width: 5; stroke-dasharray: 55 120;
}

@keyframes frega-load-cw  { to { transform: rotate(360deg); } }
@keyframes frega-load-ccw { to { transform: rotate(-360deg); } }

/* ---------------------------------------------------------------------------
 * Type: BAR — one element, two modes.
 *   indeterminate -> .frega-load-bar (slides, duration unknown)
 *   determinate   -> .frega-load-bar.is-determinate + inline width on the fill
 * Replaces #progressbar. Fixed to the viewport top; the legacy inline-styled
 * #progressbar used z-index 99999, which sat ABOVE modals — 10000 is correct
 * (over the 9000 sticky header, under the 10050 Swal layer).
 * ------------------------------------------------------------------------ */
.frega-load-bar {
  position: fixed; top: 0; left: 0; right: 0;
  height: 3px;
  z-index: var(--_fl-z, 10000);
  /* Literal fallback first: an engine without color-mix() drops that
     declaration entirely, which would leave the track invisible. */
  background: rgba(74, 138, 104, 0.18);
  background: color-mix(in srgb, var(--_fl-brand, #4A8A68) 18%, transparent);
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity 160ms ease;
}
.frega-load-bar.is-visible { opacity: 1; }

.frega-load-bar__fill {
  height: 100%;
  background: linear-gradient(90deg,
      var(--_fl-brand, #4A8A68),
      var(--_fl-brand-strong, #136242));
  border-radius: 0 2px 2px 0;
}

/* Indeterminate: a travelling segment. No faked percentage — the legacy hub.js
   bar invented one with `progCount += progCount + 1` on a 1s interval, which
   read 1,3,7,15,31,63,127 then snapped back to 0. This says "working" honestly
   without claiming to know how far along it is. */
.frega-load-bar:not(.is-determinate) .frega-load-bar__fill {
  width: 40%;
  animation: frega-load-slide 1.15s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
@keyframes frega-load-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

/* Determinate: width is driven by handle.set(pct); ease the growth so a chunky
   upload event (0 -> 40 -> 100) doesn't teleport. */
.frega-load-bar.is-determinate .frega-load-bar__fill {
  width: 0;
  transition: width 200ms ease-out;
}

/* ---------------------------------------------------------------------------
 * Type: OVERLAY — the click-shield, and its optional visible scrim.
 *
 * The shield is ALWAYS present while an overlay load is open, even in the
 * invisible tier. This is load-bearing, not decoration: the legacy
 * .s2t-busy-overlay was `position:fixed; inset:0`, so it swallowed clicks, and
 * ~94 call sites (checkout, register, forgot-password) silently depend on it
 * for double-submit protection. A "lighter" tier that stopped blocking input
 * would regress every one of them.
 * ------------------------------------------------------------------------ */
.frega-load-root {
  position: fixed; inset: 0;
  z-index: var(--_fl-z, 10000);
  display: flex; align-items: center; justify-content: center;
  background: transparent;      /* tier 1: blocks input, paints nothing */
  transition: background 220ms ease;
}

/* tier 3 only — the scrim the owner asked us to reserve for big loads. */
.frega-load-root.is-scrim { background: var(--_fl-scrim, rgba(20, 30, 25, 0.18)); }

.frega-load-card {
  display: inline-flex; flex-direction: column; align-items: center;
  gap: 12px;
  background: var(--_fl-card-bg, rgba(255, 255, 255, 0.92));
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 220ms ease, transform 220ms ease;
}
.frega-load-root.is-scrim .frega-load-card { opacity: 1; transform: none; }

.frega-load-label {
  font-size: 0.85rem; letter-spacing: 0.04em;
  color: var(--_fl-brand-strong, #136242);
}

/* ---------------------------------------------------------------------------
 * Type: INLINE — bare spinner injected into a host element. No card, no scrim.
 * ------------------------------------------------------------------------ */
.frega-load-inline {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 20px;
}

/* ---------------------------------------------------------------------------
 * Type: PAGE — first-paint veil. Replaces #preloader on besorted/FregaWorks.
 * Opaque (not a scrim): it hides unstyled content, it doesn't dim it.
 * ------------------------------------------------------------------------ */
.frega-load-veil {
  position: fixed; inset: 0;
  z-index: calc(var(--_fl-z, 10000) + 1);
  display: flex; align-items: center; justify-content: center;
  background: #fff;
  transition: opacity 300ms ease;
}
.frega-load-veil.is-leaving { opacity: 0; pointer-events: none; }

/* ---------------------------------------------------------------------------
 * A11y / motion. MASTER.md requires a prefers-reduced-motion guard on every
 * loading animation (violation class M1). Animation is the ONLY signal these
 * indicators carry, so it degrades to a static mark rather than vanishing:
 * the arcs hold their shape, and the bar shows a steady full-width fill.
 * ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .frega-load-arc--outer,
  .frega-load-arc--inner { animation: none; }
  .frega-load-bar:not(.is-determinate) .frega-load-bar__fill {
    animation: none; width: 100%; opacity: 0.65;
  }
  .frega-load-bar.is-determinate .frega-load-bar__fill { transition: none; }
  .frega-load-root, .frega-load-card, .frega-load-veil { transition: none; }
}

/* Screen readers get the state change; the visual tiering is purely cosmetic
   and must not gate the announcement. */
.frega-load-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------------------
 * COMPAT: the legacy #progressbar.
 *
 * ~280 lines across 24 files drive this element, nearly all of them genuine
 * jQuery-File-Upload `progress:` handlers doing `$('#progressbar div').css(
 * 'width', pct + '%')`. Those work and are worth keeping — so rather than
 * rewrite 24 files, the element is restyled here to match .frega-load-bar and
 * keeps its existing show()/hide() + width-setter contract.
 *
 * This rule lives in frega-loading.css (loaded by all 7 masters) rather than
 * hub.css (loaded by only some). That is the actual fix for the element being
 * completely unstyled on duw/weblet pages other than the hub — it rendered as
 * bare "Loading" text with no bar at all.
 *
 * What it replaces: a 20px-tall lime bar, rgb(146 216 91 / 0.49) track and
 * rgba(71, 243, 0, 0.75) fill — nowhere near the MASTER brand family.
 * ------------------------------------------------------------------------ */
#progressbar {
  position: fixed; top: 0; left: 0; right: 0;
  height: 3px;
  z-index: var(--_fl-z, 10000);
  padding: 0;                     /* was 4px — pushed the fill off the track */
  border-radius: 0;
  background: rgba(74, 138, 104, 0.18);
  background: color-mix(in srgb, var(--_fl-brand, #4A8A68) 18%, transparent);
  overflow: hidden;
  pointer-events: none;
}
#progressbar > div {
  height: 100%;
  width: 0;
  padding: 0;
  border-radius: 0 2px 2px 0;
  background: linear-gradient(90deg,
      var(--_fl-brand, #4A8A68),
      var(--_fl-brand-strong, #136242));
  transition: width 200ms ease-out;
  /* The markup carries a literal "Loading" text node inside the fill. At 3px
     it cannot render, but it is still worth announcing, so hide it visually
     rather than deleting it from four masters. */
  font-size: 0;
  line-height: 0;
  color: transparent;
}
@media (prefers-reduced-motion: reduce) {
  #progressbar > div { transition: none; }
}

/* No back-compat aliases are carried here. The legacy .s2t-brand-spinner /
   .s2t-spinner-arc / .s2t-spinner-inline / .s2t-busy-* names had exactly one
   consumer outside the loader itself (member/gallery/content/Default.aspx,
   which hand-built the markup inline); it now emits .frega-load-* directly.
   Verified zero remaining references across .js/.aspx/.ascx/.master/.cs/.html,
   including server-side string building in App_Code — so aliases would be dead
   code on arrival. If a missed site turns up, add the alias back here rather
   than reintroducing a second definition elsewhere. */
