/* =========================================================================
   ambient.css — the sound control, and nothing else.

   `ambient.js` owns no fragment and may not edit one, so it INJECTS its
   control into the nav's own flex row at runtime and this sheet dresses it.
   That is the whole scope of this file: one button, one rail, one live
   region. It styles no page and it moves nothing that was already there.

   THIS SHEET HOLDS NO COLOUR OF ITS OWN, on the same rule as site.css. Every
   value below is a role token from theme.css or a colour-mix() against one,
   so an ember island and a pale jungle one get the same control and never the
   same face. A test refuses this file if a raw #hex, rgb() or hsl() ever
   appears in it.

   WHY IT LOOKS LIKE THE SIGN-IN BUTTON. It sits in the same row, at the same
   height, next to the same neighbours. A sound toggle that arrived with its
   own radius, its own weight and its own idea of a border is a second design
   system entering through the back door — which is exactly what the shared
   voice pack refuses to do, and this file is held to the same rule.
   ========================================================================= */

/* -------------------------------------------------------------------------
   THE GROUP
   Inline-flex so it packs against the session lane like everything else in
   `.nav-in`. `flex: none` because the nav row is a flex container and a
   control that shrinks under pressure is a control that becomes unclickable
   on the width where it matters most.
   ------------------------------------------------------------------------- */
.wc-aud {
  display: inline-flex;
  align-items: center;
  gap: 0;
  flex: none;
}

/* -------------------------------------------------------------------------
   THE BUTTON
   Geometry copied from `.nav-auth-btn` on purpose: 9px/13px padding, --r-s,
   a 1px --border hairline, 13.5px 600 UI. Anything else and the bar has two
   button shapes in it.
   ------------------------------------------------------------------------- */
.wc-aud-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 12px;
  border-radius: var(--r-s);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink-3);
  font: 600 13.5px/1 var(--font-ui);
  white-space: nowrap;
  cursor: pointer;
  transition: border-color .16s, color .16s, background .16s;
}
.wc-aud-btn:hover { border-color: var(--edge); color: var(--ink-1); }

/* FOCUS IS VISIBLE, ALWAYS. A keyboard player has to be able to see where
   they are; `outline: none` on a real control is the accessibility defect
   this codebase already refuses elsewhere. */
.wc-aud-btn:focus-visible,
.wc-aud-vol:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---- ON ----
   The accent is a MARK, not a fill: a tinted hairline and lit ink, the same
   grammar the current nav tab uses. A solid ember button in the top bar would
   out-shout the sign-in button, and the sound toggle is not the most
   important thing on the page. */
.wc-aud[data-on="1"] .wc-aud-btn {
  border-color: color-mix(in srgb, var(--accent) 52%, var(--border));
  background: var(--accent-wash);
  color: var(--accent-hi);
}
.wc-aud[data-on="1"] .wc-aud-btn:hover {
  border-color: var(--accent);
  color: var(--fg);
}

.wc-aud-btn svg { flex: none; }
.wc-aud-txt { display: inline-block; white-space: nowrap; }

/* ---- the icon says the state, and there are THREE of them ----
   `data-sounding` is "is this site making any sound at all" and `data-on` is
   "is the island bed playing". The slash belongs to the first, the arcs to the
   second, so the control reads correctly with no colour at all — colour is
   never the only signal, the same rule the live nav tab follows.

   Click-sounds mode is deliberately the middle picture: no slash, because the
   site is not muted, and ONE static arc, because nothing is playing. Painting
   the muted icon there was the old bug in miniature — a control that told
   people they had no sound while their buttons were clicking. */
.wc-aud[data-sounding="0"] .wc-aud-w1,
.wc-aud[data-sounding="0"] .wc-aud-w2 { display: none; }
.wc-aud[data-sounding="1"] .wc-aud-x { display: none; }
.wc-aud[data-sounding="1"][data-on="0"] .wc-aud-w2 { display: none; }

/* A slow, tiny breath on the outer arc while it is playing. It exists so a
   player can tell at a glance that the island is live rather than merely
   switched on. It is opacity only — nothing reflows, nothing repaints layout,
   and it is 4.6s so it never nags. */
@keyframes wc-aud-breathe {
  0%, 100% { opacity: .30; }
  50%      { opacity: 1; }
}
.wc-aud[data-on="1"] .wc-aud-w2 {
  animation: wc-aud-breathe 4.6s ease-in-out infinite;
}
.wc-aud[data-on="1"] .wc-aud-w1 {
  animation: wc-aud-breathe 4.6s ease-in-out infinite;
  animation-delay: .55s;
}

/* -------------------------------------------------------------------------
   THE VOLUME RAIL
   It appears only when the sound is ON, because a level control for something
   that is not playing is a stop on the way to the sign-in button and nothing
   else. It is a real <input type="range">: keyboard-operable, announced, and
   draggable on touch, all of it for free. Every hand-built substitute for a
   range input is worse than the one the platform ships.

   Width, not display, so it slides open rather than snapping the nav row's
   layout. `display: none` cannot be transitioned and a jumping top bar reads
   as a bug.

   ★ THE RAIL IS A CLIPPING WRAPPER AND THAT IS WHY IT EXISTS. site.css styles
   every bare `input` with `padding: 10px 12px; border: 1px; width: 100%` — a
   correct rule that stops a form control shipping as a white slab on a dark
   page, and one this control inherits whether it wants to or not. On a range
   collapsed to `width: 0` that padding and border are still 26px of box, so
   the slider's THUMB sat in the nav bar as a stray grey dot beside the word
   "Ambience" whenever the sound was off. Found in a screenshot, not in a
   test: no assertion in this repo can see a dot.

   The fix is structural rather than another override: the wrapper is
   `overflow: hidden` at `width: 0`, so nothing inside it can paint outside it
   no matter what a shared sheet does to a form control. The reset below is
   belt as well as braces.
   ------------------------------------------------------------------------- */
.wc-aud-rail {
  display: inline-flex;
  align-items: center;
  overflow: hidden;
  width: 0;
  transition: width .18s ease;
}
.wc-aud[data-on="1"] .wc-aud-rail { width: 76px; }

.wc-aud-vol {
  -webkit-appearance: none;
  appearance: none;
  flex: none;
  width: 62px;
  height: 18px;
  margin: 0 7px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

/* THE GROOVE SHOWS THE LEVEL. A rail that is one solid accent from end to end
   is a decoration, not a control: it reads as "full" at every setting. `--wc-v`
   is written by the script on every change, so the ember stops where the level
   does and the rest of the groove stays inert. */
.wc-aud-vol::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg,
              var(--accent) 0 var(--wc-v, 50%),
              var(--edge-hair) var(--wc-v, 50%) 100%);
}
.wc-aud-vol::-moz-range-track {
  height: 3px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg,
              var(--accent) 0 var(--wc-v, 50%),
              var(--edge-hair) var(--wc-v, 50%) 100%);
}

/* the grip: small, but with a real 18px hit box around it via the input's
   own height, so a thumb on a phone still lands on it */
.wc-aud-vol::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 11px;
  height: 11px;
  margin-top: -4px;
  border-radius: var(--r-round);
  border: 1px solid var(--edge-lit);
  background: var(--fg);
  cursor: pointer;
}
.wc-aud-vol::-moz-range-thumb {
  width: 11px;
  height: 11px;
  border-radius: var(--r-round);
  border: 1px solid var(--edge-lit);
  background: var(--fg);
  cursor: pointer;
}
.wc-aud-vol:disabled { cursor: default; }

/* -------------------------------------------------------------------------
   THE SPOKEN STATE
   aria-pressed is announced when the control takes FOCUS, not when it
   changes. A player who clicks the toggle and leaves focus where it was would
   otherwise get no confirmation at all that anything happened, which on a
   control whose only other feedback is a sound they just switched off is a
   dead end. So the state is also written into a polite live region, kept off
   the screen and out of the layout but never `display: none` — a hidden live
   region is a live region screen readers skip.
   ------------------------------------------------------------------------- */
.wc-aud-say {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  white-space: nowrap;
  border: 0;
  clip-path: inset(50%);
}

/* -------------------------------------------------------------------------
   THE FALLBACK MOUNT
   Only used when a page has no `.nav-in` and no live bar to sit in — a
   stripped placeholder page, or a fork that rebuilt its own chrome. It floats
   in the bottom-left corner, ABOVE the live bar rather than under it, using
   the site's own published --livebar-h so it moves when the bar does and
   still sits correctly on a page that has no bar at all.

   z-index 95 is a deliberate literal, not a token: the shared ladder in
   theme.py runs nav 60, livebar 90, skip 200, and this belongs in the gap
   between the bar it must clear and the skip link it must never cover. It is
   a stacking number rather than a colour, so it is not the sheet's business
   to abstract it.
   ------------------------------------------------------------------------- */
.wc-aud[data-mount="float"] {
  position: fixed;
  left: var(--gut, 20px);
  bottom: calc(14px + var(--livebar-h, 0px));
  z-index: 95;
  padding: 5px;
  border-radius: var(--r-s);
  background: var(--scrim-panel);
  box-shadow: var(--lift-2);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* -------------------------------------------------------------------------
   NARROW WIDTHS
   The nav drops its text labels at 400px and keeps the icons, so this does
   the same thing at the same breakpoint rather than inventing a third one.
   The rail narrows but does not leave: on a phone the level matters more than
   the word does, because there is no hover to discover it with.
   ------------------------------------------------------------------------- */
@media (max-width: 820px) {
  .wc-aud[data-on="1"] .wc-aud-rail { width: 66px; }
  .wc-aud-vol { width: 52px; }
}
@media (max-width: 400px) {
  .wc-aud-txt { display: none; }
  .wc-aud-btn { padding: 9px 10px; }
  .wc-aud[data-on="1"] .wc-aud-rail { width: 56px; }
  .wc-aud-vol { width: 44px; margin: 0 6px; }
}

/* -------------------------------------------------------------------------
   STILLNESS
   site.css already neutralises every animation globally under
   prefers-reduced-motion. This states it again for this control rather than
   relying on that, because "somebody else's rule covers me" is how a
   component ends up moving on the one page that sheet is not on.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .wc-aud[data-on="1"] .wc-aud-w1,
  .wc-aud[data-on="1"] .wc-aud-w2 { animation: none; opacity: 1; }
  .wc-aud-rail { transition: none; }
  .wc-aud-btn { transition: none; }
}
