/* Twelfth Night — the whole stylesheet.
 *
 * The voice is print: a serif face, hairlines, square corners, wide-tracked
 * small caps. There is one colour in the whole product — the dull gold of an
 * engraving — and one place where saturation is allowed at all, the wreath.
 * Everything else is ink on paper. The moment a bright colour arrives, the
 * book becomes a flyer.
 *
 * The STRUCTURE, though, is a shop's, and that distinction cost a rewrite.
 * The first version applied the print voice to the layout as well: one idea
 * per screenful, eighty pixels of air between blocks, a hairline rule between
 * each. On a phone that reads as restraint. On a laptop it reads as a slide
 * deck — and it is, because that is exactly how a deck is built.
 *
 * So: a header that never leaves, the product visible before the first
 * scroll, sections separated by ground colour rather than by air, and an
 * offer you can read in one block. The phone layout is the base and the
 * desktop is not an afterthought — it is a different arrangement of the same
 * markup, written in the media queries at the end.
 */

/* ── the face ──────────────────────────────────────────────────────────────
 * EB Garamond, self-hosted as a variable font: one 44 KB file covers every
 * weight from 400 to 600. Self-hosted rather than linked so the page does not
 * depend on a third party being reachable, and so nothing about who is
 * reading leaves this domain.
 *
 * swap, not block: on cell data the fallback stack is what people read for
 * the first moment, and Iowan Old Style — which ships on every iPhone — is
 * close enough in colour and width that the change is barely a flicker. */
@font-face {
  font-family: 'EB Garamond';
  src: url('/fonts/eb-garamond-latin.woff2') format('woff2-variations');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'EB Garamond';
  src: url('/fonts/eb-garamond-latin-italic.woff2') format('woff2-variations');
  font-weight: 400 600;
  font-style: italic;
  font-display: swap;
}

/* ── tokens ─────────────────────────────────────────────────────────────── */
:root {
  --paper:      #F7F4ED;
  --paper-sunk: #EFEADC;
  --paper-a0:   rgba(247, 244, 237, 0);   /* the paper at zero alpha. `transparent`
                                             is transparent BLACK and greys the
                                             middle of every gradient. */
  --rule:       #DDD6C4;
  --rule-soft:  #E8E2D3;

  --ink:        #1A1822;
  --ink-soft:   #4B4655;
  --muted:      #8A8271;

  --brass:      #A8874E;
  --brass-soft: #F0E9D6;
  --sel:        #9C5A61;                  /* dry rose: the colour of a choice made */
  --bad:        #A2453C;

  /* The message mock needs a surface that sits above the paper, and a bubble
     that sits above that. Two tokens rather than hard-coded greys, so the
     illustration follows the theme like everything else. */
  --card:       #FDFBF6;
  --bubble:     #EBE5D6;

  --serif: 'EB Garamond', 'Iowan Old Style', 'Palatino Linotype', Palatino,
           Georgia, 'Times New Roman', serif;
  --sans: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI',
          Roboto, 'Helvetica Neue', Arial, sans-serif;

  /* Corners. The print language wants square, and the interface wants
     softer — a perfectly sharp button reads as unfinished on a screen rather
     than as restraint. Three values, used everywhere, so nothing drifts:
     controls, panels, and the chips that are literally called pills. */
  --r:      10px;
  --r-lg:   14px;
  --r-pill: 999px;

  --pad: 22px;                            /* the side margin of the page */
  --col: 30rem;                           /* the measure for app screens. ~480px:
                                             a column of serif text you can read
                                             without your eye losing the line. */
  --wide: 68rem;                          /* the marketing page's container */
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
}

/* Night. The whole design is token-driven, so this is ten declarations and
   not one layout rule changes. It follows the phone rather than offering a
   switch: somebody reading in bed at 1 a.m. has already made this choice
   once, in Settings, and does not need to make it again here. */
@media (prefers-color-scheme: dark) {
  :root {
    --paper:      #131219;
    --paper-sunk: #1B1A23;
    --paper-a0:   rgba(19, 18, 25, 0);
    --rule:       #2C2936;
    --rule-soft:  #232130;

    --ink:        #EDE7D9;
    --ink-soft:   #C4BCAC;
    --muted:      #837B6C;

    --brass:      #C3A468;
    --brass-soft: #262232;
    --sel:        #C98A90;

    --card:       #1B1A23;
    --bubble:     #2B2835;
  }
}

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

html {
  /* Stops iOS inflating body text when the phone is turned sideways, which
     otherwise breaks every line length that was set on purpose. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* No grey flash box on tap; every tappable thing defines its own :active
     instead, which we control. */
  -webkit-tap-highlight-color: transparent;
  overflow-x: hidden;
}

/* Kills the 300 ms wait for a double-tap without disabling pinch zoom, which
   people with poor eyesight need and which `user-scalable=no` would take
   away. */
a, button, summary, [role='button'], input, textarea, select { touch-action: manipulation; }

img, svg { max-width: 100%; height: auto; display: block; }
a { color: inherit; }

::selection { background: var(--brass-soft); color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
}

/* ── routing ────────────────────────────────────────────────────────────── */
/* Set before first paint by the inline script in index.html, so a shared
   song link never shows a flash of the sales page. */
/* The marketing header and the landing page belong to '/' only. Inside the
   app every screen has its own back arrow and its own progress, and a second
   navigation bar over the top of that is noise. */
html[data-route='app'] #landing,
html[data-route='app'] .site-head { display: none !important; }
html[data-route='home'] #app { display: none; }

/* Anchor links in the header glide rather than jump. Turned off again for
   anyone who has asked their machine to stop animating — see the motion
   block near the end. */
html { scroll-behavior: smooth; }

/* ── layout primitives ──────────────────────────────────────────────────── */

/* One container, used by every section. Sections themselves run the full
   width of the window so their background colour can separate them; the
   content inside is what gets the measure. That is the difference between a
   page with structure and a page that separates everything with air. */
.wrap {
  width: 100%;
  max-width: var(--wide);
  margin: 0 auto;
  padding-inline: var(--pad);
}

.sec { padding-block: 56px; }
/* Ground colour, not a hairline, is what tells you a new section began. A rule
   between every block is deck grammar — it makes ten small slides instead of
   one page. */
.sec-tint { background: var(--paper-sunk); }

/* Anchored sections have to clear the fixed header when you jump to them. */
[id] { scroll-margin-top: 88px; }

.sec-head { margin-bottom: 38px; }
.sec-sub {
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.6;
  color: var(--muted);
  margin: 10px 0 0;
  max-width: 44ch;
}

hr.rule {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 0;
}

.eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 16px;
}

.h1 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(30px, 8.5vw, 38px);
  line-height: 1.16;
  letter-spacing: -0.01em;
  margin: 0 0 10px;
}
.h2 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(26px, 6.4vw, 34px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0;
}
.sub {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.6;
  color: var(--muted);
  margin: 0 0 28px;
}
.muted { color: var(--muted); }
.fine {
  font-size: 13px;
  line-height: 1.65;
  color: var(--muted);
  margin: 16px 0 0;
}
.fine b { color: var(--ink-soft); font-weight: 600; }
.center { text-align: center; }

/* The ordering flow, the song page and the prose pages are app screens, not
   marketing. They keep their own narrow measure. */
.view { max-width: var(--col); margin: 0 auto; padding-inline: var(--pad); }

/* ── the crest ──────────────────────────────────────────────────────────── */
/* A Midsummer wreath with a twelve-rayed star at its centre. The wreath is a
   fixed image because its colours are the same in both themes; the star is
   drawn in CSS because it is ink, and ink changes. */
.crest {
  position: relative;
  width: 168px;
  height: 168px;
  margin: 0 auto;
  flex: none;
}
.crest-lg { width: 208px; height: 208px; }
.crest .wreath { width: 100%; height: 100%; }

.star {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}
.star i {
  position: absolute;
  width: 1.5px;
  height: 19.1%;
  /* Faded at both ends, so a ray tapers to a point instead of stopping like
     a cut matchstick. */
  background: linear-gradient(to bottom,
              var(--paper-a0), var(--ink) 26%, var(--ink) 74%, var(--paper-a0));
  transform: rotate(var(--d));
}
/* 104 and 62 of the mini program's 260-unit stage, after its 0.8 scale. */
.star i.long { height: 32%; }

/* ── buttons ────────────────────────────────────────────────────────────── */
.btn {
  display: block;
  width: 100%;
  min-height: 54px;                       /* comfortably past the 44pt minimum */
  padding: 16px 20px;
  border: 0;
  border-radius: var(--r);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: opacity .14s ease, transform .14s ease;
}
.btn:active { opacity: .78; transform: scale(.985); }
.btn[disabled] { opacity: .34; pointer-events: none; }
.btn.off {
  background: transparent;
  color: var(--muted);
  box-shadow: inset 0 0 0 1px var(--rule);
}

/* On the cover, a solid black block is too heavy. An outline is enough. */
.btn-ghost {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
  border-radius: var(--r);
}
.btn + .btn { margin-top: 12px; }

/* The header's button. Small enough to belong in a 74px bar, still past the
   44px minimum every phone guideline asks for. */
.btn-sm {
  width: auto;
  min-height: 42px;
  padding: 11px 20px;
  font-size: 11.5px;
  letter-spacing: .16em;
}

.link-btn {
  display: block;
  width: 100%;
  margin-top: 18px;
  padding: 10px;
  border: 0;
  background: none;
  color: var(--muted);
  font-family: var(--sans);
  font-size: 14px;
  text-align: center;
  text-decoration: underline;
  text-underline-offset: 4px;
  cursor: pointer;
}
.link-btn:active { color: var(--ink); }

/* The same link, set inside a running sentence. A <button> cannot be
   display:inline — every browser computes it back to inline-block — so the
   thing that has to be undone is the full-width block, not the display. */
.link-btn.inline {
  display: inline-block;
  width: auto;
  font-size: inherit;
  vertical-align: baseline;
  /* Padding for the thumb, pulled back out of the line box by an equal
     negative margin — so the target is 24px tall while the sentence it sits
     in is still one line at its natural leading. */
  padding: 5px 3px;
  margin: -5px -3px;
}

/* ══════════════════════════ the landing page ═══════════════════════════════
 *
 * Everything from here to the flow is the shop front. It is built like a
 * commercial page and not like a set of slides: a header that never leaves,
 * the product visible before the first scroll, sections divided by ground
 * colour, and one offer block you can read without scrolling past it.
 */

/* ── the header ─────────────────────────────────────────────────────────── */
/* One pixel at the very top of the document. It is in view only while the
   page is scrolled to the top, which is the whole signal the header needs —
   cheaper and steadier than listening to every scroll event. */
#head-sentinel { height: 1px; }
/* The header is solid by default, which is what somebody with no JavaScript
   gets and is perfectly usable. The class below is REMOVED on scroll, not
   added — so a failure leaves a working header rather than an invisible one. */
.site-head {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--rule);
  padding-top: var(--safe-t);
  transition: background .3s ease, border-color .3s ease;
}
/* At the very top the title page already says the name, in 80px type. A bar
   repeating it six inches above is the sort of thing that makes a page feel
   assembled rather than designed — so over the hero the header carries only
   the navigation, and the mark arrives when the name scrolls away. */
.site-head.at-top {
  background: transparent;
  border-bottom-color: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.site-head .head-mark,
.site-head .head-cta { transition: opacity .3s ease, transform .3s ease; }

/* The button hides at the top too, at every width. The title page has one of
   its own, six inches below and four times the size — two of the same button
   on one screen is the thing that makes a page feel like it is selling at
   you. It comes back the moment the hero scrolls away, which is exactly when
   there is no other way to reach it. */
.site-head.at-top .head-cta {
  opacity: 0;
  transform: translateY(-3px);
  pointer-events: none;
}
.head-inner {
  display: flex;
  align-items: center;
  gap: 20px;
  height: 62px;
}
.head-mark {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--serif);
  font-size: 21px;
  letter-spacing: .01em;
  text-decoration: none;
  color: var(--ink);
  white-space: nowrap;
}
/* The wreath at 28px. Its five flowers are the only colour on the page above
   the fold, which is exactly the job of a mark. */
.head-crest {
  position: relative;
  display: block;
  width: 28px; height: 28px;
  flex: none;
}
.head-crest .wreath { width: 100%; height: 100%; }
.head-crest .star { position: absolute; inset: 0; display: grid; place-items: center; }
/* Hidden on a phone, where the footer carries the same links and a navbar of
   four items would crowd out the one button that matters. */
.head-nav { display: none; }
.head-nav a {
  font-size: 14.5px;
  color: var(--ink-soft);
  text-decoration: none;
  padding: 6px 0;
}
.head-nav a:hover { color: var(--ink); }
.head-cta { margin-left: auto; }

/* ── the hero ───────────────────────────────────────────────────────────── */
.hero { padding-block: 40px 56px; }
.hero-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.hero .crest-lg { width: 176px; height: 176px; }

.wordmark {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(42px, 12vw, 56px);
  line-height: 1.08;
  letter-spacing: .03em;
  margin: 30px 0 0;
}

/* An epigraph, not a slogan: italic, smaller than the title, with its source
   under it on a dash. The product gets the big type; Shakespeare does not. */
.epigraph {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(17px, 4.6vw, 19px);
  line-height: 1.5;
  color: var(--ink-soft);
  margin: 22px 0 0;
}
.attrib {
  display: block;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  font-style: normal;                     /* it is not part of the quotation */
  color: var(--muted);
  margin: 13px 0 0;
}

.lede {
  font-family: var(--serif);
  font-size: clamp(19px, 5.2vw, 22px);
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 42px 0 32px;
  max-width: 24ch;
  text-wrap: balance;
}

.hero-cta { width: 100%; max-width: 330px; }
/* No measure. The <br> in the markup already sets the two lines, and a
   max-width on top of that wrapped the second one again and left "right."
   stranded on a third. (text-wrap: balance does not help here — it balances
   across the forced break rather than around it.) */
.hero .fine { max-width: none; }

/* ── the delivery, drawn ────────────────────────────────────────────────────
 * NOT CURRENTLY ON THE PAGE. An illustration of the two messages that arrive
 * twelve hours later — the second of which plays when you tap it — kept here
 * ready for the demo section that goes in once there are real songs to show.
 * Drop the markup back in (a .msg block with two .bubble children) and it
 * works; nothing else references these rules.
 */
.hero-visual { margin-top: 44px; }
.msg {
  max-width: 352px;
  margin: 0 auto;
  background: var(--card);
  border: 1px solid var(--rule);
  padding: 22px 20px 20px;
}
.msg-when {
  margin: 0 0 18px;
  text-align: center;
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}
.bubble {
  max-width: 90%;
  margin: 0 0 8px;
  padding: 12px 16px;
  border-radius: 17px;
  background: var(--bubble);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14.5px;
  line-height: 1.5;
}
.msg-link { color: var(--brass); word-break: break-all; }
.bubble-audio {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px 15px;
  max-width: 96%;
}
.msg-play {
  position: relative;
  flex: none;
  width: 27px; height: 27px;
  border-radius: 50%;
  background: var(--ink);
}
.msg-play::after {
  content: '';
  position: absolute;
  left: 10px; top: 8px;
  border-left: 8px solid var(--bubble);
  border-top: 5.5px solid transparent;
  border-bottom: 5.5px solid transparent;
}
.msg-wave {
  flex: 1;
  min-width: 0;
  height: 26px;
  display: flex;
  align-items: center;
  gap: 2px;
}
.msg-wave i {
  flex: 1;
  min-width: 1px;
  height: var(--h);
  min-height: 2px;
  background: var(--ink-soft);
  opacity: .45;
}
.msg-dur {
  flex: none;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.msg-caption {
  margin: 18px 0 0;
  text-align: center;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}

/* ── how it works ───────────────────────────────────────────────────────── */
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 14px;
}
/* Stacked on a phone, each step wants its own rule above it. Side by side on
   a laptop they share ONE rule that runs the whole width — see the desktop
   block. Three short lines floating over three columns is the silhouette of
   every feature-grid template ever made; one line with the steps hanging off
   it is a single object. */
.steps li {
  padding: 26px 0 0;
  border-top: 1px solid var(--rule);
}
/* Roman numerals, in the serif, at size. An 11px sans label is a caption on
   a column; a numeral this size is the thing the column hangs from, and it is
   the same figure the play sets its acts in. */
.steps .num {
  display: block;
  font-family: var(--serif);
  font-size: 28px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: .08em;
  color: var(--brass);
  margin-bottom: 20px;
}
.steps h3 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 23px;
  line-height: 1.25;
  margin: 0 0 11px;
}
/* ink-soft, not muted. At this size the grey was reading as disabled text. */
/* Body copy on the shop front is set in the serif, not the system sans.
   The sans is right for buttons, labels and forms — it is an interface face —
   but a paragraph in it reads as an app describing itself. Reading matter
   goes in the book face. */
.steps p {
  margin: 0;
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.7;
  color: var(--ink-soft);
  max-width: 32ch;
}

/* ── the offer ──────────────────────────────────────────────────────────────
 * One block, bordered, that contains the whole transaction: what it costs,
 * what is in it, the button, and the two promises. A price floating on an
 * empty field is a title card; this is a thing you buy from.
 */
.offer {
  max-width: 30rem;
  margin: 0 auto;
  border-radius: var(--r-lg);
  /* Sunk rather than paper: this block sits on the page's own ground, so it
     has to be the card that is darker, not the ground. Reverse them and the
     one thing somebody is meant to read disappears into the background. */
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
  padding: 36px 28px 30px;
}
.offer-top { text-align: center; padding-bottom: 26px; border-bottom: 1px solid var(--rule); }
.offer-top .eyebrow { margin-bottom: 10px; }
.price {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(54px, 15vw, 66px);
  line-height: 1;
  letter-spacing: -0.025em;
  margin: 0;
}
.price-sub {
  font-family: var(--serif);
  font-size: 16px;
  color: var(--muted);
  margin: 10px 0 0;
}
.offer-list { list-style: none; margin: 24px 0 26px; padding: 0; }
.offer-list li {
  position: relative;
  padding: 9px 0 9px 28px;
  font-family: var(--serif);
  font-size: 16.5px;
  line-height: 1.55;
  color: var(--ink-soft);
}
/* A tick, drawn from two borders. No icon font, nothing to load. */
.offer-list li::before {
  content: '';
  position: absolute;
  left: 2px; top: 15px;
  width: 10px; height: 5px;
  border-left: 1.5px solid var(--brass);
  border-bottom: 1.5px solid var(--brass);
  transform: rotate(-45deg);
}
.offer-fine {
  margin-top: 24px;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
}
.offer-fine p { margin: 0 0 12px; font-size: 13.5px; line-height: 1.6; color: var(--muted); }
.offer-fine p:last-child { margin-bottom: 0; }
.offer-fine b { color: var(--ink); font-weight: 600; }

/* ── questions ──────────────────────────────────────────────────────────── */
.qa-list { max-width: 44rem; margin: 0 auto; border-top: 1px solid var(--rule); }
.qa { border-bottom: 1px solid var(--rule); }
.qa summary {
  list-style: none;
  cursor: pointer;
  padding: 18px 34px 18px 0;
  position: relative;
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.4;
}
.qa summary::-webkit-details-marker { display: none; }
/* A plus that becomes a minus. Two strokes sharing a centre — the horizontal
   one spans right 4px to 17px, so its middle is 10.5px in, which is where the
   vertical one has to sit. */
.qa summary::before,
.qa summary::after {
  content: '';
  position: absolute;
  top: 50%;
  background: var(--muted);
  transition: transform .18s ease, opacity .18s ease;
}
.qa summary::before { width: 13px; height: 1px; right: 4px; margin-top: -0.5px; }
.qa summary::after { width: 1px; height: 13px; right: 10px; margin-top: -6.5px; }
.qa[open] summary::after { transform: rotate(90deg); opacity: 0; }
.qa p {
  margin: 0;
  padding: 0 40px 20px 0;
  font-family: var(--serif);
  font-size: 16.5px;
  line-height: 1.72;
  color: var(--ink-soft);
}

/* ── samples ────────────────────────────────────────────────────────────── */
.sample {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 0;
  border-top: 1px solid var(--rule);
  width: 100%;
  background: none;
  border-left: 0; border-right: 0; border-bottom: 0;
  text-align: left;
  cursor: pointer;
  color: inherit;
}
.sample:last-child { border-bottom: 1px solid var(--rule); }
.sample img, .sample .noart {
  width: 58px; height: 58px; flex: none;
  border-radius: 8px;
  object-fit: cover;
  background: var(--paper-sunk);
}
.sample-name { font-family: var(--serif); font-size: 18px; line-height: 1.3; }
.sample-meta { font-size: 13px; color: var(--muted); }
.sample .tri {
  margin-left: auto;
  width: 0; height: 0; flex: none;
  border-left: 11px solid var(--ink);
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
}
.sample.playing .tri {
  border: 0;
  width: 10px; height: 13px;
  background: linear-gradient(to right,
    var(--ink) 0 3px, transparent 3px 7px, var(--ink) 7px 10px);
}

/* ── footer ─────────────────────────────────────────────────────────────── */
.foot { background: var(--paper); padding-block: 48px 0; }
.foot-grid { display: grid; gap: 30px; }
.foot-mark {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .26em;
  color: var(--ink);
  margin: 0 0 12px;
}
.foot-brand p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--muted); max-width: 34ch; }
.foot-col { display: flex; flex-direction: column; gap: 9px; }
.foot-col h4 {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 4px;
}
.foot-col a { font-size: 14.5px; color: var(--ink-soft); text-decoration: none; }
.foot-col a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.foot-legal {
  margin-top: 40px;
  padding-block: 20px calc(24px + var(--safe-b));
  border-top: 1px solid var(--rule);
}
.foot-legal p { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--muted); }

/* ── the flow ───────────────────────────────────────────────────────────── */
.view {
  padding-top: calc(var(--safe-t) + 18px);
  /* Room for the fixed footer button plus the home indicator. */
  padding-bottom: calc(150px + var(--safe-b));
  min-height: 100dvh;
}
.view.no-foot { padding-bottom: calc(48px + var(--safe-b)); }

/* Back arrow: two hairlines making a chevron, the same rule used everywhere
   else. No icon font, nothing to load. */
.back {
  display: block;
  width: 44px; height: 44px;
  margin: 0 0 14px -12px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  position: relative;
}
.back::before {
  content: '';
  position: absolute;
  left: 17px; top: 15px;
  width: 11px; height: 11px;
  border-left: 1.25px solid var(--ink);
  border-bottom: 1.25px solid var(--ink);
  transform: rotate(45deg);
}
.back:active { opacity: .5; }

/* Progress: a rule that fills. It says how far along you are without a
   number, and it is the same hairline as every other rule on the site. */
.progress {
  height: 1px;
  background: var(--rule);
  margin-bottom: 26px;
  overflow: hidden;
}
.progress i {
  display: block;
  height: 100%;
  background: var(--ink);
  transform-origin: left;
  transition: transform .4s cubic-bezier(.22,.61,.36,1);
}

/* The fixed action at the bottom of each step. Fixed rather than in flow so
   the primary action is always under the thumb — on a phone, a button below
   the fold is a button that does not exist. */
.foot-action {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  padding: 14px var(--pad) calc(14px + var(--safe-b));
  background: linear-gradient(to bottom, var(--paper-a0), var(--paper) 34%);
}
.foot-action > * { max-width: calc(var(--col) - var(--pad) * 2); margin-inline: auto; }

/* ── form controls ──────────────────────────────────────────────────────── */
/* 17px, never smaller. At 16px or below iOS zooms the page when a field takes
   focus and never zooms back — the single most common way a form feels
   broken on an iPhone. */
.field, .area {
  display: block;
  width: 100%;
  padding: 15px 16px;
  border: 0;
  border-radius: var(--r);
  background: var(--paper-sunk);
  box-shadow: inset 0 0 0 1px var(--rule);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.5;
  -webkit-appearance: none;
  appearance: none;
}
.field::placeholder, .area::placeholder { color: var(--muted); opacity: 1; }
.field:focus, .area:focus {
  outline: none;
  box-shadow: inset 0 0 0 1px var(--ink);
}
.area { min-height: 210px; resize: none; line-height: 1.66; }
.label {
  display: block;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 32px 0 12px;
}
.label .opt { font-weight: 400; letter-spacing: 0.04em; text-transform: none; }
.count { font-size: 12.5px; color: var(--muted); text-align: right; margin-top: 8px; }

/* Choices. Outlined, square, and the chosen one goes solid — no pill shapes,
   no fill colour except the one. */
.pills { display: flex; flex-wrap: wrap; gap: 8px; }
.pill {
  padding: 10px 17px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--rule);
  color: var(--ink-soft);
  font-family: var(--serif);
  font-size: 16px;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.pill.on {
  background: var(--sel);
  box-shadow: inset 0 0 0 1px var(--sel);
  color: #fff;
}
.pill:active { opacity: .7; }

/* ── searching for a song ───────────────────────────────────────────────────
 * Built to match the search in erised-web, because it is the one that has
 * been used and because two of our own products should not disagree about
 * what a song row looks like.
 *
 * The part that matters is the BOUNDED panel. An unbounded list of eight
 * results pushes the page down half a screen every time somebody types, and
 * the thing they are typing into jumps away from them. A panel with a fixed
 * height that scrolls inside itself keeps the field still.
 */
.search { position: relative; }
.search .spin {
  position: absolute;
  right: 15px; top: 50%;
  width: 17px; height: 17px;
  margin-top: -8.5px;
  border: 2px solid var(--rule);
  border-top-color: var(--ink-soft);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.results {
  margin-top: 12px;
  max-height: 19rem;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--paper-sunk);
}

.row {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  padding: 10px 13px;
  border: 0;
  border-bottom: 1px solid var(--rule-soft);
  background: none;
  text-align: left;
  color: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.row:last-child { border-bottom: 0; }
.row:active { background: var(--brass-soft); }
.row .art, .picked .art {
  width: 46px; height: 46px; flex: none;
  border-radius: 7px;
  object-fit: cover;
  background: var(--rule-soft);
}
.row .rt, .picked .rt { min-width: 0; flex: 1; }
.row .rn, .picked .rn {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row .ra, .picked .ra {
  font-size: 13px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The one that was chosen. It replaces the search box rather than sitting
   under it, so there is never a question of which of the two is in force. */
.picked {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 12px 13px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--paper-sunk);
}
/* A cross drawn from two rules, like every other mark on this site. */
.picked .x {
  position: relative;
  flex: none;
  width: 36px; height: 36px;
  margin-right: -6px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--muted);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.picked .x::before, .picked .x::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: 14px; height: 1.5px;
  margin: -0.75px 0 0 -7px;
  background: currentColor;
}
.picked .x::before { transform: rotate(45deg); }
.picked .x::after { transform: rotate(-45deg); }
.picked .x:active { color: var(--ink); }

/* ── the two voices ─────────────────────────────────────────────────────────
 *
 * A note low on a stave and a note high on one — carried over from the mini
 * program unchanged, down to the line positions and the timings.
 *
 * Deliberately NOT a pair of gender symbols. Those are signage, and they turn
 * a question about a voice into a question about identity. This draws the
 * thing actually being asked: where the voice sits. Both notes begin on the
 * middle line and separate as the page settles, which explains the question
 * without a sentence.
 */
.voices {
  display: flex;
  margin: 46px 0 8px;
  opacity: 0;
  transform: translateY(9px);
  transition: opacity .7s ease, transform .7s cubic-bezier(.22, .61, .36, 1);
}
.voices.in { opacity: 1; transform: none; }

.voice {
  flex: 1;
  min-width: 0;
  padding: 16px 0 22px;
  border: 0;
  background: none;
  cursor: pointer;
  color: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  -webkit-appearance: none;
  appearance: none;
}
/* Two panels side by side is hopscotch. One hairline between them is enough,
   and it is the same rule used everywhere else. */
.voice + .voice { box-shadow: inset 1px 0 0 0 var(--rule); }

.stave { position: relative; width: 110px; height: 78px; }
/* `.staffline`, not `.ln` — `.ln` is the lyric line on the song page, and its
   9px of padding turned each 1px staff line into an 18px slab, so the stave
   rendered as a solid block. Second time a short class name has collided in
   this file (see `.tone`); short names are cheap to type and expensive to
   share. */
.stave .staffline {
  position: absolute;
  left: 0; right: 0;
  height: 1px;
  background: var(--rule);
  transition: background .5s ease;
}

/* The head is tilted and the stem is not — which is how notes are actually
   written, and why they are two layers. `.tone` owns the position, because it
   is the thing that travels; rotate a combined element and the stem leans
   with it. */
.tone {
  position: absolute;
  left: 50%;
  margin-left: -10px;
  width: 20px; height: 14px;
  top: 38px;                              /* both start on the middle line */
  transition: top .82s cubic-bezier(.22, .61, .36, 1);
}
/* A beat apart. Moving together is a switch; moving one after the other looks
   like somebody writing them. */
.voice + .voice .tone { transition-delay: .12s; }
.voices.in .tone.low { top: 54px; }
.voices.in .tone.high { top: 9px; }

.tone .head {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--ink-soft);
  transform: rotate(-18deg);
  transition: background .5s ease, transform .45s cubic-bezier(.22, .61, .36, 1),
              opacity .5s ease;
}
.tone .stem {
  position: absolute;
  width: 1.5px; height: 34px;
  background: var(--ink-soft);
  transition: background .5s ease, opacity .5s ease;
}
/* Stem up on the right below the middle line, down on the left above it. */
.tone.low .stem { right: 0; bottom: 6px; }
.tone.high .stem { left: 0; top: 6px; }

/* The chosen side turns brass, staff lines and all. The other retreats to
   grey — it is not removed and it is not scolded. */
.voice.on .staffline { background: var(--brass); }
.voice.on .head, .voice.on .stem { background: var(--brass); }
.voice.on .head { transform: rotate(-18deg) scale(1.08); }
.voice.off .head, .voice.off .stem { background: var(--muted); opacity: .42; }

.voice .vn {
  margin-top: 29px;
  font-family: var(--serif);
  font-size: 21px;
  letter-spacing: .16em;
  text-indent: .16em;
  color: var(--ink-soft);
  transition: color .4s ease;
}
.voice.on .vn { color: var(--ink); }
.voice.off .vn { color: var(--muted); }

/* Sweeps out from the left. One hairline, the same one as everywhere else. */
.voice .ul {
  margin-top: 10px;
  width: 65px; height: 1px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .42s cubic-bezier(.22, .61, .36, 1);
}
.voice.on .ul { transform: scaleX(1); }

/* ── recording ──────────────────────────────────────────────────────────── */
.mic-wrap { text-align: center; margin: 40px 0 28px; }
.mic {
  width: 104px; height: 104px;
  margin: 0 auto;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--ink);
  display: grid;
  place-items: center;
  cursor: pointer;
  position: relative;
}
.mic .dot {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--bad);
  transition: border-radius .22s ease, width .22s ease, height .22s ease;
}
.mic.on .dot { width: 24px; height: 24px; border-radius: 3px; }
/* One slow ring going out. A pulse that keeps up with the voice would be a
   toy; this is a metronome telling you it is listening. */
.mic.on::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--bad);
  animation: ring 1.9s ease-out infinite;
}
@keyframes ring {
  from { transform: scale(1); opacity: .7; }
  to   { transform: scale(1.34); opacity: 0; }
}
.timer {
  font-family: var(--serif);
  font-size: 34px;
  font-variant-numeric: tabular-nums;
  margin-top: 20px;
}
.mic-hint { font-size: 14px; color: var(--muted); margin-top: 16px; min-height: 22px; }

/* The level, while they sing — with the range it has to land in marked on it.
 *
 * It used to fill up with elapsed seconds, which measured the one thing that
 * was never in doubt. The order that came back inaudible had a full bar the
 * whole way through. Two hairline ticks now mark the band a voice must sit
 * in, the fill turns brass inside it and rose above it, and the whole
 * instruction is "get it between the ticks" — no words, nobody told off. */
.meter {
  position: relative;
  height: 2px;
  background: var(--rule-soft);
  margin: 26px auto 0;
  max-width: 220px;
}
/* -24 dBFS to -9 dBFS, on a scale running from -60 to 0. */
.meter .band { position: absolute; inset: 0 15% 0 60%; background: var(--rule); }
.meter .band::before, .meter .band::after {
  content: '';
  position: absolute;
  top: -5px; height: 12px; width: 1px;
  background: var(--rule);
}
.meter .band::before { left: 0; }
.meter .band::after { right: 0; }
.meter i {
  position: absolute;
  inset: 0;
  background: var(--muted);
  transform-origin: left;
  /* Fast enough to feel like a meter, slow enough not to strobe. */
  transition: transform .07s linear, background .2s ease;
}
.meter.in-band i { background: var(--brass); }
.meter.hot i { background: var(--bad); }

/* Long enough is now said by the clock, since the bar is saying something
   else. It stops being a target the moment it is met. */
.timer { transition: color .3s ease; }
.timer.enough { color: var(--brass); }

/* ── the song page ──────────────────────────────────────────────────────── */
.stage { text-align: center; margin: 24px 0 8px; }
.clock {
  position: relative;
  width: 232px; height: 232px;
  margin: 0 auto;
  cursor: pointer;
  /* The drag-to-scrub gesture owns vertical movement inside this ring, so
     the browser must not steal it for scrolling. */
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}
/* The hand is the clock. Due north, clockwise, one full turn per song.
 *
 * It is the north ray, carried on past the others — not a separate object
 * laid over them. So it starts at the centre and it is set in the same ink
 * and the same 1.5px as every ray, and the only thing that distinguishes it
 * is that it moves.
 *
 * **It must not outrun the face.** The first version hung a floating tick
 * out between 29% and 46% of the radius, which put its tip past the wreath
 * and made it read as a stray line crossing the artwork rather than a hand
 * on a dial. The numbers below are the mini program's, as fractions of the
 * stage: the long rays reach 32%, the needle 23.8% from the centre — a
 * little further than the rays, and comfortably inside the wreath. */
.hand {
  position: absolute;
  inset: 0;
  transition: transform .96s linear;
}
/* No interpolation while a finger is on it: half a beat behind the thumb is
   not following the thumb. */
.hand.nolerp { transition: none; }
.hand .needle {
  position: absolute;
  left: 50%;
  bottom: 50%;                            /* the base sits on the centre */
  width: 1.5px;
  height: 23.8%;                          /* 62 of the mini program's 260 */
  margin-left: -0.75px;
  /* Solid at the root, fading at the tip — the same stroke as the rays. */
  background: linear-gradient(to bottom, var(--paper-a0), var(--ink) 22%, var(--ink));
}
.cue {
  display: inline-block;
  margin-top: 22px;
  padding: 10px 18px;
  border: 0;
  background: none;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  cursor: pointer;
}
.cue:active { opacity: .55; }

.lyrics {
  font-family: var(--serif);
  font-size: 18px;
  line-height: 2.05;
  white-space: pre-line;
  color: var(--ink-soft);
  margin: 34px 0 0;
  text-align: center;
}
.lyric-panel {
  height: 46vh;
  max-height: 420px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  margin: 30px 0 0;
  /* Fade top and bottom so lines arrive and leave rather than being cut. */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
  scroll-behavior: smooth;
  text-align: center;
  /* No scrollbar. The top and bottom are already faded out by the mask, and
     a grey bar down the side of a lyric sheet undoes that in one stroke.
     Scrolling still works; only the furniture is gone. */
  scrollbar-width: none;
}
.lyric-panel::-webkit-scrollbar { display: none; }
.song-actions { margin-top: 34px; }
/* The prose pages and the song page both have a full-width tail under their
   grid; keep it out of the gutter on a phone. */
.song-extra { margin-top: 0; }
.lyric-panel .pad { height: 40%; }
.ln {
  font-family: var(--serif);
  font-size: 19px;
  line-height: 1.5;
  padding: 9px 4px;
  color: var(--muted);
  /* Legible at rest, not merely present. Before anything plays every line is
     in this state, and the page should look like a lyric sheet then, not
     like a lyric sheet with the lights off. */
  opacity: .62;
  cursor: pointer;
  transition: opacity .3s ease, color .3s ease;
}
.ln.past { opacity: .3; }
.ln.on { opacity: 1; color: var(--ink); }

/* Cover candidates. Square, tight grid, the chosen one ruled in ink. */
.covers { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 8px; }
.covers button {
  padding: 0; border: 0; background: none; cursor: pointer;
  position: relative; aspect-ratio: 1;
}
.covers img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--r); }
.covers button::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: var(--r);
  box-shadow: inset 0 0 0 2px var(--ink);
  opacity: 0;
  transition: opacity .16s ease;
}
.covers button.on::after { opacity: 1; }

/* ── the waiting page ───────────────────────────────────────────────────── */
.wait { text-align: center; }
.countdown {
  font-family: var(--serif);
  font-size: clamp(42px, 13vw, 54px);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  margin: 8px 0 10px;
  letter-spacing: -0.01em;
}
.wait-when { font-size: 14px; color: var(--muted); margin: 0 0 30px; }
/* Feste, juggling — the mini program's routine, number for number.
 *
 * Three of the four images share one 620x620 canvas — body, left arm, right
 * arm — so they stack at the same size and position with nothing to compute,
 * and each arm can turn about its own shoulder. The HAT is not one of them:
 * it is a small 110x68 drawing of a hat and nothing else, so it needs its own
 * size and its own starting point. Stretching it to fill the canvas like the
 * others produces a bowler the size of the man.
 *
 * **There are THREE hats in the air, on one set of keyframes.** That is the
 * trick, and an earlier version here had one hat travelling the whole circuit
 * alone, which reads as a hat blowing around rather than a man juggling. The
 * three are offset by negative delays of a third of a cycle each — a negative
 * delay means "this animation has already been running that long", so all
 * three are in their own positions on the first frame instead of starting
 * stacked and fanning out.
 *
 * Every keyframe below is generated from the mini program's own hatCycle,
 * rpx for rpx, scaled by --fs. Its offsets are measured against a 440-unit
 * layer, so k/440 x --fs reproduces the routine at any size. They are not
 * re-eyeballed: the shape of the arc is where the weight of the thing lives,
 * and the spacing of those keyframes is uneven on purpose — even time, uneven
 * distance, so the hat hangs at the top and drops fast into the hand. An
 * easing function cannot do that, because easing is symmetric and gravity
 * is not.
 */
.feste {
  --fs: 210px;
  width: var(--fs); height: var(--fs);
  margin: 0 auto 26px;
  position: relative;
}
.feste .body, .feste .armL, .feste .armR {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain;
}
/* The shoulders, as a fraction of the shared canvas: left (272,244), right
   (324,244) of 620. An arm turning about anything else swings from its elbow.

   One second, not three: the arms run at a THIRD of the hat's cycle, because
   the three hats are a third of a cycle apart. So one hat passes through his
   hands every second and the reach meets it. At three seconds the arms moved
   once per hat-circuit and caught nothing. */
.feste .armL { transform-origin: 43.9% 39.4%; animation: armL 1s ease-in-out infinite; }
.feste .armR { transform-origin: 52.3% 39.4%; animation: armR 1s ease-in-out infinite; }
.feste .body { animation: knees 1s ease-in-out infinite; }

/* The hat starts ON THE LEFT HAND, because every offset in the cycle below is
   measured from there. Centring it in the frame instead — the obvious thing —
   shifts the entire routine right by the width of one arm, and the hat then
   reaches neither hand nor head.

   Vertically it is anchored to the BRIM, not the top edge of the drawing: the
   brim sits 78% down the image, so the top is the hand's height less that. */
.feste .hat {
  position: absolute;
  left: 50%;
  width: 15.45%;                      /* 68 of the 440-unit layer */
  height: 9.55%;                      /* 42 of it */
  margin-left: -25.45%;               /* half the hat, plus the reach to the hand */
  top: 26.36%;
  animation-name: hatCycle;
  animation-duration: 3s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
/* A third of a cycle apart. */
.feste .hB { animation-delay: -1s; }
.feste .hC { animation-delay: -2s; }

@keyframes hatCycle {
  0% { transform: translate(0, 0) rotate(-11deg); }
  2% { transform: translate(0, 0) rotate(-11deg); }
  4% { transform: translate(0, 0) rotate(-11deg); }
  6% { transform: translate(0, 0) rotate(-11deg); }
  8% { transform: translate(calc(var(--fs) * 0.01477), calc(var(--fs) * -0.05159)) rotate(19deg); }
  10% { transform: translate(calc(var(--fs) * 0.02955), calc(var(--fs) * -0.09545)) rotate(50deg); }
  12% { transform: translate(calc(var(--fs) * 0.04432), calc(var(--fs) * -0.13159)) rotate(80deg); }
  14% { transform: translate(calc(var(--fs) * 0.05909), calc(var(--fs) * -0.15977)) rotate(111deg); }
  16% { transform: translate(calc(var(--fs) * 0.07386), calc(var(--fs) * -0.18000)) rotate(141deg); }
  18% { transform: translate(calc(var(--fs) * 0.08864), calc(var(--fs) * -0.19250)) rotate(172deg); }
  20% { transform: translate(calc(var(--fs) * 0.10341), calc(var(--fs) * -0.19727)) rotate(202deg); }
  22% { transform: translate(calc(var(--fs) * 0.11818), calc(var(--fs) * -0.19409)) rotate(232deg); }
  24% { transform: translate(calc(var(--fs) * 0.13295), calc(var(--fs) * -0.18318)) rotate(263deg); }
  26% { transform: translate(calc(var(--fs) * 0.14795), calc(var(--fs) * -0.16432)) rotate(293deg); }
  28% { transform: translate(calc(var(--fs) * 0.16273), calc(var(--fs) * -0.13773)) rotate(324deg); }
  30% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  32% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  34% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  36% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  38% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  40% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  42% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  44% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  46% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  48% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  50% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  52% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  54% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  56% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  58% { transform: translate(calc(var(--fs) * 0.17750), calc(var(--fs) * -0.10318)) rotate(354deg); }
  60% { transform: translate(calc(var(--fs) * 0.22023), calc(var(--fs) * -0.11205)) rotate(358deg); }
  62% { transform: translate(calc(var(--fs) * 0.26295), calc(var(--fs) * -0.09136)) rotate(361deg); }
  64% { transform: translate(calc(var(--fs) * 0.30568), calc(var(--fs) * -0.04114)) rotate(364deg); }
  66% { transform: translate(calc(var(--fs) * 0.34841), calc(var(--fs) * 0.03864)) rotate(368deg); }
  68% { transform: translate(calc(var(--fs) * 0.32341), calc(var(--fs) * -0.02682)) rotate(392deg); }
  70% { transform: translate(calc(var(--fs) * 0.29864), calc(var(--fs) * -0.08250)) rotate(417deg); }
  72% { transform: translate(calc(var(--fs) * 0.27364), calc(var(--fs) * -0.12886)) rotate(441deg); }
  74% { transform: translate(calc(var(--fs) * 0.24886), calc(var(--fs) * -0.16523)) rotate(465deg); }
  76% { transform: translate(calc(var(--fs) * 0.22386), calc(var(--fs) * -0.19227)) rotate(490deg); }
  78% { transform: translate(calc(var(--fs) * 0.19909), calc(var(--fs) * -0.20932)) rotate(514deg); }
  80% { transform: translate(calc(var(--fs) * 0.17409), calc(var(--fs) * -0.21705)) rotate(538deg); }
  82% { transform: translate(calc(var(--fs) * 0.14932), calc(var(--fs) * -0.21500)) rotate(563deg); }
  84% { transform: translate(calc(var(--fs) * 0.12432), calc(var(--fs) * -0.20318)) rotate(587deg); }
  86% { transform: translate(calc(var(--fs) * 0.09955), calc(var(--fs) * -0.18182)) rotate(612deg); }
  88% { transform: translate(calc(var(--fs) * 0.07455), calc(var(--fs) * -0.15091)) rotate(636deg); }
  90% { transform: translate(calc(var(--fs) * 0.04977), calc(var(--fs) * -0.11023)) rotate(660deg); }
  92% { transform: translate(calc(var(--fs) * 0.02477), calc(var(--fs) * -0.06000)) rotate(685deg); }
  94% { transform: translate(0, 0) rotate(709deg); }
  96% { transform: translate(0, 0) rotate(709deg); }
  98% { transform: translate(0, 0) rotate(709deg); }
  100% { transform: translate(0, 0) rotate(709deg); }
}
@keyframes armL {
  0%   { transform: rotate(-3deg); }
  20%  { transform: rotate(7deg); }
  50%  { transform: rotate(-16deg); }
  74%  { transform: rotate(-8deg); }
  100% { transform: rotate(-3deg); }
}
@keyframes armR {
  0%   { transform: rotate(3deg); }
  24%  { transform: rotate(16deg); }
  54%  { transform: rotate(-6deg); }
  78%  { transform: rotate(2deg); }
  100% { transform: rotate(3deg); }
}
@keyframes knees {
  0%, 100% { transform: translateY(0); }
  30%      { transform: translateY(calc(var(--fs) * -0.01136)); }
  62%      { transform: translateY(calc(var(--fs) * -0.00455)); }
}

.status-line {
  font-family: var(--serif);
  font-size: 18px;
  color: var(--ink-soft);
  margin: 4px 0 0;
}

/* ── your songs ─────────────────────────────────────────────────────────── */
.track {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 13px 0;
  border: 0;
  border-bottom: 1px solid var(--rule-soft);
  background: none;
  text-align: left;
  color: inherit;
  cursor: pointer;
}
.track:active { background: var(--paper-sunk); }
.track .art, .track .no {
  width: 56px; height: 56px; flex: none;
  border-radius: 8px;
  object-fit: cover;
  background: var(--paper-sunk);
}
.track .no {
  display: grid; place-items: center;
  font-family: var(--serif); font-size: 17px; color: var(--muted);
}
.track .tn { font-family: var(--serif); font-size: 18px; line-height: 1.3; }
.track .tn.dim { color: var(--muted); }
.track .tm { font-size: 13px; color: var(--muted); margin-top: 1px; }
.track .mark { margin-left: auto; flex: none; }
.track .tri {
  width: 0; height: 0;
  border-left: 10px solid var(--ink);
  border-top: 6.5px solid transparent;
  border-bottom: 6.5px solid transparent;
}
.tag {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 4px 8px;
  box-shadow: inset 0 0 0 1px var(--rule);
}
.tag.making { color: var(--brass); box-shadow: inset 0 0 0 1px var(--brass); }

/* ── the review page ────────────────────────────────────────────────────────
 *
 * The last screen before somebody pays, so every answer on it is a thing they
 * might want to change — which means every answer is a button, not a line of
 * text with an edit link hiding at the end of it. The chevron is the only
 * decoration; the row itself is the target, which is what makes it work with
 * a thumb.
 */

/* What they wrote, first and largest. It is the thing they most want to check
   before paying, and a summary that buries it three rows down is a summary of
   something else. The brass rule down the left is the one used for a pulled
   quote throughout. */
/* ── the order, before it is paid for ──────────────────────────────────────
 *
 * Set as a ledger, not as a form. One column of hairlines runs from the thing
 * they wrote down to the thing it costs, with nothing boxed, nothing filled
 * and no accent colour anywhere in it.
 *
 * The first version put the story in a sunken panel with a brass rule down
 * its left edge. That rule is the tell: a coloured stripe beside a block of
 * text is the house style of every alert box on the web, and it makes a
 * page about somebody's private writing look like a validation warning. What
 * replaces it is space and size — the story is simply the largest thing on
 * the page after the title, which is also the truth about its importance.
 *
 * Every row is a button. There is no small "edit" link at the end of a line,
 * because a link at the end of a line is a target the width of a word and
 * this page is read with a thumb. */
.sum-story {
  display: block;
  width: 100%;
  margin: 28px 0 0;
  padding: 0 32px 28px 0;
  border: 0;
  background: none;
  text-align: left;
  color: inherit;
  cursor: pointer;
  position: relative;
  -webkit-appearance: none;
  appearance: none;
}
.sum-story .eyebrow { margin-bottom: 13px; }
.sum-text {
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.54;
  letter-spacing: -0.004em;
  color: var(--ink);
  /* Long stories are clamped rather than scrolled: this is a summary, and
     tapping it opens the whole thing in the editor anyway. */
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-wrap: pretty;
}

.summary { border-top: 1px solid var(--rule); }
.sum-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  width: 100%;
  padding: 16px 32px 16px 0;
  border: 0;
  border-bottom: 1px solid var(--rule-soft);
  background: none;
  text-align: left;
  color: inherit;
  cursor: pointer;
  position: relative;
  -webkit-appearance: none;
  appearance: none;
}
.sum-row:last-child { border-bottom: 0; }

/* The labels are the same small caps as every other label in the product.
   Sans, tracked wide, quiet — so the serif beside them is the only thing
   with a voice. */
.sum-row .k, .sum-total .k {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  flex: none;
}
.sum-row .v {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.35;
  text-align: right;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Pressing one. The row does not flash a colour — it dims, the way ink does
   under a thumb, and the chevron steps toward the edge it is pointing at. */
.sum-row:active .v, .sum-story:active .sum-text { opacity: 0.5; }
.sum-row:active::after, .sum-story:active::after {
  border-color: var(--ink);
  transform: translateX(2px) rotate(45deg);
}

/* The chevron. Two hairlines, the same mark as the back arrow, pointing the
   other way. */
.sum-row::after, .sum-story::after {
  content: '';
  position: absolute;
  right: 6px;
  width: 7px; height: 7px;
  border-top: 1.25px solid var(--rule);
  border-right: 1.25px solid var(--rule);
  transform: rotate(45deg);
  transition: transform .14s ease, border-color .14s ease;
}
.sum-row::after { top: 50%; margin-top: -3.5px; }
.sum-story::after { top: 3px; }
@media (hover: hover) {
  .sum-row:hover::after, .sum-story:hover::after { border-color: var(--muted); }
}

/* The reference track, with its sleeve. People recognise a cover long before
   they finish reading a title. */
.ref { display: inline-flex; align-items: center; gap: 10px; justify-content: flex-end; }
.ref-art {
  width: 36px; height: 36px;
  flex: none;
  border-radius: 3px;
  object-fit: cover;
  background: var(--rule-soft);
  /* A hairline instead of a shadow: a sleeve is a printed square, and the
     inset keeps a pale cover from bleeding into pale paper. */
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.1);
}
.ref-name { min-width: 0; overflow-wrap: anywhere; }

/* On a narrow screen the label and the value stop competing for one line.
   Squeezed side by side, a long track name wraps to four lines in a column
   two words wide — the value gets the full width instead. */
@media (max-width: 540px) {
  .sum-text { font-size: 19px; }
  .sum-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    padding: 13px 28px 13px 0;
  }
  .sum-row .v { text-align: left; }
  .ref { justify-content: flex-start; }
}

/* The total is not editable, so it is not a button — and it carries the
   weight of the page. */
.sum-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  padding: 26px 0 28px;
  border-top: 1px solid var(--rule);
  margin-top: 4px;
  margin-bottom: 30px;
}
.sum-total .v {
  font-family: var(--serif);
  font-size: 34px;
  line-height: 1;
  letter-spacing: -0.015em;
}

/* ── the take, played back ─────────────────────────────────────────────────
 *
 * What fifteen seconds of your own voice looks like when you come back to
 * check it. A ring, a triangle, a hairline that fills — the same three marks
 * the song page uses, at a quarter of the size, because this is a thing you
 * confirm rather than a thing you sit with. */
.take {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 18px 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  margin: 26px 0 22px;
}
.take-play {
  width: 54px; height: 54px;
  flex: none;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--ink);
  display: grid;
  place-items: center;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
/* The triangle is nudged right by two pixels. Centred by its bounding box it
   reads as leaning left, because the mass of a triangle is not where its box
   says it is. */
.take-play .tri {
  width: 0; height: 0;
  margin-left: 3px;
  border-left: 13px solid var(--ink);
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
}
.take-play.on .tri {
  width: 13px; height: 15px;
  margin-left: 0;
  border: 0;
  background: var(--ink);
  /* Two bars from one element: a gap cut out of the middle. */
  -webkit-mask: linear-gradient(#000 0 0) 0 0 / 4px 100% no-repeat,
                linear-gradient(#000 0 0) 100% 0 / 4px 100% no-repeat;
          mask: linear-gradient(#000 0 0) 0 0 / 4px 100% no-repeat,
                linear-gradient(#000 0 0) 100% 0 / 4px 100% no-repeat;
}
.take-body { flex: 1; min-width: 0; }
.take-k {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 9px;
}
.take-bar { height: 2px; background: var(--rule); overflow: hidden; }
.take-bar i {
  display: block; height: 100%;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
}
.take-time {
  font-family: var(--serif);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  color: var(--muted);
  margin: 9px 0 0;
}

/* The same rows, read-only — the confirmation page states facts rather than
   offering choices, so nothing there is a button. */
.facts {
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  margin: 26px 0;
}
.facts div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  padding: 14px 0;
  border-bottom: 1px solid var(--rule-soft);
}
.facts div:last-child { border-bottom: 0; }
.facts .k {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  flex: none;
}
.facts .v {
  font-family: var(--serif);
  font-size: 17px;
  text-align: right;
  min-width: 0;
  overflow-wrap: anywhere;
}

.terms-note {
  font-size: 14px;
  line-height: 1.7;
  color: var(--muted);
  margin: 0 0 16px;
}
.terms-note b { color: var(--ink-soft); }

/* A notice. Square-ish, hairline, no coloured background — an alert box in a
   printed thing is a marginal note, not a traffic light. */
.note {
  padding: 15px 16px;
  border-radius: var(--r);
  box-shadow: inset 0 0 0 1px var(--rule);
  background: var(--paper-sunk);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 20px 0;
}
.note b { font-weight: 600; }
.note.warn { box-shadow: inset 0 0 0 1px var(--bad); }
.note.warn b { color: var(--bad); }

/* ── prose pages ────────────────────────────────────────────────────────── */
.prose { font-size: 15.5px; line-height: 1.75; color: var(--ink-soft); }
.prose h2 {
  font-family: var(--serif); font-weight: 500;
  font-size: 21px; line-height: 1.3;
  margin: 34px 0 10px; color: var(--ink);
}
.prose p { margin: 0 0 14px; }
.prose ul { margin: 0 0 14px; padding-left: 20px; }
.prose li { margin-bottom: 8px; }
.prose a { color: var(--ink); }

/* ── toast ──────────────────────────────────────────────────────────────── */
#toast {
  position: fixed;
  left: 50%;
  bottom: calc(96px + var(--safe-b));
  z-index: 60;
  transform: translate(-50%, 14px);
  max-width: calc(100vw - 48px);
  padding: 12px 18px;
  background: var(--ink);
  color: var(--paper);
  font-size: 14.5px;
  line-height: 1.45;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
#toast.on { opacity: 1; transform: translate(-50%, 0); }

/* ── motion ─────────────────────────────────────────────────────────────── */
.fade-in { animation: fade .26s ease both; }
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; } }

/* Somebody who has asked their phone to stop animating things has asked for
   a reason. Transitions that carry meaning (the clock hand) keep working;
   decoration stops. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .hand { transition: none; }
}

/* ══════════════════════════ wider screens ═════════════════════════════════
 *
 * The phone layout above is the base. From 900px the page becomes a page:
 * the header gets its navigation, the hero puts words beside the product,
 * and the sections that are lists become rows. The app screens — the form,
 * the song, the policies — do NOT get wider, because a 900px-wide text field
 * looks like a spreadsheet and a 140-character line is harder to read, not
 * easier. Room around them is the point.
 */

@media (min-width: 620px) {
  :root { --pad: 32px; }
  .sec { padding-block: 66px; }
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 40px; }
  .steps li:first-child { grid-column: 1 / -1; }
  .foot-grid { grid-template-columns: 1fr 1fr; }
  .foot-brand { grid-column: 1 / -1; }
  .covers { grid-template-columns: repeat(2, 1fr); gap: 14px; }
}

@media (min-width: 900px) {
  :root { --pad: 40px; }

  .sec { padding-block: 86px; }
  [id] { scroll-margin-top: 104px; }

  /* ── header ────────────────────────────────────────────────────────── */
  .head-inner { height: 74px; gap: 36px; }
  .head-mark { font-size: 23px; }
  .site-head.at-top .head-mark {
    opacity: 0;
    transform: translateY(-3px);
    pointer-events: none;
  }
  .head-nav { display: flex; gap: 30px; align-items: center; }
  .head-cta { margin-left: auto; }

  /* ── hero ────────────────────────────────────────────────────────────────
   * On a laptop the title page IS the first screen: it fills the window and
   * nothing competes with it. What sells the thing is underneath, one scroll
   * away, where somebody goes once they have decided they are interested.
   *
   * svh rather than vh so a phone's collapsing toolbar does not make it jump,
   * and min-height rather than height so a short window grows the section
   * instead of clipping it.
   */
  .hero {
    min-height: calc(100svh - 74px);
    display: grid;
    place-items: center;
    padding-block: 56px;
  }
  .hero .crest-lg { width: 208px; height: 208px; }
  .wordmark { font-size: clamp(58px, 5.6vw, 76px); margin-top: 36px; }
  /* One line each, with room to be one line. The quotation takes its source
     onto the end of itself, and the lede loses the measure that was forcing
     it to break — at this size it is well under half the column. */
  .epigraph { margin-top: 28px; font-size: 21px; }
  /* Sits on the quotation's own baseline. It had a 2px lift on it, which on
     small caps beside 21px italic reads as the name floating away from the
     line it belongs to. */
  .epigraph .attrib { display: inline; margin: 0 0 0 16px; vertical-align: baseline; }
  .lede { font-size: 24px; margin: 48px 0 36px; max-width: none; }
  .hero-cta { min-width: 300px; }

  /* ── sections ──────────────────────────────────────────────────────── */
  /* A centred section heading over a row of columns. Standard, and standard
     because it reads as one section rather than as a label on the first
     column — which is what a left-aligned heading does above a grid. */
  .sec-head { text-align: center; margin-bottom: 44px; }
  .sec-head .sec-sub { margin-inline: auto; }

  /* The single rule, and the steps hanging from it. */
  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0 56px;
    border-top: 1px solid var(--rule);
  }
  .steps li:first-child { grid-column: auto; }
  .steps li { padding: 42px 0 0; border-top: 0; }
  .steps .num { font-size: 32px; margin-bottom: 24px; }
  .steps h3 { font-size: 25px; margin-bottom: 13px; }
  .steps p { font-size: 17.5px; }

  /* ── the offer ─────────────────────────────────────────────────────── */
  .offer { max-width: 32rem; padding: 46px 44px 38px; }
  .price { font-size: 76px; }

  /* ── questions ─────────────────────────────────────────────────────── */
  .qa summary { font-size: 19px; padding: 21px 44px 21px 0; }
  .qa p { font-size: 17px; padding-bottom: 24px; }

  /* ── footer ────────────────────────────────────────────────────────── */
  .foot { padding-block: 60px 0; }
  .foot-grid { grid-template-columns: 2.2fr 1fr 1fr 1fr; gap: 48px; }
  .foot-brand { grid-column: auto; }

  /* ── the ordering flow ─────────────────────────────────────────────── */
  /* Still one column — a form is not improved by being wide — but the action
     rejoins the page instead of floating over it. A bar pinned to the bottom
     of a laptop window is a phone idiom wearing the wrong clothes. */
  .view { max-width: 34rem; padding-top: 64px; padding-bottom: 96px; }
  .foot-action { position: static; padding: 0; margin-top: 40px; background: none; }
  .foot-action > * { max-width: none; }
  .foot-action .btn { width: 100%; max-width: 330px; margin-inline: auto; }
  .back { margin-bottom: 22px; }
  .h1 { font-size: 40px; }

  /* ── a song ────────────────────────────────────────────────────────── */
  /* Cover and controls on one side, the words on the other — how a record has
     always presented itself, and it puts the lyrics at eye level instead of
     below the fold. */
  .view.song-view {
    max-width: var(--wide);
    display: grid;
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1fr);
    gap: 0 76px;
    align-items: start;
  }
  /* `display: contents` dissolves this wrapper so its children become items of
     the grid above. Without it the cover chooser sits below BOTH columns, and
     since the words are always taller than the player, the bottom-left of the
     page is a large hole. */
  .song-grid { display: contents; }
  .song-main { grid-column: 1; grid-row: 1; }
  .song-side { grid-column: 2; grid-row: 1 / span 2; padding-top: 8px; }
  .song-extra { grid-column: 1; grid-row: 2; max-width: 34rem; }
  .song-side .lyric-panel { height: 62vh; max-height: 620px; margin-top: 0; }
  .song-side .lyrics { margin-top: 0; font-size: 19px; }
  .song-actions .btn { max-width: 360px; margin-inline: auto; }
  .clock { width: 268px; height: 268px; }

  /* ── prose ─────────────────────────────────────────────────────────── */
  .view.prose-view { max-width: var(--wide); }
  .prose-grid {
    display: grid;
    grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
    gap: 0 76px;
    align-items: start;
  }
  .prose-head { position: sticky; top: 112px; }
  .prose { font-size: 16.5px; max-width: 64ch; }
  .prose h2 { margin-top: 40px; }
}

@media (min-width: 1280px) {
  :root { --wide: 74rem; }
  .hero .crest-lg { width: 232px; height: 232px; }
  .wordmark { font-size: clamp(64px, 5.4vw, 82px); }
}

/* Short phones: an SE in landscape, or any phone with the keyboard up. The
   crest is the first thing to give up its space. */
/* Short windows — a phone in landscape, a small laptop, a browser with the
   dev tools open. The crest is the first thing to give up its space, and the
   hero stops insisting on a full screen. */
@media (max-height: 680px) {
  .hero .crest-lg { width: 112px; height: 112px; }
  .wordmark { margin-top: 20px; }
  .lede { margin: 26px 0 24px; }
  .hero { padding-block: 28px 40px; min-height: 0; }
}
