/* ═══════════════════════════════════════════════════════════════════════════
   ph-globe-loader.css — Globe loading system (M2 brand card)
   ---------------------------------------------------------------------------
   Link in App.razor AFTER ph-components.css:
       <link rel="stylesheet" href="css/ph-components.css" />
       <link rel="stylesheet" href="css/ph-globe-loader.css" />

   Contains everything: the animated globe mark, the cyan brand modal card,
   the thin top progress bar, skeletons, and reduced-motion handling.

   Colour comes from tokens throughout — no component hard-codes a hex — so this
   themes automatically and is already correct in dark mode.

   Adapted from the source handoff's [data-ph-theme="dark"] to [data-mud-theme="dark"] —
   this app's MudThemeProvider toggles dark mode via that attribute (see ph-theme.js).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ════ THE GLOBE MARK ═════════════════════════════════════════════════════ */

.ph-globe {
  width: var(--ph-globe-size, 56px);
  height: var(--ph-globe-size, 56px);
  flex-shrink: 0;
  display: block;
  overflow: visible;
}

.ph-globe--sm { --ph-globe-size: 22px; }
.ph-globe--md { --ph-globe-size: 40px; }
.ph-globe--lg { --ph-globe-size: 56px; }
.ph-globe--xl { --ph-globe-size: 80px; }

/* Cyan by default (for the plain card and inline use). The brand card overrides
   these to white further down. */
.ph-globe__edge { fill: none; stroke: var(--ph-primary); stroke-width: 2.4; opacity: .30; }
.ph-globe__lat  { fill: none; stroke: var(--ph-primary); stroke-width: 1.5; opacity: .38; }
.ph-globe__mer  {
  fill: none;
  stroke: var(--ph-primary);
  stroke-width: 2.1;
  stroke-linecap: round;
  animation: ph-globe-spin 2.6s linear infinite;
}

/* Four meridians, evenly phase-shifted across one cycle. */
.ph-globe__mer--1 { animation-delay: 0s; }
.ph-globe__mer--2 { animation-delay: -.65s; }
.ph-globe__mer--3 { animation-delay: -1.3s; }
.ph-globe__mer--4 { animation-delay: -1.95s; }

/* rx through near-zero = the meridian turning edge-on. Opacity peaks at the
   limb, where a real wireframe reads densest. */
@keyframes ph-globe-spin {
  0%   { rx: 26;  opacity: .30; }
  25%  { rx: 8;   opacity: 1;   }
  50%  { rx: 0.4; opacity: .30; }
  75%  { rx: 8;   opacity: 1;   }
  100% { rx: 26;  opacity: .30; }
}

/* ════ MODAL SHELL ════════════════════════════════════════════════════════ */

.ph-modal-loader {
  position: fixed;
  inset: 0;
  z-index: 1500;                     /* above drawer (1200) and app bar (1300) */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: ph-modal-in .18s ease;
}

.ph-modal-loader__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  min-width: 236px;
  max-width: 340px;
  border-radius: 12px;
  text-align: center;
  animation: ph-modal-rise .22s cubic-bezier(.16, 1, .3, 1);
}

.ph-modal-loader__brand   { font-weight: 700; line-height: 1.2; }
.ph-modal-loader__product { font-weight: 700; text-transform: uppercase; }
.ph-modal-loader__label   { font-size: 13px; font-weight: 500; line-height: 1.45; }

/* Thin indeterminate sweep under the label — reinforces "working" without a
   second spinner competing with the globe. */
.ph-modal-loader__track {
  position: relative;
  width: 100%;
  height: 2px;
  border-radius: 1px;
  overflow: hidden;
}
.ph-modal-loader__track i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 42%;
  animation: ph-modal-sweep 1.25s ease-in-out infinite;
}

@keyframes ph-modal-in    { from { opacity: 0; } to { opacity: 1; } }
@keyframes ph-modal-rise  { from { opacity: 0; transform: translateY(10px) scale(.97); }
                            to   { opacity: 1; transform: none; } }
@keyframes ph-modal-sweep { 0% { transform: translateX(-100%); } 100% { transform: translateX(340%); } }

/* ════ M2 · CYAN BRAND CARD (the default) ═════════════════════════════════
   Cyan gradient fill, white knockout globe, white reverse lockup — the
   Trademark Global brand tile mapped to a modal.
   ═════════════════════════════════════════════════════════════════════════ */

/* Deeper scrim: a cyan card on a pale scrim floats; on a deep one it reads as
   deliberate. */
.ph-modal-loader--brand {
  background: rgba(12, 42, 54, .52);
  backdrop-filter: blur(4px);
}
[data-mud-theme="dark"] .ph-modal-loader--brand {
  background: rgba(0, 0, 0, .62);
}

.ph-modal-loader__card--brand {
  position: relative;
  overflow: hidden;
  border: 0;
  padding: 34px 38px 28px;
  background: linear-gradient(157deg,
    var(--ph-brand-1, #33C5EA) 0%,
    var(--ph-brand-2, #00B2E2) 48%,
    var(--ph-brand-3, #0090B5) 100%);
  box-shadow: 0 20px 54px rgba(0, 130, 165, .34);
}

/* Two radial washes give the flat cyan depth — same treatment as the sign-in
   panel, so the app's brand surfaces feel related. */
.ph-modal-loader__card--brand::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 76% 58% at 78% 4%,  rgba(255, 255, 255, .22), transparent 62%),
    radial-gradient(ellipse 64% 54% at 4% 100%, rgba(0, 0, 0, .16),       transparent 58%);
}
.ph-modal-loader__card--brand > * { position: relative; }

/* ── Knockout globe: white strokes on cyan ───────────────────────────────── */
.ph-modal-loader__card--brand .ph-globe__edge { stroke: #fff; opacity: .34; }
.ph-modal-loader__card--brand .ph-globe__lat  { stroke: #fff; opacity: .42; }
.ph-modal-loader__card--brand .ph-globe__mer  {
  stroke: #fff;
  animation-name: ph-globe-spin-knockout;
}

/* White strokes need a wider contrast range than cyan-on-white to read at the limb. */
@keyframes ph-globe-spin-knockout {
  0%   { rx: 26;  opacity: .34; }
  25%  { rx: 8;   opacity: 1;   }
  50%  { rx: 0.4; opacity: .34; }
  75%  { rx: 8;   opacity: 1;   }
  100% { rx: 26;  opacity: .34; }
}

.ph-modal-loader__card--brand .ph-globe {
  filter: drop-shadow(0 2px 10px rgba(0, 0, 0, .18));
}

/* ── Reverse lockup ──────────────────────────────────────────────────────── */
.ph-modal-loader__card--brand .ph-modal-loader__brand {
  color: #fff;
  font-size: 17px;
  letter-spacing: -.015em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .14);
}
.ph-modal-loader__card--brand .ph-modal-loader__product {
  color: rgba(255, 255, 255, .84);
  font-size: 10px;
  letter-spacing: .18em;
  margin-top: 3px;
}
.ph-modal-loader__card--brand .ph-modal-loader__label {
  color: rgba(255, 255, 255, .92);
}

.ph-modal-loader__rule {
  width: 34px;
  height: 2px;
  border-radius: 1px;
  background: rgba(255, 255, 255, .45);
}

.ph-modal-loader__card--brand .ph-modal-loader__track   { background: rgba(255, 255, 255, .22); }
.ph-modal-loader__card--brand .ph-modal-loader__track i {
  background: linear-gradient(90deg, transparent, #fff, transparent);
}

/* Dark mode: still cyan (it IS the brand) but a step down so it does not glare. */
[data-mud-theme="dark"] .ph-modal-loader__card--brand {
  --ph-brand-1: #00B2E2;
  --ph-brand-2: #0090B5;
  --ph-brand-3: #006F8C;
  box-shadow: 0 20px 54px rgba(0, 0, 0, .48);
}

/* ════ PLAIN CARD (opt-in via Plain="true") ═══════════════════════════════ */

.ph-modal-loader:not(.ph-modal-loader--brand) {
  background: rgba(244, 245, 247, .78);
  backdrop-filter: blur(3px);
}
[data-mud-theme="dark"] .ph-modal-loader:not(.ph-modal-loader--brand) {
  background: rgba(26, 26, 26, .80);
}

.ph-modal-loader__card:not(.ph-modal-loader__card--brand) {
  padding: 30px 34px 26px;
  background: var(--ph-surface);
  border: 1px solid var(--ph-divider);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .18);
}
.ph-modal-loader__card:not(.ph-modal-loader__card--brand) .ph-modal-loader__brand   { font-size: 15px; color: var(--ph-text); }
.ph-modal-loader__card:not(.ph-modal-loader__card--brand) .ph-modal-loader__product { font-size: 10.5px; letter-spacing: .1em; color: var(--ph-text-3); margin-top: 3px; }
.ph-modal-loader__card:not(.ph-modal-loader__card--brand) .ph-modal-loader__label   { color: var(--ph-text-2); }
.ph-modal-loader__card:not(.ph-modal-loader__card--brand) .ph-modal-loader__track   { background: rgba(0, 178, 226, .16); }
.ph-modal-loader__card:not(.ph-modal-loader__card--brand) .ph-modal-loader__track i {
  background: linear-gradient(90deg, transparent, var(--ph-primary), transparent);
}

/* ════ INLINE VARIANT (no scrim, no card) ═════════════════════════════════ */

.ph-globe-inline {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ph-text-2);
}
.ph-globe-inline .ph-globe { --ph-globe-size: 22px; }

/* ════ TOP PROGRESS BAR — the fast-operation companion ════════════════════
   The bar is instant; the modal waits 250ms. Short operations therefore show
   ONLY the bar, and long ones escalate to the modal. That progression is
   deliberate — do not remove the modal's delay to make it more visible.
   ═════════════════════════════════════════════════════════════════════════ */

.ph-progress {
  position: fixed;
  top: var(--ph-appbar-h, 64px);
  left: 0;
  right: 0;
  height: 3px;
  z-index: 1250;
  pointer-events: none;              /* never blocks interaction */
  opacity: 0;
  transition: opacity .18s ease;
}
.ph-progress--active { opacity: 1; }

.ph-progress__track {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: rgba(0, 178, 226, .18);
}
.ph-progress__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 40%;
  background: linear-gradient(90deg, transparent, var(--ph-primary) 35%,
                                     var(--ph-primary-light) 65%, transparent);
  animation: ph-indeterminate 1.15s ease-in-out infinite;
}
@keyframes ph-indeterminate {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(340%); }
}

/* ════ SKELETONS — first paint only ═══════════════════════════════════════ */

.ph-skel {
  display: inline-block;
  border-radius: 4px;
  background: linear-gradient(90deg, var(--ph-divider-light) 25%,
                                     var(--ph-divider) 37%,
                                     var(--ph-divider-light) 63%);
  background-size: 400% 100%;
  animation: ph-shimmer 1.4s ease-in-out infinite;
}
.ph-skel--circle { border-radius: 50%; }

@keyframes ph-shimmer {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* ════ BUTTON-BUSY — for the control that triggered the work ══════════════ */

.ph-btn-busy { position: relative; color: transparent !important; pointer-events: none; }
.ph-btn-busy::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 15px; height: 15px;
  margin: -7.5px 0 0 -7.5px;
  border: 2px solid rgba(255, 255, 255, .35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: ph-spin .7s linear infinite;
}
@keyframes ph-spin { to { transform: rotate(360deg); } }

/* ════ SCREEN-READER LIVE REGION ══════════════════════════════════════════ */

.ph-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ════ REDUCED MOTION ═════════════════════════════════════════════════════
   Meridians freeze at four distinct widths so the mark still reads as a globe;
   only the thin sweep remains as a motion cue.
   ═════════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .ph-globe__mer { animation: none; opacity: .55; }
  .ph-globe__mer--1 { rx: 26; }
  .ph-globe__mer--2 { rx: 17; }
  .ph-globe__mer--3 { rx: 9;  }
  .ph-globe__mer--4 { rx: 2;  }
  .ph-modal-loader__card--brand .ph-globe__mer { opacity: .6; }

  .ph-modal-loader,
  .ph-modal-loader__card { animation: none; }

  .ph-progress__fill {
    animation: ph-pulse 1.4s ease-in-out infinite;
    width: 100%;
    background: var(--ph-primary);
  }
  .ph-modal-loader__track i {
    animation: ph-pulse 1.5s ease-in-out infinite;
    width: 100%;
    background: #fff;
  }
  .ph-skel { animation: ph-pulse 1.6s ease-in-out infinite; }
  .ph-btn-busy::after { animation-duration: 1.4s; }

  @keyframes ph-pulse { 0%, 100% { opacity: .42; } 50% { opacity: 1; } }
}
