/* The homepage: porcelain, with the instrument set into it.
   From Johnny's Pinterest board "Afflato": Iroh's pressed terraces and the jewellery
   page's single object on a quiet light ground; DELE's one knob ringed with dots, a dark
   neoprene object with a rose-gold button at its centre; rm's soft breath shapes, glowing
   behind it like bx_pulsar's AIR ring; the plugin itself floated on the light like
   bx_pulsar's product shot, marked up like a spec drawing; and a field of nodes in a
   silicone slab, the notes in ink and the breath around them in baby blue, as strong as
   you hear it. Every surface is the plugin's neoprene, lit from the upper left. The page
   closes on the plugin's own dark. The shared base (tokens, pads, the switch, beckon) is
   style.css. */

/* The canvas behind the page is porcelain; while the close is on screen main.js turns it
   to the close's charcoal, so an overscroll at either end shows the right ground. */
:root:has(body.home) {
  color-scheme: light;
  background: #e7e6e3;
  scrollbar-color: rgba(30, 25, 21, 0.32) transparent;
}

.home {
  color-scheme: light;

  --porcelain: #e7e6e3;
  --porcelain-hi: #f2f1ee;
  --ink: #1e1915;
  --ink-soft: #3f372f;
  --ink-muted: #675d52;
  --hair: rgba(30, 25, 21, 0.13);
  --hair-strong: rgba(30, 25, 21, 0.3);
  --shade: 86, 76, 66;
  --rose-ink: #a24a26;          /* rose gold as text on porcelain (4.7:1) */
  --signal-light: #457638;
  --breath-sky: #7dc8f6;        /* the breath, as the brand chart draws it */
  /* The page's side margin: a little more than 5% of the width, and on very wide screens
     whatever keeps the content within 1512px, so the hero holds together. */
  --edge: max(clamp(24px, 5vw, 72px), calc((100vw - 1512px) / 2 + 72px));

  /* The shared components read these: on porcelain they are ink. */
  --text: var(--ink);
  --muted: var(--ink-muted);
  --line: var(--hair);
  --line-strong: var(--hair-strong);
  --focus: rgba(30, 25, 21, 0.55);

  background: var(--porcelain);
  color: var(--ink);
}

.home ::selection { background: rgba(var(--rose-gold-rgb), 0.3); color: var(--ink); }
.home a, .home button { -webkit-tap-highlight-color: transparent; }

.home main {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: none;
}

/* The top edge, as on Iroh: what it is on the left, the way in on the right. */
.top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 26px var(--edge);
  font-size: 12px;
}

.top-what { margin: 0; letter-spacing: 0.02em; white-space: nowrap; color: var(--ink-muted); }
.top-nav { display: flex; align-items: center; gap: clamp(18px, 3vw, 38px); }
.top-nav a { white-space: nowrap; color: var(--ink-soft); text-decoration: none; transition: color 160ms var(--ease); }
.top-nav a:hover { color: var(--ink); }
.top-nav a:active { opacity: 0.7; }

.top-nav .top-join {
  padding: 9px 16px;
  border-radius: 8px;
  background: linear-gradient(180deg, #353cce 0%, var(--lapis) 100%);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 6px 14px -8px rgba(44, 51, 196, 0.7);
  color: #f4f1ec;
}

.top-nav .top-join:hover { color: #fff; background: linear-gradient(180deg, #3b43d6 0%, #3037cb 100%); }
.top-nav .top-join:active { opacity: 1; transform: translateY(1px); }

.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* The hero ------------------------------------------------------------------------ */

.hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  grid-template-rows: auto auto;
  align-content: center;
  gap: 0 clamp(24px, 4vw, 64px);
  width: 100%;
  min-height: max(760px, 100svh);
  padding: 120px var(--edge) 80px;
  /* The outer terraces run off the page's side and on down into it, never cut. */
  overflow-x: clip;
}

/* The water lies under the words only, so it stays sharp on a retina screen. */
.water {
  position: absolute;
  inset: 0 auto 0 0;
  width: 58%;
  height: 100%;
  pointer-events: none;
}

/* Words above, the readout below, the knob beside them both. */
.hero-words, .hero-read { position: relative; z-index: 2; grid-column: 1; max-width: 500px; }
.hero-words { grid-row: 1; align-self: end; }
.hero-read { grid-row: 2; align-self: start; }

.wordmark {
  width: fit-content;
  margin: 0;
  font-family: var(--font-logo);
  font-size: clamp(64px, 8.6vw, 136px);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
}

/* While the water moves it draws the mark (water.js); still, the lettering shows. */
.wordmark.in-water { color: transparent; }

.breathe { margin: 26px 0 0; font-size: clamp(19px, 1.7vw, 23px); letter-spacing: 0.01em; }
.lede { margin: 12px 0 0; max-width: 38ch; font-size: 15px; line-height: 1.7; color: var(--ink-muted); text-wrap: pretty; }

/* What it hears, set like an instrument's readout: tiny labels, a big value. */
.readout {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 18px 32px;
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--hair);
}

.readout-label {
  display: block;
  margin-bottom: 10px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.home .heard { justify-self: start; justify-content: flex-start; align-items: flex-start; gap: 6px; min-width: 96px; }
.home .heard.idle .heard-note { display: block; color: var(--hair-strong); }
.home .heard.idle.held .heard-hz { color: var(--hair-strong); }
.home .heard-note { font-size: 34px; }
.home .heard-hz { font-size: 12px; }

.series { margin: 0; }
.series canvas { display: block; width: 100%; height: 50px; }

.live {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.live i { width: 7px; height: 7px; border-radius: 50%; background: var(--hair-strong); transition: background-color 200ms var(--ease), box-shadow 200ms var(--ease); }
.live.on i { background: var(--signal-light); }
.live.loading i { background: var(--signal-light); animation: waiting 1.4s ease-in-out infinite; }

@keyframes waiting { 50% { opacity: 0.25; } }

.home .timeline { margin-top: 26px; font-size: 12px; }
.home .progress i { background: var(--lapis); }
.caption { margin: 12px 0 0; font-size: 12px; line-height: 1.6; color: var(--ink-muted); text-wrap: pretty; }

/* Terraces: rounded squares stepping up to a plate, the pad's own shape, like ripples set
   in porcelain, each lit from the upper left. Beside the words they run off the page's
   right side; above and below them they form a contained bowl. Fine flecks, as on Iroh's,
   sit in the steps only. */
.terraces {
  --t: clamp(316px, 25vw, 372px);   /* the plate */
  --gap: clamp(44px, 4.2vw, 66px);  /* each step out */
  position: relative;
  z-index: 1;
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  justify-self: end;
  display: grid;
  place-items: center;
  width: var(--t);
  aspect-ratio: 1;
  margin-right: clamp(8px, 3vw, 48px);
}

.step {
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(var(--t) + var(--n) * 2 * var(--gap));
  aspect-ratio: 1;
  border-radius: calc(92px + var(--n) * 30px);
  background: var(--porcelain) url("images/speckle.png") 0 0 / 360px 360px;
  box-shadow:
    16px 20px 40px -8px rgba(var(--shade), 0.17),
    -12px -14px 30px rgba(255, 255, 255, 0.72),
    inset 1px 1px 0 rgba(255, 255, 255, 0.55);
  transform: translate(-50%, -50%);
}

.step:nth-child(1) { --n: 5; }
.step:nth-child(2) { --n: 4; }
.step:nth-child(3) { --n: 3; }
.step:nth-child(4) { --n: 2; }
.step:nth-child(5) { --n: 1; }

.plate {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--t);
  aspect-ratio: 1;
  padding: 24px;
  border-radius: 92px;
  background: var(--porcelain-hi);
  box-shadow:
    18px 24px 46px -8px rgba(var(--shade), 0.24),
    -14px -16px 34px rgba(255, 255, 255, 0.85),
    inset 1px 1px 0 rgba(255, 255, 255, 0.8);
  overflow: hidden;
  isolation: isolate;
}

/* Breath, as soft light behind the knob. Sky blue for the flute as recorded hands over to
   rose gold as you turn to Afflato: the blue is gone by a quarter turn, the rose arrives
   from a sixth, so the two barely meet and never mix into mud. It swells with the breath
   it hears (main.js sets --v, --air and --live on the plate). */
.breath {
  --blob: var(--breath-sky);
  position: absolute;
  inset: 0;
  z-index: -1;
  filter: blur(28px);
  opacity: calc((0.42 + 0.48 * var(--live, 0)) * clamp(0, 1 - 4 * var(--v, 0), 1));
  transform: scale(calc(0.9 + 0.22 * var(--air, 0)));
  transition: opacity 600ms var(--ease), transform 220ms var(--ease);
}

.breath i { position: absolute; border-radius: 50%; background: var(--blob); animation: drift 16s ease-in-out infinite alternate; }
.breath i:nth-child(1) { width: 44%; height: 40%; left: 12%; top: 14%; }
.breath i:nth-child(2) { width: 34%; height: 38%; right: 10%; top: 30%; animation-duration: 19s; animation-delay: -6s; }
.breath i:nth-child(3) { width: 40%; height: 34%; left: 24%; bottom: 22%; animation-duration: 23s; animation-delay: -11s; }
.breath i:nth-child(4) { width: 18%; height: 18%; right: 20%; bottom: 18%; background: color-mix(in oklab, var(--blob) 70%, #fff); animation-duration: 13s; }

.breath.warm { --blob: var(--rose-gold); opacity: calc((0.42 + 0.48 * var(--live, 0)) * clamp(0, (var(--v, 0) - 0.15) * 2.5, 1)); }

@keyframes drift {
  0% { translate: 0 0; }
  50% { translate: 6% -5%; }
  100% { translate: -5% 4%; }
}

/* The plate's own light, from the upper left; no flecks here, among the dots and labels. */
.plate-glass {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(150deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 55%);
  pointer-events: none;
}

/* The knob: DELE's, as a dark neoprene object with a rose-gold button at its centre.
   Press the button to play; turn the ring from the original into Afflato; 41 dots light
   as it turns. --v is 0 for the original and 1 for Afflato (main.js). */
.knob {
  --size: 248px;
  --v: 0;
  position: relative;
  width: var(--size);
  height: var(--size);
  touch-action: pan-y;        /* a swipe over the dots still scrolls the page */
  user-select: none;
  -webkit-user-select: none;
}

.knob-dots { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; cursor: pointer; }
.knob-dots circle { fill: rgba(30, 25, 21, 0.24); transition: fill 120ms var(--ease); }
.knob-dots circle.lit { fill: var(--rose-gold); }

.knob-ring {
  position: absolute;
  inset: 17%;
  border-radius: 50%;
  background:
    radial-gradient(90% 70% at 30% 14%, rgba(255, 236, 214, 0.08) 0%, rgba(255, 236, 214, 0) 70%),
    linear-gradient(160deg, #302822 0%, #1f1a16 62%, #171310 100%);
  box-shadow:
    16px 22px 36px -8px color-mix(in oklab, rgba(86, 76, 66, 0.55), rgba(150, 72, 40, 0.42) calc(var(--v) * 100%)),
    -9px -10px 24px rgba(255, 255, 255, 0.75),
    0 0 0 1px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 236, 214, 0.12),
    inset 0 -8px 16px rgba(0, 0, 0, 0.35);
  cursor: grab;
  touch-action: none;
}

.knob-ring:active { cursor: grabbing; }
.knob-ring:focus-visible { outline: 2px solid var(--focus); outline-offset: 6px; }

.knob-notch {
  position: absolute;
  inset: 0;
  pointer-events: none;
  transform: rotate(calc(-135deg + 270deg * var(--v)));
  transition: transform 140ms var(--ease);
}

.knob.turning .knob-notch { transition: none; }

.knob-notch::before {
  content: "";
  position: absolute;
  top: 9px;
  left: 50%;
  width: 2px;
  height: 16px;
  margin-left: -1px;
  border-radius: 1px;
  background: #efe6da;
}

/* The button: matte rose-gold neoprene, the pads' own rubber grain, lit from the upper
   left; it rises a touch under the pointer and presses in while it plays. */
.knob-cap {
  --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.4 0'/></filter><rect width='64' height='64' filter='url(%23n)'/></svg>");
  position: absolute;
  inset: 33%;
  z-index: 1;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background:
    var(--grain),
    radial-gradient(90% 70% at 30% 15%, rgba(255, 236, 214, 0.1) 0%, rgba(255, 236, 214, 0) 70%),
    linear-gradient(160deg, #f6ac88 0%, var(--rose-gold) 48%, #d8784e 100%);
  background-blend-mode: soft-light, normal, normal;
  box-shadow:
    -2px -2px 6px rgba(255, 236, 214, 0.06),
    4px 6px 12px rgba(0, 0, 0, 0.45),
    0 0 0 1px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 236, 214, 0.1),
    inset 0 -4px 8px rgba(120, 50, 20, 0.22);
  cursor: pointer;
  touch-action: none;
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease);
}

.knob-cap:not([aria-pressed="true"]):hover {
  transform: translateY(-1px);
  box-shadow:
    -2px -2px 6px rgba(255, 236, 214, 0.06),
    5px 8px 16px rgba(0, 0, 0, 0.45),
    0 0 0 1px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 236, 214, 0.1),
    inset 0 -4px 8px rgba(120, 50, 20, 0.22);
}

.knob-cap[aria-pressed="true"] {
  transform: translateY(1px);
  background:
    var(--grain),
    linear-gradient(160deg, #d8784e 0%, #e6845a 55%, var(--rose-gold) 100%);
  background-blend-mode: soft-light, normal;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.45),
    inset 3px 4px 9px rgba(110, 40, 12, 0.45),
    inset -2px -2px 6px rgba(255, 255, 255, 0.2);
}

.knob-cap:focus-visible { outline: 2px solid #efe6da; outline-offset: 4px; }
.knob-cap .glyph { inset: 50% auto auto 50%; width: 46px; height: 46px; margin: -23px 0 0 -23px; stroke: var(--ink); }
.knob-cap[aria-pressed="true"] .glyph .play { display: none; }
.knob-cap[aria-pressed="true"] .glyph .pause { display: inline; }
.knob-cap.loading .glyph, .vis-play[aria-busy="true"] .glyph { animation: waiting 1.4s ease-in-out infinite; }

/* The ends of the turn, named. What you hear is lit: the original as an ink key, Afflato
   as a rose-gold one; once you've turned to Afflato its name stays rose gold. In between,
   the dots and the number say how far. */
.knob-end {
  position: absolute;
  bottom: -4px;
  height: 28px;
  padding: 0 10px;
  border: 0;
  border-radius: 8px;
  background: none;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color 160ms var(--ease), background-color 160ms var(--ease);
}

#to-original { left: -6px; }
#to-afflato { right: -6px; }
.knob-end:hover { color: var(--ink); background-color: rgba(30, 25, 21, 0.05); }
.knob-end:active { transform: translateY(1px); }
.knob-end.lit { color: #f4f1ec; font-weight: 500; background: linear-gradient(180deg, #2c2520 0%, var(--ink) 100%); box-shadow: 0 4px 10px -6px rgba(0, 0, 0, 0.6); }
.knob-end.effect.lit { color: #20130b; background: linear-gradient(180deg, #f8b394 0%, var(--rose-gold) 100%); box-shadow: 0 4px 10px -6px rgba(162, 74, 38, 0.7); }
.home .knob-end.beckon, .home .knob-end.engaged:not(.lit) { color: var(--rose-ink); }
.knob-end.beckon:not(.lit) { box-shadow: inset 0 0 0 1px rgba(var(--rose-gold-rgb), 0.75); }
.home .knob-end.beckon:not(.lit):hover, .home .knob-end.engaged:not(.lit):hover { background-color: rgba(var(--rose-gold-rgb), 0.1); }

.amount {
  position: absolute;
  left: 50%;
  bottom: 2px;
  margin: 0;
  transform: translateX(-50%);
  font-size: 12px;
  color: var(--ink-soft);
}

/* The breath and the note (melody.js): a field of nodes pressed into a raised silicone
   slab, the neoprene of the plugin's pads, with its readouts along the top and its controls
   along the bottom. Baby blue is the breath. */
.vis {
  display: grid;
  gap: clamp(48px, 7svh, 72px);
  width: min(1040px, 100% - 48px);
  margin-top: max(clamp(120px, 15svh, 168px), calc(656px - 50svh));
}

.vis[hidden] { display: none; }

.vis h2, .finish h2 {
  margin: 0;
  font-size: clamp(26px, 3.2vw, 38px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.vis-words { display: grid; gap: 18px; justify-items: center; text-align: center; }
.vis-words p, .finish-words p { margin: 0; max-width: 56ch; font-size: 15px; line-height: 1.75; color: var(--ink-muted); text-wrap: pretty; }

.vis-slab {
  --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.35 0'/></filter><rect width='64' height='64' filter='url(%23n)'/></svg>");
  position: relative;
  display: grid;
  gap: 26px;
  min-width: 0;
  padding: 34px clamp(20px, 3.4vw, 44px) 30px;
  border-radius: 48px;
  background:
    var(--grain),
    radial-gradient(90% 70% at 22% 8%, rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 60%),
    linear-gradient(160deg, #f4f3f0 0%, #eeece8 60%, #e8e6e2 100%);
  background-blend-mode: soft-light, normal, normal;
  box-shadow:
    22px 28px 56px -14px rgba(var(--shade), 0.26),
    -16px -18px 40px rgba(255, 255, 255, 0.9),
    inset 1px 1px 0 rgba(255, 255, 255, 0.9),
    inset -1px -1px 0 rgba(var(--shade), 0.06);
}

.vis-head { display: flex; align-items: flex-start; gap: clamp(28px, 5vw, 64px); }
.vis-read { display: grid; gap: 4px; margin: 0; }
.vis-read .readout-label { margin-bottom: 4px; }
.vis-read b { min-width: 3ch; font-size: 22px; font-weight: 500; letter-spacing: -0.01em; }

/* The breath meter: a channel pressed into the silicone, filled with the breath's blue. */
.vis-meter {
  display: block;
  width: clamp(110px, 16vw, 180px);
  height: 10px;
  margin-top: 9px;
  border-radius: 999px;
  background: #e2dfda;
  box-shadow: inset 2px 2px 4px rgba(var(--shade), 0.22), inset -2px -2px 4px rgba(255, 255, 255, 0.85);
  overflow: hidden;
}

/* The fill slides in from the left (main.js sets its translate), so its rounded end stays round. */
.vis-meter i { display: block; width: 100%; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #b9e2fb 0%, var(--breath-sky) 100%); transform: translateX(-100%); transition: transform 140ms var(--ease); }
.vis-tuning { margin: 0 0 0 auto; padding-top: 2px; font-size: 11px; letter-spacing: 0.04em; color: var(--ink-muted); }

.melody-chart { position: relative; width: 100%; margin: 0; }
.melody-rows { margin: 0; padding: 0; list-style: none; }
.melody-rows li { display: grid; grid-template-columns: 72px minmax(0, 1fr) 84px; align-items: center; height: 34px; }
.melody-rows li i { height: 1px; background: rgba(30, 25, 21, 0.14); }
.melody-rows li.quiet i { visibility: hidden; }

/* The row's two ends, as neoprene pills that rise when their note is lit. */
.row-name, .row-hz {
  justify-self: center;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  transition: background-color 220ms var(--ease), box-shadow 220ms var(--ease);
}

.row-hz { font-weight: 400; letter-spacing: 0.04em; text-transform: none; color: var(--ink-soft); }
.row-name sub { margin-left: 1px; font-size: 11px; font-weight: 400; vertical-align: baseline; color: var(--ink-muted); }

.melody-rows li.on .row-name, .melody-rows li.on .row-hz {
  background: #f6f5f2;
  box-shadow: -3px -3px 7px rgba(255, 255, 255, 0.95), 3px 4px 9px rgba(var(--shade), 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.8);
}

/* The canvases reach a little past the rows' ends, for the light; their blur is set in
   melody.js with the field's size. */
.melody-canvas { position: absolute; top: 0; bottom: 0; left: 46px; width: calc(100% - 104px); height: 100%; }

/* Play and the switch: the knob's own neoprene, small. */
.vis-controls { display: flex; align-items: center; gap: 18px; }

.vis-play {
  --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.4 0'/></filter><rect width='64' height='64' filter='url(%23n)'/></svg>");
  position: relative;
  flex: none;
  width: 52px;
  height: 52px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background:
    var(--grain),
    radial-gradient(90% 70% at 30% 15%, rgba(255, 236, 214, 0.12) 0%, rgba(255, 236, 214, 0) 70%),
    linear-gradient(160deg, #f6ac88 0%, var(--rose-gold) 48%, #d8784e 100%);
  background-blend-mode: soft-light, normal, normal;
  box-shadow: -4px -4px 10px rgba(255, 255, 255, 0.9), 5px 7px 14px rgba(var(--shade), 0.35), 0 0 0 1px rgba(0, 0, 0, 0.25), inset 0 -3px 6px rgba(120, 50, 20, 0.2);
  cursor: pointer;
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease);
}

.vis-play:not([aria-pressed="true"]):hover { transform: translateY(-1px); }
.vis-play[aria-pressed="true"] {
  transform: translateY(1px);
  background: var(--grain), linear-gradient(160deg, #d8784e 0%, #e6845a 55%, var(--rose-gold) 100%);
  background-blend-mode: soft-light, normal;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3), inset 3px 4px 8px rgba(110, 40, 12, 0.4), inset -2px -2px 5px rgba(255, 255, 255, 0.25);
}

.vis-play:focus-visible { outline: 2px solid var(--focus); outline-offset: 4px; }
.vis-play .glyph { inset: 50% auto auto 50%; width: 36px; height: 36px; margin: -18px 0 0 -18px; stroke: var(--ink); }
.vis-play[aria-pressed="true"] .glyph .play { display: none; }
.vis-play[aria-pressed="true"] .glyph .pause { display: inline; }

/* Original or Afflato: a channel pressed into the silicone, the one you hear raised and lit. */
.vis-switch {
  display: flex;
  gap: 3px;
  padding: 4px;
  border-radius: 14px;
  background: #e2dfda;
  box-shadow: inset 2px 2px 5px rgba(var(--shade), 0.22), inset -2px -2px 5px rgba(255, 255, 255, 0.85);
}

.vis-switch button {
  height: 38px;
  padding: 0 16px;
  border: 0;
  border-radius: 10px;
  background: none;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color 160ms var(--ease), background-color 160ms var(--ease), box-shadow 160ms var(--ease);
}

.vis-switch button:hover { color: var(--ink); }
.vis-switch button[aria-checked="true"] { color: #f4f1ec; font-weight: 500; background: linear-gradient(180deg, #2c2520 0%, var(--ink) 100%); box-shadow: -2px -2px 5px rgba(255, 255, 255, 0.7), 3px 4px 8px rgba(var(--shade), 0.35); }
.vis-switch button.effect[aria-checked="true"] { color: #20130b; background: linear-gradient(180deg, #f8b394 0%, var(--rose-gold) 100%); }
.vis-switch button:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.vis-time { margin-left: auto; font-size: 12px; color: var(--ink-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
/* The failure note may take two lines on the narrowest phones, rather than widen the slab. */
.vis-time { min-width: 0; }
.vis-time.failed { color: var(--rose-ink); white-space: normal; text-align: right; line-height: 1.25; }
.vis-time.failed .vis-of { display: none; }

/* The plugin as a product: floated on the porcelain with its shadow below and a breath of
   baby blue under it, marked up like a spec drawing. */
.product { width: min(1040px, 100% - 48px); margin: clamp(200px, 24svh, 260px) 0 0; }
.spec-figure { margin: 0; }

.spec, .spec-pic { position: relative; }

.spec img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 16px;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.3),
    0 30px 50px -28px rgba(var(--shade), 0.7),
    0 70px 110px -50px rgba(125, 200, 246, 0.5);
}

.crop { position: absolute; width: 18px; height: 18px; border: 0 solid var(--hair-strong); pointer-events: none; }
.crop:nth-of-type(1) { top: -14px; left: -14px; border-top-width: 1px; border-left-width: 1px; }
.crop:nth-of-type(2) { top: -14px; right: -14px; border-top-width: 1px; border-right-width: 1px; }
.crop:nth-of-type(3) { bottom: -14px; left: -14px; border-bottom-width: 1px; border-left-width: 1px; }
.crop:nth-of-type(4) { bottom: -14px; right: -14px; border-bottom-width: 1px; border-right-width: 1px; }

.callouts { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none; pointer-events: none; }

/* Each callout is its leader: a hairline from the label to a small ring on its area. */
.callouts li { position: absolute; left: calc(var(--x) * 1%); width: 1px; }
.callouts li.up { top: -40px; height: calc(var(--y) * 1% + 40px); }
.callouts li.down { top: calc(var(--y) * 1%); bottom: -40px; }

/* Ink off the picture, cream on it, so the leader reads on both. */
.callouts li::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 1px; }
.callouts li.up::before { background: linear-gradient(180deg, rgba(30, 25, 21, 0.35) 0, rgba(30, 25, 21, 0.35) 40px, rgba(239, 230, 218, 0.45) 40px); }
.callouts li.down::before { background: linear-gradient(0deg, rgba(30, 25, 21, 0.35) 0, rgba(30, 25, 21, 0.35) 40px, rgba(239, 230, 218, 0.45) 40px); }

.callouts li::after {
  content: "";
  position: absolute;
  left: -4px;
  width: 9px;
  height: 9px;
  border: 1px solid rgba(239, 230, 218, 0.9);
  border-radius: 50%;
  background: rgba(15, 12, 10, 0.6);
}

.callouts li.up::after { bottom: -4px; }
.callouts li.down::after { top: -4px; }

.call {
  position: absolute;
  left: 0;
  display: grid;
  gap: 5px;
  width: max-content;
  max-width: 210px;
  margin: 0;
  transform: translateX(-50%);
  text-align: center;
}

.callouts .start .call { transform: translateX(-1px); padding-left: 12px; text-align: left; }
.callouts .end .call { left: auto; right: 0; transform: translateX(1px); padding-right: 12px; text-align: right; }
.callouts .up .call { bottom: calc(100% + 2px); }
.callouts .down .call { top: calc(100% + 2px); }
.callouts b { font-size: 11px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink); }
.callouts span { font-size: 12px; line-height: 1.45; color: var(--ink-muted); text-wrap: balance; }

.spec-line {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-top: 108px;
  padding-top: 14px;
  border-top: 1px solid var(--hair);
  font-size: 12px;
  color: var(--ink-muted);
}

/* What it does: dark panels of the plugin hung on the porcelain at one magnification,
   each marked up like the sheet above, with a leader across to its words. */
.features {
  --fgap: clamp(40px, 6vw, 88px);
  display: flex;
  flex-direction: column;
  gap: clamp(96px, 13svh, 144px);
  width: min(1040px, 100% - 48px);
  margin-top: clamp(160px, 20svh, 220px);
}

.feature {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  align-items: center;
  gap: var(--fgap);
}

/* Every panel at the same scale of the plugin, set to the column's right edge, so each
   leader meets its picture. */
.panel-wrap { position: relative; justify-self: end; width: calc(var(--w) / 710 * 100%); margin: 0; }

.feature .panel {
  display: block;
  width: 100%;
  height: auto;
  border-radius: calc(var(--r) / var(--w) * 100%) / calc(var(--r) / var(--h) * 100%);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.28), 0 22px 34px -22px rgba(var(--shade), 0.7);
}

.feature-text { position: relative; }

.feature-text h2 {
  position: relative;
  margin: 0 0 14px;
  font-size: clamp(22px, 2.2vw, 28px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

/* The leader: from the picture's edge across the gutter to the heading, ending in a ring. */
.feature-text h2::before {
  content: "";
  position: absolute;
  top: 0.6em;
  right: calc(100% + 15px);
  width: calc(var(--fgap) - 15px);
  height: 1px;
  background: var(--hair-strong);
}

.feature-text h2::after {
  content: "";
  position: absolute;
  top: calc(0.6em - 4px);
  right: calc(100% + 6px);
  width: 9px;
  height: 9px;
  border: 1px solid var(--ink-soft);
  border-radius: 50%;
  box-sizing: border-box;
}

.feature-text p { max-width: 40ch; margin: 0; font-size: 15px; line-height: 1.75; color: var(--ink-muted); }

/* The cream finish, at the bottom of a pressed-in bowl of terraces, flecked like them. */
.finish { display: grid; justify-items: center; gap: clamp(48px, 7svh, 72px); width: min(1040px, 100% - 48px); margin-top: clamp(180px, 22svh, 240px); }
.bowl { position: relative; width: min(100%, 1000px); padding: clamp(30px, 5vw, 68px); }
.bowl i { position: absolute; border-radius: 48px; background: var(--porcelain) url("images/speckle.png") 0 0 / 360px 360px; }
.bowl i:nth-child(1) { inset: 0; box-shadow: inset 12px 14px 28px rgba(var(--shade), 0.16), inset -12px -12px 26px rgba(255, 255, 255, 0.8); }
.bowl i:nth-child(2) { inset: clamp(10px, 1.7vw, 23px); border-radius: 38px; box-shadow: inset 10px 12px 24px rgba(var(--shade), 0.14), inset -10px -10px 22px rgba(255, 255, 255, 0.75); }
.bowl i:nth-child(3) { inset: clamp(20px, 3.4vw, 46px); border-radius: 28px; box-shadow: inset 8px 10px 20px rgba(var(--shade), 0.13), inset -8px -8px 18px rgba(255, 255, 255, 0.7); }
.bowl img { position: relative; display: block; width: 100%; height: auto; border-radius: 16px; box-shadow: -10px -10px 24px rgba(255, 255, 255, 0.7), 16px 22px 40px -10px rgba(var(--shade), 0.35); }
.finish-words { display: grid; gap: 14px; justify-items: center; text-align: center; }

/* The close: the plugin's own dark, risen as a plate, the name's meaning, and the list. */
.close {
  --text: #efe6da;
  --muted: #9d917f;
  --line: #2f2822;
  --line-strong: #4a4037;
  --focus: rgba(239, 230, 218, 0.7);
  color-scheme: dark;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  margin-top: clamp(128px, 16svh, 176px);
  padding: clamp(112px, 15svh, 160px) 24px 0;
  border-radius: 44px 44px 0 0;
  background: linear-gradient(180deg, #1a1512 0%, #0f0c0a 100%);
  box-shadow: 0 -14px 32px -12px rgba(255, 255, 255, 0.8), inset 0 1px 0 rgba(255, 236, 214, 0.07);
  color: var(--text);
}

.close ::selection { background: color-mix(in srgb, var(--lapis) 60%, transparent); color: var(--text); }

.meaning {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(20px, 4vw, 56px);
  width: min(100%, 1040px);
  text-align: center;
}

.rule { position: relative; height: 1px; background: var(--line); }
.rule::before { content: ""; position: absolute; top: -4px; width: 1px; height: 9px; background: var(--line-strong); }
.meaning .rule:first-child::before { left: 0; }
.meaning .rule:last-child::before { right: 0; }

.meaning-line { margin: 0; font-size: clamp(18px, 1.9vw, 24px); font-weight: 400; line-height: 1.55; letter-spacing: 0.01em; color: var(--text); }
.meaning-line span { display: block; text-wrap: balance; }

.families { max-width: 52ch; margin: clamp(64px, 9svh, 96px) 0 0; font-size: 13px; line-height: 1.75; text-align: center; text-wrap: balance; color: var(--muted); }

.join { display: flex; flex-direction: column; align-items: center; width: min(100%, 560px); margin-top: clamp(72px, 10svh, 104px); text-align: center; }
.join-title { margin: 0; font-size: clamp(28px, 3.4vw, 40px); font-weight: 500; letter-spacing: -0.02em; outline: none; }
.join-label { margin: 12px 0 26px; font-size: 14px; color: var(--muted); text-wrap: balance; }

/* The presets bar's sunk well, with a raised ultramarine chip. */
.well {
  display: flex;
  align-items: center;
  gap: 6px;
  width: min(100%, 460px);
  height: 54px;
  padding: 0 6px 0 18px;
  border-radius: 10px;
  background: var(--well);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.6), 0 1px 0 rgba(255, 236, 214, 0.04);
  transition: box-shadow 200ms var(--ease);
}

.well:has(input:focus-visible) { box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.6), 0 0 0 1px var(--focus); }

.well input[type="email"] {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  font: inherit;
  font-size: 15px;
  color: var(--text);
  caret-color: var(--lapis-light);
}

.well input::placeholder { color: var(--muted); }
.well input:is(:autofill, :-webkit-autofill) { -webkit-text-fill-color: var(--text); caret-color: var(--lapis-light); box-shadow: 0 0 0 60px var(--well) inset; }

/* A field only bots fill in. */
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

.chip {
  flex: none;
  height: 42px;
  padding: 0 24px;
  border: 0;
  border-radius: 8px;
  background: linear-gradient(180deg, #353cce 0%, var(--lapis) 100%);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 4px 8px -4px rgba(0, 0, 0, 0.8);
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  transition: transform 120ms var(--ease);
}

.chip:hover { background: linear-gradient(180deg, #3b43d6 0%, #3037cb 100%); }
.chip:active { transform: translateY(1px); }
.chip:disabled { opacity: 0.5; cursor: default; }

.join-status { min-height: 18px; margin: 12px 0 0; font-size: 12px; color: var(--muted); text-wrap: balance; }

/* Red means clipped, nothing else (DESIGN.md): a problem here is said in words, in cream. */
.join-status.ok, .join-status.error { color: var(--text); }
.join.done .well { visibility: hidden; }

.footer {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  width: calc(100% + 48px);
  margin: 0 -24px;
  padding: 140px var(--edge) 30px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.footer a { color: inherit; text-decoration: none; }
.footer a:hover { color: var(--text); }
/* Afflato's own channels sit together between the name and the maker. */
.footer .elsewhere { display: flex; gap: 28px; }

/* Smaller screens -------------------------------------------------------------------- */

/* Beside narrower words, fewer steps: the outermost first, then the next. */
@media (max-width: 1366px) {
  .step:nth-child(1) { display: none; }
  .vis { margin-top: max(clamp(120px, 15svh, 168px), calc(560px - 50svh)); }
}
@media (max-width: 1200px) {
  .step:nth-child(2) { display: none; }
  .vis { margin-top: max(clamp(120px, 15svh, 168px), calc(500px - 50svh)); }
}

@media (max-width: 1080px) {
  .hero { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; justify-items: center; gap: 0; padding-top: 128px; }
  .water { width: 100%; height: min(100%, 720px); }
  .hero-words, .hero-read { grid-column: 1; justify-self: stretch; width: 100%; max-width: 560px; margin: 0 auto; }
  .hero-words { grid-row: 1; }
  /* Here the terraces are a bowl between the words and the readout: three steps, with
     room for them above and below. */
  .terraces { --t: 340px; --gap: 52px; grid-column: 1; grid-row: 2; justify-self: center; margin: calc(3 * var(--gap) + 40px) 0 calc(3 * var(--gap) + 48px); }
  .hero-read { grid-row: 3; }
  /* Contained here, so the next section needn't clear the terraces. */
  .vis { margin-top: 96px; }
}

@media (max-width: 1000px) {
  /* The callouts leave the picture and line up under it. */
  .callouts { position: static; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px 20px; margin-top: 40px; }
  .callouts li, .callouts li.up, .callouts li.down { position: static; width: auto; height: auto; }
  .callouts li::before, .callouts li::after { display: none; }
  .callouts .call, .callouts .start .call, .callouts .end .call { position: static; width: auto; max-width: none; padding: 0; transform: none; text-align: left; }
  .spec-line { margin-top: 36px; }
  .product { margin-top: 128px; }
}

@media (max-width: 860px) {
  .feature { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .panel-wrap { justify-self: start; }
  .feature-text h2::before, .feature-text h2::after { display: none; }
}

/* A narrow single column: the bowl's steps closer, so it stays on the screen. */
@media (max-width: 712px) { .terraces { --gap: 40px; } }

@media (max-width: 600px) {
  .top { padding: 20px; }
  .top-nav { gap: 16px; }
  .top-nav a[href="#plugin"] { display: none; }
  .hero { padding: 104px 20px 64px; }
  .wordmark { font-size: clamp(56px, 18vw, 92px); }
  .terraces { --t: 300px; --gap: 34px; margin: calc(3 * var(--gap) + 32px) 0 calc(3 * var(--gap) + 40px); }
  .plate { border-radius: 74px; }
  .knob { --size: 212px; }
  .knob-cap .glyph { width: 40px; height: 40px; margin: -20px 0 0 -20px; }
  .readout { gap: 16px 22px; }
  .callouts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .spec-line { flex-direction: column; gap: 6px; }
  .crop { display: none; }
  .meaning { grid-template-columns: 1fr; gap: 20px; }
  .meaning .rule { display: none; }
  .vis { width: calc(100% - 24px); margin-top: 72px; }
  /* Nine lines would be too many to read centred: on a phone the words sit flush left. */
  .vis-words { justify-items: start; text-align: left; padding: 0 12px; }
  .vis-slab { gap: 20px; padding: 24px 12px 20px; border-radius: 30px; }
  .vis-head { gap: 22px; }
  .vis-tuning { display: none; }
  /* The lines end where the field's last column can fall: the canvas's 6px inset and its 26px PAD. */
  .melody-rows li { grid-template-columns: 40px minmax(0, 1fr) 32px; height: 26px; }
  .row-hz { display: none; }
  .melody-canvas { left: 14px; width: calc(100% - 20px); }
  .row-name { padding: 4px 6px; letter-spacing: 0.04em; }
  .vis-controls { gap: 12px; }
  .vis-of { display: none; }
  .vis-switch button { padding: 0 12px; }
  .close { border-radius: 28px 28px 0 0; }
  .footer { flex-direction: column; align-items: center; gap: 10px; }
}

/* The narrowest phones (320–359px): the slab's controls row, a little tighter, so it fits. */
@media (max-width: 359px) {
  .vis-controls { gap: 8px; }
  .vis-switch button { padding: 0 9px; }
}

@media (prefers-reduced-motion: reduce) {
  .breath i, .live.loading i, .knob-cap.loading .glyph, .vis-play[aria-busy="true"] .glyph { animation: none; }
  .knob-cap.loading .glyph, .vis-play[aria-busy="true"] .glyph { opacity: 0.35; }
  .knob-notch, .knob-dots circle, .knob-cap, .knob-end, .breath, .vis-play, .vis-switch button, .vis-meter i { transition: none; }
}

/* Windows High Contrast and other forced colours: the knob, and the slab's play, switch and
   breath meter, drawn in system colours. */
@media (forced-colors: active) {
  .knob-ring { border: 2px solid CanvasText; }
  .knob-notch::before { background: CanvasText; }
  .knob-dots circle { fill: GrayText; }
  .knob-dots circle.lit { fill: Highlight; }
  .knob-cap { border: 2px solid ButtonText; }
  .knob-cap .glyph { stroke: ButtonText; }
  .knob-cap, .knob-cap[aria-pressed="true"] { background: ButtonFace; }
  .knob-end, .chip, .top-join { border: 1px solid ButtonText; }
  .knob-end.lit, .knob-end.effect.lit, .vis-switch button[aria-checked="true"], .vis-switch button.effect[aria-checked="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; box-shadow: none; }
  .vis-switch button:focus-visible { outline: 2px solid CanvasText; outline-offset: 2px; }
  /* Two-tone rim: the slab keeps its light silicone, so one colour would vanish in one scheme. */
  .vis-meter { border: 1px solid CanvasText; outline: 1px solid Canvas; }
  .vis-meter i { forced-color-adjust: none; background: Highlight; }
  .vis-play, .vis-play[aria-pressed="true"] { background: ButtonFace; border: 2px solid ButtonText; }
  .vis-play .glyph { stroke: ButtonText; }
  .well { border: 1px solid CanvasText; }
  .well:has(input:focus-visible) { outline: 2px solid Highlight; outline-offset: 2px; }
  .knob-ring:focus-visible, .knob-cap:focus-visible { outline-color: Highlight; }
}
