/*
 * The web site of Maddox Plugins Central: its one stylesheet.
 *
 * The look is the app's (docs/ARCHITECTURE.md section 8, "Look", and section
 * 14): a clean dark gray ground and neutral raised surfaces, with the
 * owner's logo and the interactive plugin artwork carrying the colour.
 * White pill buttons and the system font keep the controls clear.
 *
 * Every name below that central/src/renderer/tokens.css also has, has the
 * same value here; a test compares the two files, so the site cannot drift
 * from the app one colour at a time.
 *
 * Nothing is written into a page: the site's headers allow styles from this
 * file only. So where a page needs one of several looks (a later start for
 * an animation, a state of the download button), it says so with a class or
 * a data- attribute and the rule is here.
 */

:root {
  color-scheme: dark;

  /* ---- Surfaces ---- */
  --ground: #161616;
  --sheet: #202020;
  --fill-1: rgb(255 255 255 / 0.05);
  --fill-2: rgb(255 255 255 / 0.09);
  --fill-3: rgb(255 255 255 / 0.13);
  --edge: rgb(255 255 255 / 0.1);

  /* ---- Text ---- */
  --label: rgb(255 255 255 / 0.93);
  --label-2: rgb(255 255 255 / 0.72);
  --label-3: rgb(255 255 255 / 0.3);
  --warm: #f5e8c4;

  /* ---- The main button: a white pill ---- */
  --pill: #ffffff;
  --pill-pressed: #e6e6e6;
  --on-pill: #161616;

  /* ---- The owner's colours: the character's ---- */
  --art-ink: #0d0a14;
  --art-cream: #f5e8c4;
  --art-yellow: #fcdc2a;
  --art-orange: #fc9925;
  --art-green: #b0f02c;
  --art-aqua: #27b2eb;
  --art-blue: #279aec;
  --art-violet: #8731f0;
  --art-magenta: #f247c3;
  --art-pink: #f9556e;

  /* ---- The logo's colours: for light and accents, never for a word ---- */
  --neon-magenta: #e617c1;
  --neon-pink: #f94c76;
  --neon-orange: #f9734c;
  --neon-yellow: #efe507;
  --neon-lime: #7df149;
  --neon-mint: #16ea99;
  --neon-blue: #105ed1;
  --neon-violet: #411b9c;

  /* Once through the logo's rainbow, as a line and as a wheel. */
  --iris: linear-gradient(
    115deg,
    var(--neon-magenta),
    var(--neon-pink),
    var(--neon-orange),
    var(--neon-yellow),
    var(--neon-lime),
    var(--neon-mint),
    var(--neon-blue),
    var(--art-violet),
    var(--neon-magenta)
  );
  --iris-wheel: conic-gradient(
    from 210deg,
    var(--neon-magenta),
    var(--neon-pink),
    var(--neon-orange),
    var(--neon-yellow),
    var(--neon-lime),
    var(--neon-mint),
    var(--neon-blue),
    var(--art-violet),
    var(--neon-magenta)
  );
  --run-cool: linear-gradient(90deg, var(--neon-blue), var(--neon-mint), var(--neon-lime));
  --run-warm: linear-gradient(90deg, var(--neon-magenta), var(--neon-pink), var(--neon-orange));
  --run-deep: linear-gradient(90deg, var(--neon-magenta), var(--art-violet) 55%, var(--neon-blue));
  --run-fresh: linear-gradient(90deg, var(--neon-lime), var(--neon-yellow));

  /* ---- Signals ---- */
  --red: #ff7a8e;
  --focus: #b0f02c;

  /* ---- Type ---- */
  --font: system-ui, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
  --weight-semibold: 600;
  --weight-heavy: 800;

  /*
   * The site's own: how heavy a heading is. Semibold, in the system's font,
   * at a large size and set a little tight: the way Apple sets a headline.
   * (It was light, 300, for a while, and read as faint beside the art; the
   * owner: "make the fonts more pro".) What is read at length is the same
   * font at its usual weight, and a sentence set large, between the two.
   */
  --weight-display: 600;
  --weight-medium: 500;

  /* ---- Corners ---- */
  --r-tile: 18px;
  --r-surface: 22px;
  --r-round: 999px;

  /* ---- Motion: little, and slow where it is light ---- */
  --quick: 140ms;
  --gentle: 280ms;
  --ease: cubic-bezier(0.2, 0, 0, 1);

  /* ---- The site's own: the page's side margin, which a window sets ---- */
  --side: clamp(24px, 7.5vw, 128px);

  /*
   * And where a page begins on its left: the logo in its head, and every
   * word under it, start on this one line (the owner: "make the a new
   * dimension of sound and apple and google log ins etc move them to left
   * like so the padding line up with the logo on the top"). The head's
   * account stands as far from the right. On a narrow window it is the
   * side margin.
   */
  --head-side: clamp(16px, 3vw, 40px);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  background: var(--ground);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ground);
  /*
   * A page may reach every edge of the screen (viewport-fit=cover, in each
   * page). On a phone held on its side the words keep clear of the camera's
   * end of it, as they did when the browser held the whole page clear.
   */
  padding: 0 env(safe-area-inset-right, 0px) 0 env(safe-area-inset-left, 0px);
  min-height: 100svh;
  overflow-x: hidden;
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--label);
  -webkit-font-smoothing: antialiased;
}

img {
  display: block;
  max-width: 100%;
}

[hidden] {
  display: none !important;
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 4px;
  border-radius: 6px;
}

::selection {
  background: var(--art-violet);
  color: #ffffff;
}

/* ---- The first screen: the words on the left, the character's stage on the right ---- */

.split {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr);
  min-height: 100svh;
  /* Keep the interactive model within the viewport. */
  overflow: clip;
}

/*
 * The words stand in front of whatever light reaches under them. (A place
 * in the order is enough for that, in a grid; they are not given a position
 * of their own, because on a narrow window the logo, which is among them,
 * takes its place from the whole first screen and not from them.)
 */
.words {
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /*
   * Clear of the page's head, which lies over the top of the first screen,
   * and beginning on the line the logo begins on.
   */
  padding: clamp(104px, 13vh, 124px) var(--side) clamp(40px, 8vh, 96px) var(--head-side);
}

.words > * {
  max-width: 34rem;
}

.words > :first-child {
  margin-top: 0;
}

/* ---- The head of every page: the logo in its top left corner, the account in its top right ---- */

/*
 * The header lies over the first screen and scrolls with it. Only the
 * controls take pointer events, leaving the model underneath interactive.
 */
.top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 4;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  /* It takes its place from the window and not from the body, so it keeps clear of a phone's camera by itself, as far as the body does. */
  margin: 0 env(safe-area-inset-right, 0px) 0 env(safe-area-inset-left, 0px);
  padding: calc(clamp(14px, 2.4vh, 22px) + env(safe-area-inset-top, 0px)) var(--head-side);
  pointer-events: none;
}

.top > * {
  pointer-events: auto;
}

/*
 * The owner's logo, as it is: never tinted, faded or put under an effect.
 * And alone: no word under it (the owner: "remove the word central please
 * on the logo").
 */
.brand {
  position: relative;
  display: block;
  width: fit-content;
}

.brand-logo {
  width: clamp(136px, 12.5vw, 184px);
  height: auto;
}

.top-nav {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 8px;
}

.top-link,
.top-signin,
.profile-button {
  display: inline-flex;
  align-items: center;
  height: 40px;
  border-radius: var(--r-round);
  font-size: 0.9375rem;
  font-weight: var(--weight-semibold);
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

/* Neutral raised controls match Central and remain clear beside the artwork. */
.top-link,
.profile-button {
  padding: 0 16px;
  background: var(--sheet);
  box-shadow: inset 0 0 0 1px var(--edge);
  color: var(--label);
  transition: background var(--quick) var(--ease);
}

.top-link[type='button'] {
  border: 0;
  font-family: inherit;
}

[data-central-download]:disabled {
  cursor: default;
  opacity: 1;
}

.top-link:hover,
.profile-button:hover,
.profile[open] .profile-button {
  background: rgb(50 50 50 / 0.98);
}

.top-signin {
  padding: 0 18px;
  background: var(--pill);
  color: var(--on-pill);
  transition: background var(--quick) var(--ease);
}

.top-signin:hover {
  background: var(--pill-pressed);
}

.top-signin[type='button'] {
  border: 0;
  font-family: inherit;
}

/* The account entry opens in the center, above an inert page. */
.signin-dialog {
  width: min(390px, calc(100vw - 32px - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)));
  max-width: none;
  max-height: calc(100svh - 32px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  max-height: calc(100dvh - 32px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  margin: auto;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--edge);
  border-radius: 24px;
  background: var(--sheet);
  box-shadow: 0 24px 100px rgb(0 0 0 / 0.45);
  color: var(--label);
}

.signin-dialog::backdrop {
  background: rgb(0 0 0 / 0.7);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.signin-dialog[open] {
  animation: rise 180ms var(--ease) both;
}

.signin-panel {
  position: relative;
  display: grid;
  gap: 18px;
  padding: 38px 28px 28px;
}

.signin-close {
  position: absolute;
  top: 10px;
  right: 10px;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 9px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--label-2);
  cursor: pointer;
}

.signin-close:hover {
  background: rgb(255 255 255 / 0.07);
  color: var(--label);
}

.signin-title {
  margin: 0;
  font-size: 1.5rem;
  font-weight: var(--weight-semibold);
  letter-spacing: -0.035em;
}

.signin-description {
  margin: -8px 0 2px;
  color: var(--label-2);
  font-size: 0.875rem;
  line-height: 1.5;
}

.signin-consent {
  display: flex;
  align-items: start;
  gap: 10px;
  color: var(--label-2);
  font-size: 0.8125rem;
  line-height: 1.6;
  cursor: pointer;
}

.signin-consent input {
  flex: none;
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  accent-color: var(--pill);
  cursor: pointer;
}

.signin-consent a {
  color: var(--label);
  text-underline-offset: 3px;
}

.signin-providers {
  display: grid;
  gap: 10px;
}

.home .signin-dialog .signin {
  flex: none;
  width: 100%;
  max-width: none;
  height: 48px;
  padding: 0 14px;
  gap: 10px;
  font-size: 0.9375rem;
}

.signin-dialog .signin-mark {
  width: 19px;
  height: 19px;
}

.signin-note {
  margin: 0;
  color: var(--label-2);
  font-size: 0.8125rem;
  line-height: 1.5;
}

.signin-dialog .signin:disabled {
  opacity: 0.45;
  cursor: default;
}

.signin-dialog[aria-busy='true'] .signin {
  cursor: progress;
}

/* Who is signed in: the first letter of the name on a disc, the name, and a menu under them. */
.profile {
  position: relative;
}

.profile-button {
  gap: 9px;
  padding: 0 13px 0 5px;
  list-style: none;
}

.profile-button::-webkit-details-marker {
  display: none;
}

.profile-face {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--fill-3);
  font-size: 0.8125rem;
}

.profile-name {
  max-width: 16ch;
  overflow: hidden;
  text-overflow: ellipsis;
}

.profile-chevron {
  flex: none;
  width: 12px;
  height: 12px;
  color: var(--label-2);
  transition: transform var(--quick) var(--ease);
}

.profile[open] .profile-chevron {
  transform: rotate(180deg);
}

.profile-menu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  display: grid;
  gap: 2px;
  width: max-content;
  min-width: 232px;
  max-width: min(320px, calc(100vw - 32px));
  max-height: calc(100dvh - 104px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px;
  border-radius: 18px;
  background: var(--sheet);
  box-shadow:
    0 0 0 1px var(--edge),
    0 24px 60px -18px rgb(0 0 0 / 0.8);
  animation: rise 200ms var(--ease) both;
}

.profile-who {
  display: grid;
  margin: 0 0 6px;
  padding: 8px 12px 12px;
  border-bottom: 1px solid var(--edge);
  line-height: 1.3;
}

.profile-who strong,
.profile-who span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.profile-who strong {
  font-weight: var(--weight-semibold);
}

.profile-who span {
  font-size: 0.8125rem;
  color: var(--label-2);
}

.profile-item {
  display: flex;
  align-items: center;
  height: 40px;
  padding: 0 12px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--label);
  font: inherit;
  font-size: 0.9375rem;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.profile-item:hover,
.profile-item:focus-visible {
  background: var(--fill-2);
}

.kicker {
  margin: clamp(36px, 6vh, 56px) 0 0;
  font-size: 0.75rem;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--label-2);
}

/*
 * The system's font sets its own letters closer as they grow, so a heading
 * is drawn in only a little more than that: more, and the letters touch.
 */
.headline {
  margin: clamp(36px, 6vh, 56px) 0 0;
  font-size: clamp(2.5rem, 4.2vw + 0.6rem, 4.25rem);
  font-weight: var(--weight-display);
  line-height: 1.04;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.kicker + .headline {
  margin-top: 14px;
}

/* A page with work to do under its heading (/subscribe/) says it smaller. */
.headline-small {
  font-size: clamp(2rem, 2.4vw + 0.8rem, 2.875rem);
  line-height: 1.07;
}

.lede {
  margin: 18px 0 0;
  font-size: clamp(1.0625rem, 0.5vw + 0.95rem, 1.3125rem);
  line-height: 1.42;
  color: var(--label-2);
  text-wrap: pretty;
}

.fine {
  margin: 18px 0 0;
  font-size: 0.9375rem;
  color: var(--label-2);
}

/* A price said in a line of words. */
.price {
  color: var(--label);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

/* ---- The download: a white pill, and the line under it ---- */

.download {
  display: grid;
  justify-items: start;
  gap: 14px;
  margin-top: clamp(28px, 5vh, 40px);
}

/* The download stays a flat white pill, matching the sign-in controls. */
.pill {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 56px;
  padding: 0 30px 0 24px;
  border: 0;
  border-radius: var(--r-round);
  background: none;
  color: var(--on-pill);
  font: inherit;
  font-size: 1.0625rem;
  font-weight: 650;
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: transform var(--quick) var(--ease);
}

.pill::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--pill);
  transition: background var(--quick) var(--ease);
}

.pill:hover {
  transform: translateY(-1px);
}

.pill:active {
  transform: none;
}

.pill:active::after {
  background: var(--pill-pressed);
}

.pill-glyph {
  flex: none;
  width: 20px;
  height: 20px;
}

/* A pill with words only has the same margin on both sides. */
.pill-plain {
  padding-left: 30px;
}

/* Not a link yet, or not at all: glass, and nothing happens under the pointer. */
.pill[aria-disabled='true'] {
  color: var(--label-2);
  cursor: default;
  transform: none;
}

.pill[aria-disabled='true']::after {
  background: var(--fill-2);
  box-shadow: inset 0 0 0 1px var(--edge);
}

.download[data-state='none'] .pill-glyph {
  display: none;
}

.download[data-state='none'] .pill {
  padding-left: 30px;
}

.download[data-state='asking'] .pill-glyph {
  animation: nod 1.1s var(--ease) infinite alternate;
}

.download-meta {
  max-width: 100%;
  margin: 0;
  overflow: hidden;
  font-size: 0.9375rem;
  color: var(--label-2);
}

/*
 * Every piece has a dot before it, in a margin of its own, and the run is
 * pulled left by that margin: the dot of whichever piece starts a line lies
 * outside the paragraph and is cut off. So a dot only ever shows between
 * two pieces, wherever the line happens to break.
 */
.download-meta-run {
  display: flex;
  flex-wrap: wrap;
  margin-left: -1.5em;
}

.download-meta-run > span {
  position: relative;
  padding-left: 1.5em;
}

.download-meta-run > span::before {
  content: '\00b7';
  position: absolute;
  left: 0;
  width: 1.5em;
  text-align: center;
  color: var(--label-3);
}

.quiet {
  padding: 0;
  border: 0;
  background: none;
  color: var(--warm);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: var(--weight-semibold);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.notes {
  margin-top: clamp(28px, 5vh, 44px);
  padding: 20px 22px;
  border: 1px solid var(--edge);
  border-radius: var(--r-tile);
  background: var(--fill-1);
}

.notes h2 {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--warm);
}

.notes p {
  margin: 10px 0 0;
  color: var(--label-2);
  white-space: pre-line;
}

/* ---- Signing in: the two buttons ---- */

/*
 * One pair: the same white pill, the same size, the same type, side by side
 * where there is room and one over the other where there is not. What each
 * keeps of its owner's rules is what makes it recognisable: Apple's logo in
 * the colour of its title, on white, as Apple asks for on a dark ground,
 * and first; Google's "G" in its own four colours, on white; the words
 * "Continue with". Flat: nothing glows around them (the owner: "remove the
 * rainbow glow around the sign in with apple and google buttons"). Under
 * the pointer a button lifts by a point, and pressed it dims.
 */
.signin-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 14px;
  width: 100%;
}

.signin {
  flex: 1 1 236px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  max-width: 300px;
  height: 52px;
  padding: 0 22px;
  border: 0;
  border-radius: 26px;
  background: #ffffff;
  color: #000000;
  font: var(--weight-semibold) 1.0625rem/1 var(--font);
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    transform var(--quick) var(--ease),
    background var(--quick) var(--ease);
}

.signin:hover {
  transform: translateY(-1px);
}

.signin:active {
  background: var(--pill-pressed);
  transform: none;
}

.signin-mark {
  flex: none;
  width: 20px;
  height: 20px;
}

/* The logo is drawn to the top of its square; this sets the apple on the title's line. */
.signin-apple .signin-mark {
  margin-top: -3px;
}

.signin-google {
  color: #1f1f1f;
}

/* Who is signed in, and the way out, on one line where there is room. */
.who {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 18px;
  margin: 0;
  color: var(--label-2);
}

.who strong {
  color: var(--label);
  font-weight: var(--weight-semibold);
  overflow-wrap: anywhere;
}

/* ---- The first page's panel: sign in, or choose a plan, or how the subscription stands ---- */

/*
 * One state at a time, under the page's heading (assets/subscribe.js): the
 * two sign-in buttons for a visitor; the two plans for whoever is signed in
 * and has none, in place of a button that only led to them (the owner:
 * "remove the subscribe button on the home page ... just show the subscribe
 * options"); and for a subscriber, how the subscription stands.
 */
.join {
  display: grid;
  justify-items: start;
  gap: 16px;
  width: 100%;
}

.join .fine {
  margin: 0;
}

/* Under the first page's heading it is the first thing to do. */
.words > .join {
  margin-top: clamp(28px, 5vh, 40px);
}

.join-note {
  margin: 0;
  font-size: 1.0625rem;
  color: var(--label-2);
  text-wrap: pretty;
}

.join[data-state='checking'] .join-note,
.join[data-state='opening'] .join-note {
  animation: breathe 1.4s ease-in-out infinite alternate;
}

.join[data-state='failed'] .join-note {
  color: var(--red);
}

/*
 * There the download is the second thing, after signing in: glass where
 * the main download button is white, and on the page only once there is an
 * installer to offer. ("Coming soon" is /download/'s to say.)
 */
.download-found:not([data-state='release']) {
  display: none;
}

.download-found {
  margin-top: 16px;
}

.download-found .pill {
  height: 44px;
  padding: 0 22px 0 18px;
  color: var(--label);
  font-size: 0.9375rem;
}

.download-found .pill::after {
  background: var(--fill-2);
  box-shadow: inset 0 0 0 1px var(--edge);
}

/* ---- /subscribe/: one state at a time, under the heading ---- */

.subscribe {
  display: grid;
  justify-items: start;
  gap: 18px;
  width: 100%;
  margin-top: clamp(28px, 5vh, 40px);
}

.subscribe .fine,
.subscribe .download {
  margin-top: 0;
}

.subscribe-note {
  margin: 0;
  font-size: 1.0625rem;
  text-wrap: pretty;
}

.subscribe[data-state='checking'] .subscribe-note,
.subscribe[data-state='opening'] .subscribe-note {
  color: var(--label-2);
  animation: breathe 1.4s ease-in-out infinite alternate;
}

.subscribe[data-state='failed'] .subscribe-note {
  color: var(--red);
}

/*
 * The account's subscription: a panel with its state in a word, a dot that
 * says how it stands (running, ending, in trouble), and one sentence with
 * the date that matters.
 */
.member {
  display: grid;
  justify-items: start;
  gap: 14px;
  width: 100%;
  padding: clamp(22px, 3vw, 30px);
  border-radius: var(--r-surface);
  background: var(--fill-1);
  box-shadow: inset 0 0 0 1px var(--edge);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
}

.member .fine {
  margin: 0;
}

.member-state {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.member-state strong {
  font-weight: var(--weight-semibold);
}

.member-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--label-3);
}

[data-member-tone='good'] .member-dot {
  background: var(--art-green);
  box-shadow: 0 0 14px var(--art-green);
}

[data-member-tone='warn'] .member-dot {
  background: var(--art-orange);
  box-shadow: 0 0 14px var(--art-orange);
}

[data-member-tone='bad'] .member-dot {
  background: var(--red);
  box-shadow: 0 0 14px var(--red);
}

.member-sentence {
  margin: 0;
  font-size: clamp(1.1875rem, 0.8vw + 1rem, 1.5rem);
  font-weight: var(--weight-medium);
  line-height: 1.3;
  letter-spacing: -0.012em;
  text-wrap: pretty;
}

.subscribe-past {
  margin: 0;
  color: var(--label-2);
}

/*
 * The two plans: two buttons of the same size (on the first page, each is
 * also a link to /subscribe/). Glass, like the page's other quiet buttons,
 * so that they belong to the page they stand on instead of lying on it as
 * two dark slabs; flat, with no rainbow at their edge; and each says where
 * it leads with an arrow at its far side (the owner: "make the monthly and
 * yearly buttons nicer more pro make them fit in more").
 */
.plans {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  width: 100%;
}

.plan {
  position: relative;
  display: grid;
  align-content: start;
  gap: 5px;
  padding: 16px 46px 18px 20px;
  border: 0;
  border-radius: 20px;
  background: var(--fill-1);
  box-shadow: inset 0 0 0 1px var(--edge);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  color: var(--label);
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition:
    background var(--quick) var(--ease),
    box-shadow var(--quick) var(--ease),
    transform var(--quick) var(--ease);
}

/* Under the pointer, and when it has the keyboard, it is lit a little and its edge is plainer to see. */
.plan:hover,
.plan:focus-visible {
  background: var(--fill-2);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.26);
  transform: translateY(-1px);
}

.plan:active {
  background: var(--fill-3);
  transform: none;
}

.plan-name {
  display: flex;
  align-items: center;
  gap: 9px;
  /* As tall with the yearly plan's tag as without: the two prices stand on one line. */
  min-height: 22px;
  font-size: 0.9375rem;
  font-weight: var(--weight-semibold);
  letter-spacing: -0.01em;
}

/* What the yearly plan saves, where the two prices bear it out: the logo's green, said quietly. */
.plan-tag {
  padding: 2px 8px;
  border-radius: var(--r-round);
  background: rgb(176 240 44 / 0.14);
  color: var(--art-green);
  font-size: 0.75rem;
  letter-spacing: 0;
  white-space: nowrap;
}

/* Where a plan is too narrow for its price on one line, "a month" goes under the amount whole, not word by word. */
.plan-price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 0.2em;
  font-size: 0.9375rem;
  color: var(--label-2);
}

.plan-amount {
  margin-right: 3px;
  color: var(--label);
  font-size: clamp(1.5rem, 1vw + 1.1rem, 1.75rem);
  font-weight: var(--weight-display);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.plan-go {
  position: absolute;
  top: 50%;
  right: 16px;
  width: 18px;
  height: 18px;
  margin-top: -9px;
  color: var(--label-3);
  transition:
    color var(--quick) var(--ease),
    transform var(--quick) var(--ease);
}

.plan:hover .plan-go,
.plan:focus-visible .plan-go {
  color: var(--label);
  transform: translateX(2px);
}

/* What a subscription is, in three lines, each with the logo's green tick. */
.perks {
  display: grid;
  gap: 8px;
  margin: 2px 0 0;
  padding: 0;
  list-style: none;
  color: var(--label-2);
}

.perks li {
  position: relative;
  padding-left: 26px;
}

.perks li::before {
  content: '';
  position: absolute;
  top: 0.42em;
  left: 2px;
  width: 11px;
  height: 6px;
  border-bottom: 2px solid var(--art-green);
  border-left: 2px solid var(--art-green);
  transform: rotate(-45deg);
}

/* Each part of the page comes in softly when its state is shown, so that nothing snaps. */
.subscribe > :not([hidden]) {
  animation: rise 420ms var(--ease) both;
}

/* ---- Paying: Stripe's form takes the character's place on the stage ---- */

/*
 * On a wide window the form does not open under the words: it opens beside
 * them, on the stage, over the liquid, and where the character stands there
 * he steps aside for as long as it is open. The words stay where they are.
 * On a narrow window the form uses the viewport beneath the header, with
 * its own way back to the plans, on both /subscribe/ and the first page.
 */
.pay {
  z-index: 2;
  padding: 0 var(--side) clamp(48px, 9vw, 96px);
  /* Brought into view under the words, it keeps a little air above it. */
  scroll-margin-top: 16px;
}

.pay-toolbar,
.pay-note {
  display: none;
}

/* Stripe uses the shared gray sheet and the matching FORM_LOOK palette. */
.checkout {
  width: min(100%, 432px);
  padding: clamp(18px, 2.4vw, 26px);
  border-radius: 28px;
  background: var(--sheet);
  box-shadow:
    0 0 0 1px var(--edge),
    0 40px 90px -30px rgb(0 0 0 / 0.8);
  animation: arrive 560ms var(--ease) both;
}

.checkout:empty {
  min-height: 460px;
  background:
    linear-gradient(100deg, transparent 30%, rgb(255 255 255 / 0.07) 50%, transparent 70%) 0 0 / 220% 100%,
    var(--sheet);
  animation:
    arrive 560ms var(--ease) both,
    sweep 1.6s linear infinite;
}

@media (min-width: 881px) {
  /* The three share one row: the words, and on the stage's side the liquid (with the character, where he is) and the form in the same place. */
  .split > .words {
    grid-column: 1;
    grid-row: 1;
  }

  .split > .poster {
    grid-column: 2;
    grid-row: 1;
  }

  /*
   * On /subscribe/ the words stay in view if the form is taller than the
   * window. They are the most words any page has, so they keep less air
   * under them: a subscriber's page, with its download button, is one
   * screen on a laptop.
   */
  .split-tall > .words {
    position: sticky;
    top: 0;
    align-self: start;
    min-height: 100svh;
    padding-bottom: clamp(28px, 5vh, 96px);
  }

  /*
   * The pane stands in the middle of the stage, under the page's head, and
   * fits the window with room to spare; on a window too low for it the
   * page scrolls.
   */
  .split > .pay {
    grid-column: 2;
    grid-row: 1;
    display: grid;
    align-content: center;
    justify-items: center;
    min-height: 100svh;
    padding: 88px var(--side) 32px clamp(8px, 2vw, 32px);
  }

  .split > .pay[hidden] {
    display: none;
  }

  /* The character steps aside while the form is opening or open, and comes back afterwards. */
  [data-subscribe-state='opening'] .split-tall .poster-figure,
  [data-subscribe-state='paying'] .split-tall .poster-figure {
    animation: leave 460ms var(--ease) forwards;
  }

  /*
   * So does the first page's model, and once it has gone it is not there
   * for the keyboard either: no control of it can be reached under the
   * form.
   */
  [data-subscribe-state='opening'] .split-model .plugin,
  [data-subscribe-state='paying'] .split-model .plugin {
    visibility: hidden;
    animation: leave 460ms var(--ease) forwards;
    transition: visibility 0s 460ms;
  }
}

/* ---- /pay/: the form by itself, for Maddox Plugins Central to show inside its own window ---- */

/*
 * Nothing but the pane and, when there is something to say, one sentence:
 * the window it is shown in is Central's, and Central has the words, the
 * plan and the way back.
 */
.frame {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 18px;
  min-height: 100svh;
  padding: 20px;
}

.frame .checkout {
  width: min(100%, 432px);
}

.frame-note {
  max-width: 26rem;
  margin: 0;
  text-align: center;
  color: var(--label-2);
  text-wrap: pretty;
}

.setup-card-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
  width: 100%;
  padding: 8px;
}

.setup-card-element { min-height: 180px; }
.setup-card-note { color: var(--label-2); font-size: 13px; line-height: 1.5; }
.setup-card-submit { align-self: stretch; justify-content: center; }
.setup-card-submit:disabled { opacity: .55; cursor: wait; }

.frame[data-state='opening'] .frame-note {
  animation: breathe 1.4s ease-in-out infinite alternate;
}

/* ---- The character's stage: plain, with colour confined to the artwork ---- */

.poster {
  position: relative;
  min-height: 100svh;
}

/*
 * The figure stands in the middle of its stage, whatever shape the window
 * gives the stage: never wider than the stage, never taller than the
 * screen, and the same on every page. It stays still on the gray surface.
 */
.poster-figure {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(84%, 76svh, 640px);
  aspect-ratio: 820 / 807;
  translate: -50% -50%;
}

.poster-figure img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/*
 * A page that grows long under its heading (/subscribe/, once the payment
 * form is on it) keeps its stage in view while the words scroll past.
 */
@media (min-width: 881px) {
  .split-tall .poster {
    position: sticky;
    top: 0;
    align-self: start;
    height: 100svh;
  }
}

/* ---- /signed-in/ and /thanks/: the mark above the heading ---- */

.mark {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--fill-2);
  box-shadow: inset 0 0 0 1px var(--edge);
}

.mark + .kicker {
  margin-top: 22px;
}

.mark svg {
  display: none;
  width: 30px;
  height: 30px;
}

[data-tone='good'] .mark {
  background: var(--fill-3);
  box-shadow: inset 0 0 0 1px var(--edge);
  color: #ffffff;
}

[data-tone='bad'] .mark {
  color: var(--red);
}

[data-tone='good'] .mark-good,
[data-tone='bad'] .mark-bad,
[data-tone='plain'] .mark-plain {
  display: block;
}

[data-tone='good'] .mark-good path {
  stroke-dasharray: 30;
  stroke-dashoffset: 30;
  animation: draw 520ms 260ms var(--ease) forwards;
}

/* ---- The first page's stage: the ACID Preamp By Maddox, to turn and to play with ---- */

/*
 * The first page is one screen: the words, and beside them the stage, with
 * a model of the plugin standing over the liquid (the owner: "i want it to
 * not be a scrollable page on the home page ... and please make it display
 * a 3d model of the plugin on the right side on top of the animated display
 * that i can play with and adjust the buttons on"). The words need less of
 * the width than the model does, so here the stage has the larger share.
 */
@media (min-width: 881px) {
  .split-model {
    grid-template-columns: minmax(0, 42fr) minmax(0, 58fr);
  }

  .split-model > .words {
    padding-right: clamp(16px, 1.9vw, 32px);
  }
}

/*
 * The stage holds a list of plugins. There is one, and the next will be
 * the next item of the list. The list is measured (it is a container), and
 * a model takes its size from that measure: it fits whatever share of the
 * window the stage is given.
 */
.plugins {
  position: relative;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 40px;
  min-height: 100svh;
  margin: 0;
  /* Clear of the page's head, which lies over the top of the stage. */
  padding: 96px clamp(20px, 2vw, 44px) 36px;
  list-style: none;
  container-type: inline-size;
}

.plugin {
  display: grid;
  justify-items: center;
  gap: clamp(22px, 4vh, 40px);
  animation: rise 720ms 200ms var(--ease) both;
}

/* The first arrival may rise; choosing another instrument responds at once. */
.plugins[data-plugin-switched='true'] > .plugin {
  animation: none;
}

/*
 * The name under a model, on dark glass of its own like everything that
 * stands on the liquid at its full strength; and, until the model has been
 * touched once, how it is used.
 */
.plugin-name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 2px 12px;
  max-width: 100%;
  margin: 0;
  padding: 8px 16px;
  border-radius: 20px;
  background: var(--sheet);
  box-shadow: inset 0 0 0 1px var(--edge);
  font-size: 0.875rem;
  font-weight: var(--weight-semibold);
  letter-spacing: -0.01em;
  text-align: center;
}

.plugin-hint {
  color: var(--label-2);
  font-size: 0.8125rem;
  font-weight: 400;
}

/*
 * The model. It is the page's own elements, stood in space: a slab with a
 * face, the plugin's art on the left of the face and its instrument on the
 * right, each dial a raised part. No picture of the plugin is loaded, and
 * but for its liquid background nothing of it is painted: every
 * control on it is a real one.
 *
 * It is drawn in the plugin's own points: the plugin's window is 1120 of
 * them wide and 480 high, and --u is one of them at the size the model has
 * here. Every measure below is so many of those, taken from the plugin's
 * editor (website/assets/plugin-model.js says where), so the model is the
 * whole plugin, from its left edge to its right, in the plugin's own
 * proportions at every size. A narrower stage makes it smaller and changes
 * nothing else about it (the owner: "as i size down never change how the
 * plug in look please always show the full plugin full left to right just
 * make it smaller and fully fit down to mobile sizing").
 *
 * How it is held is two numbers, in degrees, which assets/model.js moves:
 * --tilt-x (leaning back) and --tilt-y (turned to one side). As written
 * here they are how it rests, for a page whose script has not run.
 */
.model {
  /* A little less than the stage has: turned, its near side looks larger than it is. And never larger than the plugin's own window. */
  --model-wide: min(96cqw, 1120px);
  --u: calc(var(--model-wide) / 1120);
  --tilt-x: 8;
  --tilt-y: -14;

  /* The plugin's own colours: one ink, the cream of the character's gloves, at three strengths, on the dark of its room. */
  --model-ink: var(--art-cream);
  --model-dim: #b5ac91;
  --model-faint: #a89f87;
  --model-room: #0a0714;

  position: relative;
  /* Leaned far over, its near edge comes down over its own name: it is the nearer of the two. */
  z-index: 1;
  width: var(--model-wide);
  height: calc(480 * var(--u));
  perspective: calc(var(--model-wide) * 1.9);
  color: var(--model-ink);
  font-size: calc(13 * var(--u));
  line-height: 1;
  cursor: grab;
  /* Under a finger, a swipe up or down on its body still scrolls the page; a swipe across turns it. */
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.model[data-held='true'] {
  cursor: grabbing;
}

/* Beside the words it is never taller than the window has room for, under the page's head and over its own name. */
@media (min-width: 881px) {
  .model {
    --model-wide: min(96cqw, 1120px, (100svh - 250px) * 1120 / 480);
  }
}

/* What it throws on the liquid under it: soft, and it moves the other way as the model is turned. */
.model-shadow {
  position: absolute;
  inset: 8% 3% -12%;
  border-radius: calc(60 * var(--u));
  background: rgb(4 2 10 / 0.7);
  filter: blur(calc(34 * var(--u)));
  transform: translate(calc(var(--tilt-y) * -0.9 * var(--u)), calc((34 - var(--tilt-x) * 1.2) * var(--u)));
  /*
   * A layer of its own, which the graphics card blurs and moves: it moves at
   * every frame the model is turned or floats, and blurred anew each time on
   * the page's own layer it made a phone stutter and flicker (the owner, 14
   * October 2026: "the shadow on the plugin as i go to move it around is
   * glitchy on mobile please smooth it out").
   */
  will-change: transform;
  pointer-events: none;
}

/*
 * Turned to one side, its near half looks wider than its far half, which
 * would carry it off the middle of its place: it is moved back by as much,
 * so that it stays in the middle however it is held.
 */
.model-body {
  position: absolute;
  inset: 0;
  transform: translateX(calc(var(--tilt-y) * 2.3 * var(--u))) rotateX(calc(var(--tilt-x) * 1deg)) rotateY(calc(var(--tilt-y) * 1deg));
  transform-style: preserve-3d;
}

.model:focus-visible .model-body,
.model-body:focus-visible {
  outline: 2px solid var(--label);
  outline-offset: 4px;
  border-radius: calc(20 * var(--u));
}

.model-slab,
.model-slab span,
.model-face {
  position: absolute;
  inset: 0;
  border-radius: calc(20 * var(--u));
}

/*
 * Its thickness: eight sheets of the face's own shape, one behind the
 * other, which from any side read as one solid edge with round corners.
 * Lighter at the top, where the light is.
 */
.model-slab {
  transform-style: preserve-3d;
}

.model-slab span {
  background: linear-gradient(180deg, #403858, #211b31 20%, #110d1d 68%, #07050e);
  transform: translateZ(calc(var(--sheet) * -4 * var(--u)));
}

.model-slab span:nth-child(1) {
  --sheet: 1;
}

.model-slab span:nth-child(2) {
  --sheet: 2;
}

.model-slab span:nth-child(3) {
  --sheet: 3;
}

.model-slab span:nth-child(4) {
  --sheet: 4;
}

.model-slab span:nth-child(5) {
  --sheet: 5;
}

.model-slab span:nth-child(6) {
  --sheet: 6;
}

.model-slab span:nth-child(7) {
  --sheet: 7;
}

.model-slab span:nth-child(8) {
  --sheet: 8;
}

/* The face: the dark of the plugin's room, with a hairline of light at its edge. */
.model-face {
  background: linear-gradient(180deg, #110d1e, var(--model-room) 44%, #080511);
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 0.09),
    inset 0 1px 0 rgb(255 255 255 / 0.16);
  transform-style: preserve-3d;
}

/* A soft light across the face, which travels over it as the model is turned. */
.model-light {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(70% 110% at calc(50% - var(--tilt-y) * 1.5%) calc(8% + var(--tilt-x) * 2.2%), rgb(255 255 255 / 0.1), transparent 62%);
  pointer-events: none;
}

/* ---- The model's art: the logo over the liquid ---- */

.model-art {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(440 * var(--u));
  height: 100%;
  transform-style: preserve-3d;
}

/*
 * The liquid moves, as it does in the plugin (the
 * owner: "please make the animated background part on the plugin be
 * animated properly"): the stage's own liquid, by the same recipe, painted
 * on a canvas of the model's by assets/liquid.js.
 * Towards the instrument it goes out, as in the plugin. Under
 * it is the same still light as under the stage's, in the same colours:
 * what shows before its first picture, and for good where a browser cannot
 * paint it.
 */
.model-marble {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: calc(20 * var(--u)) 0 0 calc(20 * var(--u));
  background:
    radial-gradient(60% 52% at 52% 48%, rgb(135 49 240 / 0.5), transparent),
    radial-gradient(44% 38% at 84% 16%, rgb(230 23 193 / 0.3), transparent),
    radial-gradient(48% 40% at 20% 84%, rgb(16 94 209 / 0.3), transparent),
    radial-gradient(38% 32% at 86% 84%, rgb(22 234 153 / 0.14), transparent),
    var(--ground);
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 74%, transparent 97%);
  mask-image: linear-gradient(90deg, #000 0%, #000 74%, transparent 97%);
}

.model-liquid {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 1400ms var(--ease);
}

.model-liquid[data-liquid='on'] {
  opacity: 1;
}

/* The maker's mark, where the plugin has it. As it is: nothing is done to it. */
.model-logo {
  position: absolute;
  top: calc(32 * var(--u));
  left: calc(32 * var(--u));
  width: calc(144 * var(--u));
  height: auto;
  transform: translateZ(calc(3 * var(--u)));
  pointer-events: none;
}

/* ---- The model's instrument: the chart over four bands, the three levels beside them ---- */

.model-panel {
  position: absolute;
  top: calc(40 * var(--u));
  left: calc(448 * var(--u));
  width: calc(672 * var(--u));
  height: calc(440 * var(--u));
  transform-style: preserve-3d;
}

.model-rail {
  position: absolute;
  top: calc(-14 * var(--u));
  left: calc(584 * var(--u));
  display: grid;
  grid-template-rows: repeat(3, calc(150 * var(--u)));
  width: calc(56 * var(--u));
  transform-style: preserve-3d;
}

.model-rail .module { grid-area: auto; }

.model[data-eq-editing='true'] .model-body {
  transform: none;
}

.model[data-eq-editing='true'] .node {
  transform: none;
}

/* Both scales share the right gutter; each unit stays directly over its own figures. */
.chart {
  position: absolute;
  top: 0;
  left: calc(-8 * var(--u));
  width: calc(560 * var(--u));
  height: calc(440 * var(--u));
  display: grid;
  grid-template-columns: calc(492 * var(--u)) calc(24 * var(--u)) calc(28 * var(--u));
  grid-template-rows: calc(12 * var(--u)) calc(384 * var(--u)) calc(44 * var(--u));
  grid-template-areas:
    '. gain-unit level-unit'
    'plot gain level'
    'hz . .';
  column-gap: calc(8 * var(--u));
  color: var(--model-dim);
  font-size: calc(11 * var(--u));
  white-space: nowrap;
  transform-style: preserve-3d;
}

.chart-unit {
  justify-self: stretch;
  align-self: end;
  margin-bottom: calc(10 * var(--u));
  line-height: calc(12 * var(--u));
  text-align: center;
}

.chart-unit-gain {
  grid-area: gain-unit;
}

.chart-unit-level {
  grid-area: level-unit;
}

/* A scale's five figures stand on the plot's five lines. */
.chart-scale {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  font-variant-numeric: tabular-nums;
}

.chart-scale span {
  display: flex;
  align-items: center;
  height: 0;
}

.chart-scale-gain {
  grid-area: gain;
}

.chart-scale-level {
  grid-area: level;
  color: rgb(245 232 196 / 0.66);
}

/*
 * Each frequency stands under its own line: how far across is worked out
 * as plugin-model.js works it out (acrossOf), and a test holds the two
 * together.
 */
.chart-hz {
  grid-area: hz;
  position: relative;
}

.chart-hz span {
  position: absolute;
  top: calc(17 * var(--u));
  left: calc(var(--across) * 100%);
  transform: translate(-50%, -50%);
}

.chart-hz [data-hz='20'] {
  --across: 0;
}

.chart-hz [data-hz='50'] {
  --across: 0.1326;
}

.chart-hz [data-hz='100'] {
  --across: 0.233;
}

.chart-hz [data-hz='200'] {
  --across: 0.3333;
}

.chart-hz [data-hz='500'] {
  --across: 0.466;
}

.chart-hz [data-hz='1000'] {
  --across: 0.5663;
}

.chart-hz [data-hz='2000'] {
  --across: 0.6667;
}

.chart-hz [data-hz='5000'] {
  --across: 0.7993;
}

.chart-hz [data-hz='10000'] {
  --across: 0.8997;
}

.chart-hz [data-hz='20000'] {
  --across: 1;
}

.plot {
  grid-area: plot;
  position: relative;
  transform-style: preserve-3d;
}

/*
 * The plot's lines are written in a square of 1000 and stretched over the
 * plot, whatever its shape; a line keeps its own width however far it is
 * stretched. The curve is one line in the accent, and what it boosts or
 * cuts is laid in faintly in the same colour.
 */
.plot-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.plot-lines path {
  fill: none;
  stroke-width: max(1px, var(--u));
  vector-effect: non-scaling-stroke;
}

.plot-minor {
  stroke: #1a1720;
}

.plot-major {
  stroke: #262229;
}

.plot-nought {
  stroke: #343034;
}

.plot-lines .plot-fill {
  fill: rgb(176 240 44 / 0.09);
}

.plot-stems {
  stroke: rgb(245 232 196 / 0.24);
}

.plot-lines .plot-curve {
  stroke: var(--art-green);
  stroke-width: max(1.5px, calc(2 * var(--u)));
  stroke-linecap: round;
  stroke-linejoin: round;
}

/*
 * A band's number: on its node on the chart, and before its name. Hollow
 * while the band does nothing, filled with the accent once it does. Where
 * a node stands is two numbers model.js moves; as written here, they are
 * where the plugin's own settings put them.
 */
.node,
.mark {
  display: grid;
  flex: none;
  place-items: center;
  width: calc(16 * var(--u));
  height: calc(16 * var(--u));
  border-radius: 50%;
  background: var(--model-room);
  box-shadow: inset 0 0 0 calc(1.5 * var(--u)) var(--model-dim);
  color: var(--model-dim);
  font-size: calc(11 * var(--u));
  font-weight: 700;
}

.node[data-in-use='true'],
.mark[data-in-use='true'] {
  background: var(--art-green);
  box-shadow: none;
  color: var(--model-room);
}

.node {
  --down: 0.5;

  position: absolute;
  top: calc(var(--down) * 100%);
  left: calc(var(--across) * 100%);
  margin: calc(-8 * var(--u)) 0 0 calc(-8 * var(--u));
  transform: translateZ(calc(2.4 * var(--u)));
  cursor: move;
  touch-action: none;
  outline-offset: 4px;
}

.node::before {
  content: '';
  position: absolute;
  inset: -10px;
  border-radius: 50%;
}

.node-readout {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: calc(100% + 8px);
  display: none;
  padding: 5px 8px;
  border: 1px solid var(--edge);
  border-radius: 6px;
  background: var(--model-room);
  color: var(--model-ink);
  font-size: max(10px, calc(12 * var(--u)));
  font-weight: 500;
  white-space: nowrap;
  transform: translateX(-50%);
  pointer-events: none;
}

.node:is(:hover, :focus-within, [data-held='true']) .node-readout { display: block; }
.node[data-node='1'] .node-readout { left: 0; transform: none; }
.node[data-node='4'] .node-readout { left: auto; right: 0; transform: none; }
.node:focus-within { outline: 2px solid var(--focus); }

.node-axis {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Where two nodes share a place, the one that is shaping the sound stays in view. */
.node[data-in-use='true'] {
  transform: translateZ(calc(3.2 * var(--u)));
}

.node[data-node='1'] {
  --across: 0.0264;
}

.node[data-node='2'] {
  --across: 0.2468;
}

.node[data-node='3'] {
  --across: 0.5147;
}

.node[data-node='4'] {
  --across: 0.9261;
}

/* A module: its name, and under it one or two controls. */
.module {
  display: grid;
  grid-template-rows: calc(14 * var(--u)) minmax(0, 1fr);
  row-gap: calc(23 * var(--u));
  align-content: start;
  justify-items: center;
  transform-style: preserve-3d;
}

.module-lowcut {
  grid-area: lowcut;
}

.module-low {
  grid-area: low;
}

.module-mid {
  grid-area: mid;
}

.module-high {
  grid-area: high;
}

.module-input {
  grid-area: input;
}

.module-drive {
  grid-area: drive;
}

.module-output {
  grid-area: output;
}

.module-name {
  display: flex;
  align-items: center;
  gap: calc(8 * var(--u));
  height: calc(14 * var(--u));
  margin: 0;
  color: var(--model-dim);
  white-space: nowrap;
}

.module-controls {
  display: flex;
  align-items: flex-start;
  gap: calc(16 * var(--u));
  transform-style: preserve-3d;
}

.control {
  display: grid;
  justify-items: center;
  width: calc(56 * var(--u));
  transform-style: preserve-3d;
}

/*
 * A dial. Flat on the face lies its ring: the dial's travel, with the part
 * between where it rests and where it stands in the accent. Off the face
 * stand a skirt and, higher, a cap with the pointer on it, with two sheets
 * between them: turned, the dial reads as a solid thing. It takes the
 * whole of a finger's gesture, up, down and across.
 *
 * --turn is how far the pointer is turned from upright, which model.js
 * sets; as written here it is where the plugin's own settings put each
 * dial, and a test holds that to plugin-model.js.
 */
.knob {
  --turn: 0deg;
  --cap-high: #37313f;
  --cap-low: #1b1722;

  position: relative;
  width: calc(56 * var(--u));
  height: calc(56 * var(--u));
  border-radius: 50%;
  outline-offset: calc(6 * var(--u));
  cursor: ns-resize;
  touch-action: none;
  /* A hair off the face: a press on it is plainly on it, and not on the face under it. */
  transform: translateZ(calc(0.5 * var(--u)));
  transform-style: preserve-3d;
}

/*
 * What takes the pointer for a dial is larger than the dial: the room
 * round it, down to the foot of its value. The model may be drawn small,
 * and a dial should not have to be hit exactly.
 */
.knob::before {
  content: '';
  position: absolute;
  inset: calc(-12 * var(--u)) calc(-8 * var(--u)) calc(-32 * var(--u));
}

.knob[data-knob='DRIVE'] {
  --turn: -86.4deg;
}

.knob[data-knob='LOW_FREQ'] {
  --turn: 26.2deg;
}

.knob[data-knob='MID_FREQ'] {
  --turn: -55.2deg;
}

.knob-ring {
  position: absolute;
  top: calc(-8 * var(--u));
  left: calc(-8 * var(--u));
  width: calc(72 * var(--u));
  height: calc(72 * var(--u));
  overflow: visible;
  pointer-events: none;
}

.knob-ring path {
  fill: none;
  stroke-width: 3;
  stroke-linecap: round;
}

.knob-track {
  stroke: rgb(245 232 196 / 0.24);
}

.knob-arc {
  stroke: var(--art-green);
}

/* A gain's one fine mark, over the ring, where it rests. */
.knob-ring .knob-rest {
  stroke: rgb(245 232 196 / 0.4);
  stroke-width: 1;
  stroke-linecap: butt;
}

.knob-skirt,
.knob-cap {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

.knob-skirt {
  inset: calc(3.4 * var(--u));
  background: #0c0915;
  box-shadow: inset 0 0 0 max(1px, var(--u)) rgb(255 255 255 / 0.05);
  transform: translateZ(calc(1.6 * var(--u)));
  transform-style: preserve-3d;
}

.knob-skirt::before,
.knob-skirt::after {
  content: '';
  position: absolute;
  inset: calc(2.5 * var(--u));
  border-radius: 50%;
  background: #14111c;
  transform: translateZ(calc(2.2 * var(--u)));
}

.knob-skirt::after {
  background: #1a1623;
  transform: translateZ(calc(4.4 * var(--u)));
}

.knob-cap {
  inset: calc(6 * var(--u));
  background: radial-gradient(circle at 36% 22%, var(--cap-high), var(--cap-low) 76%);
  box-shadow:
    inset 0 max(1px, var(--u)) 0 rgb(255 255 255 / 0.13),
    inset 0 0 0 max(1px, var(--u)) rgb(255 255 255 / 0.04);
  transform: translateZ(calc(8.4 * var(--u)));
}

/* The pointer: a line in the ink, from near the cap's middle out towards its edge. */
.knob-pointer {
  position: absolute;
  inset: 0;
  transform: rotate(var(--turn));
}

.knob-pointer::before {
  content: '';
  position: absolute;
  top: calc(3.5 * var(--u));
  left: 50%;
  width: calc(2 * var(--u));
  height: calc(10.6 * var(--u));
  margin-left: calc(-1 * var(--u));
  border-radius: var(--u);
  background: var(--model-ink);
}

/* Under the pointer of the mouse the cap and the ring are a step lighter; held, the cap is lighter still and the whole ring is lit. */
.knob:hover,
.knob:focus-visible {
  --cap-high: #443d4e;
  --cap-low: #231e2c;
}

.knob:hover .knob-track,
.knob:focus-visible .knob-track {
  stroke: rgb(245 232 196 / 0.38);
}

.knob[data-held='true'] {
  --cap-high: #4f4759;
  --cap-low: #2a2433;
}

.knob[data-held='true'] .knob-track {
  stroke: rgb(176 240 44 / 0.36);
}

/* The exact value, under its dial: the number in the ink, its unit a step dimmer. */
.reading {
  height: calc(14 * var(--u));
  margin: calc(13 * var(--u)) 0 0;
  color: var(--model-dim);
  line-height: calc(14 * var(--u));
  text-align: center;
  white-space: nowrap;
}

.reading b {
  color: var(--model-ink);
  font-weight: var(--weight-medium);
}

/*
 * A list: one line to a choice, each with its unit, and the chosen one on
 * a pill with a little of the accent in it (of plain glass for "Off",
 * whose band does nothing). Each line is a real radio button, which is
 * what the keyboard moves through; the button itself is not drawn.
 */
.choices {
  position: relative;
  display: grid;
  width: calc(56 * var(--u));
  margin-top: calc(-12 * var(--u));
  cursor: pointer;
  touch-action: none;
  /* A hair off the face, like a dial, and it takes the pointer a little to either side of its pills. */
  transform: translateZ(calc(0.5 * var(--u)));
}

.choices::before {
  content: '';
  position: absolute;
  inset: calc(-4 * var(--u)) calc(-6 * var(--u));
}

.choice {
  position: relative;
  display: block;
  height: calc(16 * var(--u));
  cursor: pointer;
}

.choice input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.choice-entry {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Between a number and its unit: the space a line of words has there. */
  gap: 0.26em;
  height: 100%;
  border-radius: var(--r-round);
  color: var(--model-faint);
  white-space: nowrap;
}

.choice-entry b {
  font-weight: inherit;
}

.choice:hover .choice-entry {
  color: var(--model-ink);
}

.choice input:checked + .choice-entry {
  background: rgb(176 240 44 / 0.16);
  color: var(--model-dim);
}

.choice input:checked + .choice-off {
  background: rgb(245 232 196 / 0.08);
}

.choice input:checked + .choice-off,
.choice input:checked + .choice-entry b {
  color: var(--model-ink);
  font-weight: var(--weight-medium);
}

.choice input:focus-visible + .choice-entry {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* ---- Coming in: one after another, once, when the page opens ---- */

.rise {
  animation: rise 720ms var(--ease) both;
}

.rise-2 {
  animation-delay: 90ms;
}

.rise-3 {
  animation-delay: 180ms;
}

.rise-4 {
  animation-delay: 270ms;
}

.rise-5 {
  animation-delay: 360ms;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
}

@keyframes nod {
  to {
    transform: translateY(3px);
  }
}

@keyframes breathe {
  to {
    opacity: 0.55;
  }
}

/* The form's place comes up into its position; the character gives way to it. */
@keyframes arrive {
  from {
    opacity: 0;
    transform: translateY(18px) scale(0.985);
  }
}

@keyframes leave {
  to {
    opacity: 0;
    transform: translateY(10px) scale(0.94);
  }
}

@keyframes sweep {
  from {
    background-position: 120% 0, 0 0;
  }

  to {
    background-position: -120% 0, 0 0;
  }
}

@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}

/* ---- A narrow window: the stage on top, the words under it ---- */

@media (max-width: 880px) {
  /* A flat root and body also fill the iPhone time and battery area. */
  .split {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }

  .poster {
    order: -1;
    min-height: 0;
    height: min(108vw, 66svh);
  }

  /* A little below the middle: the logo has the stage's top corner. */
  .poster-figure {
    top: 56%;
    width: min(68%, 50svh, 360px);
  }

  .brand-logo {
    width: min(40vw, 168px);
  }

  /* The account keeps its corner; the link beside it would crowd the logo. */
  .top-link {
    display: none;
  }

  /* The head stands on the same margins as the words under it: the page's left line is the side margin here. */
  :root {
    --head-side: var(--side);
  }

  /*
   * The first page's stage holds the model and is as tall as the model
   * makes it: the plugin first, then the heading and the buttons, and the
   * page scrolls as far as that takes it (the owner: "on mobile please put
   * 1 above the sign in buttons the main display plugin and then the rest
   * when we add them under and make it scrollable on mobile").
   */
  .split-model .poster {
    height: auto;
  }

  /* The model has nearly all of the window's width: on a phone it is small enough as it is. */
  .plugins {
    min-height: 0;
    padding: 100px 12px 4px;
  }

  .words {
    justify-content: flex-start;
    padding-top: 0;
    padding-bottom: 56px;
  }

  /* The words begin where the stage ends. */
  .words > :first-child {
    margin-top: 4px;
  }

  /* Under the model's name they keep a little more air. */
  .split-model .words > :first-child {
    margin-top: 30px;
  }

  /* Under the words, the form is as wide as they are. */
  .checkout {
    width: 100%;
  }

  /*
   * On /subscribe/ the stage is a strip, not most of the screen: whoever
   * comes back from signing in should see the plans without scrolling.
   */
  .split-tall .poster {
    height: min(62vw, 36svh);
  }

  .split-tall .poster-figure {
    top: 58%;
    width: min(38%, 27svh, 210px);
  }
}

/*
 * A phone. The margins are a phone's, and everything in a column is as wide
 * as the column: a button is pressed with a thumb, and a panel has no room
 * to spare for padding.
 */
@media (max-width: 520px) {
  :root {
    --side: 22px;
  }

  /* The account is its disc alone: the name is in its menu. */
  .profile-name {
    display: none;
  }

  .profile-button {
    padding-right: 11px;
  }

  .profile-item {
    height: 46px;
  }

  .headline {
    font-size: clamp(2.125rem, 9.6vw, 2.5rem);
  }

  .headline-small {
    font-size: clamp(1.75rem, 7.8vw, 2rem);
  }

  .words {
    padding-bottom: 44px;
  }

  /* One over the other, each the full width of the words. */
  .signin {
    flex-basis: 100%;
    max-width: none;
  }

  .member {
    padding: 20px;
  }

  .pay {
    padding-bottom: 44px;
  }

  .checkout {
    padding: 16px;
    border-radius: 24px;
  }
}

/* The smallest phones: the heading keeps to two lines. */
@media (max-width: 350px) {
  .headline {
    font-size: 1.9375rem;
  }
}

/* Under a finger, a link in a line of text is taller than its letters. */
@media (pointer: coarse) {
  .quiet {
    margin: -10px 0;
    padding: 10px 0;
  }
}

/* The two plans, one under the other, where two side by side would be cramped. */
@media (max-width: 460px) {
  .plans {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- Home: one viewport, with account controls in the header ---- */

.home {
  --home-logo-width: clamp(136px, 12.5vw, 184px);
  --home-head-height: calc(var(--home-logo-width) * 204 / 600 + clamp(16px, 2.5dvh, 24px) + clamp(14px, 2.4vh, 22px) + env(safe-area-inset-top, 0px));
  /* At the allowed 18°/30° tilt, a near corner rises by 23.2% of its height. */
  --model-lift-top: .25;
  --model-lift-bottom: .07;
  --home-bottom-space: calc(env(safe-area-inset-bottom, 0px) + 20px);
}

html.home,
.home body {
  width: 100%;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  overscroll-behavior: none;
}

.home body {
  position: relative;
  padding: 0;
}

.home main,
.home .split-model {
  height: 100svh;
  height: 100dvh;
  min-height: 0;
}

.home .split-model {
  isolation: isolate;
  padding-top: 0;
  overflow: visible;
}

.home .top {
  top: 0;
  align-items: center;
  gap: 12px;
  padding-top: calc(clamp(16px, 2.5dvh, 24px) + env(safe-area-inset-top, 0px));
}

.home .top-nav {
  padding-top: 0;
}

/* Platform information stays quiet and has no action to compete with sign-in. */
.home-platform {
  position: static;
  display: grid;
  align-content: center;
  gap: 3px;
  color: var(--label-2);
  font-size: 0.75rem;
  line-height: 1.45;
  letter-spacing: -0.01em;
}

.home-platform strong {
  color: var(--label);
  font-size: 0.8125rem;
  font-weight: var(--weight-semibold);
}

.home[data-subscribe-state='opening'] .home-platform,
.home[data-subscribe-state='paying'] .home-platform {
  display: none;
}

.home .top-download-mark {
  display: none;
  width: 18px;
  height: 18px;
}

.home .words {
  min-height: 0;
  padding-top: calc(clamp(110px, 20dvh, 210px) + env(safe-area-inset-top, 0px));
  padding-bottom: var(--home-bottom-space);
  padding-left: max(var(--head-side), env(safe-area-inset-left, 0px));
}

/* One quiet baseline lets the instruments carry the colour. */
.home .home-bottom-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  max-width: none;
  margin-top: auto;
}

.home .home-bottom-line > :is(.lede, .home-platform) {
  display: grid;
  align-content: center;
  gap: 2px;
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
}

.home .home-bottom-line > .lede {
  max-width: 32ch;
  font-size: clamp(1rem, 1.6vw, 1.375rem);
  line-height: 1.35;
  letter-spacing: -0.025em;
  text-align: left;
}

.home[data-subscribe-state='opening'] .home-bottom-line,
.home[data-subscribe-state='paying'] .home-bottom-line {
  grid-template-columns: minmax(0, 1fr);
}

.home .lede {
  flex: none;
  max-width: 27rem;
  font-size: clamp(1.375rem, 2vw, 1.875rem);
  font-weight: var(--weight-semibold);
  line-height: 1.25;
  letter-spacing: -0.028em;
  color: var(--label);
  text-wrap: balance;
}

.home .words > .join {
  flex: none;
  margin-top: 0;
  padding-top: 16px;
  gap: 14px;
}

.home .signin-buttons {
  gap: 10px;
}

.home .signin {
  max-width: none;
  height: 52px;
  font-size: 1rem;
  font-weight: 600;
}

.home .join .fine {
  width: 100%;
  font-size: 0.8125rem;
  line-height: 1.55;
  letter-spacing: 0;
  color: rgb(255 255 255 / 0.65);
}

/* A published installer is already available through the header's download link. */
.home .download-found[data-state='release'] {
  display: none;
}

.home .plans {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.home .plan {
  padding: 16px;
}

.home .plan-name {
  flex-wrap: wrap;
  gap: 4px 6px;
}

.home .plan-go {
  display: none;
}

.home .plan-price {
  font-size: 0.8125rem;
}

.home .member {
  padding: 16px;
  gap: 10px;
}

.home .member-sentence {
  font-size: 1rem;
}

/* Ownership belongs in the account page. Billing problems remain visible here. */
.home .join[data-state='free'],
.home .join[data-state='member']:has([data-member-state][data-member-tone='good']) {
  display: none;
}

/* The stage positions the model against the shared gray ground. */
.home .poster {
  position: static;
  min-height: 0;
  height: auto;
}

.home .plugins {
  z-index: 1;
  height: 100%;
  min-height: 0;
  padding-top: calc(96px + env(safe-area-inset-top, 0px));
  padding-bottom: max(40px, env(safe-area-inset-bottom, 0px));
}

.home[data-subscribe-state='opening'] .plugins,
.home[data-subscribe-state='paying'] .plugins {
  visibility: hidden;
}

.home[data-subscribe-state='opening'] .plugin,
.home[data-subscribe-state='paying'] .plugin {
  visibility: hidden;
  animation: none;
  transition: none;
}

/* Payment stays usable inside the screen, even when Stripe's form is tall. */
.home .pay {
  z-index: 3;
  align-content: start;
  min-height: 0;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
}

@media (max-width: 880px) {
  .home {
    --home-logo-width: min(40vw, 168px);
  }

  .home .top-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    padding: 0;
  }

  .home .top-link span {
    display: none;
  }

  .home .top-download-mark {
    display: block;
  }

  .home .split-model {
    grid-template-rows: minmax(0, 1fr) auto;
  }

  .home .poster {
    grid-row: 1;
    grid-column: 1;
  }

  .home .plugins {
    container-type: size;
    padding: calc(90px + env(safe-area-inset-top, 0px)) 12px 18px;
    align-content: center;
  }

  .home .plugin {
    gap: 18px;
  }

  .home .model {
    --model-wide: min(94cqw, 740px, max(0px, (100cqh - 56px) * 1120 / 480));
    touch-action: none;
  }

  .home .plugin-name {
    padding: 6px 12px;
    font-size: 0.75rem;
  }

  .home .plugin-hint {
    font-size: 0.6875rem;
  }

  .home .words {
    grid-row: 2;
    grid-column: 1;
    height: auto;
    min-height: 0;
    padding: 0 max(var(--head-side), env(safe-area-inset-right, 0px)) var(--home-bottom-space) max(var(--head-side), env(safe-area-inset-left, 0px));
  }

  .home .lede {
    font-size: 1.375rem;
  }

  .home .words > .join {
    padding-top: 16px;
    gap: 12px;
  }

  .home .join .fine {
    text-align: center;
  }

  .home .pay {
    grid-row: 1;
    grid-column: 1;
    margin-top: calc(86px + env(safe-area-inset-top, 0px));
    padding: 8px var(--side) max(20px, env(safe-area-inset-bottom, 0px));
    background: var(--ground);
  }
}

/* On a short phone, keep every control visible before spending space on the model. */
@media (max-width: 880px) and (max-height: 700px) {
  .home .lede {
    font-size: 1.1875rem;
  }

  .home .signin {
    height: 48px;
  }

  .home .words > .join {
    padding-top: 12px;
    gap: 10px;
  }

  .home .plugins {
    padding-top: calc(82px + env(safe-area-inset-top, 0px));
    padding-bottom: 12px;
  }

  .home .plugin {
    gap: 12px;
  }

  .home .plugin-hint {
    display: none;
  }
}

@media (min-width: 600px) and (max-height: 520px) {
  .home .split-model {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
  }

  .home .words {
    grid-row: 1;
    grid-column: 1;
    height: 100%;
    min-height: 0;
    padding-top: max(76px, env(safe-area-inset-top, 0px));
    padding-right: 12px;
    padding-bottom: var(--home-bottom-space);
  }

  .home .lede {
    font-size: 1.125rem;
  }

  .home .words > .join {
    padding-top: 10px;
    gap: 8px;
  }

  .home .signin {
    flex-basis: 100%;
    height: 44px;
    font-size: 0.875rem;
  }

  .home .join .fine {
    font-size: 0.6875rem;
    line-height: 1.4;
  }

  .home .join .fine br {
    display: none;
  }

  .home .plan {
    gap: 2px;
    padding: 10px 12px;
    border-radius: 16px;
  }

  .home .plan-name {
    min-height: 18px;
    font-size: 0.8125rem;
    gap: 4px;
  }

  .home .plan-tag {
    padding: 2px 4px;
    font-size: 0.625rem;
  }

  .home .plan-amount {
    font-size: 1.25rem;
  }

  .home .plan-price {
    font-size: 0.6875rem;
  }

  .home .poster {
    grid-column: 2;
    grid-row: 1;
  }

  .home .model {
    --model-wide: min(90cqw, 740px, (100dvh - 150px) * 1120 / 480);
  }

  .home .pay {
    grid-column: 2;
    grid-row: 1;
    margin-top: 70px;
  }
}

/* The resting hero uses the full viewport width, with its own row above the words.
 * Checkout keeps the existing side-by-side or mobile payment layout. */
.home:not([data-subscribe-state='opening']):not([data-subscribe-state='paying']) .split-model {
  grid-template-rows: minmax(0, 1fr) auto;
}

.home:not([data-subscribe-state='opening']):not([data-subscribe-state='paying']) .poster {
  grid-column: 1 / -1;
  grid-row: 1;
}

.home:not([data-subscribe-state='opening']):not([data-subscribe-state='paying']) .words {
  grid-column: 1 / -1;
  grid-row: 2;
  height: auto;
  padding-top: 0;
  padding-inline: max(var(--head-side), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  /* Enlarged text and billing warnings can outgrow a phone's single screen. */
  max-height: calc(100dvh - 104px - env(safe-area-inset-top, 0px));
  overflow-y: auto;
  overscroll-behavior: contain;
}

.home:not([data-subscribe-state='opening']):not([data-subscribe-state='paying']) .plugins {
  container-type: size;
  padding-top: calc(var(--home-head-height) + 8px);
}

.home:not([data-subscribe-state='opening']):not([data-subscribe-state='paying']) .model {
  --model-wide: min(90cqw, 1120px, max(0px, (100cqh - 80px) / (1 + var(--model-lift-top) + var(--model-lift-bottom)) * 1120 / 480));
  margin: calc(var(--model-lift-top) * 480 * var(--u)) 0 calc(var(--model-lift-bottom) * 480 * var(--u));
}

/* When enlarged account text fills the screen, keep the preview out of its header. */
@container (max-height: 140px) {
  .home .plugins > .plugin { display: none; }
}

/* A single readable column keeps the footer clear on an iPhone. */
@media (max-width: 599px) {
  .home .home-bottom-line {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    gap: 12px;
  }

  .home .home-bottom-line > :is(.lede, .home-platform) {
    justify-items: center;
    text-align: center;
  }

  .home .home-bottom-line > .lede { font-size: 1rem; }
  .home .home-platform { font-size: 0.6875rem; }
  .home .home-platform strong { font-size: 0.75rem; }
}

/* Mobile checkout uses the screen beneath the header, without a second plan panel. */
@media (max-width: 880px) {
  :is([data-subscribe-state='opening'], [data-subscribe-state='paying']) .words {
    display: none;
  }

  .home .pay,
  .split-tall > .pay {
    position: fixed;
    top: calc(76px + env(safe-area-inset-top, 0px));
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 3;
    width: 100%;
    max-height: none;
    margin: 0;
    padding: 0 max(16px, env(safe-area-inset-right, 0px)) max(16px, env(safe-area-inset-bottom, 0px)) max(16px, env(safe-area-inset-left, 0px));
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--ground);
    animation: checkout-enter 220ms var(--ease) both;
  }

  .pay-toolbar {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    width: min(100%, 432px);
    min-height: 60px;
    margin: 0 auto;
    padding: 4px 0 12px;
    background: var(--ground);
    font-size: 0.9375rem;
    font-weight: 600;
  }

  .pay-back {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--edge);
    border-radius: 50%;
    color: var(--label);
    background: var(--fill-2);
    cursor: pointer;
  }

  .pay-back svg {
    width: 20px;
    height: 20px;
  }

  .pay-note:not([hidden]) {
    display: block;
    width: min(100%, 432px);
    margin: 0 auto 16px;
    color: var(--label-2);
    font-size: 0.9375rem;
    line-height: 1.5;
  }

  .pay .checkout {
    width: min(100%, 432px);
    margin: 0 auto;
    padding: 4px 0 16px;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    animation: none;
  }

  .pay .checkout:empty {
    min-height: min(420px, calc(100dvh - 160px));
    background: linear-gradient(100deg, transparent 30%, rgb(255 255 255 / 0.04) 50%, transparent 70%) 0 0 / 220% 100%;
    animation: sweep 1.6s linear infinite;
  }
}

@keyframes checkout-enter {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}

.signin-legal {
  display: flex;
  justify-content: center;
  gap: 16px;
  margin-top: 16px;
}

.signin-legal a {
  color: var(--label-2);
  font-size: 0.6875rem;
  line-height: 1.5;
  text-decoration: none;
  text-underline-offset: 3px;
}

.signin-legal a:hover {
  color: var(--label);
  text-decoration: underline;
}

/* ---- Someone whose system asks for less motion gets none ---- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }

  .model-liquid[data-liquid='on'] {
    opacity: 1;
  }

  /* Without motion the character is simply not there while the form is. */
  [data-subscribe-state='opening'] .split-tall .poster-figure,
  [data-subscribe-state='paying'] .split-tall .poster-figure {
    opacity: 0;
  }

  [data-tone='good'] .mark-good path {
    stroke-dashoffset: 0;
  }
}

/* Two complete instruments share one stage. Each keeps its controls when hidden. */
.home .poster { position: relative; }
.plugin-caption { position: relative; z-index: 2; display: grid; justify-items: center; gap: 7px; }
.plugin-selector { display: flex; align-items: center; justify-content: center; gap: 10px; }
.plugin-arrow { display: grid; place-items: center; flex: 0 0 auto; width: 36px; height: 36px; padding: 8px; border: 1px solid rgb(255 255 255 / .10); border-radius: 50%; color: var(--label-2); background: rgb(255 255 255 / .035); cursor: pointer; touch-action: manipulation; transition: color 120ms ease, background 120ms ease; }
.plugin-arrow svg { display: block; width: 18px; height: 18px; }
.plugin-arrow:hover { color: var(--label); background: rgb(255 255 255 / .08); }
.plugin-arrow:focus-visible { outline: 2px solid var(--label); outline-offset: 3px; }
.plugin-browse { display: flex; align-items: center; gap: 10px; }
.plugin-browse-label { color: var(--label-3); font-size: 11px; white-space: nowrap; }
.plugin-arrow-below { width: 28px; height: 28px; padding: 5px; border-color: transparent; background: transparent; }
.home .plugin-browse { display: none; }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
@media (max-width: 880px) {
  .plugin-selector { gap: 7px; }
  .plugin-arrow { width: 32px; height: 32px; padding: 6px; }
  .plugin-arrow-below { width: 26px; height: 26px; padding: 4px; }
  .plugin-caption { gap: 4px; }
  .plugin-caption .plugin-hint { font-size: 10px; }
}

/* One set of controls, with comfortable finger targets outside the scaled instrument. */
@media (pointer: coarse) {
  .plugin-selector > .plugin-arrow { width: 44px; height: 44px; padding: 12px; }
  .top-signin, .profile-button { min-height: 44px; }
  .signin-close { width: 44px; height: 44px; }
}

/*
 * TRIP Limiter's model (its face is trip-model.css, generated from Central's).
 * Its editor is 1040 of its points wide and 480 high, where ACID's is 1120: it
 * keeps ACID's point (--u) and so its height, and its slab is 1040 of them
 * wide. So that it is as wide as ACID wherever the width decides (a phone),
 * each rule above that sizes the model has a twin here: the same selector and
 * the same weight, for .model-trip-limiter in place of .model, with only the
 * part taken from the stage's width made larger by 1120 / 1040 (14 / 13). The
 * parts taken from the height, and the largest sizes in pixels, are ACID's.
 */
.model.model-trip-limiter {
  width: calc(1040 * var(--u));
}

.model-trip-limiter {
  --model-wide: min(96cqw * 14 / 13, 1120px);
}

@media (min-width: 881px) {
  .model-trip-limiter {
    --model-wide: min(96cqw * 14 / 13, 1120px, (100svh - 250px) * 1120 / 480);
  }
}

@media (max-width: 880px) {
  .home .model-trip-limiter {
    --model-wide: min(94cqw * 14 / 13, 740px, max(0px, (100cqh - 56px) * 1120 / 480));
  }
}

@media (min-width: 600px) and (max-height: 520px) {
  .home .model-trip-limiter {
    --model-wide: min(90cqw * 14 / 13, 740px, (100dvh - 150px) * 1120 / 480);
  }
}

.home:not([data-subscribe-state='opening']):not([data-subscribe-state='paying']) .model-trip-limiter {
  --model-wide: min(90cqw * 14 / 13, 1120px, max(0px, (100cqh - 80px) / (1 + var(--model-lift-top) + var(--model-lift-bottom)) * 1120 / 480));
}

/* ACID 3.1.0's current native face. Keep these overrides off TRIP. */
.model[data-acid-model] .chart { grid-template-rows: calc(42 * var(--u)) calc(330 * var(--u)) calc(68 * var(--u)); }
.model[data-acid-model] .chart-scale-level { position: relative; display: block; }
.model[data-acid-model] .chart-scale-level span { position: absolute; left: 0; right: 0; top: calc(var(--acid-level-y, 0) * 100%); transform: translateY(-50%); justify-content: center; }
.model[data-acid-model] .chart-scale-level span[hidden] { display: none; }
.model[data-acid-model] .model-rail { top: calc(-10 * var(--u)); }
.model[data-acid-model] .module { row-gap: calc(15 * var(--u)); }
.model[data-acid-model] .module-name { font-size: calc(12 * var(--u)); }
.model[data-acid-model] .control { width: calc(92 * var(--u)); }
.model[data-acid-model] .knob { width: calc(72 * var(--u)); height: calc(72 * var(--u)); background: none; outline-color: #16ea99; }
.model[data-acid-model] .knob::before { inset: calc(-7 * var(--u)) calc(-10 * var(--u)) calc(-23 * var(--u)); }
.model[data-acid-model] .acid-knob-svg { width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.model[data-acid-model] .acid-knob-material { display: none; position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.model[data-acid-model] [data-acid-knob-material][data-ready='true'] { display: block; }
.model[data-acid-model] [data-acid-knob-material][data-ready='true'] + .acid-knob-svg .acid-capsule,
.model[data-acid-model] [data-acid-knob-material][data-ready='true'] + .acid-knob-svg .knob-track,
.model[data-acid-model] [data-acid-knob-material][data-ready='true'] + .acid-knob-svg .knob-arc { visibility: hidden; }
.model[data-acid-model] .acid-knob-ring path { fill: none; stroke-width: 2.7; stroke-linecap: round; }
.model[data-acid-model] .acid-knob-ring .knob-track { stroke: #474954; }
.model[data-acid-model] .acid-knob-ring .knob-rest { stroke: #a89f87; stroke-width: .8; }
.model[data-acid-model] [data-knob='INPUT_GAIN'] .knob-arc { stroke: #f94c76; }
.model[data-acid-model] [data-knob='DRIVE'] .knob-arc { stroke: #efe507; }
.model[data-acid-model] [data-knob='OUTPUT'] .knob-arc { stroke: #16ea99; }
.model[data-acid-model] .acid-capsule { filter: drop-shadow(0 1px 1.5px rgb(0 0 0 / .5)); }
.model[data-acid-model] .reading { margin-top: calc(5 * var(--u)); font-size: calc(13 * var(--u)); }
.model[data-acid-model] .acid-cap-folds { animation: acid-site-capsule-flow 8s ease-in-out infinite alternate; animation-play-state: paused; }
.model[data-acid-model][data-acid-motion='running'] .acid-cap-folds { animation-play-state: running; }
@keyframes acid-site-capsule-flow { from { transform: translate(-2px, -2px); } to { transform: translate(3px, 2px); } }
.model[data-acid-model] .acid-spectrum { fill: none; stroke-width: 1; vector-effect: non-scaling-stroke; animation: acid-site-spectrum-pulse var(--acid-trace-decay, 2.4s) ease-in-out infinite alternate; animation-play-state: paused; }
.model[data-acid-model] .acid-spectrum-in { stroke: #6ce9e3; opacity: .42; }
.model[data-acid-model] .acid-spectrum-out { stroke: #f5e8c4; opacity: .5; }
.model[data-acid-model][data-acid-source='in'] .acid-spectrum-out,
.model[data-acid-model][data-acid-source='out'] .acid-spectrum-in { visibility: hidden; }
.model[data-acid-model][data-acid-motion='running'][data-acid-frozen='false'] .acid-spectrum { animation-play-state: running; }
@keyframes acid-site-spectrum-pulse { from { stroke-opacity: .7; } to { stroke-opacity: 1; } }
.model[data-acid-model][data-acid-listen='true'] .plot { box-shadow: inset 0 0 0 max(.5px, var(--u)) rgb(176 240 44 / .35); }
.model[data-acid-model] .acid-meters { position: absolute; left: calc(-8 * var(--u)); top: calc(409 * var(--u)); width: calc(520 * var(--u)); height: calc(19 * var(--u)); display: flex; gap: calc(28 * var(--u)); }
.model[data-acid-model] .acid-meter { display: flex; align-items: center; gap: calc(8 * var(--u)); width: calc(246 * var(--u)); height: 100%; color: #b5ac91; background: none; border: 0; padding: 0; border-radius: calc(3 * var(--u)); font: inherit; font-size: calc(10 * var(--u)); cursor: pointer; touch-action: manipulation; }
.model[data-acid-model] .acid-meter-label { flex: none; width: calc(24 * var(--u)); text-align: left; white-space: nowrap; }
.model[data-acid-model] .acid-meter-in .acid-meter-label { color: #6ce9e3; }
.model[data-acid-model] .acid-meter-track { position: relative; flex: 1; height: calc(4 * var(--u)); background: #28242e; border-radius: calc(2 * var(--u)); }
.model[data-acid-model] .acid-meter-fill { position: absolute; left: 0; top: 0; bottom: 0; width: calc(var(--acid-level, .6) * 100%); border-radius: inherit; background: #6ce9e3; }
.model[data-acid-model] .acid-meter-out .acid-meter-fill { background: #f5e8c4; }
.model[data-acid-model] .acid-meter-peak { position: absolute; left: calc(var(--acid-level, .77) * 100%); top: calc(-2 * var(--u)); width: max(.5px, var(--u)); height: calc(8 * var(--u)); background: #f5e8c4; }
.model[data-acid-model] .acid-meter-value { width: calc(66 * var(--u)); flex: none; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.model[data-acid-model] .acid-meter:focus-visible { outline: max(.5px, var(--u)) solid #f5e8c4; outline-offset: calc(3 * var(--u)); }
@media (prefers-reduced-motion: reduce) { .model[data-acid-model] .acid-cap-folds, .model[data-acid-model] .acid-spectrum { animation: none; } }

/* The native 3.1 monitor rail, in the ACID face's 1120 × 480 design points. */
.model[data-acid-model] .acid-toolbar {
  position: absolute;
  left: calc(-8 * var(--u));
  top: calc(-19 * var(--u));
  width: calc(547 * var(--u));
  height: calc(26 * var(--u));
  z-index: 8;
  display: flex;
  align-items: center;
  gap: calc(4 * var(--u));
  color: var(--model-dim, #b5ac91);
  font: 500 calc(10.5 * var(--u)) / 1 -apple-system, BlinkMacSystemFont, sans-serif;
  cursor: default;
  transform-style: preserve-3d;
}

.model[data-acid-model] .acid-toolbar button {
  flex: none;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: calc(26 * var(--u));
  min-width: 0;
  padding: 0 calc(4 * var(--u));
  margin: 0;
  appearance: none;
  box-sizing: border-box;
  border: max(0.5px, calc(0.65 * var(--u))) solid rgb(245 232 196 / 0.075);
  border-radius: calc(13 * var(--u));
  background: #2b2b2b;
  color: inherit;
  font: inherit;
  white-space: nowrap;
  line-height: 1;
  box-shadow: none;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
}

.model[data-acid-model] .acid-toolbar button:hover { background: #353535; color: var(--model-ink, #f5e8c4); }
.model[data-acid-model] .acid-toolbar button:active { background: #303030; }
.model[data-acid-model] .acid-toolbar button[aria-pressed='true'] { background: #414141; color: var(--model-ink, #f5e8c4); border-color: rgb(245 232 196 / 0.12); }
.model[data-acid-model] .acid-toolbar button[aria-pressed='true']:active { background: #3c3c3c; }
.model[data-acid-model] .acid-toolbar button:focus-visible { outline: max(1px, var(--u)) solid rgb(245 232 196 / 0.9); outline-offset: calc(2 * var(--u)); }
.model[data-acid-model] .acid-toolbar button:disabled { cursor: inherit; }

.model[data-acid-model] .acid-toolbar .acid-source,
.model[data-acid-model] .acid-toolbar .acid-banks {
  position: relative;
  display: grid;
  flex: none;
  height: calc(26 * var(--u));
  gap: var(--u);
  border: max(0.5px, calc(0.65 * var(--u))) solid rgb(245 232 196 / 0.075);
  border-radius: calc(13 * var(--u));
  background: #242424;
  box-sizing: border-box;
}
.model[data-acid-model] .acid-toolbar .acid-source { width: calc(114 * var(--u)); grid-template-columns: 32fr 36fr 44fr; margin-right: calc(8 * var(--u)); }
.model[data-acid-model] .acid-toolbar .acid-banks { width: calc(53 * var(--u)); grid-template-columns: 1fr 1fr; margin-right: calc(4 * var(--u)); }
.model[data-acid-model] .acid-toolbar .acid-source button,
.model[data-acid-model] .acid-toolbar .acid-banks button { height: calc(22 * var(--u)); align-self: center; background: transparent; border-color: transparent; margin: 0 var(--u); padding: 0; }
.model[data-acid-model] .acid-toolbar .acid-source button[aria-pressed='true'],
.model[data-acid-model] .acid-toolbar .acid-banks button[aria-pressed='true'] { background: #414141; border-color: rgb(245 232 196 / 0.12); }
.model[data-acid-model] .acid-toolbar .acid-mode { width: calc(52 * var(--u)); }
.model[data-acid-model] .acid-toolbar .acid-freeze { width: calc(56 * var(--u)); }
.model[data-acid-model] .acid-toolbar .acid-options { width: calc(28 * var(--u)); margin-right: calc(10 * var(--u)); }
.model[data-acid-model] .acid-toolbar .acid-copy { width: calc(44 * var(--u)); margin-right: calc(8 * var(--u)); background: transparent; border-color: transparent; }
.model[data-acid-model] .acid-toolbar .acid-match { width: calc(84 * var(--u)); margin-right: calc(2 * var(--u)); }
.model[data-acid-model] .acid-toolbar .acid-listen { width: calc(56 * var(--u)); touch-action: none; }

/* Native MonitorMenuLookAndFeel geometry, including its live liquid backdrop. */
.model[data-acid-model] .acid-toolbar .acid-options { position: relative; height: calc(26 * var(--u)); flex: none; }
.model[data-acid-model] .acid-toolbar .acid-options-trigger { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; padding: 0; margin: 0; background: #2b2b2b; }
.model[data-acid-model] .acid-toolbar .acid-options-trigger svg { position: static; display: block; width: 100%; height: 100%; fill: currentColor; }
.model[data-acid-model] .acid-toolbar .acid-options-trigger:hover { background: #353535; }
.model[data-acid-model] .acid-toolbar .acid-options-trigger[aria-expanded='true'] { background: #414141; color: #f5e8c4; }
.model[data-acid-model] .acid-toolbar .acid-options-menu {
  position: absolute;
  left: 0;
  top: calc(31 * var(--u));
  z-index: 10;
  width: calc(220 * var(--u));
  padding: calc(6 * var(--u));
  box-sizing: border-box;
  overflow: hidden;
  border: max(.5px, calc(.8 * var(--u))) solid rgb(245 232 196 / .10);
  border-radius: calc(10 * var(--u));
  background: #202020;
  color: #f5e8c4;
  box-shadow: 0 calc(8 * var(--u)) calc(24 * var(--u)) rgb(0 0 0 / .4);
  transform: translateY(calc(-4 * var(--u))) scale(.985);
  transform-origin: 14px 0;
  opacity: 0;
  transition: opacity 120ms ease, transform 120ms ease;
  pointer-events: none;
}
.model[data-acid-model] .acid-toolbar .acid-options-menu[hidden] { display: none; }
.model[data-acid-model] .acid-toolbar .acid-menu-liquid { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .22; pointer-events: none; }
.model[data-acid-model] .acid-toolbar .acid-options-menu[data-open='true'] { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; animation: acid-site-menu-open 140ms ease-out; }
@keyframes acid-site-menu-open { from { opacity: 0; transform: translateY(calc(-4 * var(--u))) scale(.985); } to { opacity: 1; transform: translateY(0) scale(1); } }
.model[data-acid-model] .acid-toolbar .acid-options-heading { position: relative; height: calc(23 * var(--u)); box-sizing: border-box; display: flex; align-items: center; padding: calc(4 * var(--u)) calc(12 * var(--u)) 0 calc(20 * var(--u)); font-size: calc(9.5 * var(--u)); line-height: 1; font-weight: 500; text-transform: uppercase; color: rgb(245 232 196 / .9); }
.model[data-acid-model] .acid-toolbar .acid-options-item { position: relative; width: calc(100% - 6 * var(--u)); height: calc(24 * var(--u)); min-height: 0; display: flex; align-items: center; justify-content: flex-start; gap: 0; margin: var(--u) calc(3 * var(--u)); padding: 0 calc(10 * var(--u)) 0 calc(28 * var(--u)); border: 0; border-radius: calc(5.5 * var(--u)); background: transparent; text-align: left; font-size: calc(11.5 * var(--u)); line-height: 1; font-weight: 500; color: #f5e8c4; cursor: pointer; }
.model[data-acid-model] .acid-toolbar .acid-options-item span { position: static; display: block; }
.model[data-acid-model] .acid-toolbar .acid-options-item[aria-checked='true'] { background: rgb(119 119 119 / .36); }
.model[data-acid-model] .acid-toolbar .acid-options-item:hover,
.model[data-acid-model] .acid-toolbar .acid-options-item:focus-visible { background: rgb(146 146 146 / .18); outline: none; }
.model[data-acid-model] .acid-toolbar .acid-options-item svg { position: absolute; left: calc(4 * var(--u)); top: calc(5 * var(--u)); width: calc(14 * var(--u)); height: calc(14 * var(--u)); fill: none; stroke: currentColor; stroke-width: 1.45; stroke-linecap: round; stroke-linejoin: round; visibility: hidden; }
.model[data-acid-model] .acid-toolbar .acid-options-item[aria-checked='true'] svg { visibility: visible; }
.model[data-acid-model] .acid-toolbar .acid-options-separator { position: relative; height: calc(11 * var(--u)); }
.model[data-acid-model] .acid-toolbar .acid-options-separator::after { content: ''; position: absolute; left: calc(15 * var(--u)); right: calc(15 * var(--u)); top: 50%; height: max(.5px, var(--u)); background: rgb(245 232 196 / .10); }
.model[data-acid-model] .acid-toolbar .acid-toolbar-description { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@media (prefers-reduced-motion: reduce) { .model[data-acid-model] .acid-toolbar .acid-options-menu { transition: none; animation: none !important; } }
/* Lift the flat monitor controls clear of the preserved 3D face's hit plane. */
.model[data-acid-model] .acid-toolbar { transform: translateZ(calc(3 * var(--u))); transform-style: flat; }
.model[data-acid-model] .acid-meters { transform: translateZ(calc(3 * var(--u))); transform-style: flat; }
/* Keep the stage still when its first-use hint disappears during a press. */
.plugin-caption .plugin-hint[data-model-hint][hidden] { display: block !important; visibility: hidden; }
