/* =========================================================================
   Audio codes and the sound wave.

   Every style is the same measurements drawn a different way. None of them
   carry a colour, so the fill or stroke is set here and the same markup is
   one colour on screen, another as the progress bar, and solid black on a
   printer.
   ========================================================================= */

.wave { display: block; width: 100%; height: 100%; }
.wave-bars, .wave-ribbon, .wave-dots { fill: currentColor; }

/* The outline is the same closed shape as the ribbon, stroked instead of
   filled. Non-scaling-stroke keeps the line an even weight even though the
   viewBox is stretched to whatever width it lands in. */
.wave-line {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.5;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.wave-ring { stroke: currentColor; fill: none; }

/* ------------------------------------------------------------- the player
   The page somebody lands on after scanning. It has one job and should look
   like it: the wave, and something to press. */

.playwrap {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--s5);
  background: var(--bg);
}

.player {
  width: 100%;
  max-width: 560px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg, var(--shadow));
  padding: var(--s5);
  text-align: center;
}
.player h1 { font-size: 22px; margin: 0 0 6px; letter-spacing: -0.01em; }
.playcap {
  margin: 0 0 var(--s4);
  color: var(--ink-2);
  font-size: 15px;
  line-height: 1.55;
}

/* The container query unit is what lets the played layer be clipped without
   also being squashed: the copy underneath is always sized to the whole wave,
   whatever width the clip is currently showing. */
.playwave {
  position: relative;
  height: 140px;
  margin: var(--s4) 0;
  color: var(--line);
  container-type: inline-size;
}
.playwave.isring {
  height: auto;
  aspect-ratio: 1 / 1;
  max-width: 340px;
  margin-inline: auto;
}
.playwave.live { cursor: pointer; }

.waveplayed {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  width: 0;
  overflow: hidden;
  color: var(--brand);
}
.waveplayed .wave { width: 100%; width: 100cqw; }

.player audio { width: 100%; margin-top: var(--s2); }
.playfoot {
  margin: var(--s4) 0 0;
  font-size: 12.5px;
  color: var(--ink-3);
}

/* ------------------------------------------------------- making one */

.audioform .audiostatus {
  display: block;
  margin: var(--s2) 0 0;
  font-size: 13.5px;
  color: var(--ink-2);
  min-height: 18px;
}
.audioform .audiostatus.bad { color: var(--bad); }

.audiorec { display: inline-flex; align-items: center; gap: 8px; }
.audiorec .dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--bad);
  flex: none;
}
.audiorec.on { border-color: var(--bad); color: var(--bad); }
.audiorec.on .dot { animation: recpulse 1.1s ease-in-out infinite; }
@keyframes recpulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) {
  .audiorec.on .dot { animation: none; }
}

/* The wave as it appears on the code's own screen. */
.audiopanel {
  display: flex;
  gap: var(--s4);
  align-items: center;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--s4);
  margin-bottom: var(--s4);
}
.audiopanel .wavebox {
  flex: 1;
  min-width: 220px;
  height: 72px;
  color: var(--brand);
}
.audiopanel .wavebox.isring {
  flex: none;
  width: 128px;
  height: 128px;
  min-width: 0;
}
.audiopanel audio { width: 100%; max-width: 320px; }
.audiometa { font-size: 13px; color: var(--ink-3); }

/* ------------------------------------------------------- choosing a style
   Every option draws the real recording rather than a stock sample, because
   the only useful question is which one suits this wave. */

.styleset {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s3);
  margin-bottom: var(--s4);
}
.styleopt {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  padding: 14px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  cursor: pointer;
  font: inherit;
  color: var(--ink-3);
  text-align: center;
}
.styleopt:hover { border-color: var(--brand); color: var(--ink-2); }
.styleopt:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.styleopt.on {
  border-color: var(--brand);
  box-shadow: inset 0 0 0 1px var(--brand);
  color: var(--ink);
}
.stylepic {
  display: block;
  width: 100%;
  height: 46px;
  color: var(--ink-3);
}
.styleopt.on .stylepic, .styleopt:hover .stylepic { color: var(--brand); }
.stylepic.isring { width: 62px; height: 62px; }
.stylename { font-size: 13px; line-height: 1.35; }

@media (max-width: 600px) {
  .player { padding: var(--s4); }
  .playwave { height: 110px; }
}

/* ------------------------------------------------------- on paper
   Black on white whatever the screen was doing. */

.cell .cellwave {
  color: #000;
  height: calc(var(--qs, 2in) * 0.42);
  margin-bottom: 0.06in;
}
.cell .cellwave .wave { height: 100%; }

/* The ring: one object, the recording wrapped around the thing people scan.
   The wave is drawn with a clear middle at 32 percent of its radius, and the
   symbol is set at 44 percent of the width so its corners always stay inside
   that circle, whatever the recording looks like. */
.ringwrap {
  position: relative;
  width: var(--qs, 2in);
  height: var(--qs, 2in);
}
.ringwave {
  position: absolute;
  inset: 0;
  color: #000;
}
.ringwave .wave { width: 100%; height: 100%; }
.ringcode {
  position: absolute;
  left: 28%;
  top: 28%;
  width: 44%;
  height: 44%;
}
.ringcode svg { width: 100%; height: 100%; display: block; }
