/* Adamas Digital — ambient sound dock.
   The fixed bottom-right control that plays and pauses the site's audio bed.
   Loaded after site.css; nothing here touches the reference build's own
   selectors. The control is drawn as four stacked layers so the playing state
   can animate independently: a rotating signal ring, an outward pulse, the ink
   disc, and a live equalizer that flattens into a single line when sound is
   off. That flattened line — not a speaker glyph — is the off state, so the
   button reads as one continuous object rather than two swapped icons. */

.sound-dock {
  position: fixed;
  right: clamp(18px, 2.6vw, 34px);
  bottom: clamp(18px, 2.6vw, 34px);
  z-index: 46; /* one above .mobile-sticky-cta */
}

.sound-dock[hidden] { display: none; }

.sound-toggle {
  --sound-size: 64px;
  width: var(--sound-size);
  height: var(--sound-size);
  color: var(--paper);
  cursor: pointer;
  background: none;
  border: 0;
  place-items: center;
  padding: 0;
  display: grid;
  position: relative;
  transition: transform .35s cubic-bezier(.22, 1, .36, 1);
  -webkit-tap-highlight-color: transparent;
}

.sound-toggle:hover { transform: translateY(-3px); }
.sound-toggle:active { transform: translateY(-1px) scale(.97); }

/* The disc carries the focus ring — the button box itself is transparent. */
.sound-toggle:focus-visible { outline: 0; }
.sound-toggle:focus-visible .sound-core {
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 5px var(--blue-accent);
}

/* ---- Layer 1: signal ring -------------------------------------------
   A masked conic sweep sitting just outside the disc. Hidden while paused so
   the control stays quiet against light sections, then spun up on play. */
.sound-ring {
  border-radius: 50%;
  opacity: 0;
  background: conic-gradient(from 0deg, #0000 0 42%, var(--blue-accent) 70%, var(--paper) 88%, #0000 97%);
  transition: opacity .4s;
  position: absolute;
  inset: -4px;
  -webkit-mask: radial-gradient(closest-side, #0000 0 90%, #000 91%);
  mask: radial-gradient(closest-side, #0000 0 90%, #000 91%);
}

.sound-dock.is-playing .sound-ring {
  opacity: 1;
  animation: sound-spin 3.6s linear infinite;
}

/* ---- Layer 2: pulse --------------------------------------------------
   Two rings released on a half-cycle offset, so the dock keeps breathing
   even when the equalizer bars happen to line up flat. */
.sound-pulse {
  border-radius: 50%;
  pointer-events: none;
  position: absolute;
  inset: 0;
}

.sound-pulse:before,
.sound-pulse:after {
  content: "";
  border: 1px solid var(--blue-accent);
  border-radius: 50%;
  opacity: 0;
  position: absolute;
  inset: 0;
}

.sound-dock.is-playing .sound-pulse:before { animation: sound-pulse 2.8s ease-out infinite; }
.sound-dock.is-playing .sound-pulse:after { animation: sound-pulse 2.8s ease-out 1.4s infinite; }

/* ---- Layer 3: the disc ----------------------------------------------
   Ink on every background: the dock floats over the blue hero, white
   sections and dark sections alike, so it cannot borrow the page's colour. */
.sound-core {
  width: 100%;
  height: 100%;
  background: radial-gradient(120% 120% at 30% 18%, #2c2c3d 0%, var(--ink) 58%), var(--ink);
  border: 1px solid #ffffff24;
  border-radius: 50%;
  place-items: center;
  display: grid;
  position: relative;
  box-shadow: 0 16px 38px #0d0d0d59, inset 0 1px #ffffff1a;
  transition: box-shadow .4s, border-color .4s;
}

.sound-dock.is-playing .sound-core {
  border-color: #6d5cff7a;
  box-shadow: 0 16px 38px #0900704d, 0 0 26px #3f2bff3d, inset 0 1px #ffffff24;
}

/* ---- Layer 4: the equalizer ------------------------------------------ */
.sound-eq {
  align-items: center;
  gap: 3px;
  height: 22px;
  display: flex;
}

.sound-eq i {
  width: 2.5px;
  height: 100%;
  background: currentColor;
  border-radius: 999px;
  transform: scaleY(.11);
  transition: transform .45s cubic-bezier(.22, 1, .36, 1);
}

/* Staggered collapse reads as the sound settling, not as a state flip. */
.sound-eq i:nth-child(2) { transition-delay: .04s; }
.sound-eq i:nth-child(3) { transition-delay: .08s; }
.sound-eq i:nth-child(4) { transition-delay: .12s; }

/* Paused hover: the bars lift just enough to promise they will move. */
.sound-toggle:hover .sound-eq i { transform: scaleY(.32); }

/* Negative delays desynchronise the bars from the first frame — with four
   equal-phase bars the icon would otherwise open as a solid block. */
.sound-dock.is-playing .sound-eq i { animation: sound-bar 1s ease-in-out infinite; }
.sound-dock.is-playing .sound-eq i:nth-child(1) { animation-duration: .82s; animation-delay: -.2s; }
.sound-dock.is-playing .sound-eq i:nth-child(2) { animation-duration: 1.14s; animation-delay: -.55s; }
.sound-dock.is-playing .sound-eq i:nth-child(3) { animation-duration: .68s; animation-delay: -.1s; }
.sound-dock.is-playing .sound-eq i:nth-child(4) { animation-duration: 1.02s; animation-delay: -.4s; }

/* ---- Hover label ------------------------------------------------------
   An equalizer alone does not say "this makes noise", so name the action on
   hover and focus. translate keeps the vertical centring while transform
   stays free for the slide. */
.sound-label {
  white-space: nowrap;
  color: var(--paper);
  background: var(--ink);
  border-radius: 999px;
  align-items: center;
  gap: 5px;
  padding: 8px 13px;
  font-family: var(--display);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  opacity: 0;
  pointer-events: none;
  display: flex;
  position: absolute;
  top: 50%;
  right: calc(100% + 12px);
  translate: 0 -50%;
  transform: translateX(8px);
  box-shadow: 0 12px 28px #0d0d0d3d;
  transition: opacity .3s, transform .35s cubic-bezier(.22, 1, .36, 1);
}

.sound-toggle:hover .sound-label,
.sound-toggle:focus-visible .sound-label {
  opacity: 1;
  transform: translateX(0);
}

.sound-label b { color: var(--blue-accent); font-weight: 600; }

/* ---- Unavailable ------------------------------------------------------
   The track could not be loaded. The control stays put and stays clickable —
   a click calls load() and retries — but it dims, stops promising motion on
   hover, and holds its label open so the state explains itself. */
.sound-dock.is-unavailable .sound-core {
  background: var(--ink);
  border-color: #ffffff1a;
  box-shadow: 0 10px 24px #0d0d0d3d;
  opacity: .55;
}

.sound-dock.is-unavailable .sound-eq i,
.sound-dock.is-unavailable .sound-toggle:hover .sound-eq i { transform: scaleY(.11); }

.sound-dock.is-unavailable .sound-toggle:hover { transform: none; }

.sound-dock.is-unavailable .sound-label {
  opacity: 1;
  transform: translateX(0);
}

.sound-dock.is-unavailable .sound-label b { color: #9a9ab5; }

@keyframes sound-spin {
  to { transform: rotate(1turn); }
}

@keyframes sound-pulse {
  0% { opacity: .5; transform: scale(1); }
  70%, 100% { opacity: 0; transform: scale(1.75); }
}

@keyframes sound-bar {
  0%, 100% { transform: scaleY(.24); }
  50% { transform: scaleY(1); }
}

/* Below 720px .mobile-sticky-cta owns the bottom of the screen: a 48px pill
   at bottom:12px. Clear it, then clear the home indicator underneath. */
@media (max-width: 720px) {
  .sound-dock {
    right: 16px;
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
  }
  .sound-toggle { --sound-size: 54px; }
  /* No hover on touch, so the label has no trigger — except in the
     unavailable state, where it is the only explanation on offer. */
  .sound-label { display: none; }
  .sound-dock.is-unavailable .sound-label { display: flex; }
}

@media (prefers-reduced-motion: reduce) {
  .sound-toggle,
  .sound-core,
  .sound-label,
  .sound-eq i { transition-duration: .01ms; }

  .sound-dock.is-playing .sound-ring,
  .sound-dock.is-playing .sound-pulse:before,
  .sound-dock.is-playing .sound-pulse:after,
  .sound-dock.is-playing .sound-eq i { animation: none; }

  /* Still needs a legible on state — hold the bars open instead. */
  .sound-dock.is-playing .sound-eq i { transform: scaleY(.62); }
}
