/* One stylesheet for every page.

   The palette and typefaces come from lib/app/colabroom_theme.dart, so the
   site and the app are recognisably the same object. Dark on purpose — the
   app is dark, and most of this gets read in a rehearsal room at night.

   Shared rather than copied into each page because one person maintains this,
   and five copies of a colour is five places to forget. */

:root {
  --ink: #050B16;
  --surface: #0A1728;
  --line: #16304F;
  --text: #F2F7FF;
  --body: #C6D3E8;
  --muted: #8A9AB6;
  --cyan: #3AD3FF;
  --gold: #E3B34D;
  --green: #45D6A5;
  --a1: #FFC857;
  --a2: #FF6FAE;
  --a3: #2ED3B7;
  --a4: #B993FF;

  --display: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --serif: 'Newsreader', Georgia, 'Times New Roman', serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* How loud the background plays.
     A phone overrides these near the bottom of this file: the same opacity
     that reads as texture across a laptop is invisible on a screen a quarter
     the size, held at arm's length, often in daylight. */
  --lane-peak: 0.15;
  --lane-rest: 0.06;
  --inst-peak: 0.07;
  --inst-rest: 0.05;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--body);
  font-family: var(--serif);
  font-size: 1.0625rem;
  line-height: 1.6;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 60rem; margin: 0 auto; padding: 0 1.5rem; }

h1, h2, h3 { font-family: var(--display); margin: 0; text-wrap: balance; }
p { margin: 0; }

a { color: var(--cyan); }
a:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* ---------- nav ---------- */
header.top {
  display: flex; align-items: center; gap: 1rem 1.5rem;
  padding: 1.5rem 0; flex-wrap: wrap;
}
.brand {
  font-family: var(--display); font-weight: 800; font-size: 1rem;
  color: var(--text); letter-spacing: -0.01em; text-decoration: none;
}
nav.pages {
  display: flex; gap: 1.25rem; flex-wrap: wrap;
  font-family: var(--display); font-size: 0.85rem; font-weight: 600;
}
nav.pages a { color: var(--muted); text-decoration: none; }
nav.pages a:hover { color: var(--text); }
nav.pages a[aria-current="page"] { color: var(--text); }
header.top .sp { flex: 1; }

.cta {
  display: inline-block; font-family: var(--display); font-weight: 700;
  font-size: 0.9rem; text-decoration: none;
  background: var(--gold); color: #14100A;
  padding: 0.55rem 1.1rem; border-radius: 100px;
}
.cta.quiet { background: transparent; color: var(--cyan); border: 1px solid var(--line); }

/* The one action on the front page that needs nothing from anybody.
   Wraps rather than shrinks: at 22rem the button and its note sit on
   two lines, which is better than a button with no room for its
   own words. */
.hero-do {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.6rem 1rem; margin-top: 1.6rem;
}
.hero-note {
  font-family: var(--mono); font-size: 0.7rem; color: var(--muted);
  letter-spacing: 0.06em;
}


.meta {
  font-family: var(--mono); font-size: 0.72rem; color: var(--muted);
  letter-spacing: 0.08em; margin-top: 2.5rem;
}

/* ---------- hero, used at the top of every page ---------- */
.hero { padding: 4rem 0 4.5rem; }
.hero h1 {
  font-weight: 900;
  font-size: clamp(2.75rem, 10vw, 7rem);
  line-height: 0.94;
  letter-spacing: -0.045em;
  color: var(--text);
}
.hero p {
  max-width: 30ch; margin-top: 1.75rem;
  font-size: clamp(1.2rem, 3vw, 1.7rem); line-height: 1.35; color: var(--body);
}
.hero.inner h1 { font-size: clamp(2.25rem, 7vw, 4.25rem); }
.hero.inner p { max-width: 46ch; font-size: clamp(1.1rem, 2.4vw, 1.4rem); }

/* ---------- a moment ---------- */
section.moment { padding: 4.5rem 0; border-top: 1px solid var(--line); }
.eyebrow {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--gold); margin-bottom: 1.25rem;
}
section.moment h2 {
  font-weight: 900; font-size: clamp(1.85rem, 5.5vw, 3.25rem);
  line-height: 1.03; letter-spacing: -0.035em; color: var(--text); max-width: 18ch;
}
section.moment .lede {
  max-width: 46ch; margin-top: 1.5rem;
  font-size: clamp(1.0625rem, 2.2vw, 1.25rem); line-height: 1.5;
}
section.moment .more {
  display: inline-block; margin-top: 1.5rem;
  font-family: var(--display); font-weight: 700; font-size: 0.9rem;
  text-decoration: none;
}

/* ---------- drawn pictures of the real thing ---------- */
.art {
  margin-top: 2.5rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: 1rem; padding: 1.25rem 1.35rem;
}

.take { display: flex; align-items: center; gap: 0.8rem; padding: 0.65rem 0; }
.take + .take { border-top: 1px solid var(--line); }
.dot { width: 0.5rem; height: 0.5rem; border-radius: 100px; flex: none; }
.take .name {
  font-family: var(--display); font-weight: 700; font-size: 0.88rem;
  color: var(--text); flex: none; min-width: 8.5rem;
}
.take .fader { flex: 1; height: 3px; background: var(--line); border-radius: 100px; position: relative; }
.take .fader i { position: absolute; top: 0; bottom: 0; left: 0; background: var(--cyan); border-radius: 100px; }
.take .fader b {
  position: absolute; top: 50%; width: 0.8rem; height: 0.8rem;
  margin-top: -0.4rem; margin-left: -0.4rem; background: var(--cyan); border-radius: 100px;
}
.take .pct { font-family: var(--mono); font-size: 0.68rem; color: var(--muted); flex: none; min-width: 3.25rem; text-align: right; }
.take.off .name { color: var(--muted); }
.take.off .fader i, .take.off .fader b { background: var(--muted); opacity: 0.45; }

.stats { display: flex; flex-wrap: wrap; gap: 1.75rem 3rem; }
.stat .k {
  font-family: var(--mono); font-size: 0.65rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted);
}
.stat .v {
  font-family: var(--display); font-weight: 900; font-size: 1.7rem;
  color: var(--text); letter-spacing: -0.02em; line-height: 1.15;
}

.lyric span.line { display: flex; align-items: center; gap: 0.75rem; padding: 0.3rem 0; }
.lyric em { font-style: normal; color: var(--text); font-size: 1.05rem; }
.lyric .chords {
  font-family: var(--mono); font-size: 0.72rem; color: var(--gold);
  letter-spacing: 0.06em; padding-left: 1.25rem;
}

/* A chord, as the app answers it: the shape, what is in it, and what
   works over it. Drawn rather than screenshotted so it stays legible at
   any width and matches the rest of the page's ink. */
.chordcard .chordhead {
  display: flex; align-items: baseline; gap: 0.85rem; flex-wrap: wrap;
  padding-bottom: 0.9rem; border-bottom: 1px solid var(--line);
}
.chordcard .chordname {
  font-family: var(--display); font-weight: 900; font-size: 1.9rem;
  color: var(--text); letter-spacing: -0.02em; line-height: 1;
}
.chordcard .chordqual {
  font-family: var(--mono); font-size: 0.68rem; color: var(--muted);
  letter-spacing: 0.04em;
}
/* Six strings, low to high — × is a string you do not play. */
.chordrow { display: flex; gap: 4px; margin: 1rem 0 1.1rem; }
.chordrow .cell {
  flex: 1; height: 2.4rem; border: 1px solid var(--line); border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 0.85rem; font-weight: 700;
  color: var(--cyan); background: color-mix(in srgb, var(--cyan) 7%, transparent);
}
.chordrow .cell.x { color: var(--muted); background: none; }
.chordnotes { display: flex; flex-wrap: wrap; gap: 0.6rem 1.6rem; }
.chordnotes span {
  display: flex; flex-direction: column; gap: 0.15rem;
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted);
}
.chordnotes b {
  font-family: var(--display); font-weight: 900; font-size: 1.15rem;
  color: var(--text); letter-spacing: -0.01em; text-transform: none;
}
.chordfoot {
  margin-top: 1.1rem; padding-top: 0.9rem; border-top: 1px solid var(--line);
  font-family: var(--mono); font-size: 0.7rem; color: var(--gold);
  letter-spacing: 0.06em;
}

/* Numbers and shape in one picture: what came back, and how it is laid out. */
.art .stats + .form { margin-top: 1.75rem; }

/* A song's shape, as the analyzer reports it. */
.form { display: flex; gap: 3px; margin-top: 0.25rem; }
.form span {
  flex: 1; height: 2.25rem; border-radius: 4px;
  font-family: var(--mono); font-size: 0.6rem; color: var(--ink);
  display: flex; align-items: center; justify-content: center; font-weight: 700;
}

.pill-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.pill {
  font-family: var(--mono); font-size: 0.68rem; color: var(--body);
  border: 1px solid var(--line); border-radius: 100px; padding: 0.3rem 0.7rem;
}

/* ---------- a short list of plain facts ---------- */
ul.plain { margin: 1.5rem 0 0; padding: 0; list-style: none; max-width: 46ch; }
ul.plain li { padding-left: 1.1rem; position: relative; margin-top: 0.7rem; }
ul.plain li::before {
  content: ''; position: absolute; left: 0; top: 0.72em;
  width: 0.45rem; height: 1px; background: var(--gold);
}
ul.plain li b { color: var(--text); font-weight: 600; }

/* ---------- close ---------- */
.close { padding: 5rem 0 3.5rem; border-top: 1px solid var(--line); text-align: center; }
.close h2 {
  font-weight: 900; font-size: clamp(1.85rem, 6vw, 3.5rem);
  line-height: 1; letter-spacing: -0.04em; color: var(--text);
}
.close p { max-width: 34ch; margin: 1.25rem auto 2rem; }
.close .meta { margin-top: 1.25rem; }

/* ---------- required small print ---------- */
details.legal { border-top: 1px solid var(--line); padding: 2rem 0; }
details.legal summary {
  font-family: var(--display); font-weight: 700; font-size: 0.95rem;
  color: var(--text); cursor: pointer; list-style: none;
}
details.legal summary::-webkit-details-marker { display: none; }
details.legal summary::after { content: '  +'; color: var(--muted); }
details.legal[open] summary::after { content: '  \2212'; }
details.legal .inner { max-width: 46rem; margin-top: 1.25rem; font-size: 0.95rem; }
details.legal .inner p { margin-top: 0.9rem; }
details.legal h3 { font-size: 0.95rem; font-weight: 800; color: var(--text); margin: 1.75rem 0 0.5rem; }
details.legal ol { padding-left: 1.2rem; margin: 0.5rem 0; }

/* ---------- where to go next ----------
   The bottom of a page was a dead end: finish reading and the only way
   onward was to scroll all the way back up to the nav. Repeating that nav
   here would work, but it answers "where can I go" when the question at
   the end of a page is "what should I read next" — so these carry what
   each page actually says, and the page you are on is left out. */
.keep-reading { padding: 3.5rem 0 1rem; border-top: 1px solid var(--line); }
.onward-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.onward {
  flex: 1 1 14rem;
  display: block;
  padding: 1.1rem 1.2rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  text-decoration: none;
  transition: border-color .2s ease, background .2s ease;
}
.onward:hover { border-color: var(--cyan); background: var(--raised, var(--surface)); }
.onward .where {
  display: block;
  font-family: var(--display); font-weight: 800; font-size: 1rem;
  color: var(--text); letter-spacing: -0.01em;
}
.onward .what {
  display: block; margin-top: 0.35rem;
  font-family: var(--serif); font-size: 0.92rem; line-height: 1.4;
  color: var(--muted);
}

footer {
  border-top: 1px solid var(--line); padding: 2rem 0 3rem;
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; align-items: center;
  font-family: var(--mono); font-size: 0.72rem; color: var(--muted);
}
footer a { color: var(--muted); text-decoration: none; }
footer a:hover { color: var(--cyan); }
footer .sp { flex: 1; }

.reveal { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(14px); transition: opacity .7s ease, transform .7s ease; }
  .reveal.in { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ============================================================
   The stage: the page as a multitrack.

   The site is about layering takes over each other, so the background
   performs that while you read about it. One waveform lane is playing
   when you arrive; reach the second section and a second fades up
   beneath it; by the fourth you are looking at an arrangement, with a
   playhead that has been travelling down the page the whole way.

   Held far enough back that it never competes with the type. This is
   meant to be noticed second, on the way past — and nothing here is the
   only place anything is said.
   ============================================================ */

.stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

/* One rule lifts every page's content above the stage. */
.wrap { position: relative; z-index: 1; }

.lane {
  position: absolute;
  left: -4%;
  width: 108%;
  height: 15vh;
  opacity: 0;
}
.lane svg { width: 100%; height: 100%; display: block; }
.lane svg rect { fill: currentColor; }

.lane.l1 { top: 24vh; color: var(--a1); }
.lane.l2 { top: 44vh; color: var(--a2); }
.lane.l3 { top: 64vh; color: var(--a3); }

.inst {
  position: absolute;
  width: clamp(9rem, 24vw, 19rem);
  aspect-ratio: 1;
  color: var(--text);
  opacity: 0;
}
.inst svg { width: 100%; height: 100%; display: block; }

.inst.i1 { top: 12vh; right: 4vw; }
.inst.i2 { top: 30vh; left: 3vw; }
.inst.i3 { top: 48vh; right: 6vw; }
.inst.i4 { top: 26vh; left: 8vw; }

/* One hairline crossing the page as you read, the way a playhead crosses
   a take. */
.playhead {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold) 20%, var(--gold) 80%, transparent);
  opacity: 0.2;
}

/* Two drivers for one set of animations. Where scroll-driven CSS exists
   the browser runs these off the main thread and they cannot judder.
   Firefox stable does not have it yet, so stage.js writes the same
   progress into --scroll and the fallback block below reads it. */

@keyframes lane-1 { 0% { opacity: 0 } 12% { opacity: var(--lane-peak) } 70% { opacity: var(--lane-peak) } 100% { opacity: var(--lane-rest) } }
@keyframes lane-2 { 0% { opacity: 0 } 30% { opacity: 0 } 46% { opacity: var(--lane-peak) } 100% { opacity: var(--lane-rest) } }
@keyframes lane-3 { 0% { opacity: 0 } 55% { opacity: 0 } 70% { opacity: var(--lane-peak) } 100% { opacity: var(--lane-rest) } }
@keyframes drift  { 0% { transform: translateY(5vh) } 100% { transform: translateY(-5vh) } }
@keyframes inst-1 { 0% { opacity: var(--inst-peak) } 22% { opacity: var(--inst-peak) } 34% { opacity: 0 } 100% { opacity: 0 } }
@keyframes inst-2 { 0% { opacity: 0 } 24% { opacity: 0 } 36% { opacity: var(--inst-peak) } 50% { opacity: var(--inst-peak) } 62% { opacity: 0 } 100% { opacity: 0 } }
@keyframes inst-3 { 0% { opacity: 0 } 52% { opacity: 0 } 64% { opacity: var(--inst-peak) } 78% { opacity: var(--inst-peak) } 88% { opacity: 0 } 100% { opacity: 0 } }
@keyframes inst-4 { 0% { opacity: 0 } 78% { opacity: 0 } 90% { opacity: var(--inst-peak) } 100% { opacity: var(--inst-rest) } }
@keyframes head   { 0% { top: 0 } 100% { top: 100% } }

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .lane, .inst, .playhead {
      animation-timeline: scroll(root block);
      animation-duration: 1ms; /* ignored on a scroll timeline; the syntax wants one */
      animation-fill-mode: both;
      animation-timing-function: linear;
    }
    .lane.l1 { animation-name: lane-1, drift; }
    .lane.l2 { animation-name: lane-2, drift; }
    .lane.l3 { animation-name: lane-3, drift; }
    .inst.i1 { animation-name: inst-1; }
    .inst.i2 { animation-name: inst-2; }
    .inst.i3 { animation-name: inst-3; }
    .inst.i4 { animation-name: inst-4; }
    .playhead { animation-name: head; }
  }
}

@supports not (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    :root { --scroll: 0; }
    .lane, .inst { transition: opacity .4s linear; }
    .lane.l1 { opacity: calc(var(--lane-peak) * clamp(0, var(--scroll) * 8, 1)); }
    .lane.l2 { opacity: calc(var(--lane-peak) * clamp(0, (var(--scroll) - 0.3) * 7, 1)); }
    .lane.l3 { opacity: calc(var(--lane-peak) * clamp(0, (var(--scroll) - 0.55) * 7, 1)); }
    .inst.i1 { opacity: calc(var(--inst-peak) * clamp(0, (0.34 - var(--scroll)) * 8, 1)); }
    .inst.i2 { opacity: calc(var(--inst-peak) * clamp(0, min((var(--scroll) - 0.24) * 8, (0.62 - var(--scroll)) * 8), 1)); }
    .inst.i3 { opacity: calc(var(--inst-peak) * clamp(0, min((var(--scroll) - 0.52) * 8, (0.88 - var(--scroll)) * 8), 1)); }
    .inst.i4 { opacity: calc(var(--inst-peak) * clamp(0, (var(--scroll) - 0.78) * 8, 1)); }
    .playhead { top: calc(var(--scroll) * 100%); }
  }
}

/* Reduced motion keeps the arrangement and drops the performance: lanes
   rest at a quiet opacity, nothing moves, no playhead is drawn. */
@media (prefers-reduced-motion: reduce) {
  .lane.l1, .lane.l2, .lane.l3 { opacity: var(--lane-rest); }
  .inst.i1, .inst.i4 { opacity: var(--inst-rest); }
}

/* The line that tells a first-time visitor what they are looking at.
   Without it the hero is a poem next to a button — memorable, and no help
   at all to somebody who has never heard of this. */
.kicker {
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--gold); margin-bottom: 1.5rem;
}


/* ============================================================
   Phones.

   Everything above is written for a page with room in it. A phone has a
   third of the width, a fifth of the area, and is usually being read
   one-handed in worse light — so several things that are fine at desk
   size are wrong here, and each needs its own answer rather than a
   global shrink.
   ============================================================ */

@media (max-width: 46rem) {

  /* The background was almost invisible. Two causes compounding: the
     instruments are sized in vw, so a shape 300px across on a laptop is
     90px on a phone, and the same opacity carries far less on a small
     bright screen. Bigger and louder — an abstract line drawing at half
     the viewport reads as deliberate, where the same thing small reads
     as a smudge. */
  :root {
    --lane-peak: 0.30;
    --lane-rest: 0.14;
    --inst-peak: 0.15;
    --inst-rest: 0.10;
  }

  .inst { width: clamp(13rem, 62vw, 24rem); }
  .inst.i1 { top: 16vh; right: -8vw; }
  .inst.i2 { top: 34vh; left: -12vw; }
  .inst.i3 { top: 46vh; right: -14vw; }
  .inst.i4 { top: 30vh; left: -10vw; }

  /* Lanes spread across the height instead of bunching in the middle
     third, which is what they did on a tall screen. */
  .lane { height: 12vh; }
  .lane.l1 { top: 18vh; }
  .lane.l2 { top: 43vh; }
  .lane.l3 { top: 68vh; }

  /* The header wrapped into a jumble: brand, four nav items, a flexible
     spacer and a button, all fighting for one row. Clean rows instead —
     who this is, then where to go, then what to do.

     The buttons used to leave entirely here, on the reasoning that the
     one button was already at the bottom of every page. That was true of
     the invite ask and never became true of Sign in, which exists on no
     other page — so on a phone, which is most of the traffic, somebody
     with an account had no way into the app from six of these pages.
     They stay, smaller, on a row of their own. */
  header.top { display: block; padding: 1.25rem 0 0.75rem; }
  header.top .sp { display: none; }
  header.top .cta {
    display: inline-block;
    margin-top: 0.9rem;
    font-size: 0.8rem;
    padding: 0.45rem 0.9rem;
  }
  header.top .cta.quiet { margin-right: 0.45rem; }
  .brand { display: block; margin-bottom: 0.9rem; }
  nav.pages {
    gap: 1.35rem;
    font-size: 0.9rem;
    padding-bottom: 0.25rem;
  }

  /* Tighter gutters and less air between sections. 72px of vertical
     padding is generous on a laptop and a chasm on a phone, where it
     separates things that belong together. */
  .wrap { padding: 0 1.25rem; }
  .hero { padding: 2.5rem 0 3rem; }
  .hero p { margin-top: 1.25rem; max-width: 24ch; }
  .meta { margin-top: 1.75rem; }
  section.moment { padding: 3.25rem 0; }
  section.moment .lede { margin-top: 1.1rem; }
  .art { margin-top: 1.75rem; padding: 1rem; }
  .close { padding: 3.5rem 0 2.5rem; }
  .kicker { margin-bottom: 1.1rem; }

  /* Headlines were set to wrap at 18ch, which on a narrow column left
     ragged one-word lines. Let them use the width they have. */
  section.moment h2 { max-width: none; font-size: clamp(1.7rem, 8vw, 2.4rem); }
  .hero h1 { font-size: clamp(2.6rem, 14vw, 4rem); }
  .hero.inner h1 { font-size: clamp(2rem, 10vw, 2.9rem); }

  /* A take row ran out of width: a 136px fixed name, a percentage
     column and a fader all in one line left the fader a stub. Name on
     its own line, fader full width under it. */
  .take { flex-wrap: wrap; gap: 0.5rem 0.7rem; padding: 0.75rem 0; }
  .take .name { min-width: 0; flex: 1; }
  .take .pct { min-width: 0; }
  .take .fader { flex-basis: 100%; order: 3; }

  /* Three big numbers per row does not fit. Two do. */
  .stats { gap: 1.25rem 2rem; }
  .stat { flex: 1 1 40%; }
  .stat .v { font-size: 1.45rem; }

  /* The song's shape is a row of eight labels; on a phone the words do
     not fit their blocks. It scrolls sideways at a readable size rather
     than compressing into initials nobody can read. */
  .form { overflow-x: auto; gap: 2px; }
  .form span { flex: none; min-width: 4.25rem; }

  .lyric em { font-size: 1rem; }
  .lyric .chords { padding-left: 0; }

  .keep-reading { padding: 2.5rem 0 0.5rem; }
  .onward { flex-basis: 100%; padding: 0.9rem 1rem; }
  .onward .what { font-size: 0.88rem; }

  footer { gap: 0.4rem 1rem; }
  footer .sp { flex-basis: 100%; }
}

/* Very narrow phones. One extra step rather than a smaller everything:
   only the things that actually break get another value. */
@media (max-width: 22rem) {
  .wrap { padding: 0 1rem; }
  nav.pages { gap: 1rem; font-size: 0.85rem; }
  .stat { flex-basis: 100%; }
}

/* ---------------------------------------------------------------------
   The free chord tool (chords.html)
   ---------------------------------------------------------------------
   The one page on this site that does something rather than describing
   something. It borrows the same tokens as everything else so it reads as
   part of the app rather than as a widget somebody embedded. */

.tool { margin: 0 0 4.5rem; }

.drop {
  display: block;
  width: 100%;
  border: 1px dashed var(--line);
  border-radius: 16px;
  background: var(--surface);
  padding: 3rem 1.5rem;
  text-align: center;
  cursor: pointer;
  transition: border-color .18s ease, background .18s ease;
}
.drop:hover, .drop.over { border-color: var(--cyan); background: #0C1D33; }
.drop:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }

.drop-lead {
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--text);
  margin: 0 0 .35rem;
}
.drop-sub { color: var(--muted); font-size: .9375rem; }

/* Five bars, the shape of the app's own take rows. Still, not animated:
   a drop zone that moves before anybody has dropped anything is a page
   asking for attention it has not earned yet. */
.drop-mark {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 5px;
  height: 34px;
  margin: 0 0 1.1rem;
}
.drop-mark span {
  width: 5px;
  border-radius: 3px;
  background: var(--cyan);
  opacity: .55;
}
.drop-mark span:nth-child(1) { height: 40%; }
.drop-mark span:nth-child(2) { height: 78%; }
.drop-mark span:nth-child(3) { height: 100%; }
.drop-mark span:nth-child(4) { height: 62%; }
.drop-mark span:nth-child(5) { height: 30%; }

.linkish {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--cyan);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.working { margin-top: 1.5rem; text-align: center; color: var(--muted); }
.working .bar {
  height: 3px;
  border-radius: 3px;
  background: var(--line);
  overflow: hidden;
  margin-bottom: .75rem;
}
/* Indeterminate on purpose. The endpoint cannot say how far through it is,
   and a bar that pretends to know is a bar that sits at 90% for forty
   seconds. */
.working .bar i {
  display: block;
  height: 100%;
  width: 38%;
  border-radius: 3px;
  background: var(--cyan);
  animation: slide 1.4s ease-in-out infinite;
}
@keyframes slide {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(300%); }
}
@media (prefers-reduced-motion: reduce) {
  .working .bar i { animation: none; width: 100%; opacity: .5; }
}

.problem {
  margin-top: 1.5rem;
  padding: 1rem 1.15rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--gold);
  border-radius: 10px;
  background: var(--surface);
  color: var(--body);
  font-size: .9375rem;
}

.result { margin-top: 1.75rem; }

.result-head {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 3rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--line);
}
.result-label {
  font-family: var(--mono);
  font-size: .625rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 .3rem;
}
.result-key {
  font-family: var(--display);
  font-size: 1.9rem;
  font-weight: 800;
  color: var(--text);
  margin: 0;
}
.result-prog {
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--cyan);
  margin: 0;
}

.chart {
  margin: 1.25rem 0 1.5rem;
  max-height: 26rem;
  overflow-y: auto;
}
.chart-row {
  display: grid;
  grid-template-columns: 4rem 1fr 3.5rem;
  align-items: baseline;
  gap: 1rem;
  padding: .55rem 0;
  border-bottom: 1px solid rgba(22, 48, 79, .55);
}
.chart-at, .chart-held {
  font-family: var(--mono);
  font-size: .75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.chart-held { text-align: right; }
.chart-chord {
  font-family: var(--display);
  font-size: 1.0625rem;
  font-weight: 800;
  color: var(--text);
}
.chart-chord.quiet { color: var(--muted); font-weight: 500; }

.shared-note {
  margin: 0 0 1.5rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--line);
  font-size: .95rem;
  line-height: 1.5;
  color: var(--muted);
}

.result-foot { display: flex; flex-wrap: wrap; gap: .75rem; }

@media (max-width: 40rem) {
  .drop { padding: 2.25rem 1rem; }
  .result-key { font-size: 1.6rem; }
  .result-prog { font-size: 1.15rem; }
  .chart-row { grid-template-columns: 3.25rem 1fr 3rem; gap: .75rem; }
}

/* Where the free tool stops and the app starts.

   Styled as an offer, not an error. The .problem panel above uses a gold
   left-edge and reads as something going wrong; this shares none of that
   language on purpose, because somebody who has used their free songs has
   just demonstrated they have music and want to know what is in it. That is
   the best moment this page gets and it should not look like a fault. */
.gate {
  margin-top: 1.75rem;
  padding: 2rem 1.5rem;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: linear-gradient(180deg, #0C1D33 0%, var(--surface) 100%);
  text-align: center;
}
.gate-lead {
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--text);
  margin: 0 0 .5rem;
}
.gate-sub {
  color: var(--body);
  font-size: .9375rem;
  max-width: 34rem;
  margin: 0 auto 1.5rem;
}
.gate-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  justify-content: center;
}

/* ---------------------------------------------------------------------
   The generated pages: one song, or one musician.
   --------------------------------------------------------------------- */

/* These are the only pages on this site somebody arrives at cold, from a
   search result or a link somebody sent them — every other page is reached
   from the one before it. So they lead with the thing itself and carry the
   least chrome of anything here. */
.page { padding: 3rem 0 4rem; max-width: 42rem; }
.page h1 {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(2.1rem, 7vw, 3.4rem); line-height: 1.02;
  letter-spacing: -0.03em; margin: 0.6rem 0 0.9rem;
  text-wrap: balance;
}

.facts {
  list-style: none; padding: 0; margin: 2rem 0 0;
  border-top: 1px solid var(--line);
}
.facts li {
  display: flex; gap: 1rem; align-items: baseline;
  padding: 0.8rem 0; border-bottom: 1px solid var(--line);
}
.facts span {
  font-family: var(--mono); font-size: 0.7rem; color: var(--muted);
  letter-spacing: 0.08em; text-transform: uppercase;
  flex: 0 0 8.5rem;
}
.facts b { font-weight: 600; }

.note {
  margin-top: 2.2rem; color: var(--muted);
  font-size: 0.95rem; line-height: 1.6;
}
