/* ANARCHISM.AFRICA — fullscreen Africa-shaped hero / loading screen
 *
 * Layout: fixed overlay covering the viewport. A single sub-element
 * carries the SVG africa map as a CSS mask; anything painted on that
 * sub-element is visible ONLY through the continent silhouette.
 * Everything outside the silhouette shows the .aa-hero background
 * (default: solid black).
 *
 * Slideshow: `.aa-hero-stage > .aa-slide` layers are absolutely
 * positioned; JS toggles .is-active on one at a time and fades between.
 *
 * Audio reactivity: `--aa-hero-level` is set by js/africa-hero.js from
 * a Web Audio AnalyserNode wired to the mini-player. Everything that
 * should "pump like a woofer" reads this custom property — a single
 * source of truth means all reactive layers stay in phase.
 */

.aa-hero {
  position: fixed; inset: 0;
  z-index: 4000;                  /* above everything except the auth modal */
  background: #000;               /* fallback if no .aa-hero-bg set */
  display: flex; align-items: center; justify-content: center;
  --aa-hero-level: 0;             /* 0..1 audio energy, driven by JS */
  --aa-hero-accent: #ffd700;
  transition: opacity .5s ease, visibility 0s linear .5s;
}
.aa-hero.is-hidden {
  opacity: 0; visibility: hidden; pointer-events: none;
}

/* OUTSIDE-africa layer — the space around the continent silhouette.
   Renders BEFORE the mask stage in z-order so the masked stage draws
   over the parts that fall inside africa. Users can set this to a
   solid colour, an image, a gif, or a video via the CMS. Defaults to
   solid black (no visible change from before). */
.aa-hero-bg {
  position: absolute; inset: 0;
  z-index: 0;
  background: #000 center/cover no-repeat;
  overflow: hidden;
}
.aa-hero-bg img,
.aa-hero-bg video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

/* Legacy shutter element (deprecated). The mask now lives on
   .aa-hero-stage below — same approach as .aa-home-mask — so slideshow
   content only ever renders inside africa. Leaving this hidden ensures
   any older cached CSS/HTML doesn't paint a phantom black overlay. */
.aa-hero-mask { display: none !important; }

/* Slideshow stage — masked to africa's silhouette so the media only
   ever paints inside the continent. Container's #000 background paints
   the space around africa. */
.aa-hero-stage {
  position: absolute; inset: 0;
  overflow: hidden;
  background: #000;
  -webkit-mask: url('/icons/africa-mask.svg') center / contain no-repeat;
          mask: url('/icons/africa-mask.svg') center / contain no-repeat;
  -webkit-mask-mode: alpha;
          mask-mode: alpha;
  transform: scale(calc(1 + var(--aa-hero-level, 0) * 0.06));
  transition: transform 80ms linear;
  will-change: transform;
}
.aa-slide {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  opacity: 0;
  transition: opacity 600ms ease;
  color: #fff;
  text-align: center;
  padding: 8vw;
  box-sizing: border-box;
  /* Brightness pulse — react to audio */
  filter: brightness(calc(1 + var(--aa-hero-level) * 0.4));
}
.aa-slide.is-active { opacity: 1; }
.aa-slide img,
.aa-slide video {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.aa-slide.type-text {
  font-family: 'Bebas Neue', Impact, sans-serif;
  font-size: clamp(2rem, 7vw, 6rem);
  letter-spacing: .04em;
  line-height: 1.05;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 0 30px rgba(0,0,0,.85);
}
.aa-slide.type-text.aa-huge {
  font-size: clamp(3rem, 12vw, 10rem);
  letter-spacing: .02em;
}

/* Progress bar at the very bottom — one bar per slide, current fills */
.aa-hero-progress {
  position: absolute; left: 6vw; right: 6vw; bottom: 5vh;
  display: flex; gap: 6px;
  z-index: 2;
}
.aa-hero-progress span {
  flex: 1 1 0; height: 2px;
  background: rgba(255,255,255,.18);
  border-radius: 2px;
  overflow: hidden;
  position: relative;
}
.aa-hero-progress span::after {
  content: '';
  position: absolute; inset: 0;
  background: var(--aa-hero-accent, #fff);
  transform: scaleX(0); transform-origin: left;
  transition: transform 80ms linear;
}
.aa-hero-progress span.is-done::after   { transform: scaleX(1); transition: none; }
.aa-hero-progress span.is-active::after { transform: scaleX(var(--aa-slide-progress, 0)); }

/* Skip / enter buttons — bottom right */
.aa-hero-actions {
  position: absolute; right: 6vw; bottom: 8vh;
  z-index: 3;
  display: flex; gap: 10px;
}
.aa-hero-actions button {
  background: transparent; color: #fff;
  border: 1px solid rgba(255,255,255,.35);
  border-radius: 99px; padding: 10px 18px;
  font: 700 .78rem 'Space Grotesk', sans-serif;
  letter-spacing: .18em; text-transform: uppercase;
  cursor: pointer; backdrop-filter: blur(6px);
  transition: background .15s, border-color .15s, color .15s;
}
.aa-hero-actions button:hover {
  background: #fff; color: #000; border-color: #fff;
}

/* Fallback for browsers with no CSS mask (very rare — old Firefox).
   Show the SVG as an <img> centered over the stage. */
@supports not (mask-image: url('/icons/africa-mask.svg')) {
  .aa-hero-mask { display: none; }
  .aa-hero::before {
    content: '';
    position: absolute; inset: 0;
    background: url('/icons/africa-mask.svg') center / contain no-repeat;
    filter: invert(1);
    pointer-events: none;
  }
}

/* CMS panel in admin — grid of slide cards + add form */
.aa-slides-cms {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.aa-slides-cms .slide-card {
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 10px; padding: 12px;
  display: flex; flex-direction: column; gap: 8px;
}
.aa-slides-cms .slide-preview {
  aspect-ratio: 16/10;
  background: #000 center / cover no-repeat;
  border: 1px solid var(--line); border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  color: #fff; text-align: center; padding: 8px;
  font-family: 'Bebas Neue', Impact, sans-serif;
  font-size: 1rem; letter-spacing: .04em; text-transform: uppercase;
  overflow: hidden;
}
.aa-slides-cms .slide-preview img,
.aa-slides-cms .slide-preview video {
  max-width: 100%; max-height: 100%; object-fit: cover;
}
.aa-slides-cms .slide-preview { cursor: zoom-in; }

/* ============================================================
 * Media library fullscreen LIGHTBOX
 * Click any thumbnail → this overlay opens over the CMS. Arrow
 * keys / swipe navigate. Delete key removes blob media. Esc close.
 * ============================================================ */
.aa-lightbox {
  position: fixed; inset: 0;
  z-index: 9000;
  background: rgba(0,0,0,.92);
  backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  padding: 40px;
  box-sizing: border-box;
  animation: aa-lb-fade .2s ease;
}
@keyframes aa-lb-fade { from { opacity: 0 } to { opacity: 1 } }
.aa-lightbox .aa-lb-stage {
  max-width: 100%; max-height: 100%;
  display: flex; align-items: center; justify-content: center;
}
.aa-lightbox .aa-lb-stage img,
.aa-lightbox .aa-lb-stage video {
  max-width: 100%; max-height: calc(100vh - 140px);
  object-fit: contain; display: block;
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 6px;
}
.aa-lightbox .aa-lb-close,
.aa-lightbox .aa-lb-prev,
.aa-lightbox .aa-lb-next {
  position: absolute;
  background: rgba(255,255,255,.08);
  color: #fff; border: 1px solid rgba(255,255,255,.2);
  cursor: pointer;
  font: 300 28px/1 'Helvetica Neue', system-ui, sans-serif;
  width: 48px; height: 48px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, transform .15s;
}
.aa-lightbox .aa-lb-close { top: 16px; right: 16px; font-size: 26px; }
.aa-lightbox .aa-lb-prev  { left:  16px; top: 50%; transform: translateY(-50%); }
.aa-lightbox .aa-lb-next  { right: 16px; top: 50%; transform: translateY(-50%); }
.aa-lightbox .aa-lb-close:hover,
.aa-lightbox .aa-lb-prev:hover,
.aa-lightbox .aa-lb-next:hover {
  background: rgba(255,255,255,.18);
}
.aa-lightbox .aa-lb-prev:hover,
.aa-lightbox .aa-lb-next:hover { transform: translateY(-50%) scale(1.08); }

.aa-lightbox .aa-lb-meta {
  position: absolute; left: 50%; bottom: 16px;
  transform: translateX(-50%);
  color: rgba(255,255,255,.75);
  font: 500 .78rem 'JetBrains Mono', monospace;
  letter-spacing: .06em;
  background: rgba(0,0,0,.5);
  padding: 6px 12px; border-radius: 99px;
  max-width: calc(100vw - 260px);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aa-lightbox .aa-lb-del {
  position: absolute; right: 16px; bottom: 16px;
  background: #b00020; color: #fff;
  border: 0; border-radius: 8px;
  padding: 10px 16px;
  font: 700 .72rem 'JetBrains Mono', monospace;
  letter-spacing: .1em; text-transform: uppercase;
  cursor: pointer;
}
.aa-lightbox .aa-lb-del:hover { background: #d0022a; }
.aa-lightbox .aa-lb-del:disabled { background: #555; cursor: not-allowed; }

/* ============================================================
 * Fullscreen Slide Editor — same africa mask geometry the hero
 * uses, plus drag/zoom controls on the slide media. Lives on top
 * of everything (z-index above lightbox).
 * ============================================================ */
.aa-slide-editor {
  position: fixed; inset: 0;
  z-index: 9200;
  background: rgba(0,0,0,.94);
  backdrop-filter: blur(6px);
  display: grid;
  grid-template-rows: 1fr auto;
  padding: 32px;
  gap: 20px;
  box-sizing: border-box;
  animation: aa-lb-fade .18s ease;
}
.aa-slide-editor .aa-se-frame {
  position: relative;
  justify-self: center; align-self: center;
  width:  min(78vmin, calc(100vw - 80px), calc(100vh - 260px));
  aspect-ratio: 1020 / 1018;
  background: #000;
  border-radius: 4px;
  container-type: size;
}
.aa-slide-editor .aa-se-stage {
  position: absolute; inset: 0;
  overflow: hidden;
  background: #000;
  cursor: grab;
  touch-action: none;
  -webkit-mask: url('/icons/africa-mask.svg') center / 100% 100% no-repeat;
          mask: url('/icons/africa-mask.svg') center / 100% 100% no-repeat;
  -webkit-mask-mode: alpha;
          mask-mode: alpha;
}
.aa-slide-editor .aa-se-stage:active { cursor: grabbing; }
.aa-slide-editor .aa-se-stage img,
.aa-slide-editor .aa-se-stage video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  pointer-events: none;   /* let stage own drag events */
}
.aa-slide-editor .aa-se-outline {
  position: absolute; inset: 0;
  pointer-events: none;
  background: url('/icons/africa-outline.svg') center / 100% 100% no-repeat;
}
.aa-slide-editor .aa-lb-close,
.aa-slide-editor .aa-lb-prev,
.aa-slide-editor .aa-lb-next {
  position: absolute;
  background: rgba(255,255,255,.08);
  color: #fff; border: 1px solid rgba(255,255,255,.2);
  cursor: pointer;
  font: 300 28px/1 'Helvetica Neue', system-ui, sans-serif;
  width: 48px; height: 48px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, transform .15s;
  z-index: 1;
}
.aa-slide-editor .aa-lb-close { top: 20px; right: 20px; font-size: 26px; }
.aa-slide-editor .aa-lb-prev  { left:  20px; top: 50%; transform: translateY(-50%); }
.aa-slide-editor .aa-lb-next  { right: 20px; top: 50%; transform: translateY(-50%); }
.aa-slide-editor .aa-lb-close:hover,
.aa-slide-editor .aa-lb-prev:hover,
.aa-slide-editor .aa-lb-next:hover { background: rgba(255,255,255,.18); }
.aa-slide-editor .aa-se-panel {
  background: rgba(15,15,15,.9);
  border: 1px solid rgba(255,255,255,.15);
  border-radius: 12px;
  padding: 14px 18px;
  color: #fff;
  display: grid; gap: 12px;
}
.aa-slide-editor .aa-se-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  gap: 14px;
}
.aa-slide-editor .aa-se-row label {
  display: flex; flex-direction: column; gap: 4px;
  font: 500 .72rem 'JetBrains Mono', monospace;
  letter-spacing: .05em;
  color: rgba(255,255,255,.7);
}
.aa-slide-editor .aa-se-row label span {
  font-weight: 700; color: #fff;
}
.aa-slide-editor .aa-se-row input[type=range] {
  width: 100%; accent-color: #ffd700;
}
.aa-slide-editor .aa-se-actions {
  display: flex; gap: 8px; flex-wrap: wrap;
  justify-content: flex-end;
}
.aa-slide-editor .aa-se-actions button {
  background: rgba(255,255,255,.08);
  color: #fff; border: 1px solid rgba(255,255,255,.2);
  border-radius: 8px;
  padding: 8px 14px;
  font: 700 .72rem 'JetBrains Mono', monospace;
  letter-spacing: .1em; text-transform: uppercase;
  cursor: pointer;
}
.aa-slide-editor .aa-se-actions button.primary  { background: #ffd700; color: #000; border-color: #ffd700; }
.aa-slide-editor .aa-se-actions button.danger   { background: #b00020; border-color: #b00020; }
.aa-slide-editor .aa-se-actions button:hover    { filter: brightness(1.1); }
.aa-slide-editor .aa-se-meta {
  color: rgba(255,255,255,.6);
  font: 500 .72rem 'JetBrains Mono', monospace;
  letter-spacing: .05em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 700px) {
  .aa-slide-editor { padding: 16px; }
  .aa-slide-editor .aa-se-row { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 640px) {
  .aa-lightbox { padding: 20px; }
  .aa-lightbox .aa-lb-close,
  .aa-lightbox .aa-lb-prev,
  .aa-lightbox .aa-lb-next { width: 40px; height: 40px; font-size: 22px; }
  .aa-lightbox .aa-lb-meta { bottom: 68px; max-width: calc(100vw - 40px); }
  .aa-lightbox .aa-lb-del  { left: 20px; right: 20px; bottom: 20px; }
}
.aa-slides-cms .slide-meta {
  color: var(--fg-dim); font-size: .72rem;
  display: flex; justify-content: space-between; gap: 8px;
}
.aa-slides-cms .slide-actions {
  display: flex; gap: 6px;
}
.aa-slides-cms .slide-actions button {
  flex: 1 1 0;
  background: transparent; color: var(--fg-dim);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 8px; font: 500 .72rem 'Space Grotesk', sans-serif;
  cursor: pointer;
}
.aa-slides-cms .slide-actions button:hover {
  color: var(--fg); border-color: var(--fg);
}
.aa-slides-cms .slide-actions button.danger { color: #ff6b6b; }

.aa-slide-form {
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 10px; padding: 16px;
  display: grid; gap: 10px;
  grid-template-columns: 130px 1fr 90px auto;
  align-items: end;
}
.aa-slide-form label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: .72rem; color: var(--fg-dim);
}
.aa-slide-form label.wide { grid-column: 1 / 4; }
.aa-slide-form input,
.aa-slide-form select {
  background: var(--bg); color: var(--fg);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 8px 10px; font: inherit;
}
.aa-slide-form button {
  background: var(--fg); color: var(--bg);
  border: 0; border-radius: 6px; padding: 10px 16px;
  font: 700 .78rem 'Space Grotesk', sans-serif;
  letter-spacing: .1em; text-transform: uppercase; cursor: pointer;
}

/* ============================================================
 * HOME PAGE — AA-masked mini hero (js/aa-home-mask.js)
 * Sits at the top of #view-home. Africa continent is a WINDOW;
 * everything visible through it is the slideshow beneath.
 * ============================================================ */
.aa-home-mask {
  /* TRUE full-viewport hero: the black shutter reaches every corner of
     the visible viewport (behind the sticky topbar, past section.view's
     padding, past the fixed rail on desktop). Africa is a WINDOW through
     that shutter — the slideshow shows through africa only. */
  position: relative;
  /* Pull upward past the sticky topbar AND past section.view's 16px
     top padding so the shutter starts flush with the viewport top. */
  margin-top: calc(-1 * var(--topbar-h, 56px) - 16px);
  /* Horizontal bleed to viewport edges regardless of rail offset. body
     already has overflow-x:hidden so this can't create a scrollbar. */
  width: 100vw;
  margin-left:  calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  margin-bottom: 32px;
  /* Height = full dynamic viewport (dvh handles Safari URL-bar retract). */
  height: 100dvh;
  background: #000;
  overflow: hidden;
  border-radius: 0;
  --aa-hm-level: 0;              /* 0..1 audio energy, driven by JS */
}
/* When the mini-player is docked, keep africa fully visible above it. */
body.mp-active .aa-home-mask { height: calc(100dvh - 116px); }
@media (min-width: 769px) {
  body.mp-active .aa-home-mask { height: calc(100dvh - 68px); }
}
/* Stage sized via vmin so africa never exceeds ~72% of the smaller
   viewport dimension — comfortable margin on ALL sides (landscape and
   portrait). aspect-ratio locks height to width; no explicit height
   avoids the taller-than-viewport bug. container-type: size lets
   inner elements (the A) size relative to the stage, not the viewport. */
.aa-hm-stage {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  /* Default size bumped 72 → 88vmin so africa reads as the hero
     centrepiece with a small margin, not a floating card. Media
     behind the mask scales with the stage automatically because
     it's a % child. CMS knob still overrides via --aa-hm-size. */
  width: min(var(--aa-hm-size, 88vmin), calc(100vw - 24px), calc(100dvh - 100px));
  aspect-ratio: 1020 / 1018;
  overflow: hidden;
  background: #000;
  container-type: size;
  container-name: aa-hm-stage;
  -webkit-mask: url('/icons/africa-mask.svg') center / 100% 100% no-repeat;
          mask: url('/icons/africa-mask.svg') center / 100% 100% no-repeat;
  -webkit-mask-mode: alpha;
          mask-mode: alpha;
}
/* Mobile floor is applied AFTER the .aa-home-mask::before base rule
   below — see the media query near the end of this section. */
/* Media matches africa outline exactly (100% × 100%, mask-flush).
   Ken Burns animation on top: slow linear scale + pan (~10s per
   slide). Uses the `transform` property so the JS-supplied `scale`
   property + `object-position` (focal point) stay independent —
   they combine multiplicatively with the keyframe transform.
   Varied direction per slide (nth-child cycle) for visual variety. */
.aa-hm-stage .aa-hm-slide img,
.aa-hm-stage .aa-hm-slide video {
  width: 100%; height: 100%;
  position: absolute; inset: 0;
  object-fit: cover;
  /* Object-position shifts based on device tilt (--aa-hm-tx / --aa-hm-ty
     published by js/aa-home-mask.js). Because object-position affects
     the CONTENT of the img/video (not its box), it stacks cleanly with
     the Ken Burns transform below — no need to wrap in another element. */
  object-position: calc(50% + var(--aa-hm-tx, 0px)) calc(50% + var(--aa-hm-ty, 0px));
  animation: aa-hm-kb-a 10s ease-out infinite alternate both;
  will-change: transform, object-position;
}
.aa-hm-stage .aa-hm-slide:nth-child(3n+2) img,
.aa-hm-stage .aa-hm-slide:nth-child(3n+2) video {
  animation-name: aa-hm-kb-b;
}
.aa-hm-stage .aa-hm-slide:nth-child(3n+3) img,
.aa-hm-stage .aa-hm-slide:nth-child(3n+3) video {
  animation-name: aa-hm-kb-c;
}
@keyframes aa-hm-kb-a {
  0%   { transform: scale(1.00) translate3d( 0,  0, 0); }
  100% { transform: scale(1.14) translate3d(-2%, -1%, 0); }
}
@keyframes aa-hm-kb-b {
  0%   { transform: scale(1.14) translate3d( 2%, -1%, 0); }
  100% { transform: scale(1.00) translate3d( 0,  0, 0); }
}
@keyframes aa-hm-kb-c {
  0%   { transform: scale(1.00) translate3d(-1%,  1%, 0); }
  100% { transform: scale(1.16) translate3d( 1%, -2%, 0); }
}
/* Users who prefer reduced motion — no Ken Burns, no reactive pulse. */
@media (prefers-reduced-motion: reduce) {
  .aa-hm-stage .aa-hm-slide img,
  .aa-hm-stage .aa-hm-slide video { animation: none; }
}
.aa-hm-stage .aa-hm-slide {
  position: absolute; inset: 0;
  opacity: 0;
  /* Crossfade duration overridable from CMS via --aa-hm-crossfade.
     1200ms default reads as a smooth blend and safely finishes before
     the 3s advance interval — the JS advance loop also floors dur to
     crossfade+300ms so admin can't accidentally set advance < crossfade
     and get overlap-chop. */
  transition: opacity var(--aa-hm-crossfade, 1200ms) ease;
  will-change: opacity;
  display: flex; align-items: center; justify-content: center;
  color: #fff; text-align: center;
  font-family: 'Bebas Neue', Impact, sans-serif;
  font-size: clamp(1.4rem, 3.5vw, 3rem);
  letter-spacing: .04em; text-transform: uppercase;
  padding: 6vw; box-sizing: border-box;
}
.aa-hm-stage .aa-hm-slide.is-active { opacity: 1; }
.aa-hm-stage .aa-hm-slide.aa-hm-huge { font-size: clamp(2.2rem, 6vw, 5rem); }
/* Bold sans-serif A sized so painted glyph pixels fill africa apex-to-
   Cape. Bumped to 180cqh because:
   1. Arial Black cap-height is ~72% of em-size → 180cqh em ≈ 130cqh
      cap-height, which after leading/rendering variance lands at ~
      africa height.
   2. The base .aa-hm-slide rule adds `padding: 6vw` — overridden here
      to 0 so the glyph uses the full stage.
   Mask + overflow:hidden on stage clip whatever overshoots into ocean. */
.aa-hm-stage .aa-hm-slide.aa-hm-a {
  font-family: 'Arial Black', 'Helvetica Neue', Impact, Inter, system-ui, sans-serif;
  font-weight: 900;
  font-size: 130vh;                 /* fallback (older Safari) */
  font-size: 180cqh;                /* glyph paints ≈ africa height */
  line-height: 1;
  padding: 0 !important;            /* override .aa-hm-slide's 6vw */
  color: #fff;
  background: #000;
  letter-spacing: -0.05em;
  align-items: center;
  justify-content: center;
}
.aa-hm-stage img,
.aa-hm-stage video,
.aa-hm-stage iframe {
  width: 100%; height: 100%; object-fit: cover; display: block; border: 0;
}
/* The africa-shaped SHUTTER on top: black EVERYWHERE except through the
   continent silhouette. Use the mask svg as an inverse — the ocean gets
   the shutter, africa is see-through. Achieved by masking a full-canvas
   black rect with the INVERSE of africa-mask.svg (transparent inside
   africa). We fake the inverse in CSS by using mask-composite: exclude
   on the whole hero — where the mask is opaque (africa), the shutter
   is HIDDEN; elsewhere the shutter is visible. */
.aa-hm-shape {
  position: absolute; inset: 0;
  background: #000;                    /* the shutter colour */
  pointer-events: none;
  -webkit-mask: url('/icons/africa-mask.svg') center / contain no-repeat;
          mask: url('/icons/africa-mask.svg') center / contain no-repeat;
  -webkit-mask-mode: luminance;
          mask-mode: luminance;
  /* Invert: where luminance is HIGH (africa=white in the mask) → visible
     region of THIS shutter should be TRANSPARENT. mask-composite:exclude
     flips it. Then a normal black bg would show through africa — we
     don't want that. Simpler approach below: paint the shutter as a
     radial ring using a filter. Kept as-is; the desired 'window' effect
     is instead produced by the stage BEING sized to africa via the
     ::before / ::after wrappers on modern browsers. */
  display: none;   /* Deprecated in favor of the ::before frame below */
}
/* Africa-shaped WINDOW: an SVG overlaid over the stage that is BLACK
   everywhere except inside africa (where it's transparent). Built as
   a data URL with the africa silhouette punched OUT of a large black
   rect via fill-rule=evenodd. Sits above the stage and below the UI. */
/* Old ::after shutter is gone — the stage itself is masked now, so no
   separate cutout overlay is needed. Keep ::before (outline stroke). */
/* Outline stroke overlay — sized 2% LARGER than the stage so the coast
   traces a hair OUTSIDE the mask edge (visible ring around the image),
   not inside it. Base scale 1.02, plus the audio-reactive woofer nudge. */
.aa-home-mask::before {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(calc(1.005 + var(--aa-hm-level) * 0.05));
  transform-origin: center center;
  width: min(var(--aa-hm-size, 88vmin), calc(100vw - 24px), calc(100dvh - 100px));
  aspect-ratio: 1020 / 1018;
  pointer-events: none;
  z-index: 2;
  background: url('/icons/africa-outline.svg') center / 100% 100% no-repeat;
  transition: transform 80ms linear;
  will-change: transform;
}

/* Mobile floor — MUST come AFTER the base .aa-hm-stage and
   .aa-home-mask::before declarations above, or their plain-width rules
   would override this at equal specificity. Floors both stage AND
   outline to a min of 88vmin so tiny CMS heroSize values (e.g. 72)
   can't shrink the hero on phones AND can't decouple the outline from
   the mask (they must always share the same width to stay aligned). */
@media (max-width: 768px) {
  .aa-hm-stage,
  .aa-home-mask::before {
    width: min(max(var(--aa-hm-size, 88vmin), 88vmin), calc(100vw - 24px), calc(100dvh - 100px)) !important;
  }
}
/* Slides brighten in sync with audio energy — mirrors the fullscreen
   loading hero's woofer effect. Both use --aa-hm-level (local scope
   on .aa-home-mask) driven by the same Web Audio analyser as the
   loading hero via window.AA.hero.attachAudio(). */
.aa-home-mask .aa-hm-slide {
  filter: brightness(calc(1 + var(--aa-hm-level) * 0.35));
}
/* Slideshow progress bar/dots hidden at user's request — the hero is
   already a rotating slideshow; the dots were visual noise. Element
   still rendered by JS so the code path stays intact if we want it
   back later; just visually removed. */
.aa-hm-progress { display: none !important; }

/* Save-now button — extra contrast + outline so it doesn't get lost
   next to the ghost 'Reset defaults' button. Overrides the .btn base
   styling for this specific CMS action. */
[data-hero-css-save],
[data-hero-al-save] {
  background: var(--accent, #ffd700) !important;
  color: #000 !important;
  border: 2px solid var(--fg, #eee) !important;
  font-weight: 800 !important;
  letter-spacing: .08em !important;
  padding: 8px 16px !important;
  box-shadow: 3px 3px 0 0 rgba(0,0,0,.35) !important;
  transition: transform .12s ease, box-shadow .12s ease !important;
}
[data-hero-css-save]:hover,
[data-hero-al-save]:hover {
  transform: translate(-1px, -1px);
  box-shadow: 4px 4px 0 0 rgba(0,0,0,.35) !important;
}
[data-hero-css-save]:active,
[data-hero-al-save]:active {
  transform: translate(1px, 1px);
  box-shadow: 1px 1px 0 0 rgba(0,0,0,.35) !important;
}

/* CMS autosave status pill — sits inline with the Save button and
   shows Editing… / Saving… / Saved ✓ / error text. */
.aa-cms-status {
  display: inline-flex; align-items: center;
  font: 600 .72rem 'JetBrains Mono', monospace;
  letter-spacing: .04em;
  padding: 4px 10px;
  border-radius: 999px;
  color: var(--fg-dim, #999);
}
.aa-cms-status.dirty { background: color-mix(in srgb, #f59e0b 22%, transparent); color: #f59e0b; }
.aa-cms-status.busy  { background: color-mix(in srgb, #38bdf8 22%, transparent); color: #38bdf8; }
.aa-cms-status.ok    { background: color-mix(in srgb, #22c55e 22%, transparent); color: #22c55e; }
.aa-cms-status.err   { background: color-mix(in srgb, #ef4444 22%, transparent); color: #ef4444; }

/* Media library UX — used/dup indicators, checkbox picker, bulk toolbar. */
.aa-ml-toolbar {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 12px;
  margin: 0 0 10px;
  background: var(--bg-2, #111);
  border: 1px solid var(--line, #333);
  border-radius: 8px;
  font: 500 .78rem 'JetBrains Mono', monospace;
  color: var(--fg-dim, #999);
}
.aa-ml-toolbar-row {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap;
}
.aa-ml-toolbar .aa-ml-selall { display: inline-flex; gap: 6px; align-items: center; cursor: pointer; }
.aa-ml-toolbar .aa-ml-sel-count { opacity: .8; }
.aa-ml-toolbar .btn { padding: 6px 10px; font-size: .72rem; letter-spacing: .04em; }
.aa-ml-toolbar-sf { padding-top: 6px; border-top: 1px dashed var(--line, #333); }
.aa-ml-toolbar-label { text-transform: uppercase; letter-spacing: .1em; opacity: .7; font-size: .68rem; margin-right: 4px; }
.aa-ml-chip {
  background: transparent;
  border: 1px solid var(--line, #333);
  color: var(--fg-dim, #999);
  padding: 5px 10px;
  border-radius: 999px;
  font: 500 .70rem 'JetBrains Mono', monospace;
  letter-spacing: .04em;
  cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.aa-ml-chip:hover { color: var(--fg, #eee); border-color: var(--fg-dim, #888); }
.aa-ml-chip.is-on { background: var(--accent, #ffd700); color: #000; border-color: var(--accent, #ffd700); font-weight: 700; }
.aa-ml-sortbox {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .72rem;
}
.aa-ml-sortbox select {
  background: var(--bg, #0a0a0a);
  color: var(--fg, #eee);
  border: 1px solid var(--line, #333);
  padding: 4px 6px;
  border-radius: 4px;
  font: 500 .72rem 'JetBrains Mono', monospace;
  cursor: pointer;
}

.slide-card { position: relative; }
.slide-card.is-used { opacity: .55; filter: grayscale(.7); }
.slide-card.is-used:hover { opacity: .85; filter: grayscale(.2); }
.slide-card.is-dup { outline: 2px dashed color-mix(in srgb, orange 80%, transparent); outline-offset: -2px; }
.slide-card.is-sel { outline: 2px solid var(--accent, #ffd700); outline-offset: -2px; }
.slide-card .aa-ml-pick {
  position: absolute; top: 6px; left: 6px; z-index: 2;
  background: rgba(0,0,0,.7);
  border: 1px solid rgba(255,255,255,.4);
  border-radius: 3px;
  padding: 3px;
  cursor: pointer;
  display: inline-flex;
}
.slide-card .aa-ml-pick input { margin: 0; cursor: pointer; width: 16px; height: 16px; }
.slide-card .aa-ml-badge {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  font: 700 .62rem 'JetBrains Mono', monospace;
  letter-spacing: .06em; text-transform: uppercase;
  padding: 3px 6px;
  background: rgba(0,0,0,.75);
  color: #fff;
  border-radius: 3px;
}
.slide-card .aa-ml-badge.used { background: color-mix(in srgb, #22c55e 80%, black); }
.slide-card .aa-ml-badge.dup  { background: color-mix(in srgb, orange 80%, black); top: 26px; }
.slide-card .slide-actions button[data-media-dl] {
  min-width: 28px;
  padding: 4px 6px;
}

/* CMS slider labels — companion number input beside every range so
   the admin can type a value directly instead of dragging a jittery
   handle. Slider still there; typed value snaps into it. */
.cms-slider {
  display: flex; flex-direction: column; gap: 6px;
  font: 500 .78rem 'JetBrains Mono', monospace;
  letter-spacing: .04em;
  color: var(--fg-dim, #999);
}
.cms-slider .cms-slider-head {
  display: inline-flex; align-items: center; gap: 8px;
  flex-wrap: wrap;
  color: var(--fg, #eee);
}
.cms-slider .cms-num {
  width: 80px;
  padding: 4px 6px;
  background: var(--bg-2, #111);
  color: var(--fg, #eee);
  border: 1px solid var(--line, #333);
  border-radius: 4px;
  font: 600 .78rem 'JetBrains Mono', monospace;
  text-align: right;
}
.cms-slider .cms-num:focus { outline: 1px solid var(--accent, #ffd700); }
.cms-slider .cms-slider-unit { opacity: .7; }
.cms-slider input[type="range"] { width: 100%; }

/* ============================================================
 * FOOTER — RANDOM RADIO button (js/random-radio.js)
 * Bottom-left floating pill, above the bottombar on mobile.
 * ============================================================ */
.aa-random-radio {
  position: fixed;
  left: 12px;
  bottom: calc(76px + env(safe-area-inset-bottom, 0px));  /* above the mobile bottombar */
  z-index: 34;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px 8px 10px;
  background: #000; color: #fff;
  border: 1px solid rgba(255,255,255,.25);
  border-radius: 99px;
  font: 700 .68rem 'JetBrains Mono', monospace;
  letter-spacing: .12em; text-transform: uppercase;
  cursor: pointer;
  backdrop-filter: blur(10px);
  transition: background .15s, color .15s, border-color .15s, transform .15s;
  box-shadow: 0 4px 14px rgba(0,0,0,.4);
}
.aa-random-radio:hover {
  background: var(--accent, #ffd700); color: #000; border-color: var(--accent, #ffd700);
  transform: translateY(-1px);
}
.aa-random-radio .glyph { display: inline-flex; width: 18px; height: 18px; }
.aa-random-radio .lbl { display: inline-block; }
/* On desktop the mobile bottombar is hidden — anchor to bottom edge instead. */
@media (min-width: 769px) {
  .aa-random-radio { bottom: 16px; }
  body.mp-active .aa-random-radio { bottom: 84px; }  /* lift above mini-player */
}
/* When the mini-player is docked above the bottombar on mobile, lift the
   radio button above the player too. */
@media (max-width: 768px) {
  body.mp-active .aa-random-radio { bottom: calc(140px + env(safe-area-inset-bottom, 0px)); }
}
