/* =============================================================================
   CUSTOM LOADING OVERLAY
   Ported from the CodeCraftCo learnerships site. Geometry, timing and easing
   are unchanged from the original.

   The wordmark keeps its own colors in both themes: the letter-boxes stay dark
   chips with white borders/letters and the red/blue/orange glow. Only the
   backdrop and the surrounding text adapt to the active theme.

   See THEME DETECTION below for how dark/light is decided.
   ============================================================================= */

:root {
  /* --- wordmark: identical in every theme --------------------------------- */
  --ldr-glow-red:    #ff0000;
  --ldr-glow-blue:   #0099ff;
  --ldr-glow-orange: #ff8800;
  --ldr-box-fill:    rgba(60, 60, 60, 0.8);
  --ldr-box-line:    #fff;
  --ldr-letter:      #fff;

  /* --- theme-dependent: dark (default) ------------------------------------ */
  --ldr-bg-from:  #1e293b;
  --ldr-bg-to:    #0f172a;
  --ldr-halo:     rgba(66, 133, 244, 0.15);
  --ldr-text:     #ffffff;
  --ldr-text-dim: rgba(255, 255, 255, 0.8);
  --ldr-track:    rgba(255, 255, 255, 0.2);
}

/* ---------------------------------------------------------------------------
   THEME DETECTION
   The platform signals dark mode three different ways, because the shells were
   built separately and all three are still live:

     <html data-theme="dark">   staff shell  (static/js/staff-theme.js)
                                signup/public (static/js/brand-theme.js)
     .dark-theme on <html>/<body>
                                shop + customer shell
                                (customer_base.html, key 'codecraftco_theme')
     prefers-color-scheme       anything with no stored choice

   The loader honours all three so its backdrop is the same on every page in a
   given mode. Tokens are set on <body> for the class-based signal because that
   shell puts the class on <body>; the loader is always inside <body>, so those
   values reach it and, being the nearer ancestor, win.
   --------------------------------------------------------------------------- */

/* OS prefers light and nothing has explicitly asked for dark */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]):not(.dark-theme) {
    --ldr-bg-from:  #ffffff;
    --ldr-bg-to:    #f9fafb;
    --ldr-halo:     rgba(66, 133, 244, 0.12);
    --ldr-text:     #1f2937;
    --ldr-text-dim: #4b5563;
    --ldr-track:    rgba(0, 0, 0, 0.12);
  }
}

/* Explicit light choice, regardless of OS preference */
:root[data-theme="light"]:not(.dark-theme) {
  --ldr-bg-from:  #ffffff;
  --ldr-bg-to:    #f9fafb;
  --ldr-halo:     rgba(66, 133, 244, 0.12);
  --ldr-text:     #1f2937;
  --ldr-text-dim: #4b5563;
  --ldr-track:    rgba(0, 0, 0, 0.12);
}

/* Explicit dark from EITHER mechanism. Declared last so it beats both rules
   above: a shop visitor who toggled dark on a light OS still gets the dark
   backdrop, which is the case the class-only signal used to get wrong. */
:root[data-theme="dark"],
:root.dark-theme,
body.dark-theme {
  --ldr-bg-from:  #1e293b;
  --ldr-bg-to:    #0f172a;
  --ldr-halo:     rgba(66, 133, 244, 0.15);
  --ldr-text:     #ffffff;
  --ldr-text-dim: rgba(255, 255, 255, 0.8);
  --ldr-track:    rgba(255, 255, 255, 0.2);
}

/* === OVERLAY ============================================================== */
.custom-loading-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  background: linear-gradient(135deg, var(--ldr-bg-from) 0%, var(--ldr-bg-to) 100%);
  z-index: 10000;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.custom-loading-overlay.active {
  opacity: 1;
  visibility: visible;
}

.custom-loading-overlay::before {
  content: '';
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background: radial-gradient(circle, var(--ldr-halo) 0%, transparent 60%);
  animation: rotateBg 25s linear infinite;
  z-index: 0;
}

@keyframes rotateBg {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* === LOGO ================================================================= */
:is(.custom-loading-overlay, .brand-ldr) .logo-loader {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px;
  animation: pulseLogo 4s ease-in-out infinite;
}

@keyframes pulseLogo {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(1.05); opacity: 0.9; }
}

:is(.custom-loading-overlay, .brand-ldr) .word {
  display: flex;
  align-items: center;
  gap: 2px;
}

:is(.custom-loading-overlay, .brand-ldr) .letter-box {
  width: var(--ldr-box-size, clamp(48px, 6vw, 60px));
  height: var(--ldr-box-size, clamp(48px, 6vw, 60px));
  border: 2px solid var(--ldr-box-line);
  background: var(--ldr-box-fill);
  display: flex;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
  backdrop-filter: blur(10px);
}

:is(.custom-loading-overlay, .brand-ldr) .letter {
  color: var(--ldr-letter);
  font-size: var(--ldr-font-size, clamp(22px, 2.6vw, 28px));
  font-weight: 800;
}

/* Sits on the backdrop, so it follows the theme text color */
:is(.custom-loading-overlay, .brand-ldr) .word-text {
  color: var(--ldr-text);
  font-size: var(--ldr-font-size, clamp(22px, 2.6vw, 28px));
  font-weight: 500;
  margin-left: 4px;
}

/* === CONSTANT GLOW ANIMATION ============================================== */
@keyframes glowRed {
  0%, 100% { box-shadow: 0 0 18px var(--ldr-glow-red), 0 0 40px var(--ldr-glow-red); }
  50%      { box-shadow: 0 0 6px  var(--ldr-glow-red), 0 0 16px var(--ldr-glow-red); }
}
@keyframes glowBlue {
  0%, 100% { box-shadow: 0 0 18px var(--ldr-glow-blue), 0 0 40px var(--ldr-glow-blue); }
  50%      { box-shadow: 0 0 6px  var(--ldr-glow-blue), 0 0 16px var(--ldr-glow-blue); }
}
@keyframes glowOrange {
  0%, 100% { box-shadow: 0 0 18px var(--ldr-glow-orange), 0 0 40px var(--ldr-glow-orange); }
  50%      { box-shadow: 0 0 6px  var(--ldr-glow-orange), 0 0 16px var(--ldr-glow-orange); }
}

/* staggered start times give the trio depth */
:is(.custom-loading-overlay, .brand-ldr) .letter-box.red    { animation: glowRed    3s ease-in-out infinite; }
:is(.custom-loading-overlay, .brand-ldr) .letter-box.blue   { animation: glowBlue   3s ease-in-out infinite 0.5s; }
:is(.custom-loading-overlay, .brand-ldr) .letter-box.orange { animation: glowOrange 3s ease-in-out infinite 1s; }

/* === LOADING MESSAGE ====================================================== */
:is(.custom-loading-overlay, .brand-ldr) .loading-message {
  position: absolute;
  bottom: 20%;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  z-index: 2;
}

:is(.custom-loading-overlay, .brand-ldr) .loading-message h3 {
  color: var(--ldr-text);
  font-size: clamp(18px, 2vw, 24px);
  font-weight: 600;
  margin-bottom: 8px;
  animation: fadeInOut 2s ease-in-out infinite;
}

:is(.custom-loading-overlay, .brand-ldr) .loading-message p {
  color: var(--ldr-text-dim);
  font-size: clamp(14px, 1.5vw, 16px);
  font-weight: 400;
  margin: 0;
  animation: fadeInOut 2s ease-in-out infinite 0.5s;
}

@keyframes fadeInOut {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1; }
}

/* === PROGRESS INDICATOR =================================================== */
:is(.custom-loading-overlay, .brand-ldr) .loading-progress {
  position: absolute;
  bottom: 15%;
  left: 50%;
  transform: translateX(-50%);
  width: 200px;
  height: 2px;
  background: var(--ldr-track);
  border-radius: 1px;
  overflow: hidden;
  z-index: 2;
}

:is(.custom-loading-overlay, .brand-ldr) .loading-progress-bar {
  height: 100%;
  background: linear-gradient(90deg, var(--ldr-glow-red), var(--ldr-glow-blue), var(--ldr-glow-orange));
  width: 0%;
  animation: progressFlow 3s ease-in-out infinite;
  border-radius: 1px;
}

@keyframes progressFlow {
  0%   { width: 0%; }
  50%  { width: 70%; }
  100% { width: 100%; }
}

/* === FLASH MESSAGES COMPATIBILITY ========================================= */
.flash-messages {
  z-index: 10001; /* above the loading overlay */
}

/* === REDUCED MOTION ======================================================= */
@media (prefers-reduced-motion: reduce) {
  .custom-loading-overlay::before,
  :is(.custom-loading-overlay, .brand-ldr) .logo-loader,
  :is(.custom-loading-overlay, .brand-ldr) .letter-box,
  :is(.custom-loading-overlay, .brand-ldr) .loading-message h3,
  :is(.custom-loading-overlay, .brand-ldr) .loading-message p,
  :is(.custom-loading-overlay, .brand-ldr) .loading-progress-bar {
    animation: none;
  }
  :is(.custom-loading-overlay, .brand-ldr) .loading-progress-bar { width: 70%; }
}

/* =============================================================================
   INLINE VARIANT — .brand-ldr
   Same wordmark, same glow, no fixed positioning. Drop it inside a product
   grid, table cell or panel while that region's data is being fetched, instead
   of covering the whole screen. Sizes: .brand-ldr--sm, .brand-ldr--xs.
   Built by static/js/brand-loader.js — see BrandLoader.into().
   ============================================================================= */
.brand-ldr {
  /* The loader is a container, so cqi below measures THIS element's width —
     which is the width of whatever region it was dropped into. A loader in a
     wide product grid gets a big wordmark, the same loader in a narrow side
     panel or a phone-width column gets a small one, with no per-site tuning
     and no viewport media queries. Clamped so it never gets illegible or
     cartoonish at the extremes. */
  container-type: inline-size;

  --ldr-box-size:  clamp(20px, 2.8cqi, 34px);
  --ldr-font-size: clamp(11px, 1.55cqi, 18px);

  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 28px 16px;
  text-align: center;
  background: transparent;

  /* Hosts are usually auto-fill grids (.products-grid, .customers-grid, the
     POS grid) or flex columns. Without these the loader is handed ONE track
     -- 115-240px -- so the wordmark wraps into a vertical stack jammed against
     the left edge instead of centring across the region. */
  grid-column: 1 / -1;
  grid-row: auto;
  flex: 1 1 100%;
  align-self: stretch;
  justify-self: stretch;
  box-sizing: border-box;
}

/* The wordmark is one horizontal unit. Wrapping it produces the stacked
   "Code / raft / o" column; below 190px the trailing text is dropped instead
   (see the container query further down). */
.brand-ldr .logo-loader {
  flex-wrap: nowrap;
  max-width: 100%;
}

/* A host with align-items:stretch would otherwise pull the C boxes into tall
   rectangles -- they must stay square at exactly --ldr-box-size. */
.brand-ldr .letter-box {
  flex: 0 0 auto;
  aspect-ratio: 1 / 1;
  align-self: center;
}

.brand-ldr .word {
  flex: 0 0 auto;
  align-items: center;
}

.brand-ldr .word-text {
  white-space: nowrap;
}

/* The inline variant is laid out in flow, so the logo must not be absolute. */
.brand-ldr .loading-message,
.brand-ldr .loading-progress {
  position: static;
  transform: none;
  left: auto;
  bottom: auto;
}

.brand-ldr .logo-loader { gap: clamp(5px, 0.9cqi, 11px); }

.brand-ldr .loading-message h3 {
  font-size: clamp(10px, 1.1cqi, 13px);
  font-weight: 600;
  margin-bottom: 2px;
}

.brand-ldr .loading-message p {
  font-size: clamp(9px, 1cqi, 12px);
}

.brand-ldr .loading-progress {
  width: clamp(70px, 16cqi, 160px);
}

/* --- small: table cells, side panels, modal bodies ----------------------- */
.brand-ldr--sm {
  --ldr-box-size:  clamp(16px, 2.2cqi, 26px);
  --ldr-font-size: clamp(9px, 1.2cqi, 13px);
  gap: 8px;
  padding: 18px 12px;
}
.brand-ldr--sm .loading-progress { width: clamp(60px, 30cqi, 110px); }

/* --- extra small: stat tiles, thumbnails, inline values ------------------ */
.brand-ldr--xs {
  --ldr-box-size:  clamp(12px, 1.6cqi, 18px);
  --ldr-font-size: clamp(7px, 0.9cqi, 10px);
  gap: 6px;
  padding: 10px 8px;
}
.brand-ldr--xs .logo-loader      { gap: clamp(3px, 1cqi, 6px); }
.brand-ldr--xs .loading-progress { width: clamp(50px, 26cqi, 80px); }
/* the glow reads as a smudge at this size */
.brand-ldr--xs .letter-box { border-width: 1px; }

/* Very narrow hosts (a slim sidebar, a phone-width table cell): the three
   words wrap badly, so drop the trailing text and keep just the C boxes. */
@container (max-width: 120px) {
  .brand-ldr .word-text { display: none; }
  .brand-ldr .loading-message p { display: none; }
}

/* Inside a table, the loader is dropped into a <td> spanning the full row. */
td > .brand-ldr,
th > .brand-ldr {
  padding: 20px 12px;
}

/* =============================================================================
   OVERLAY VARIANT — .brand-ldr--overlay
   Covers an existing block (a stat card, a chart body) instead of replacing
   what is inside it. Required wherever the container's children must survive:
   a Chart.js <canvas> cannot be replaced with innerHTML and re-created, and a
   stat card should keep its icon and label while the number is still loading.
   Applied by BrandLoader.overlay() / removed by BrandLoader.clear().
   ============================================================================= */
.brand-ldr-host { position: relative; }

.brand-ldr--overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  width: auto;
  padding: 8px;
  border-radius: inherit;

  /* Exactly the backdrop the full-screen loader uses, and fully opaque: the
     block's stale content and icons must not read through it, and the colour
     must match the loader everywhere else on the platform. */
  background: linear-gradient(135deg, var(--ldr-bg-from) 0%, var(--ldr-bg-to) 100%);

  /* It is absolutely positioned, so the grid/flex spanning rules above do not
     apply and must not leak in. */
  grid-column: auto;
  flex: none;
  align-self: auto;
  justify-self: auto;
}

/* --- logo only: no caption, no progress bar --------------------------------
   For small blocks (stat cards) where a caption and a progress bar are just
   noise -- the card's own label already says what is loading. */
.brand-ldr--logo .loading-message,
.brand-ldr--logo .loading-progress {
  display: none;
}

/* An overlay sizes to the BLOCK it covers, so the wordmark is measured against
   the card/chart width rather than a full-width region. */
.brand-ldr--overlay {
  /* Tuned so the COMPLETE wordmark -- boxes plus "ode/raft/o" -- fits inside a
     stat card (~180px) without the trailing text being dropped. */
  --ldr-box-size:  clamp(11px, 7cqi, 18px);
  --ldr-font-size: clamp(6px, 4cqi, 10px);
}

/* A chart block is large, so its caption should not inherit the tiny sizing
   meant for narrow inline regions. */
.brand-ldr--overlay .loading-message h3 {
  font-size: clamp(10px, 1.5cqi, 12px);
  margin-top: 2px;
}
.brand-ldr--overlay .loading-progress {
  width: clamp(70px, 16cqi, 120px);
}
.brand-ldr--overlay .logo-loader { gap: clamp(4px, 0.7cqi, 8px); }

/* =============================================================================
   NAV WORDMARK — .logo-container
   The header logo uses the same .word / .letter-box / .word-text markup as the
   loader, but every page styled it separately: 24px boxes squashed by
   transform: scale(.7), a weak 6px glow, Arial/bold letters. The result did not
   match the loader it sits next to, and drifted from page to page.

   One definition here, loaded after each page's own <style>, so the nav logo is
   identical everywhere and matches the loader's treatment. Size is explicit
   rather than a scale() hack, and the glow is steady -- a header should not
   pulse the way a loading state does.
   ============================================================================= */
.logo-container {
  display: flex;
  align-items: center;
  gap: 6px;
  transform: none;
  transform-origin: left center;

  --ldr-box-size: 20px;
  --ldr-font-size: 11px;
}

.logo-container .word {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 0 0 auto;
}

.logo-container .letter-box {
  width: var(--ldr-box-size);
  height: var(--ldr-box-size);
  flex: 0 0 auto;
  aspect-ratio: 1 / 1;
  box-sizing: border-box;
  background: var(--ldr-box-fill);
  border: 2px solid var(--ldr-box-line);
  display: flex;
  align-items: center;
  justify-content: center;
}

.logo-container .letter {
  color: var(--ldr-letter);
  font-size: var(--ldr-font-size);
  font-weight: 800;
  line-height: 1;
  font-family: inherit;
}

.logo-container .word-text {
  color: var(--ldr-text);
  font-size: 13px;
  font-weight: 500;
  margin-left: 3px;
  white-space: nowrap;
  font-family: inherit;
}

/* Same hues as the loader, held steady instead of animated. */
.logo-container .letter-box.red    { box-shadow: 0 0 8px var(--ldr-glow-red); }
.logo-container .letter-box.blue   { box-shadow: 0 0 8px var(--ldr-glow-blue); }
.logo-container .letter-box.orange { box-shadow: 0 0 8px var(--ldr-glow-orange); }

/* Footer / compact placements keep the same look, one step smaller. */
.footer-brand .logo-container,
.footer-logo .logo-container {
  --ldr-box-size: 17px;
  --ldr-font-size: 9px;
}
.footer-brand .logo-container .word-text,
.footer-logo .logo-container .word-text { font-size: 11px; }
