/* describesong — technicolor blocks, the Homestead way: SOLID tone panels,
   nested rows a lighter tint of the same tone, dark ink on everything, and
   the two-tone pixel "wallpaper" showing only in the gaps between blocks. */
:root { --a: rgb(50 130 165); --b: rgb(165 140 45); --ad: rgb(30 60 80); --bd: rgb(70 60 20);
  --ink: #15151a; --ink2: rgb(21 21 26 / .68); --ink3: rgb(21 21 26 / .45);
  --a1: color-mix(in oklab, var(--a) 78%, white); --a2: color-mix(in oklab, var(--a) 62%, white);
  --b1: color-mix(in oklab, var(--b) 78%, white); --b2: color-mix(in oklab, var(--b) 62%, white);
  --r: 14px; --ri: 10px; --gap: 12px;
  /* the visitor's own UI font: SF Pro on a Mac, Segoe on Windows, whatever fontconfig says on Linux */
  --font: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif }
* { box-sizing: border-box } html { background: #15151a } body { margin: 0; background: transparent }  /* body must NOT paint: an in-flow body background sits above the z-index:-1 canvas */
body { color: var(--ink); font: 15px/1.5 var(--font); min-height: 100vh; -webkit-font-smoothing: antialiased; font-variant-numeric: tabular-nums }
#wp, #water { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: -1 } #wp { image-rendering: auto } #water[hidden] { display: none }
a { color: inherit }
main { width: 100%; min-height: 100vh; margin: 0; padding: var(--gap); display: grid; gap: var(--gap); grid-template-rows: auto auto 1fr auto; grid-template-columns: minmax(0, 1fr) clamp(340px, 27vw, 520px); grid-template-areas: "ban ban" "top top" "res side" "foot foot" }

/* panels: solid tone. .a = primary tone, .b = secondary */
.panel { border-radius: var(--r); padding: 18px 20px; background: var(--a) } .panel.b { background: var(--b) }
/* NO z-index HERE ON PURPOSE. It used to be 3, which made the header a stacking
   context — and that trapped the settings menu inside it, so #tcbody's z-index:20
   only ranked it against its own siblings. To everything else the header and the
   menu were one layer at 3, and nothing could be put between them. The header
   still needs `position: relative` to anchor the menu; it does not need a layer.
   The menu now competes at the top level, where 20 beats the sack outright. */
.top { grid-area: top; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 12px 14px; position: relative }
.side { grid-area: side; align-self: stretch; display: flex; flex-direction: column } .foot { grid-area: foot; display: flex; gap: 8px; flex-wrap: wrap; padding: 10px 12px; align-items: center; position: relative }
.resarea { grid-area: res; display: flex; flex-direction: column; gap: var(--gap) } .resarea > .panel { flex: 1 }   /* the main panel fills its column, like the app window does */

/* blocks nested in a panel: lighter tint of the panel's tone */
.blk { border-radius: var(--ri); padding: 10px 14px; display: inline-flex; align-items: center; gap: 10px; min-height: 46px; text-decoration: none; background: var(--a1); color: var(--ink) }
.panel.b .blk { background: var(--b1) } .panel.b .blk.alt, .blk.alt { background: var(--a) } .panel .blk.alt2 { background: var(--b) }
.blk.push { margin-left: auto } .blk:where(a):hover { filter: brightness(1.06) }
.k { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink2) } .v { font-weight: 700 }
.dot { width: 12px; height: 12px; border-radius: 50%; background: var(--ink) }
.brand { font-size: clamp(24px, 2.2vw, 34px); font-weight: 800; letter-spacing: -.03em; padding: 6px 18px }

/* rings — the bar's stat rings: track, arc, number */
.ring { --p: 0; width: 44px; height: 44px; border-radius: 50%; flex: none; display: grid; place-items: center; position: relative; font-weight: 800; font-size: 13px; background: conic-gradient(var(--ink) calc(var(--p) * 1%), rgb(21 21 26 / .16) 0) }
.ring::before { content: ""; position: absolute; inset: 5px; border-radius: 50%; background: var(--a1) } .panel.b .ring::before { background: var(--b1) } .ring span { position: relative }
.ring.big { width: 64px; height: 64px; font-size: 16px } .ring.big::before { inset: 7px }

/* search */
h1 { font-size: clamp(30px, 3.6vw, 52px); font-weight: 800; line-height: 1.02; letter-spacing: -.03em; margin: 2px 0 8px } h1 span { color: var(--ink); background: var(--b); padding: 0 .14em; border-radius: .18em }
.lead { color: var(--ink2); margin: 0 0 18px }
form.search { display: flex; gap: 8px; flex-wrap: wrap }
form.search input { flex: 1 1 320px; font: 500 clamp(17px, 1.6vw, 22px)/1.3 var(--font); color: var(--ink); background: var(--a2); border: 0; border-radius: var(--ri); padding: 14px 16px; outline: none; min-width: 0 }
form.search input:focus { box-shadow: inset 0 0 0 2px var(--ink) } form.search input::placeholder { color: var(--ink3) }
form.search button { font: 800 13px/1 var(--font); letter-spacing: .1em; text-transform: uppercase; color: var(--a); background: var(--ink); border: 0; border-radius: var(--ri); padding: 0 26px; cursor: pointer; min-height: 50px } form.search button:hover { color: var(--b) }
.hint { margin: 14px 0 0; padding: 10px 14px; border-radius: var(--ri); background: var(--b); font-size: 13px; font-weight: 500 }

/* results = nested rows */
#res { display: flex; flex-direction: column; gap: 8px; margin-top: 12px }
.hit { display: grid; grid-template-columns: auto auto 1fr auto; gap: 14px; align-items: center; animation: pop .3s both; animation-delay: var(--d, 0ms) }
/* the cover is the play button: art from the store, a triangle over it, bars while it plays, a thin line of progress along the bottom */
.cover { position: relative; display: block; width: 54px; height: 54px; border-radius: 6px; overflow: hidden; padding: 0; border: 0; background: var(--b2, rgba(0,0,0,.12)); flex: none }
.cover img { width: 100%; height: 100%; object-fit: cover; display: block }
.cover.ph { background: rgba(0,0,0,.10) }
.cover.play { cursor: pointer } .cover.play svg { position: absolute; inset: 0; width: 100%; height: 100%; padding: 15px; fill: #fff; filter: drop-shadow(0 1px 3px rgba(0,0,0,.6)); opacity: .0; transition: opacity .15s }
.cover.play:hover svg, .cover.play:focus-visible svg, .hit.playing .cover.play svg { opacity: 1 } .cover.play:not(:has(img)) svg { opacity: .9; fill: var(--ink) ; filter: none }
.cover.play .bars { display: none } .hit.playing .cover.play .bars { display: block } .hit.playing .cover.play .tri { display: none }
.hit.playing .cover::after { content: ""; position: absolute; left: 0; bottom: 0; height: 3px; width: calc(100% * var(--played, 0)); background: #fff; opacity: .9 }
.cover.dead { cursor: default; opacity: .5 }
.hit .src { display: none; font-size: 11px; color: var(--ink3); text-decoration: none; margin-top: 4px } .hit.playing .src { display: inline-block } .hit .src:hover { text-decoration: underline }
.hit .t { font-size: 17px; font-weight: 800; line-height: 1.2 } .hit .s { color: var(--ink2); font-size: 12.5px; margin-top: 2px } .hit .n { color: var(--ink3); font-size: 11px; margin-right: 6px }
.tag { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; padding: 6px 10px; border-radius: 8px; color: var(--ink2); background: rgb(21 21 26 / .08); white-space: nowrap; font-weight: 700 }
.tag.v { background: var(--ink); color: var(--a) }
@keyframes pop { from { opacity: 0; transform: translateY(6px) } }

/* add music (side panel, secondary tone) */
.side h2 { font-size: 22px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 8px; line-height: 1.1 } .side h2 span { color: var(--ink); background: var(--a); padding: 0 .14em; border-radius: .18em }
.side p { margin: 0 0 14px; color: var(--ink); font-size: 14.5px; line-height: 1.55 } .side p b { color: var(--ink) }
.scan { width: 100%; text-align: left; font: 800 14px/1.2 var(--font); letter-spacing: .06em; text-transform: uppercase; color: var(--b); background: var(--ink); border: 0; border-radius: var(--ri); padding: 16px 18px; cursor: pointer } .scan:hover { color: var(--a) }
.scan small { display: block; font-weight: 500; text-transform: none; letter-spacing: 0; font-size: 11.5px; margin-top: 6px; color: rgb(245 245 248 / .6) }
.facts { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px }
.facts li { background: var(--b1); border-radius: var(--ri); padding: 9px 12px; font-size: 12.5px; color: var(--ink2) } .facts li b { color: var(--ink) }
#prog { margin-top: 12px; display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: center; background: var(--b1); border-radius: var(--ri); padding: 12px 14px } #prog[hidden] { display: none }
#prog progress { display: none } #status { white-space: pre-line; font-size: 12px; line-height: 1.7 } #prog .ghost { grid-column: 2; justify-self: start }
.ghost { font: 800 11px/1 var(--font); letter-spacing: .08em; text-transform: uppercase; color: var(--ink); background: var(--b2); border: 0; border-radius: 8px; padding: 9px 12px; cursor: pointer } .ghost:hover { filter: brightness(1.06) }
.log { grid-column: 1 / -1; font-size: 11.5px; line-height: 1.6; color: var(--ink2); max-height: 200px; overflow: auto; white-space: pre-wrap; border-top: 1px solid rgb(21 21 26 / .15); padding-top: 8px }
dialog { background: var(--b); color: var(--ink); border: 0; border-radius: var(--r); padding: 22px; max-width: 440px; font: 13.5px/1.5 var(--font) } dialog::backdrop { background: #000a }
.foot .blk { font-size: 12px; min-height: 38px; padding: 8px 12px; color: var(--ink2) } .foot .blk a { color: var(--ink) }
@media (max-width: 860px) { main { grid-template-columns: 1fr; grid-template-areas: "ban" "top" "res" "side" "foot" } .hit { grid-template-columns: auto auto 1fr } .hit .tag { grid-column: 2; justify-self: start } .hide-sm { display: none !important } }

/* corner settings block — the desktop's Colors / Water tabs, in miniature */
.tc label { display: grid; grid-template-columns: 74px 1fr 40px; align-items: center; gap: 8px; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink2) }
.tc label output { text-align: right; color: var(--ink); font-weight: 700; letter-spacing: 0; text-transform: none }
.tc input[type=range] { width: 100%; accent-color: var(--ink); margin: 0 } .tc .k2 { font-size: 10.5px; color: var(--ink2); text-transform: none; letter-spacing: 0 }
.tc .chk { grid-template-columns: auto 1fr; text-transform: none; letter-spacing: 0; font-size: 12px; color: var(--ink) }


/* sidebar: the support block sits at the bottom, whatever the height */
.support { margin-top: auto; padding-top: 14px; display: flex; flex-direction: column; gap: 8px }
.support .blk { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding: 12px 14px }
.support b { font-size: 15px } .support .k2 { font-size: 12px; color: var(--ink2); line-height: 1.5 } .support .k2 a { color: var(--ink) }
/* the colours & water box lives IN the bottom bar and opens upward, so it never covers anything */
.tc { position: relative; margin-left: auto; padding: 0; display: flex; box-shadow: none; width: auto; overflow: visible; max-height: none; align-self: stretch }
.tc .tch { padding: 0 14px; min-height: 46px; align-self: stretch; display: inline-flex; align-items: center; border-radius: var(--ri); background: var(--a); color: var(--ink); cursor: pointer; user-select: none } .tc .tch svg { display: block } .tc .tch:hover svg { transform: rotate(30deg) } .tc .tch svg { transition: transform .25s }
#tcbody { display: none; position: absolute; right: 0; top: calc(100% + 10px); width: 270px; max-height: calc(100vh - 90px); overflow: auto; padding: 12px 14px; flex-direction: column; gap: 8px; border-radius: var(--r); background: var(--b); box-shadow: 0 14px 40px -16px #000; z-index: 20 }
.tc.open #tcbody { display: flex }

/* a count that just changed */
.tick { animation: tick .6s ease-out } @keyframes tick { 0% { transform: scale(1.18) } 100% { transform: scale(1) } }

/* the label-conflict dialog */
.lbl { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 12px 0; align-items: baseline } .lbl .k { padding-top: 2px } dialog .s { color: var(--ink2); font-size: 12.5px } dialog { max-width: 520px }

#tcSack { align-self: flex-start }   /* only as wide as their text */

/* two counts stacked in one header cell. "of ~200M ever released" is gone: it
   existed to feed a ring chart that no longer exists, and the space is better
   spent saying what the index actually holds. */
.stat.stack { display: flex; flex-direction: column; align-items: flex-start; gap: 3px }
.stat.stack .ln { display: flex; align-items: baseline; gap: 8px; white-space: nowrap }
.stat.stack .k { font-size: 11px }
.odo.sm { font-size: 14px; opacity: .75 }
.odo.sm .dg { border-radius: 5px }
@media (max-width: 860px) { .top .stat.stack .odo.sm { font-size: 13px } .stat.stack .k { font-size: 10px } }

/* odometer: one cell per digit, a column of 0–9 that rolls when the digit changes */
.odo { display: inline-flex; align-items: center; gap: 3px; font-weight: 800; font-size: 20px; font-variant-numeric: tabular-nums; line-height: 1 }
.odo .dg { width: .74em; height: 1.3em; overflow: hidden; border-radius: 6px; background: rgb(21 21 26 / .10); position: relative }
.odo .dg .col { display: flex; flex-direction: column; transition: transform .7s cubic-bezier(.2, .8, .2, 1); will-change: transform }
.odo .dg .col span { display: block; height: 1.3em; line-height: 1.3em; text-align: center }
.odo .sym { width: .6em; text-align: center } .odo .gap { width: 4px }

/* the one-line notice at the top: what the server is doing to itself, and why */
.banner { grid-area: ban; border-radius: var(--ri); background: var(--ink); color: var(--a); padding: 10px 16px; font-size: 13.5px; display: flex; gap: 12px; align-items: center }
.banner[hidden] { display: none } .banner a { color: inherit } .banner .bar { flex: 1; height: 3px; background: rgb(245 245 248 / .15); border-radius: 3px; overflow: hidden } .banner .bar i { display: block; height: 100%; background: var(--a); transition: width .8s }
.spin { display: inline-block; width: 12px; height: 12px; border: 2px solid rgb(21 21 26 / .25); border-top-color: var(--ink); border-radius: 50%; animation: spin .8s linear infinite; vertical-align: -2px; margin-right: 6px } @keyframes spin { to { transform: rotate(360deg) } }
#more { margin-top: 8px; font-size: 12.5px; color: var(--ink2) }

/* "what the index hears" */
.hear { margin-top: 6px; font: 600 11px/1 var(--font); letter-spacing: .04em; color: var(--ink2); background: rgb(21 21 26 / .08); border: 0; border-radius: 7px; padding: 5px 8px; cursor: pointer } .hear:hover { color: var(--ink) }
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; align-items: center } .tags[hidden] { display: none }
.chip { font-size: 12px; font-weight: 600; background: var(--ink); color: var(--a); border-radius: 8px; padding: 5px 9px } .chip small { opacity: .6; font-weight: 500; margin-left: 4px }
.chipnote { font-size: 11.5px; color: var(--ink2); flex-basis: 100% }

.tagcol { display: flex; flex-direction: column; gap: 6px; align-items: flex-end }
.tag.via { background: var(--b); color: var(--ink); }
/* A transcription is not a lookup, so it does not get the solid badge a lookup
   gets: outlined, in the same tone, so it reads as the weaker claim it is. */
.tag.via.guess { background: transparent; box-shadow: inset 0 0 0 1.5px var(--b); }
/* a fact match is a different kind of claim from a word match: the same shape,
   the panel's own lighter tint rather than the contrasting tone */
.tag.via.fact { background: var(--a2); color: var(--ink) }

.similar-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px } .similar-head .ghost { margin-left: auto }
/* the divider under a named artist's own songs: the answer ends here */
.similar-head.sep { margin: 14px 0 6px; padding-top: 12px; border-top: 2px dashed var(--a1); flex-wrap: wrap }
.similar-head.sep .k { color: var(--ink3) } .similar-head.sep b { color: var(--ink) } .similar-head.sep .s { color: var(--ink2) }

@media (max-width: 860px) { .top { gap: 8px } .top .stat { padding: 8px 10px; min-height: 40px } .top .stat .odo { font-size: 16px } .top .stat .k { font-size: 10px } .top .stat .v { font-size: 12px } .top .brand { font-size: 22px; padding: 6px 12px } .top a.alt .k { display: none } }


.hit .facts { color: var(--ink3); font-size: 11.5px; margin-left: 6px; letter-spacing: .04em }

.chip.ev { background: var(--b); color: var(--ink) }

/* what can find this track: one pip per search path, lit if the index has it */
.known { display: flex; flex-wrap: wrap; gap: 3px; justify-content: flex-end; max-width: 190px; margin-top: 3px }
.pip { font-size: 9.5px; font-weight: 700; letter-spacing: .05em; padding: 2px 6px; border-radius: 5px; cursor: default; color: var(--ink3); box-shadow: inset 0 0 0 1px currentColor; opacity: .5 }

/* "go by sound alone": for songs the internet has nothing written about */
/* its own row, clearly separate from the sentence above it — merged into that
   paragraph it read as one continuous thing */
.soundonly { display: flex; align-items: center; gap: 8px; width: fit-content; font-size: 12.5px; color: var(--ink2);
  cursor: pointer; margin: 10px 0 12px; padding: 7px 11px 7px 9px; border-radius: var(--ri);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, currentColor 22%, transparent) }
.soundonly:hover { color: var(--ink) }
.soundonly input { accent-color: var(--ink); width: 15px; height: 15px; cursor: pointer }

/* Header: the wordmark and the two counts sit ON the panel, no plate behind
   them. The boxes read as chrome; the words are the thing. */
.top > .brand, .top > .stat { background: none !important; padding-left: 0; padding-right: 0 }
.top > .brand { padding: 6px 0; margin-right: 6px }
/* A divider between the header items while they share a line. The breakpoint
   below is where they stack, and the rule is dropped there — there is no way
   in CSS to ask "did this wrap?", but this header has a fixed three items, so
   the breakpoint knows. */
.top > .stat { margin-right: 18px; padding-left: 18px; border-left: 1px solid currentColor; border-left-color: color-mix(in oklab, currentColor 22%, transparent) }
.top > .brand:where(a):hover { filter: none; opacity: .75 }

@media (max-width: 860px) { .top > .stat { border-left: 0; padding-left: 0; margin-right: 12px } }

/* whether the graphics card is usable here — said before a scan, not after */
.gpu { font-size: 12px; line-height: 1.45; padding: 9px 12px; border-radius: var(--ri); margin-top: 8px }
.gpu.ok { color: var(--ink2); box-shadow: inset 0 0 0 1px color-mix(in oklab, currentColor 20%, transparent) }
.gpu.no { background: var(--a); color: var(--ink) }
/* Softer than .no: a phone is not broken, it is just a poor fit for a job
   this long, so it gets an outline rather than the full alert fill. */
.gpu.warn { color: var(--ink2); box-shadow: inset 0 0 0 1px color-mix(in oklab, currentColor 26%, transparent) }
.gpu code { font-size: 11.5px; padding: 1px 4px; border-radius: 4px; background: color-mix(in oklab, currentColor 14%, transparent) }

/* the lyrics-only button: clearly secondary to the main scan above it */
#pickLyrics { margin-top: 8px; background: var(--b); color: var(--ink); box-shadow: inset 0 0 0 1px color-mix(in oklab, currentColor 22%, transparent) }
#pickLyrics small { opacity: .72 }

/* the hacky sack. Sits above everything, catches its own clicks and nothing
   else's, and is drawn in the page's own ink and second tone like every other
   solid thing here. */
.sack { position: fixed; left: 0; top: 0; width: 26px; height: 26px; z-index: 4;
  cursor: grab; touch-action: none; will-change: transform; filter: drop-shadow(0 2px 3px rgb(21 21 26 / .35)) }
.sack:active { cursor: grabbing }
.sack { width: 40px; height: 40px }
.sack svg { width: 40px; height: 40px; display: block; overflow: visible }
.sack .bag { fill: var(--b); stroke: var(--ink); stroke-width: 1.6; stroke-linejoin: round }
.sack .seam { fill: none; stroke: var(--ink); stroke-width: 1.1; opacity: .5 }

/* the sack's airtime, tucked into the empty space beside the headline. The board
   sits to its LEFT rather than under it, so a page-wide dropdown never lands on
   top of the search box — the one thing anyone came here for. */
.resarea > .panel { position: relative }
/* The order that matters, bottom to top: water (-1), the page (0), the timer and
   board (5), the sack (4 — under the board, so a score stays readable), and the
   settings menu (20) over all of it. The sack passes IN FRONT of the header bar
   and BEHIND an open menu, which is only expressible now that the header is not
   a stacking context of its own. */
.atwrap { position: absolute; right: 20px; top: 16px; z-index: 5; display: flex;
  align-items: flex-start; gap: 10px; pointer-events: none }
.atwrap > * { pointer-events: auto }

/* invisible but present is still a click target: the clock only takes clicks
   once it has a time to show. */
.airtime { pointer-events: none } .airtime.set { pointer-events: auto }
.airtime { font-variant-numeric: tabular-nums; font-weight: 800; font-size: 26px;
  letter-spacing: -.03em; line-height: 1; color: var(--ink); opacity: 0; transition: opacity .25s }
.airtime small { font-size: 14px; font-weight: 700; opacity: .55; margin-left: 1px }
.airtime.set { opacity: 1 }                       /* a time was set: no fading about it */

/* TWO COLUMNS OF FIVE, not a column of ten. Ten stacked rows hung down over the
   search bar, and a leaderboard for a hacky sack does not get to cover the thing
   the site is for. Split in half it clears the bar at every size that shows it. */
.atboard { width: 212px; padding: 6px 10px 7px; border-radius: var(--ri);
  background: var(--a1); color: var(--ink); box-shadow: 0 12px 30px -18px #000; font-size: 11px }
.atboard[hidden] { display: none }
.atboard h4 { margin: 0 0 5px; font-size: 9px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink2); font-weight: 800 }
.atboard ol { margin: 0; padding: 0; list-style: none; font-variant-numeric: tabular-nums;
  display: grid; grid-template-columns: 1fr 1fr; grid-auto-flow: column; grid-template-rows: repeat(5, auto); column-gap: 14px }
.atboard.entry { width: 134px; padding: 7px 9px 8px } .atboard.entry ol { display: block }
.atboard li { display: flex; justify-content: space-between; gap: 6px; line-height: 1.45 }
.atboard li.me { font-weight: 800 }
.atboard .initials { display: flex; align-items: center; gap: 4px; margin: 1px 0 5px }
.atboard .initials input { width: 22px; height: 26px; text-align: center; text-transform: uppercase;
  font: 800 14px/1 var(--font); color: var(--ink); background: var(--a2); border: 0;
  border-radius: 6px; outline: none; caret-color: transparent }
.atboard .initials input:focus { box-shadow: inset 0 0 0 2px var(--ink) }
.atboard .msg { color: var(--ink2); margin-top: 4px; font-size: 10px; line-height: 1.35 }
/* the single-column layout has no empty corner to put this in, and a phone has
   no pointer to keep a sack up with */
@media (max-width: 860px) { .atwrap { display: none } }

/* "That's the one" — the only control here that teaches the index what a WORD
   means rather than what a sound is. Quiet until you want it, and gone from
   every other row the moment one is chosen. */
/* it belongs with the track it is about, beside "what the index hears" —
   the right-hand column is where the row explains ITSELF, not where you answer it */
.gotit { align-self: flex-start; margin-left: 6px; padding: 3px 9px; border: 0; border-radius: 999px; cursor: pointer;
  font: 700 10.5px/1.6 var(--font); letter-spacing: .02em; color: var(--ink2);
  background: rgb(21 21 26 / .07); transition: background .15s, color .15s }
.gotit:hover { background: rgb(21 21 26 / .13); color: var(--ink) }
.gotit.done { background: var(--ink); color: var(--b); cursor: default }
#res.answered .gotit:not(.done) { display: none }

/* an entry whose sound came from shop previews rather than a whole song */
.tag.glimpsed { background: none; box-shadow: inset 0 0 0 1px currentColor; opacity: .55; font-weight: 700 }
/* nothing to play: send them somewhere that will have it */
/* no shop clip: the cover becomes a way to go and find it, with the same hover
   behaviour as the play button so it reads as the same affordance */
.cover.look { cursor: pointer; text-decoration: none }
.cover.look svg { position: absolute; inset: 0; width: 100%; height: 100%; padding: 17px;
  fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.6)); opacity: 0; transition: opacity .15s }
.cover.look:hover svg, .cover.look:focus-visible svg { opacity: 1 }
.cover.look:not(:has(img)) svg { opacity: .5; stroke: var(--ink); filter: none }
.cover.look:not(:has(img)):hover svg { opacity: .9 }

/* the query drawn back with each part named. Sits under the bar, never in the
   way, and disappears the moment the box loses focus. */
.search { position: relative }
.parsebar { position: absolute; left: 0; right: 0; top: calc(100% + 3px); height: 32px; pointer-events: none; z-index: 3 }
.parsebar[hidden] { display: none }
.pspan { position: absolute; top: 0; display: block }
.pspan i { display: block; height: 6px; border: 2px solid currentColor; border-top: 0;
  border-radius: 0 0 5px 5px; opacity: .55 }
/* the label is its OWN box, not the brace's: inside the brace it was clamped to
   the width of the word ("AND" under a 15px "&"), which no max-width could undo.
   It grows to its text, up to the room draw() leaves before the next brace. */
.pspan b { position: absolute; top: 9px; left: 0; width: max-content; font-size: 11px; font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; opacity: .7; white-space: nowrap; overflow: hidden; text-overflow: clip }
.pspan.place  { color: #1d7a5f }
.pspan.year   { color: #8a5a00 }
.pspan.vocals { color: #7a2f6a }
.pspan.label  { color: #333 }
.pspan.sound  { color: var(--ink2) }
/* the pale set is for a DARK panel only. tones.js sets data-ink from the same
   luminance test that picks --ink; this used to key off [data-theme], which
   nothing sets, so it applied always and the dark set above never painted. */
:root[data-ink="light"] .pspan.place  { color: #6fe0b8 }
:root[data-ink="light"] .pspan.year   { color: #f0c069 }
:root[data-ink="light"] .pspan.vocals { color: #e9a6db }
/* the parts search learned after the braces were built: a name, an era word
   ("early kendrick"), lyrics, the & / | between two searches, and words after
   "not"/"without" that the sound model is never given */
.pspan.name    { color: #2b4d9c }
.pspan.era     { color: #9a3412 }
.pspan.lyrics  { color: #6d28d9 }
.pspan.op      { color: var(--ink) }
.pspan.ignored { color: var(--ink3) }
:root[data-ink="light"] .pspan.name    { color: #a8c0ff }
:root[data-ink="light"] .pspan.era     { color: #fdba74 }
:root[data-ink="light"] .pspan.lyrics  { color: #c4b5fd }
/* a label may be wider than the word it sits under ("and" under "&"); it was
   clipped to the brace width and read "AN". It may run past its own brace now
   (draw() caps it at the next brace's edge), a touch smaller for the operator. */
.pspan b { overflow: hidden; text-overflow: ellipsis }
.pspan.op b { font-size: 10px; letter-spacing: 0 }

/* an offscreen copy of the input used only to measure where characters fall */
.parsemirror { position: absolute; visibility: hidden; white-space: pre; top: -9999px; left: -9999px }

/* the labels need room, and the label chips below must not sit on top of them */
.search { margin-bottom: 40px }   /* 11px labels (were 9.5) need the room, his ask */
@media (max-width: 560px) { .parsebar { display: none } }

/* the operators read as operators, not as footnotes */

/* ONE ROW UNDER THE BAR: the toggle, & and |, the obscure checkbox */
.howbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 14px 0 0 }
.howbar .soundonly { margin: 0 }
.howtoggle { display: inline-flex; align-items: center; gap: 8px; font: 700 13.5px/1 var(--font); color: var(--ink); background: var(--a1);
  border: 0; border-radius: var(--ri); padding: 12px 14px; cursor: pointer; min-height: 42px }
.howtoggle:hover { filter: brightness(1.07) } .howtoggle:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--ink) }
.howtoggle::after { content: ""; width: 7px; height: 7px; border: solid var(--ink); border-width: 0 2px 2px 0; transform: translateY(-2px) rotate(45deg); transition: transform .15s }
.howtoggle[aria-expanded="false"]::after { transform: rotate(-45deg) }
/* OPEN, THE TOGGLE IS A TAB OF THE BOX: one shape, like his quickshell popups
   opening out of the bar, so it is obvious which button the box belongs to.
   Square bottom on the tab, square top-left on the box, and a concave fillet
   (a quarter circle cut out of a --ri square) where the tab meets the box's top
   edge. The tab is 8 px taller than its neighbours and the row aligns to the
   bottom, so it touches the box while the others keep an 8 px gap above it. */
.howtoggle { position: relative }
/* THE TAB MUST BE BOTTOM-LEFT AT EVERY WIDTH, and where the row wraps depends on
   the visitor's font, so no breakpoint can say when. wrap-reverse stacks the
   lines UPWARD: the first line, which starts with the toggle, is always the one
   touching the box, and whatever does not fit goes above it. (The first try
   moved the toggle last below 700 px, which put the tab mid-edge at 700, where
   nothing wraps.) Under wrap-reverse the cross axis flips, so flex-start is the
   bottom of a line. */
.howbar { flex-wrap: wrap-reverse }
.howbar:has(.howtoggle[aria-expanded="true"]) { align-items: flex-start }
.howbar:has(.howtoggle[aria-expanded="true"]) > :not(.howtoggle) { margin-bottom: 8px }
.howtoggle[aria-expanded="true"] { border-radius: var(--ri) var(--ri) 0 0; padding-bottom: 20px; min-height: 50px; filter: none }
.howtoggle[aria-expanded="true"]::before { content: ""; position: absolute; left: 100%; bottom: 0; width: var(--ri); height: var(--ri); pointer-events: none;
  background: radial-gradient(circle at 100% 0, transparent calc(var(--ri) - .5px), var(--a1) var(--ri)) }
.howbar:has(.howtoggle[aria-expanded="true"]) + .howto { margin-top: 0; border-top-left-radius: 0 }
/* the & | buttons are gone (his call): the box's examples teach them, and the
   row is one toggle plus one checkbox now */
/* THE BOX: open on arrival, closed after a search. Two columns where there is
   room, so the right half of the panel is used instead of left empty. */
.howto { margin: 8px 0 0; padding: 14px 18px 16px; background: var(--a1); border-radius: var(--ri);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 32px }
.howto[hidden] { display: none }
.howto h3 { font-size: 11px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ink2); margin: 0 0 6px }
.howto dl { display: grid; grid-template-columns: max-content 1fr; gap: 5px 12px; align-items: baseline; margin: 0; font-size: 13.5px; line-height: 1.35 }
.howto dt, .howto dd { margin: 0 }
.howto code { font-family: var(--font); font-weight: 700; font-size: 13px; background: rgb(21 21 26 / .10); border-radius: 5px; padding: 1px 6px; white-space: nowrap }
@media (max-width: 760px) { .howto { grid-template-columns: 1fr } }
@media (max-width: 440px) { .howto dl { grid-template-columns: 1fr; gap: 0 } .howto dd { margin-bottom: 6px } }

/* DOC PAGES: search.html, legal.html (privacy), scale.html. Here and not in a
   file of their own because sync.sh only version-stamps the file names it lists,
   and an unstamped stylesheet gets pinned at Cloudflare's edge. One narrow
   column; every entry a row: the thing on the left, a few words on the right. */
main.doc { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; grid-template-areas: "top" "res"; max-width: 860px; margin: 0 auto }
main.doc .top nav { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto }
main.doc .top nav .blk { min-height: 40px; font-weight: 700; font-size: 14px }
.docbody { grid-area: res; align-self: start; padding: 22px 24px 28px }
.docbody h1 { font-size: clamp(30px, 3.6vw, 44px); margin: 0 0 6px }
.docbody .lead { font-size: 16px; margin: 0 }
.docbody h2 { font-size: 12px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ink2); margin: 26px 0 8px }
.docbody .rows { display: grid; gap: 6px }
.docbody .rows > div { display: grid; grid-template-columns: 15rem 1fr; gap: 16px; align-items: baseline; background: var(--a1); border-radius: var(--ri); padding: 10px 14px; font-size: 14.5px; line-height: 1.45 }
.docbody .rows > div > span { color: var(--ink) }
.docbody .rows > div > :first-child { justify-self: start }   /* a chip hugs its text instead of filling the column */
.docbody .rows .ex { display: flex; flex-wrap: wrap; gap: 6px }  /* two examples on one row stay in the left column */
.docbody .lead + .rows { margin-top: 18px }
.docbody code { font-family: var(--font); font-weight: 700; font-size: 14px; background: rgb(21 21 26 / .10); border-radius: 5px; padding: 1px 6px; white-space: nowrap }
.docbody .note { font-size: 14.5px; margin: 0 } .docbody .mute { color: var(--ink2); font-size: 12.5px; margin-top: 22px }
@media (max-width: 620px) { .docbody .rows > div { grid-template-columns: 1fr; gap: 2px } main.doc .top nav { margin-left: 0 } }

/* instruments, from the music tagger — a different measurement from the
   AudioSet sounds beside them, so a different tone rather than one pile */
.chip.ins { background: var(--a); color: var(--ink) }
