/* ambience.css — TELETONICMD.COM (the clinic). The ambient sound control,
   in the practice's own dress.
   ===========================================================================
   WHICH SITE THIS IS, AND WHAT IS SHARED.

   Three sites offer this control: thetreatmenttapes.com, theterminologytales.com
   and this one, the clinic's marketing site. The ENGINE is shared — ambience.js
   is deliberately kept byte-identical across all three except for its storage
   key, so `diff` stays a useful review tool between them. If you improve the
   engine on any one site — the synthesis, the scheduler, the autoplay
   behaviour, the markup it generates — CARRY THE CHANGE TO THE OTHER TWO.
   Nothing in this stylesheet should ever be the reason that becomes awkward:
   it styles the markup ambience.js emits and adds no markup of its own.

   WHAT IS NOT SHARED IS THE LOOK, AND IT CANNOT BE. Both podcast sites are
   dark pages, so over there the control is a translucent ink pill with a blur
   behind it — glass over night, which is exactly right on a black ground. This
   page is warm cream (#FBF9F4). Glass over cream, scrolling past a portrait
   and a photograph of an exam room, is where legibility goes to die, and a
   dark pill dropped on cream reads as something that fell onto the page from
   another website. On a physician's site the one thing you cannot afford is
   chrome that looks borrowed. So this file is a redesign, not a recolour:
   every surface here is OPAQUE, the blur is gone, and the pill is paper.

   ---------------------------------------------------------------------------
   WHY SAGE, AND NOT A WHITE CARD.

   The obvious move was a white card with a hairline and the paper shadow, like
   every other card on the site. It was rejected: a white card parked over the
   page is one more object floating in front of the practice. So the pill is the
   leaf instead — --sage, the pastel this page already pours into this exact
   corner. The homepage hero's second radial sits at 6% 88% (index.html) and
   every subpage repeats it at 2% 54vh (site.css), both --sage-tint, both of
   them right here. The control belongs to that ground rather than sitting on
   top of it.

   It is also, deliberately, a sibling of the AzTechTonic chat bubble in the
   opposite corner, which is the same sage behind the same soft pine edge one
   alpha step down. Two small green controls hold the two bottom corners, and
   they read as one idea rather than two. The panel keeps the reading: a tray of
   that same wash, with the five beds as white paper inside it. Wash, then
   paper, then leaf.

   WHY BOTTOM LEFT. The chat bubble is fixed bottom right at z-index 10000
   (12px inset on phones, which this file mirrors). Two controls under one thumb
   is one control too many. We take the other corner at z-index 60 — above the
   page watermark (40), below the header (1000), far below the chat window,
   which always wins if they ever meet.

   ---------------------------------------------------------------------------
   THE ONE BRASS.

   The site spends its single metallic on the focus ring (--focus-ring, the
   brass-ink tone). That is this control's brass and its only one. The playing
   state therefore does NOT get a gold accent. It is carried by the pine ramp
   and by words — four channels at once, so no single one is load-bearing:

     1. the four bars turn --action and start moving
     2. the fill deepens one step within the same leaf, --sage to --sage-deep
     3. the edge goes from --label to --action
     4. the label stops saying "Ambience" and names the bed — "Distant storm"

   A reader who sees no colour at all still gets the sentence. Three of the four
   survive prefers-reduced-motion.

   ---------------------------------------------------------------------------
   CONTRAST LEDGER — every figure recomputed from brand-tokens.css v2.3, and
   each measured against the ground the pixel actually lands on, not the
   convenient one. The panel's tray is --sage-tint composited over --cream,
   which resolves to #E6F2E8 exactly; the homepage's bottom-left wash peaks at
   the same value, so the tray and the pill's ground are the same colour.

     PILL     --ink label on --sage 9.30 · on --sage-deep 8.90
              resting edge --label: 5.33 on cream, 4.86 on the wash, 4.90 on sand
              open edge --action-hover: 5.44 on cream, 4.96 on the wash
              playing edge --action: 7.09 on cream, 6.47 on the wash
     BARS     resting --action-hover on --sage 4.60 · playing --action on
              --sage-deep 5.74
     PANEL    --label 4.86 · --text-secondary 5.67 · --ink 10.04, all on #E6F2E8
     BEDS     title --ink on white 11.56 · note --text-muted on white 5.65
              hover edge --action-hover on white 5.72
     SELECTED --action title, edge and dot 6.00 on --sage · note
              --text-secondary 5.26 · hover edge --ink 9.30
     LEVEL    track (--ink at 60% over the tray, #69877D) 3.40 · thumb
              --action 6.47
     SILENCE  label --text-secondary 5.67 · edge (--ink at 58%, #6D8B80) 3.22
              hover ground is --ink-wash over the tray = #D9E7DD, and on it
              --ink text is 9.04 and the --action edge 5.83
     FOCUS    --focus-ring (--brass-ink): 5.75 cream · 6.05 white · 5.25 tray
              · 4.86 sage · 4.65 sage-deep

   BELOW 3:1 AND DELIBERATE — the complete list, not a sample. WCAG 1.4.11 asks
   3:1 of the visual information REQUIRED to identify a control or its state.
   None of these five is required for that, because in every case a
   contrast-passing text or shape is doing the identifying:

     1. --sage pill fill vs cream 1.18, vs the wash it actually sits on 1.08.
        The pill is identified by a 9.30:1 word and a 5.33:1 edge, never by its
        fill. (The fill being nearly invisible against the wash is the whole
        point of choosing it — and it is also why the resting EDGE is a full
        --label green rather than a soft ink tint: at 1.08:1 of fill contrast,
        the edge is the only thing that makes the pill an object.)
     2. --hairline bed edge on white 1.34. House card language; each bed is
        identified by its 11.56:1 title.
     3. Panel edge, --ink at 22% over the tray: 1.48 inward, 1.62 against the
        cream outside. Pure ornament — a container, not a control, so 1.4.11
        does not reach it. --shadow-lg does the separating.
     4. Selected bed's --sage fill vs the white row 1.24. The state is carried
        by a 6.00 edge, a 6.00 title and a dot that appears where there was no
        shape at all, so it is never colour alone.
     5. The tray vs cream, 1.09. The panel's tone step is intentionally almost
        nothing; the shadow and the content give it its edge.

   ---------------------------------------------------------------------------
   HOW THIS FILE BEHAVES INSIDE THE PAGE FRAME — three things worth knowing
   before anyone moves them:

     · The toast region (motion.css) is centred at bottom 1.5rem with z-index
       3000. On a 375px phone it overlaps this pill. The toast covers it, which
       is the right outcome — a confirmation the visitor asked for beats an
       ambience pill — and it is stated here so nobody discovers it as a bug.
     · The footer's copyright line starts at the page's bottom left, which is
       where this now lives, so the footer leaves it room once the control has
       mounted. See the clearance rule near the end for the arithmetic.
     · Two cascade disciplines, because this file has to survive being
       reordered. (a) :hover on the pill touches ONLY transform and box-shadow —
       no state rule touches either, so hover can never be out-specified by
       .is-on or .is-open, which is exactly the trap a flatter version of this
       file fell into. (b) Everywhere two states could collide, the selectors
       are written mutually exclusive (:not(.is-sel), :not(.is-on)) or at a
       higher specificity, so nothing here depends on source order.

   TOKEN DRIFT. Where an ink tint is needed, it is written as
   color-mix(in srgb, var(--ink) N%, transparent) with a literal rgba() on the
   line above as the pre-2023 fallback. The Conifer rotation cost 52 files and
   426 grep-able occurrences precisely because these values get written out by
   hand; the mix keeps the live value tied to the token, and the fallback only
   bites in browsers that predate color-mix.
   =========================================================================== */

/* ---- the control ------------------------------------------------------- */
.amb {
  position: fixed;
  left: max(14px, env(safe-area-inset-left));
  bottom: max(14px, env(safe-area-inset-bottom));
  z-index: 60;                        /* watermark 40 < us < header 1000 < chat 10000 */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;                          /* the panel sits above the pill */
  font-family: var(--sans);
  -webkit-tap-highlight-color: transparent;
}
/* Scoped, because the control is appended to <body> by a script and has to
   survive whichever page it lands on. index.html and site.css both reset
   box-sizing globally, but nothing guarantees the next page will, and the bed
   rows are width:100% with padding and a border — content-box would burst the
   tray. */
.amb, .amb *, .amb *::before, .amb *::after { box-sizing: border-box; }

/* ---- the pill ---------------------------------------------------------- */
.amb-toggle {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 36px;
  padding: 9px 15px 9px 12px;
  border: 1px solid var(--label);     /* 5.33 on cream, 4.86 on the wash */
  border-radius: var(--radius-pill);
  background-color: var(--sage);
  color: var(--ink);                  /* 9.30 on --sage */
  font-family: var(--sans);
  font-size: 0.625rem;                /* 10px — the micro-label size */
  font-weight: 600;                   /* the Figtree ceiling, and only here */
  line-height: 1;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  box-shadow: var(--shadow-sm);       /* lighter than --shadow-paper: a leaf, not a card */
  cursor: pointer;
  touch-action: manipulation;
  -webkit-appearance: none;
  appearance: none;
  transition: transform var(--dur-fast) var(--ease-luxe),
              box-shadow var(--dur-base) var(--ease-luxe),
              background-color var(--dur-fast) var(--ease-luxe),
              border-color var(--dur-fast) var(--ease-luxe);
}
/* The site's one hover gesture: a single 1px lift, the shadow quietly deepens.
   It touches nothing a state rule touches, so it works while playing and while
   open — the states in which somebody is actually reaching for this control. */
.amb-toggle:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}
/* (0,3,0), so the press beats :hover's transform without relying on order. */
.amb .amb-toggle:active { transform: translateY(0); transition-duration: 0.08s; }
.amb-toggle:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }

/* Open but silent. Written :not(.is-on) so it and the playing rule below are
   mutually exclusive and neither can win by being later in the file. */
.amb.is-open:not(.is-on) .amb-toggle { border-color: var(--action-hover); }

/* Playing. The fill deepens one step within the same leaf, the edge becomes the
   action pine, and the label (set by ambience.js) names the bed in words. */
.amb.is-on .amb-toggle {
  background-color: var(--sage-deep);
  border-color: var(--action);        /* 7.09 on cream */
}
.amb-label { white-space: nowrap; }

/* Four bars. Flat and quiet at rest — a speaker glyph would promise a volume
   control, and this is a bed chooser. The resting colour is measured rather
   than an opacity fade, so its contrast is a number somebody can check. They
   are scaled, not resized: scaleY runs on the compositor, so a control that may
   be on screen for an hour does not relayout four elements sixty times a
   second. (The podcast sheets animate height; this is the one place this file
   deliberately departs from them.) */
.amb-wave {
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  height: 12px;
}
.amb-wave i {
  display: block;
  width: 2px;
  height: 12px;
  border-radius: 1px;
  background: var(--action-hover);    /* 4.60 on --sage */
  transform: scaleY(0.25);
  transform-origin: 50% 100%;
  transition: background-color var(--dur-fast) var(--ease-luxe);
}
.amb.is-on .amb-wave i {
  background: var(--action);          /* 5.74 on --sage-deep */
  animation: amb-bar 1.15s var(--ease-luxe) infinite;
}
/* Prime numbers of nothing — just four delays that never line up, so the row
   never reads as one bar four times. */
.amb.is-on .amb-wave i:nth-child(1) { animation-delay: 0ms; }
.amb.is-on .amb-wave i:nth-child(2) { animation-delay: 160ms; }
.amb.is-on .amb-wave i:nth-child(3) { animation-delay: 420ms; }
.amb.is-on .amb-wave i:nth-child(4) { animation-delay: 260ms; }

/* Namespaced, and checked against every keyframe the site already defines
   (backdropIn, chatSlideUp, fadeIn, float, m-*, modalIn, p-toast-*, typing). */
@keyframes amb-bar {
  0%, 100% { transform: scaleY(0.25); }
  50%      { transform: scaleY(1); }
}

/* ---- the panel --------------------------------------------------------- */
/* The tray is --sage-tint over --cream, written out as the flat value it
   resolves to. The house rule is to verify composites rather than sources, and
   here the source cannot be trusted anyway: a translucent wash would take its
   second colour from whatever happened to be scrolling underneath. #E6F2E8 is
   arithmetically exact for rgba(208,234,219,.5) over #FBF9F4 — if --sage-tint
   or --cream ever move, this line has to move with them. */
.amb-panel {
  display: flex;
  flex-direction: column;
  width: min(296px, calc(100vw - 28px));
  /* Only the bed list scrolls (see .amb-list) — the heading, the level and
     Silence stay pinned. Somebody reaching for silence is not in the mood to
     scroll for it. dvh second so a browser without it keeps the vh. */
  max-height: calc(100vh - 96px);
  max-height: calc(100dvh - 96px);
  padding: 16px 16px 14px;
  border: 1px solid rgba(21, 64, 53, 0.22);
  border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
  border-radius: var(--radius);
  background-color: #E6F2E8;          /* = var(--sage-tint) over var(--cream) */
  box-shadow: var(--shadow-lg);
  color: var(--text-secondary);
}
/* [hidden] is how ambience.js closes the panel. (0,2,0) beats the display:flex
   above at (0,1,0), so the attribute keeps winning whatever gets added later. */
.amb-panel[hidden] { display: none; }
.amb.is-open .amb-panel { animation: amb-rise var(--dur-base) var(--ease-luxe) both; }

@keyframes amb-rise {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.amb-h {
  flex: 0 0 auto;
  margin: 0;
  color: var(--label);                /* 4.86 on the tray */
  font-family: var(--sans);
  font-size: 0.625rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}
.amb-sub {
  flex: 0 0 auto;
  margin: 9px 0 9px;
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-secondary);       /* 5.67 on the tray */
}

/* ---- the beds ---------------------------------------------------------- */
/* The one part that scrolls. The negative margin with matching padding gives
   the rows' 4px focus-ring reach somewhere to live inside a scroll container
   without indenting the rows or provoking a horizontal scrollbar. */
.amb-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(21, 64, 53, 0.32) transparent;
  scrollbar-color: color-mix(in srgb, var(--ink) 32%, transparent) transparent;
  list-style: none;
  margin: 0 -4px;
  padding: 4px;
  display: grid;
  gap: 5px;
}
.amb-list li { margin: 0; }
/* For WebKit builds that predate scrollbar-width/color. Same thumb, same
   nothing of a track. */
.amb-list::-webkit-scrollbar { width: 8px; }
.amb-list::-webkit-scrollbar-track { background: transparent; }
.amb-list::-webkit-scrollbar-thumb {
  border-radius: 999px;
  background: rgba(21, 64, 53, 0.32);
  background: color-mix(in srgb, var(--ink) 32%, transparent);
}

.amb-bed {
  position: relative;
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 26px 9px 11px;         /* the right gutter holds the playing dot */
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  background-color: var(--white);
  color: var(--text-muted);
  font-family: var(--sans);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-appearance: none;
  appearance: none;
  transition: background-color var(--dur-fast) var(--ease-luxe),
              border-color var(--dur-fast) var(--ease-luxe),
              box-shadow var(--dur-fast) var(--ease-luxe);
}
.amb-bed b {
  display: block;
  font-family: var(--serif);
  font-size: 0.875rem;
  font-weight: 500;                   /* Newsreader never goes past 500 */
  line-height: 1.25;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);                  /* 11.56 on white */
}
.amb-bed span {
  display: block;
  margin-top: 2px;
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 400;
  line-height: 1.35;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-muted);           /* 5.65 on white */
}
/* Hover moves the edge and nothing else, which is what .service-tab does on the
   homepage. A sage fill on hover was tried and thrown out: it landed a shade
   off --sage and made every row you passed look like the one that was playing.
   The fill belongs to the selected state alone. Scoped :not(.is-sel) so the
   selected row gets its own, louder hover below instead of losing this one to a
   specificity tie. */
.amb-bed:not(.is-sel):hover {
  border-color: var(--action-hover);  /* 5.72 on the white row */
  box-shadow: var(--shadow-sm);
}
/* A press has to answer on touch, where there is no hover to fall back on and
   the AudioContext can take a moment to come up. */
.amb-bed:not(.is-sel):active { background-color: var(--ink-wash); }
/* The rows sit 5px apart, so a 2px ring at a 2px offset reaches 4px and still
   clears its neighbour — the same ring, at the same offset, the site puts on
   everything else. --brass-ink is 6.05 on the row and 5.25 on the tray. */
.amb-bed:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* The bed that is playing — ambience.js only sets .is-sel while sound is on.
   Fill, edge and title all move, and so does the dot: a shape appears where
   there was none, so the state is never carried by colour alone. */
.amb-bed.is-sel {
  background-color: var(--sage);
  border-color: var(--action);        /* 6.00 against its own fill */
}
.amb-bed.is-sel b { color: var(--action); }             /* 6.00 on --sage */
.amb-bed.is-sel span { color: var(--text-secondary); }  /* 5.26 on --sage */
/* The row most likely to be hovered is the one already playing — clicking it
   again is how you stop. It gets the same gesture, one step darker. */
.amb-bed.is-sel:hover {
  border-color: var(--ink);           /* 9.30 against the sage fill */
  box-shadow: var(--shadow-sm);
}
.amb-bed.is-sel:active { background-color: var(--sage-deep); }
.amb-bed.is-sel::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 11px;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--action);
}

/* ---- level ------------------------------------------------------------- */
.amb-vol {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 10px 0 0;
}
.amb-vol span {
  font-family: var(--sans);
  font-size: 0.625rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--label);
}
.amb-vol input {
  flex: 1;
  min-width: 0;
  height: 22px;
  margin: 0;
  padding: 0;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background: transparent;
  touch-action: manipulation;
  cursor: pointer;
}
/* The track is pine at 60% over the tray (#69877D, 3.40) rather than a hairline
   token: a warm grey hairline is invisible on sage, and a slider whose track you
   cannot see is a slider you cannot aim. Both vendor families, because Firefox
   draws none of the WebKit pseudo-elements and vice versa. */
.amb-vol input::-webkit-slider-runnable-track {
  height: 3px;
  border: 0;
  border-radius: 999px;
  background: rgba(21, 64, 53, 0.6);
  background: color-mix(in srgb, var(--ink) 60%, transparent);
}
.amb-vol input::-moz-range-track {
  height: 3px;
  border: 0;
  border-radius: 999px;
  background: rgba(21, 64, 53, 0.6);
  background: color-mix(in srgb, var(--ink) 60%, transparent);
}
.amb-vol input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  margin-top: -5.5px;                 /* (14 − 3) ÷ 2 */
  border: 0;
  border-radius: 50%;
  background: var(--action);          /* 6.47 on the tray */
  cursor: pointer;
}
.amb-vol input::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border: 0;                          /* Firefox draws one unless told not to */
  border-radius: 50%;
  background: var(--action);
  cursor: pointer;
}
.amb-vol input::-moz-focus-outer { border: 0; }
/* Written :focus:not(:focus-visible) rather than a bare :focus, so a browser
   that does not know :focus-visible drops the whole rule and keeps its own
   outline instead of being left with no focus indicator at all. */
.amb-vol input:focus:not(:focus-visible) { outline: none; }
.amb-vol input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }

/* ---- silence ----------------------------------------------------------- */
/* The one thing in here shaped like a button, because it is the one thing that
   ends something. It borrows the site's ghost-pill language (.sfoot__cta)
   rather than inventing a third shape. Its edge is deliberately pushed to
   3.22:1 so that it is a real control boundary rather than a decorative one —
   this is the only place in the file where a sub-3:1 line would have been on a
   control the visitor has to find in a hurry. */
.amb-off {
  flex: 0 0 auto;
  display: block;
  width: 100%;
  margin: 12px 0 0;
  padding: 9px 10px;
  min-height: 36px;
  border: 1px solid rgba(21, 64, 53, 0.58);
  border: 1px solid color-mix(in srgb, var(--ink) 58%, transparent);
  border-radius: var(--radius-pill);
  background-color: transparent;
  color: var(--text-secondary);       /* 5.67 on the tray */
  font-family: var(--sans);
  font-size: 0.625rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-appearance: none;
  appearance: none;
  transition: color var(--dur-fast) var(--ease-luxe),
              border-color var(--dur-fast) var(--ease-luxe),
              background-color var(--dur-fast) var(--ease-luxe);
}
/* --ink-wash over the tray composites to #D9E7DD; the figures below are
   measured on that, not on the tray it replaces. */
.amb-off:hover {
  color: var(--ink);                  /* 9.04 on #D9E7DD */
  border-color: var(--action);        /* 5.83 on #D9E7DD */
  background-color: var(--ink-wash);
}
/* (0,3,0), so the press beats :hover regardless of where either rule sits. */
.amb .amb-off:active { background-color: var(--sage-tint); }
.amb-off:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* ---- room for it ------------------------------------------------------- */
/* The footer's copyright line starts at the bottom left of the page, which is
   where this now lives, so once the control has mounted (ambience.js marks
   <html>) the footer leaves it that much room. A browser with no Web Audio
   never gets the class and never gets stray padding.

   The arithmetic, because getting this breakpoint wrong is how the pill ends up
   sitting on the copyright line: the footer's inner column is 1200px centred,
   so its left edge is at (W − 1200) ÷ 2. The pill is at most ~168px wide at its
   longest label ("Distant storm") plus a 14px inset, so it reaches ~182px. The
   gutter only clears that above about 1564px, and 104em (1664px) leaves room
   for the label growing. Below it, 6rem of footer padding clears the 58px the
   pill occupies plus its focus ring with room to spare — and it is an INCREASE
   on the footer's existing 34–54px, never a reduction.

   `screen` is not decoration: a printed page is about 816px, which would match
   this query and print up to 6rem of blank footer to make room for a control
   that @media print has already removed. Specificity (0,2,1) beats both
   index.html's inline .sfoot and its 760px override at (0,1,0), so this works
   regardless of load order — index.html does not load site.css at all. */
@media screen and (max-width: 104em) {
  html.has-ambience .sfoot { padding-bottom: 6rem; }
}

/* ---- print, motion, forced colours, phones ----------------------------- */
/* Paper has no sound. */
@media print {
  .amb { display: none; }
}

/* A reader who asked for less motion still has to be able to tell that sound is
   coming out of their machine. The bars stop, but they stop at four DIFFERENT
   heights so the row keeps a waveform silhouette instead of collapsing into a
   flat rule — four equal marks read as an ellipsis, as if the label had been
   truncated. The fill, the edge and the bed's name in the label are all still
   doing their share. */
@media (prefers-reduced-motion: reduce) {
  .amb.is-on .amb-wave i { animation: none; }
  .amb.is-on .amb-wave i:nth-child(1) { transform: scaleY(0.35); }
  .amb.is-on .amb-wave i:nth-child(2) { transform: scaleY(0.8); }
  .amb.is-on .amb-wave i:nth-child(3) { transform: scaleY(0.5); }
  .amb.is-on .amb-wave i:nth-child(4) { transform: scaleY(1); }
  .amb.is-open .amb-panel { animation: none; }
  .amb-toggle, .amb-bed, .amb-off, .amb-wave i { transition: none; }
  .amb-toggle:hover, .amb .amb-toggle:active { transform: none; }
}

/* Windows High Contrast and friends. appearance:none has stripped the platform
   slider and the OS drops box-shadows and substitutes author colours, so every
   state has to be said again in system colours — otherwise ON and OFF collapse
   into each other and only the animation is left to carry it. System colour
   keywords declared inside this query are honoured, which is the whole point of
   the query existing. */
@media (forced-colors: active) {
  .amb-toggle, .amb-panel, .amb-bed, .amb-off {
    background: Canvas;
    color: CanvasText;
    border-color: ButtonBorder;
  }
  .amb-wave i { background: CanvasText; }
  .amb.is-on .amb-toggle { border-color: Highlight; color: Highlight; }
  .amb.is-on .amb-wave i { background: Highlight; }
  .amb-bed.is-sel { border-color: Highlight; }
  .amb-bed.is-sel b { color: Highlight; }
  .amb-bed.is-sel::after { background: Highlight; }
  .amb-vol input::-webkit-slider-runnable-track { background: ButtonBorder; }
  .amb-vol input::-moz-range-track { background: ButtonBorder; }
  .amb-vol input::-webkit-slider-thumb { background: Highlight; }
  .amb-vol input::-moz-range-thumb { background: Highlight; }
}

/* Phones. The word STAYS — unlike the podcast sites, nothing else is fighting
   for this corner here, and "Distant storm" is the clearest possible way to say
   that sound is playing. The inset drops to 12px to match the chat widget's own
   phone inset in the opposite corner, and both targets grow to 44px, because a
   thumb is not a cursor. */
@media (max-width: 480px) {
  .amb {
    left: max(12px, env(safe-area-inset-left));
    bottom: max(12px, env(safe-area-inset-bottom));
    gap: 9px;
  }
  .amb-toggle { min-height: 44px; padding: 12px 15px 12px 13px; }
  .amb-panel {
    width: min(296px, calc(100vw - 24px));
    padding: 15px 14px 13px;
    max-height: calc(100vh - 104px);  /* the target is 44px here, not 36 */
    max-height: calc(100dvh - 104px);
  }
  .amb-bed { padding: 9px 26px 10px 11px; }
  .amb-off { padding: 12px 10px; min-height: 44px; }
}
