/* HARZ store: dark 2000s glass. Smoked black glass panels with a soft top-half shine, glassy black buttons,
   faint cool reflections. Layout of a mid-2000s music app: toolbar, LCD now-playing, striped list, status bar.
   Kept dark so the background visualizer glows through. */
/* Michroma (SIL OFL 1.1, fonts/LICENSE-michroma.txt), served from the store itself: no wait on another server. */
@font-face { font-family: "Michroma"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(/fonts/michroma-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Michroma"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(/fonts/michroma-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
:root {
  --bg: #000;
  --text: #e8eef2;
  --muted: #b7c0c7; /* brighter grey text (BPM, key, artist, search hint): #8b949b read too dim on phones */
  --edge: rgba(255, 255, 255, .14);          /* glass edge highlight */
  --edge-dark: #000;
  --cool: rgba(170, 215, 255, .10);          /* faint cool reflection */
  --shine: linear-gradient(180deg, rgba(255,255,255,.16) 0%, rgba(255,255,255,.05) 49%, rgba(255,255,255,0) 50%);
  --glass: linear-gradient(180deg, rgba(40,44,48,.85), rgba(10,11,12,.92));
  --ui: "Segoe UI", Tahoma, Verdana, system-ui, sans-serif;
  --mono: "Lucida Console", Consolas, monospace;
  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { background: var(--bg); }
/* Dark backdrop with the visualizer off: dusky plum and amber glows under a light film grain, fixed so it stays put while scrolling. Static, no motion. */
html:not([data-mode="light"]), html:not([data-mode="light"]) body {
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .05 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(70% 60% at 20% 10%, rgba(92, 74, 110, .42), transparent 70%),
    radial-gradient(60% 50% at 85% 80%, rgba(120, 84, 60, .3), transparent 70%),
    #060508;
  background-attachment: fixed;
}
body { margin: 0; color: var(--text); font: 12px/1.4 var(--ui); padding: 0 0 48px; min-height: 100vh; min-height: 100dvh; position: relative; -webkit-font-smoothing: antialiased; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; height: auto; display: block; }
button { font: inherit; color: inherit; cursor: pointer; background: none; border: none; }
:focus-visible { outline: 1px dotted #fff; outline-offset: 2px; }
.muted { color: var(--muted); }

/* ---------- background visualizer: quick fade in, slow fade out ---------- */
#viz { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; opacity: 0;
       transition: opacity 1.2s ease-out; } /* shown exactly as drawn: no filters or blending over it */
/* Dark mode shows it at full strength all the time (no dimming); immersive mode only hides the UI. */
#viz.on { opacity: .9; transition: opacity .25s ease-in; }
/* A style that has just been switched to fades in (from the black the old one leaves) instead of cutting in. */
@starting-style { #viz.on { opacity: 0; } }
/* The two styles handing over (viz-switch.js): the canvas on top fades quickly; the one underneath snaps to full
   strength (hidden by the one above), so the picture never dips. AVS's preset-change still only shows with AVS. */
html.viz-blend #viz, html.viz-blend #viz.on { transition: opacity .4s ease-in-out; }
html.viz-blend #viz.snap { transition: none; }
/* Immersive: after 30 s of playback with no input, the UI fades away and the visualizer takes the screen.
   Light mode keeps its look exactly; only the menus fade. */
.toolbar, .window, .statusbar, .page, .top, .sitefoot { transition: opacity .4s ease; }
/* At 30 s everything fades but the bottom player bar (.toolbar), which never fades. */
html.immersive :is(.window, .statusbar, .page, .top, .drawer:not(.open), .sitefoot) { opacity: 0; pointer-events: none; transition: opacity 1.8s ease; } /* an open cart never fades: opened from the player while the rest has faded, it would be an invisible sheet under the dimmed screen */
/* Every element: buttons, links and rows set their own pointer cursor, which would otherwise stay visible. */
html.immersive, html.immersive body, html.immersive * { cursor: none !important; }
.toolbar, .window, .statusbar, .page, .top { position: relative; z-index: 1; }
/* Overall UI scale: everything (type, rows, buttons, LCD) grows together. The visualizer canvas is not scaled. */
.toolbar, .window, .statusbar, .drawer, .page, .top { zoom: 1.25; }
.window { max-width: 1040px; }
body { padding-bottom: 48px; }

/* Shared smoked-glass button */
.glassbtn, .tbtn, .lcd-buy, .cart-btn, .play, .price-btn, .add, .checkout, .btn, .files a, .mode-btn {
  color: #f2f6f8; border: 1px solid #000; text-shadow: 0 -1px 0 rgba(0,0,0,.7);
  background: var(--shine), linear-gradient(180deg, #3a3f44 0%, #16181a 100%);
  box-shadow: inset 0 1px 0 var(--edge), inset 0 0 0 1px rgba(255,255,255,.03), 0 1px 2px rgba(0,0,0,.8);
  transition: box-shadow .15s, background .15s, transform .18s cubic-bezier(.3, 1.6, .5, 1);
  position: relative; transform: translateZ(0); -webkit-tap-highlight-color: transparent; user-select: none;
}
/* Tactile press: buttons sink into the panel, then spring back with a quick glass flash. */
.glassbtn:active, .tbtn:active, .lcd-buy:active, .cart-btn:active, .play:active, .price-btn:active, .add:active,
.checkout:active, .btn:active, .files a:active, .mode-btn:active {
  transform: translateY(1px) scale(.93); transition-duration: .05s;
}
.pop::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  animation: press-flash .45s ease-out forwards;
}
@keyframes press-flash {
  0%   { box-shadow: 0 0 0 0 rgba(190, 230, 255, .55), inset 0 0 12px rgba(255, 255, 255, .35); }
  100% { box-shadow: 0 0 0 9px rgba(190, 230, 255, 0), inset 0 0 0 rgba(255, 255, 255, 0); }
}
html[data-mode="light"] .pop::after { animation-name: press-flash-light; }
@keyframes press-flash-light {
  0%   { box-shadow: 0 0 0 0 rgba(60, 120, 170, .45), inset 0 0 10px rgba(255, 255, 255, .9); }
  100% { box-shadow: 0 0 0 9px rgba(60, 120, 170, 0), inset 0 0 0 rgba(255, 255, 255, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .pop::after { animation: none; }
  .glassbtn:active, .tbtn:active, .lcd-buy:active, .cart-btn:active, .play:active, .price-btn:active, .add:active,
  .checkout:active, .btn:active, .files a:active, .mode-btn:active { transform: none; }
}
.tbtn:hover, .lcd-buy:hover, .cart-btn:hover, .play:hover, .price-btn:hover, .add:hover, .checkout:hover, .btn:hover, .files a:hover {
  background: var(--shine), linear-gradient(180deg, #4b5157 0%, #1d2023 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 0 10px var(--cool), 0 1px 2px rgba(0,0,0,.8);
}
.tbtn:active, .add:active, .checkout:active { background: linear-gradient(180deg, #121416, #2c3034); box-shadow: inset 0 1px 3px rgba(0,0,0,.8); }

/* ---------- toolbar ---------- */
.toolbar {
  position: sticky; top: 0; z-index: 10;
  display: grid; grid-template-columns: minmax(max-content, 1fr) minmax(0, 760px) minmax(max-content, 1fr); gap: 16px; /* the now-playing display as long as the room allows, up to 760px */ align-items: center; padding: 8px 14px;
  background: var(--shine), linear-gradient(180deg, rgba(34,37,40,.92), rgba(6,7,8,.96));
  backdrop-filter: blur(10px);
  border-bottom: 1px solid #000; box-shadow: inset 0 1px 0 var(--edge), 0 1px 0 rgba(255,255,255,.05), 0 6px 20px rgba(0,0,0,.6);
}
.transport { display: flex; align-items: center; gap: 6px; }
.tbtn { width: 30px; height: 30px; border-radius: 50%; font-size: 11px; }
#p-shuffle { font-size: 13px; opacity: .55; }
#p-shuffle.on { opacity: 1; box-shadow: inset 0 1px 0 var(--edge), 0 0 10px var(--cool), 0 0 0 1px rgba(160,220,255,.35); }
.tbtn.big { width: 38px; height: 38px; font-size: 13px; box-shadow: inset 0 1px 0 var(--edge), 0 0 12px var(--cool), 0 1px 2px rgba(0,0,0,.8); }

/* LCD now-playing display: dark glass screen */
.lcd {
  display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; gap: 10px; align-items: center;
  width: 100%; justify-self: center; padding: 5px 10px 5px 6px; border-radius: 7px;
  background: linear-gradient(180deg, rgba(255,255,255,.06) 0%, rgba(255,255,255,0) 45%), linear-gradient(180deg, #0c0e10, #050607);
  border: 1px solid #000; box-shadow: inset 0 1px 4px rgba(0,0,0,.9), 0 1px 0 rgba(255,255,255,.08);
}
.lcd img { width: 40px; height: 40px; object-fit: cover; border: 1px solid #000; box-shadow: 0 0 0 1px rgba(255,255,255,.08); }
.lcd img:not([src]), .lcd img[src=""] { visibility: hidden; }
.lcd-text { min-width: 0; text-align: center; }
.lcd-title { display: block; font-weight: 700; color: #f4f8fa; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-shadow: 0 0 8px rgba(190,225,255,.25); }
.lcd-title[href]:hover { text-decoration: underline; }
.lcd-sub { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lcd-row { display: grid; grid-template-columns: auto 1fr auto; gap: 6px; align-items: center; font: 10px var(--mono); color: #7f8a92; margin-top: 2px; }
.lcd .bar { height: 6px; border-radius: 3px; border: 1px solid #000; background: #15181a; cursor: pointer; position: relative; box-shadow: inset 0 1px 2px rgba(0,0,0,.8), 0 1px 0 rgba(255,255,255,.06); }
.lcd .fill { position: absolute; inset: 0 auto 0 0; width: 0; border-radius: 3px; background: var(--shine), linear-gradient(90deg, #8f9aa3, #dfe7ec); box-shadow: 0 0 6px rgba(200,230,255,.35); }
.lcd-buy { font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 4px; }

.right { display: flex; align-items: center; gap: 14px; }
.wordmark { font-family: "Michroma", var(--ui); font-size: 14px; letter-spacing: .28em; text-transform: uppercase; color: #f2f6f8; text-shadow: 0 0 10px rgba(190,225,255,.2); }
.cart-btn { font-size: 11px; padding: 4px 12px; border-radius: 12px; }
.cart-btn b { color: #fff; }
@media (max-width: 760px) {
  .toolbar { grid-template-columns: auto 1fr; }
  .lcd { grid-column: 1 / -1; order: 3; max-width: none; }
  .toolbar .wordmark { display: none; } /* the thanks, legal and payee pages keep theirs: their only way back */
}

/* Mid-size windows: not enough room for a long display between the transport and the right-hand buttons, so it
   takes its own full-width row under them instead of being squeezed. */
@media (min-width: 761px) and (max-width: 1100px) {
  .toolbar { grid-template-columns: auto 1fr auto; row-gap: 8px; }
  .toolbar .right { grid-column: 3; justify-self: end; }
  .toolbar .lcd { grid-column: 1 / -1; grid-row: 2; max-width: 760px; }
}

/* volume slider: dark glass */
.vol { display: flex; align-items: center; margin-left: 6px; }
.vol input {
  -webkit-appearance: none; appearance: none; width: 80px; height: 6px; border-radius: 3px; cursor: pointer;
  background: linear-gradient(90deg, #c9d3da 0, #7f8a92 var(--fill, 80%), #0d0f10 var(--fill, 80%));
  border: 1px solid #000; box-shadow: inset 0 1px 2px rgba(0,0,0,.7), 0 1px 0 rgba(255,255,255,.07);
}
.vol input::-webkit-slider-thumb {
  -webkit-appearance: none; width: 13px; height: 13px; border-radius: 50%;
  background: radial-gradient(circle at 40% 30%, #ffffff 0 18%, #b7c2ca 40%, #4a5258 100%);
  border: 1px solid #000; box-shadow: 0 0 6px rgba(200,230,255,.35), 0 1px 1px rgba(0,0,0,.7);
}
.vol input::-moz-range-thumb { width: 13px; height: 13px; border-radius: 50%; background: radial-gradient(circle at 40% 30%, #fff 0 18%, #b7c2ca 40%, #4a5258 100%); border: 1px solid #000; }
@media (max-width: 760px) { .vol { display: none; } }

/* ---------- main window: striped glass track list ---------- */
.window { max-width: 980px; margin: 14px auto 0; padding: 0 14px; }
.filterbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.search {
  width: 230px; padding: 5px 10px 5px 26px; border-radius: 13px; font: 12px var(--ui); color: var(--text);
  background: #0b0d0e url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12'><circle cx='5' cy='5' r='3.6' fill='none' stroke='%238b949b' stroke-width='1.4'/><path d='M7.8 7.8 11 11' stroke='%238b949b' stroke-width='1.4'/></svg>") 9px 50% no-repeat;
  border: 1px solid #000; box-shadow: inset 0 1px 3px rgba(0,0,0,.9), 0 1px 0 rgba(255,255,255,.07);
}
.search:focus { outline: none; box-shadow: inset 0 1px 3px rgba(0,0,0,.9), 0 0 0 1px rgba(200,230,255,.25), 0 0 10px var(--cool); }
.count { color: var(--muted); font-size: 11px; }
.filterbar > .search { width: auto; flex: 1 1 auto; min-width: 0; } /* the search fills the bar, the tabs and buttons sit at its end */
/* Two-line rows (wider screens; phones keep their own layout): a bigger disc, the name with "140 BPM · A minor"
   underneath, the price at the end; no column header. BPM sits in its own auto-width column with the key straight after
   it, so the gap between them is the same on every row. */
@media (min-width: 761px) {
  html.store .window .thead { display: none; }
  html.store .window .row { grid-template-columns: 30px 44px auto minmax(0, 1fr) auto auto; grid-template-rows: auto auto;
    height: auto; min-height: 58px; padding: 7px 10px; column-gap: 12px; row-gap: 1px; }
  html.store .window .row > :is(.play, img, .price-btn, .more) { grid-row: 1 / 3; }
  html.store .window .row > img { width: 44px; height: 44px; }
  html.store .window .row > .t-wrap { grid-column: 3 / 5; grid-row: 1; align-self: end; min-width: 0; }
  html.store .window .row .t { font-size: 13.5px; }
  html.store .window .row > :is(.num, .key) { grid-row: 2; align-self: start; font-size: 11px; color: var(--muted); text-align: left; }
  html.store .window .row > .num { grid-column: 3; }
  html.store .window .row > .num:not(:empty)::after { content: " BPM"; }
  html.store .window .row > .key { grid-column: 4; margin-left: -12px; } /* cancels the column gap: the dot's own spaces set it */
  html.store .window .row > .num:not(:empty) + .key:not(:empty)::before { content: "\00a0· "; }
  html.store .window .row > .price-btn { grid-column: 5; }
  html.store .window .row > .more { grid-column: 6; }
}

.table { border: 1px solid #000; border-radius: 6px; overflow: hidden; box-shadow: 0 0 0 1px rgba(255,255,255,.06), 0 10px 30px rgba(0,0,0,.6); }
.thead, .row { display: grid; grid-template-columns: 30px 32px minmax(0, 1fr) 56px 90px 76px; gap: 8px; align-items: center; padding: 0 8px; }
.thead { height: 22px; font-size: 11px; color: #c3cbd1; background: var(--shine), linear-gradient(180deg, #2c3034, #111315); border-bottom: 1px solid #000; }
.thead span + span { border-left: 1px solid #000; padding-left: 6px; box-shadow: inset 1px 0 0 rgba(255,255,255,.06); }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.list { list-style: none; margin: 0; padding: 0; }
.row { height: 34px; cursor: pointer; background: rgba(10,11,12,.28); border-bottom: 1px solid rgba(255,255,255,.04); }
.row.alt { background: rgba(20,22,24,.36); }
.row.playing {
  background: var(--shine), linear-gradient(180deg, rgba(70,78,86,.95), rgba(28,31,34,.95));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), inset 0 0 18px var(--cool);
}
.row .idx, .thead span:nth-child(2) { display: none; } /* no track numbers or "#" column */
.row .idx { color: #5f686f; text-align: right; font-variant-numeric: tabular-nums; }
.row.playing .idx { color: #dfe7ec; }
.row img { width: 28px; height: 28px; object-fit: cover; border: 1px solid #000; box-shadow: 0 0 0 1px rgba(255,255,255,.06); }
.row .t { font-weight: 600; user-select: none; -webkit-user-select: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row .t:hover { text-decoration: underline; }
.row.playing .t { color: #fff; text-shadow: 0 0 8px rgba(200,230,255,.35); }
.row .key { color: var(--muted); }
.play { width: 20px; height: 20px; border-radius: 50%; font-size: 8px; }
/* List rows' buttons aren't a compositor layer each (the shared glass button's translateZ): scrolling the list stays cheap. */
.row .play:not(:active), .row .price-btn:not(:active) { transform: none; }
.row.playing .play { box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 0 8px rgba(200,230,255,.4); }
.price-btn { justify-self: end; font-weight: 700; padding: 2px 9px; border-radius: 10px; }
.empty { padding: 18px; color: var(--muted); background: rgba(10,11,12,.55); }
@media (max-width: 600px) {
  /* Phones: the name gets the room (BPM, key and the number are on the beat or loop page and in the player). */
  .thead, .row { grid-template-columns: 26px 28px minmax(0, 1fr) 54px; }
  /* Names in full: a long one wraps onto a second line (the row grows) instead of being cut short; the price button
     is a compact pill so the name gets the room. */
  .row .t { white-space: normal; overflow: visible; overflow-wrap: anywhere; line-height: 1.25; }
  .list .row { height: auto; min-height: 40px; padding-block: 4px; }
  .row .price-btn { padding: 3px 7px; font-size: 10px; border-radius: 9px; }
  .thead span:nth-child(2), .row .idx, .thead span:nth-child(5), .row > .num, .thead span:nth-child(6), .row .key { display: none; }
}

/* ---------- beat page ---------- */
.beat { display: grid; grid-template-columns: minmax(0, 360px) minmax(0, 1fr); gap: 28px; padding-top: 10px; padding-bottom: 40px; align-items: start; }
@media (max-width: 700px) { .beat { grid-template-columns: 1fr; } }
.beat .art img { width: 100%; border: 1px solid #000; box-shadow: 0 0 0 1px rgba(255,255,255,.08), 0 12px 34px rgba(0,0,0,.7);
                 -webkit-box-reflect: below 2px linear-gradient(transparent 70%, rgba(255,255,255,.14)); }
.back { display: inline-flex; align-items: center; gap: 2px; font-size: 12px; font-weight: 600; padding: 6px 14px; margin-bottom: 12px; }
.back:hover { color: #fff; text-decoration: none; }
/* The back arrow is a drawn shape centred with the label (the text triangle sat low and off-centre). */
.back { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.back-ic { width: .9em; height: .9em; vertical-align: 0; flex: none; }
.beat h1 { font: 700 30px/1.1 var(--ui); margin: 0 0 4px; letter-spacing: -.01em; text-shadow: 0 0 14px rgba(200,230,255,.15); }
.sub { color: var(--muted); margin-bottom: 14px; }
.beat .coprod { color: var(--muted); font-size: 12px; letter-spacing: .06em; margin: 2px 0 8px; }
.beat .tbtn.big { margin-bottom: 16px; }
.tiers { border: 1px solid #000; border-radius: 6px; overflow: hidden; box-shadow: 0 0 0 1px rgba(255,255,255,.06); }
.tier { display: flex; justify-content: space-between; align-items: center; gap: 14px; padding: 9px 10px; background: rgba(10,11,12,.88); }
.tier:nth-child(even) { background: rgba(20,22,24,.88); }
.tier .name { font-weight: 700; }
.tier .terms { color: var(--muted); font-size: 11px; margin-top: 2px; }
/* The phone's Now Playing details: a licence's Add is a shopping cart there (phone.js). */
.tier .add.cart-add { display: inline-flex; align-items: center; justify-content: center; }
.tier .add.cart-add .ic { width: 20px; height: 20px; vertical-align: 0; }
.add, .checkout, .btn, .files a { font-size: 11px; font-weight: 700; padding: 5px 13px; border-radius: 12px; white-space: nowrap; }
.add.ghost { color: var(--muted); }
.note { color: var(--muted); font-size: 11px; margin-top: 10px; }

/* ---------- cart drawer ---------- */
.drawer {
  position: fixed; inset: 0 0 0 auto; width: min(360px, 80vw); z-index: 20; /* 80vw x zoom 1.25 = full phone width */ display: flex; flex-direction: column;
  background: var(--shine), linear-gradient(180deg, rgba(30,33,36,.97), rgba(6,7,8,.98)); border-left: 1px solid #000;
  box-shadow: inset 1px 0 0 rgba(255,255,255,.08), -10px 0 30px rgba(0,0,0,.75); transform: translateX(100%);
  visibility: hidden; transition: transform .2s ease, visibility 0s .2s; /* closed: no shadow peeking in at the edge */
}
.drawer.open { transform: none; visibility: visible; transition: transform .2s ease; }
.drawer header { display: flex; justify-content: space-between; align-items: center; padding: 10px 12px; border-bottom: 1px solid #000; box-shadow: 0 1px 0 rgba(255,255,255,.06); }
.drawer .items { flex: 1; overflow: auto; }
.drawer .items > p { padding: 0 12px; }
.drawer .line { display: flex; justify-content: space-between; gap: 10px; padding: 8px 12px; border-bottom: 1px solid rgba(255,255,255,.04); }
.drawer .line { align-items: center; }
.drawer .line-cover { width: 40px; height: 40px; flex: none; border-radius: 50%; object-fit: cover; }
.drawer .line-title { flex: 1; min-width: 0; }
.drawer .line-link { color: inherit; text-decoration: none; }
.drawer .line-link:hover, .drawer .line-link:focus-visible { text-decoration: underline; }
.drawer .line:nth-child(even) { background: rgba(255,255,255,.025); }
.drawer .free { font-weight: 700; color: #fff; }
.drawer footer { padding: 12px; border-top: 1px solid #000; box-shadow: inset 0 1px 0 rgba(255,255,255,.06); }
.drawer footer p { margin: 0 0 10px; }
.checkout { width: 100%; padding: 8px; font-size: 12px; }
.pay-or { display: none; align-items: center; gap: 8px; margin: 8px 0; font-size: 11px; color: #6f787f; }
:is(html.paypal, html.applepay) .pay-or { display: flex; } /* only with a second way to pay (PayPal set up, or Apple Pay on this device: app.js) */
.pay-or::before, .pay-or::after { content: ""; flex: 1; border-top: 1px solid rgba(255,255,255,.12); }
html[data-mode="light"] .pay-or::before, html[data-mode="light"] .pay-or::after { border-color: #c3cbd1; }
.checkout.paypal, html[data-mode="light"] .checkout.paypal { color: #111; border-color: #c99a1c; background: var(--shine), linear-gradient(180deg, #ffd35c 0%, #f5b82a 100%); }
.checkout.paypal:hover, html[data-mode="light"] .checkout.paypal:hover { background: var(--shine), linear-gradient(180deg, #ffdc78 0%, #f7c241 100%); }
.checkout.paypal:active, html[data-mode="light"] .checkout.paypal:active { background: linear-gradient(180deg, #e0a51c, #f5b82a); box-shadow: inset 0 1px 3px rgba(0,0,0,.35); }
.checkout.paypal .pp-logo { font: italic 800 15px/1 Verdana, Arial, sans-serif; letter-spacing: -.03em; }
.checkout.paypal .pp-logo i:first-child { color: #003087; }
.checkout.paypal .pp-logo i:last-child { color: #009cde; }
.drawer footer .checkout-note { margin: 8px 0 2px; font-size: 12px; line-height: 1.4; color: #ffb4b4; text-align: center; } /* why checkout didn't open (app.js) */
html[data-mode="light"] .drawer footer .checkout-note { color: #a12a2a; }
.checkout-note[hidden], .checkout.paypal[hidden], .checkout.applepay[hidden] { display: none; }
html:not(.paypal) .pay-banner .pp-card { display: none; } /* the PayPal badge only once the store takes PayPal (app.js) */
@media (min-width: 761px) { .drawer .m-grab { display: none; } } /* the drag handle is for the phones' bottom sheet only */
.x { color: var(--muted); font-size: 18px; }
.drawer .x { min-width: 36px; min-height: 36px; } /* a fingertip, not a hairline */

/* ---------- status bar ---------- */
.statusbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 10; height: 24px; display: flex; justify-content: center; gap: 22px; align-items: center;
  font-size: 11px; color: #a9b2b8; background: var(--shine), linear-gradient(180deg, rgba(30,33,36,.95), rgba(6,7,8,.98));
  border-top: 1px solid #000; box-shadow: inset 0 1px 0 rgba(255,255,255,.08);
}
.statusbar a:hover { color: #fff; }
@media (max-width: 600px) { .statusbar span:first-child { display: none; } }

/* ---------- thanks page ---------- */
.top { display: flex; padding: 10px 14px; background: var(--shine), linear-gradient(180deg, rgba(34,37,40,.92), rgba(6,7,8,.96)); border-bottom: 1px solid #000; }
.page { max-width: 680px; margin: 0 auto; padding: 28px 16px 60px; }
.page h1 { font: 700 26px var(--ui); }
.files a { display: inline-block; margin: 6px 8px 0 0; }
.license { margin-top: 14px; padding: 18px 22px; border-radius: 12px; line-height: 1.55; color: var(--text);
  background: var(--shine), var(--glass); border: 1px solid #000; box-shadow: inset 0 1px 0 var(--edge), 0 6px 20px rgba(0,0,0,.6); }
.license h3 { margin: 0 0 10px; font-size: 15px; }
.license b { color: #e4eaee; }
.license .btn { margin-top: 4px; }
html[data-mode="light"] .license { background: var(--shine), linear-gradient(180deg, #ffffff, #dfe5e9); border-color: #9aa4ac; box-shadow: inset 0 1px 0 #fff; }
html[data-mode="light"] .license b { color: #1b2126; }

@media print { body * { visibility: hidden; } .license, .license * { visibility: visible; } .license { position: absolute; inset: 0; background: #fff; color: #111; border: 0; box-shadow: none; } .license b { color: #111; } .license .btn { display: none; } }

/* ================= Light mode (2000s glass, bright) ================= */
html[data-mode="light"] {
  --bg: #e9eef2;
  --text: #1b2126;
  --muted: #5d6871;
  --edge: rgba(255, 255, 255, .95);
  --cool: rgba(120, 170, 210, .25);
  --shine: linear-gradient(180deg, rgba(255,255,255,.9) 0%, rgba(255,255,255,.35) 49%, rgba(255,255,255,0) 50%);
  color-scheme: light;
}
html[data-mode="light"], html[data-mode="light"] body { background: radial-gradient(1200px 600px at 50% -10%, #ffffff, #e9eef2 55%, #d6dde3); background-attachment: fixed; }

/* Light mode: the visualizers are drawn on black, so the pictures are inverted (hues kept) to sit on a light background. */
html[data-mode="light"] :is(#viz, #viz-egg) { filter: invert(1) hue-rotate(180deg); }

html[data-mode="light"] .glassbtn, html[data-mode="light"] .tbtn, html[data-mode="light"] .lcd-buy, html[data-mode="light"] .cart-btn,
html[data-mode="light"] .play, html[data-mode="light"] .price-btn, html[data-mode="light"] .add, html[data-mode="light"] .checkout,
html[data-mode="light"] .btn, html[data-mode="light"] .files a, html[data-mode="light"] .mode-btn {
  color: #1d2328; text-shadow: 0 1px 0 rgba(255,255,255,.8); border-color: #8d979f;
  background: var(--shine), linear-gradient(180deg, #ffffff 0%, #d9e0e5 100%);
  box-shadow: inset 0 1px 0 #fff, 0 1px 2px rgba(60,80,95,.35);
}
html[data-mode="light"] .tbtn:hover, html[data-mode="light"] .lcd-buy:hover, html[data-mode="light"] .cart-btn:hover,
html[data-mode="light"] .play:hover, html[data-mode="light"] .price-btn:hover, html[data-mode="light"] .add:hover,
html[data-mode="light"] .checkout:hover, html[data-mode="light"] .btn:hover, html[data-mode="light"] .files a:hover, html[data-mode="light"] .mode-btn:hover {
  background: var(--shine), linear-gradient(180deg, #ffffff 0%, #e6ecf0 100%);
  box-shadow: inset 0 1px 0 #fff, 0 0 8px var(--cool), 0 1px 2px rgba(60,80,95,.35);
}

html[data-mode="light"] .toolbar, html[data-mode="light"] .statusbar, html[data-mode="light"] .top {
  background: var(--shine), linear-gradient(180deg, rgba(250,252,253,.95), rgba(214,222,228,.95));
  border-color: #a3adb5; box-shadow: inset 0 1px 0 #fff, 0 2px 12px rgba(60,80,95,.18); color: #2a3137;
}
html[data-mode="light"] .lcd {
  background: linear-gradient(180deg, rgba(255,255,255,.7) 0%, rgba(255,255,255,0) 45%), linear-gradient(180deg, #eef1e8, #d7dccf);
  border-color: #7d8790; box-shadow: inset 0 1px 3px rgba(0,0,0,.25), 0 1px 0 #fff;
}
html[data-mode="light"] .lcd-title { color: #1b2126; text-shadow: none; }
html[data-mode="light"] .lcd-row { color: #5b646b; }
html[data-mode="light"] .lcd .bar { background: #f7f8f5; border-color: #8b949b; box-shadow: inset 0 1px 2px rgba(0,0,0,.2); }
html[data-mode="light"] .lcd .fill { background: var(--shine), linear-gradient(90deg, #6f7a83, #3d464d); box-shadow: none; }
html[data-mode="light"] .wordmark { color: #20262b; text-shadow: 0 1px 0 #fff; }
html[data-mode="light"] .cart-btn b { color: #10161a; }
html[data-mode="light"] .vol input { background: linear-gradient(90deg, #6f7a83 0, #3d464d var(--fill, 80%), #f4f6f7 var(--fill, 80%)); border-color: #7d8790; }

html[data-mode="light"] .search { background-color: #fff; color: #1b2126; border-color: #8d979f; box-shadow: inset 0 1px 2px rgba(0,0,0,.18); }
html[data-mode="light"] .table, html[data-mode="light"] .tiers { border-color: #8d979f; box-shadow: 0 6px 20px rgba(60,80,95,.18); }
html[data-mode="light"] .thead { color: #2a3137; background: var(--shine), linear-gradient(180deg, #f7f9fa, #d3dadf); border-color: #9aa4ac; }
html[data-mode="light"] .thead span + span { border-left-color: #b4bdc4; box-shadow: inset 1px 0 0 #fff; }
html[data-mode="light"] .row, html[data-mode="light"] .tier, html[data-mode="light"] .empty { background: rgba(255,255,255,.6); border-bottom-color: rgba(0,0,0,.04); }
html[data-mode="light"] .row.alt, html[data-mode="light"] .tier:nth-child(even) { background: rgba(237,242,245,.65); }
html[data-mode="light"] .row.playing { background: var(--shine), linear-gradient(180deg, #c9d4dc, #9fadb8); box-shadow: inset 0 1px 0 #fff; }
html[data-mode="light"] .row.playing .t, html[data-mode="light"] .row.playing .idx { color: #10161a; text-shadow: 0 1px 0 rgba(255,255,255,.6); }
html[data-mode="light"] .row img, html[data-mode="light"] .lcd img { border-color: #7d8790; }
html[data-mode="light"] .drawer { background: var(--shine), linear-gradient(180deg, #f7f9fa, #dfe5e9); border-color: #9aa4ac; color: #1b2126; }
html[data-mode="light"] .drawer header, html[data-mode="light"] .drawer footer { border-color: #b4bdc4; box-shadow: none; }
html[data-mode="light"] .drawer .line { border-color: #d3dadf; }
html[data-mode="light"] .drawer .free { color: #10161a; }
html[data-mode="light"] .beat h1 { text-shadow: none; }
html[data-mode="light"] .beat .art img { box-shadow: 0 0 0 1px #9aa4ac, 0 12px 30px rgba(60,80,95,.3); }
/* Covers are cut-out circles (transparent around the dish): black behind them in dark mode, white in light. */
.row img, .lcd img, .beat .art img, #feature img { background-color: #000; background-size: cover; }
html[data-mode="light"] .row img, html[data-mode="light"] .lcd img, html[data-mode="light"] .beat .art img, html[data-mode="light"] #feature img { background-color: #fff; }

/* Light/dark switch button */
.mode-btn { width: 26px; height: 26px; border-radius: 50%; font-size: 13px; line-height: 1; padding: 0; }

/* Fallback note when a browser blocks new tabs from the HARZ logo */
.link-note { position: fixed; top: 70px; right: 16px; z-index: 30; padding: 8px 12px; border-radius: 8px; font-size: 12px;
  color: var(--text); background: var(--shine), var(--glass); border: 1px solid #000; box-shadow: inset 0 1px 0 var(--edge), 0 6px 20px rgba(0,0,0,.6);
  opacity: 0; transform: translateY(-6px); pointer-events: none; transition: opacity .2s, transform .2s; }
.link-note.show { opacity: 1; transform: none; pointer-events: auto; }
.link-note a { text-decoration: underline; }
html[data-mode="light"] .link-note { background: var(--shine), linear-gradient(180deg, #ffffff, #dfe5e9); border-color: #9aa4ac; }
.filter-right { display: flex; align-items: center; gap: 12px; }

/* "All beats": a physical key with real depth; it travels down into the panel when pressed. */
.cart-btn.back {
  padding: 8px 16px 7px; border-radius: 9px; letter-spacing: .04em; text-transform: uppercase; font-size: 11px;
  background: var(--shine), linear-gradient(180deg, #4a5056 0%, #24282b 55%, #1a1d1f 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), inset 0 -2px 0 rgba(0,0,0,.45),
    0 1px 0 #2b2f33, 0 2px 0 #1e2124, 0 3px 0 #141618, 0 4px 0 #0a0b0c, 0 6px 10px rgba(0,0,0,.7);
  transform: translateY(0); transition: transform .08s ease-out, box-shadow .08s ease-out;
}
.cart-btn.back:hover { background: var(--shine), linear-gradient(180deg, #575e64 0%, #2b3034 55%, #1f2225 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.32), inset 0 -2px 0 rgba(0,0,0,.45),
    0 1px 0 #2b2f33, 0 2px 0 #1e2124, 0 3px 0 #141618, 0 4px 0 #0a0b0c, 0 6px 12px rgba(0,0,0,.7), 0 0 12px var(--cool); }
.cart-btn.back:active { transform: translateY(3px);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.7), 0 1px 0 #0a0b0c, 0 2px 4px rgba(0,0,0,.6); }
html[data-mode="light"] .cart-btn.back {
  background: var(--shine), linear-gradient(180deg, #ffffff 0%, #dfe5ea 60%, #cdd5db 100%);
  box-shadow: inset 0 1px 0 #fff, inset 0 -2px 0 rgba(90,105,118,.25),
    0 1px 0 #b7c0c7, 0 2px 0 #a6b0b8, 0 3px 0 #96a1aa, 0 4px 0 #87929b, 0 6px 10px rgba(60,80,95,.35);
}
html[data-mode="light"] .cart-btn.back:active { box-shadow: inset 0 1px 3px rgba(60,80,95,.45), 0 1px 0 #87929b, 0 2px 4px rgba(60,80,95,.3); }

/* Cursor hides after a few seconds without movement (viz-switch.js) and comes back on the next move. */

/* Admin-only rename pencils (shown once /api/admin/me confirms the session). */
.edit { display: none; width: 18px; height: 18px; margin-left: 4px; padding: 0; border-radius: 4px; font-size: 11px; line-height: 18px;
  color: var(--muted); opacity: .6; vertical-align: middle; flex: none; }
html.admin .edit { display: inline-block; }
html.admin .edit[hidden] { display: none; }
.lcd-title-row { display: flex; justify-content: center; align-items: center; min-width: 0; }
.lcd-title-row .lcd-title { min-width: 0; }
.edit:hover { opacity: 1; color: var(--text); background: rgba(255,255,255,.08); }
.row .t-wrap { display: flex; align-items: center; min-width: 0; }
.rename { font: inherit; font-weight: 600; width: 100%; min-width: 0; padding: 1px 4px; border-radius: 4px;
  color: var(--text); background: rgba(0,0,0,.6); border: 1px solid rgba(200,230,255,.35); }
html[data-mode="light"] .rename { background: #fff; border-color: #8d979f; }
.row .t-wrap .t { min-width: 0; }

/* Visualizer switch (list page and beat pages), shown only while audio plays. It keeps its space so nothing shifts. */
:is(#p-vizstyle, #p-switchup) { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .25s ease, visibility 0s .25s; }
html.viz-live :is(#p-vizstyle, #p-switchup) { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .25s ease; }
html.viz-live :is(#p-vizstyle, #p-switchup)[aria-pressed="false"] { opacity: .4; } /* switched off */

/* ---------- Beats / loops toggle (the counter): one button, the whole list changes over ---------- */
.list-mode { display: inline-flex; padding: 0; overflow: hidden; white-space: nowrap; }
.list-mode span { padding: 4px 11px; opacity: .55; transition: opacity .15s, background .15s; }
.list-mode span + span { border-left: 1px solid rgba(0,0,0,.55); box-shadow: inset 1px 0 0 rgba(255,255,255,.06); }
.list-mode span.on { opacity: 1; background: rgba(255,255,255,.1); box-shadow: inset 0 0 10px var(--cool); }
html[data-mode="light"] .list-mode span.on { background: rgba(255,255,255,.7); }
html[data-mode="light"] .list-mode span + span { border-color: rgba(0,0,0,.18); box-shadow: none; }
/* Loops only: All / Solo / Collab, the same pill look with a real button per choice. */
.kind-switch[hidden] { display: none; }
/* The Beats / Loops switch stays put: counts keep their width as they change, the visualizer button keeps one
   width whatever its label, and the Solo / Collab pill opens to the left of the switch. */
#count b { display: inline-block; min-width: 4ch; text-align: left; font-variant-numeric: tabular-nums; }
:is(#p-vizstyle, #p-switchup) { min-width: 7.2em; text-align: center; }
.kind-switch button { padding: 4px 11px; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; opacity: .55; transition: opacity .15s, background .15s; }
.kind-switch button + button { border-left: 1px solid rgba(0,0,0,.55); box-shadow: inset 1px 0 0 rgba(255,255,255,.06); }
.kind-switch button.on { opacity: 1; background: rgba(255,255,255,.1); box-shadow: inset 0 0 10px var(--cool); }
html[data-mode="light"] .kind-switch button.on { background: rgba(255,255,255,.7); }
html[data-mode="light"] .kind-switch button + button { border-color: rgba(0,0,0,.18); box-shadow: none; }
.player-link { white-space: nowrap; }
@media (max-width: 600px) {
  .filterbar { flex-wrap: wrap; }
  .search { width: auto; flex: 1 1 120px; min-width: 0; }
  .filter-right { gap: 6px; }
}

/* Progress bar: a taller invisible hit area (easy to grab on touch screens) without changing how it looks;
   touch drags seek instead of scrolling the page. */
.lcd .bar { touch-action: none; }
.lcd .bar::before { content: ""; position: absolute; inset: -9px 0; }
.lcd .bar:focus-visible { outline: 1px solid rgba(200,230,255,.6); outline-offset: 2px; }
.lcd .bar.scrubbing .fill { transition: none; }

/* The list page starts flush under the toolbar, so the sticky bar sits in the same place scrolled or not. */
.window:has(.filterbar) { margin-top: 0; }
/* The search / beats-loops / visualizer bar stays reachable under the toolbar while the list scrolls. */
.filterbar { position: sticky; top: var(--sticky-top, 56px); z-index: 5; margin: 0 -14px 8px; padding: 6px 14px;
  background: linear-gradient(180deg, rgba(6,7,8,.82), rgba(6,7,8,.6)); backdrop-filter: blur(8px); }
html[data-mode="light"] .filterbar { background: linear-gradient(180deg, rgba(240,243,245,.85), rgba(240,243,245,.65)); }

/* Back to top: appears once the page is scrolled well down; bottom-right, placed between the Key and Price columns by app.js. */
.to-top { position: fixed; right: 16px; bottom: 16px; z-index: 15; zoom: 1.25; width: 30px; height: 30px; padding: 0; border-radius: 50%;
  font-size: 11px; opacity: 0; visibility: hidden; transform: translateY(6px); transition: opacity .25s, transform .25s, visibility 0s .25s; }
.to-top.show { opacity: 1; visibility: visible; transform: none; transition: opacity .25s, transform .25s; }
.to-top { display: inline-grid; place-items: center; touch-action: manipulation; }
.to-top svg.ic { width: 14px; height: 14px; vertical-align: 0; }
html.immersive .to-top { opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .to-top, .to-top.show { transition: none; transform: none; } }

/* Admin edit dialog */
.editor { width: min(400px, calc(100vw - 32px)); padding: 18px; border-radius: 10px; border: 1px solid #000; color: var(--text); zoom: 1.25;
  background: var(--shine), linear-gradient(180deg, #2a2e32, #121416); box-shadow: inset 0 1px 0 var(--edge), 0 10px 30px rgba(0,0,0,.6); }
.editor::backdrop { background: rgba(0,0,0,.55); }
.editor h2 { font-size: 14px; margin: 0 0 10px; }
.editor label { display: block; font-size: 11px; color: var(--muted); margin-bottom: 8px; }
.editor label.check { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text); cursor: pointer; }
.editor .search { display: block; width: 100%; margin-top: 3px; padding-left: 10px; background-image: none; }
.editor .pair { display: grid; grid-template-columns: 1fr 90px; gap: 10px; }
.editor .source { font-size: 11px; margin: -4px 0 10px; overflow-wrap: anywhere; user-select: all; }
.editor .shown-as { font-size: 11px; margin: 2px 0 6px; overflow-wrap: anywhere; }
.editor .msg { min-height: 1.2em; font-size: 12px; margin: 4px 0 10px; }
.editor .actions { display: flex; gap: 8px; align-items: center; }
.editor .grow { flex: 1; }
.admin-tools { display: inline-flex; flex: none; align-items: center; }
.edit.regen, .edit.star { margin-left: 1px; }
.edit.star { font-size: 12px; }
.edit.star.on { opacity: 1; color: var(--text); text-shadow: 0 0 6px rgba(190,225,255,.45); } /* starred: in the ☆ shelf (phone.js) */
html[data-mode="light"] .edit.star.on { text-shadow: none; }
.edit.listen { margin-left: 1px; font-size: 12px; }
.edit.listen.on { opacity: 1; color: var(--text); } /* listen only: not for sale */
.listen-tag { justify-self: end; font-size: 10px; color: var(--muted); padding: 2px 9px; white-space: nowrap; }
.btn.listen-tag { font-size: inherit; cursor: default; }
.listen-note { color: var(--muted); }
.edit.regen:disabled { opacity: 1; animation: regen-busy .8s linear infinite; }
@keyframes regen-busy { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) { .edit.regen:disabled { animation: none; } }
.editor .del { color: #ff9b9b; }
.editor .vibe-edit { border: 1px solid rgba(255,255,255,.12); border-radius: 8px; padding: 8px 10px 10px; margin: 2px 0 8px; }
.editor .vibe-edit legend { font-size: 11px; color: var(--muted); padding: 0 4px; }
.editor .vibe-edit select { width: 100%; margin: 0 0 8px; font: inherit; font-size: 12px; padding: 4px 6px; border-radius: 6px; }
.editor .slider { display: grid; grid-template-columns: 62px 1fr 62px; align-items: center; gap: 6px; margin: 0 0 4px; font-size: 10px; }
.editor .slider span:last-child { text-align: right; }
.editor .slider input { width: 100%; margin: 0; accent-color: var(--text); }
.editor .slider input:not([data-touched]) { opacity: .45; } /* not set: the analysis decides */
.editor .vibe-edit .btn { margin-top: 6px; font-size: 11px; }
html[data-mode="light"] .editor { background: var(--shine), linear-gradient(180deg, #ffffff, #dfe5e9); border-color: #9aa4ac; }
html[data-mode="light"] .editor .del { color: #b02020; }
.toast { top: auto; bottom: 60px; right: 16px; }

/* ---------- beat page: back key and visualizer switch side by side ---------- */
.beat-tools { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 12px; }
.beat-tools .back { margin-bottom: 0; }

/* ---------- light / dark: one cross-fade of the whole page (viz-core.js harzSwapTheme) ---------- */
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .25s; animation-timing-function: cubic-bezier(.2, 0, 0, 1); } /* quick and starting at once: the switch answers the click */
/* ---------- page to page (app.js navigate): the two pages cross-fade in one go, no gap between them ---------- */
/* Only <main> moves; the header, player and visualizer stay put. Both pages share one duration and curve, so their
   opacities always add up to one and the screen never dips. Phones slide sideways (forward: left; back: right). */
html.vt-page { --vt-x: -24px; --vt-y: 0px; }
html.vt-page.vt-back { --vt-x: 24px; }
@media (min-width: 761px) { html.vt-page { --vt-x: 0px; --vt-y: -8px; } html.vt-page.vt-back { --vt-y: 8px; } }
html.vt-page main { view-transition-name: page; }
/* The sticky search bar gets a layer of its own, kept where it sits on screen: inside the list's snapshot it was drawn
   down the page (or left out until the end) whenever the list was scrolled. It fades with the page, no sliding. */
html.vt-page .filterbar { view-transition-name: filterbar; }
html.vt-page::view-transition-group(filterbar) { animation: none; }
html.vt-page::view-transition-old(filterbar) { animation: vt-page-out .26s cubic-bezier(.4, 0, .2, 1) both; }
html.vt-page::view-transition-new(filterbar) { animation: vt-page-in .26s cubic-bezier(.4, 0, .2, 1) both; }
/* The page's snapshot is drawn above the whole live page, so the player bar (fixed over the content on phones) and
   the status bar get layers of their own: those come after the page's (they paint above it) and stay still. */
html.vt-page .toolbar { view-transition-name: player; }
html.vt-page .statusbar { view-transition-name: statusbar; }
html.vt-page::view-transition-old(player), html.vt-page::view-transition-old(statusbar) { display: none; }
html.vt-page::view-transition-new(player), html.vt-page::view-transition-new(statusbar) { animation: none; }
html.vt-page::view-transition-group(player), html.vt-page::view-transition-group(statusbar) { animation: none; }
html.vt-page::view-transition-old(root), html.vt-page::view-transition-new(root) { animation: none; }
html.vt-page::view-transition-old(page) { animation: vt-page-out .26s cubic-bezier(.4, 0, .2, 1) both; }
html.vt-page::view-transition-new(page) { animation: vt-page-in .26s cubic-bezier(.4, 0, .2, 1) both; }
@keyframes vt-page-out { to { opacity: 0; transform: translate(var(--vt-x), var(--vt-y)); } }
@keyframes vt-page-in { from { opacity: 0; transform: translate(calc(var(--vt-x) * -1), calc(var(--vt-y) * -1)); } }
/* Skipping tracks on a beat/loop page: the page swipes, next in from the right, previous from the left (--vt-swipe ±1, app.js). */
html.vt-page.vt-swipe::view-transition-old(page) { animation: vt-swipe-out .24s cubic-bezier(.4, 0, .2, 1) both; }
html.vt-page.vt-swipe::view-transition-new(page) { animation: vt-swipe-in .24s cubic-bezier(.4, 0, .2, 1) both; }
@keyframes vt-swipe-out { to { transform: translateX(calc(var(--vt-swipe) * -100vw)); } }
@keyframes vt-swipe-in { from { transform: translateX(calc(var(--vt-swipe) * 100vw)); } }
/* Browsers without view transitions: colours, surfaces and the visualizer's filter glide instead of jumping. */
html.theme-fade, html.theme-fade body, html.theme-fade *, html.theme-fade *::before, html.theme-fade *::after {
  transition: background-color .25s ease-out, color .25s ease-out, border-color .25s ease-out, box-shadow .25s ease-out, filter .25s ease-out, opacity .25s ease-out !important; }


/* ---------- lighter effects (phones and tablets from the start; any device whose frames run late) ----------
   Blurring the glass over a moving full-screen canvas is the most expensive thing on the page: the bars get a
   more solid tint instead. */
html.lowfx .toolbar, html.lowfx .filterbar { backdrop-filter: none; -webkit-backdrop-filter: none; }
html.lowfx .filterbar { background: linear-gradient(180deg, rgba(6,7,8,.93), rgba(6,7,8,.84)); }
html.lowfx[data-mode="light"] .filterbar { background: linear-gradient(180deg, rgba(240,243,245,.95), rgba(240,243,245,.88)); }

/* ---------- phones and small windows ---------- */
/* Covers keep their square before they load, so rows and pages never jump. */
.beat .art img { aspect-ratio: 1 / 1; object-fit: cover; }
#feature img { aspect-ratio: 1 / 1; object-fit: cover; }
.statusbar { padding-bottom: env(safe-area-inset-bottom); height: calc(24px + env(safe-area-inset-bottom)); }
@media (pointer: coarse) {
  /* Finger-sized targets (the UI is zoomed 1.25x: 28px here is 35px on screen). */
  .play { width: 28px; height: 28px; font-size: 10px; }
  .row { height: 40px; }
  .list .row { contain-intrinsic-size: auto 40px; }
  .tbtn { width: 34px; height: 34px; }
  .tbtn.big { width: 40px; height: 40px; }
  .mode-btn { width: 30px; height: 30px; }
  .price-btn { padding: 5px 10px; }
  .cart-btn { padding: 6px 12px; }
  .edit { width: 26px; height: 26px; line-height: 26px; }
  /* 13px x 1.25 zoom = 16px: phones don't zoom the page when the search box is tapped. */
  .search, .editor .search { font-size: 13px; }
  .lcd .bar { height: 8px; }
  .lcd .bar::before { inset: -12px 0; }
}
@media (max-width: 600px) {
  .window { padding: 0 10px; }
  .filterbar { margin: 0 -10px 8px; padding: 6px 10px; gap: 6px; }
  .filter-right { flex-wrap: wrap; justify-content: flex-end; row-gap: 6px; }
  :is(#p-vizstyle, #p-switchup) { min-width: 6.4em; }
  .toolbar { gap: 8px 10px; padding: 6px 10px; }
  .right { gap: 8px; }
  .lcd { grid-template-columns: 34px minmax(0, 1fr) auto; gap: 8px; }
  .lcd img { width: 34px; height: 34px; }
  .beat { gap: 16px; padding-top: 6px; }
  .beat .art { max-width: 420px; width: 100%; justify-self: center; }
  .beat h1 { font-size: 24px; overflow-wrap: anywhere; }
  .tier { flex-wrap: wrap; }
  .to-top { right: 10px; bottom: calc(34px + env(safe-area-inset-bottom)); }
}
@media (max-width: 380px) {
  /* Narrow phones: the UI zoom steps down a little so the toolbar and filter bar keep everything on screen. */
  .toolbar, .window, .statusbar, .drawer, .page, .top, .editor, .to-top { zoom: 1.1; }
  .drawer { width: 90.9vw; } /* 90.9vw x zoom 1.1 = full phone width */
  .transport { gap: 4px; }
  #p-shuffle { display: inline-block; }
}

/* When a beat or loop was made (from its audio file's tags): small, under the BPM | key line. */
.beat .made { color: var(--muted); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; margin: -8px 0 14px; opacity: .8; }

/* ---------- beat / loop page text over the moving visualizer ----------
   Credit, BPM | key and year are full white on dark (full black on light) instead of grey, and every line of the
   heading block gets a soft, tight shadow (a dark halo on dark, a white halo on light) so it stays readable
   whatever the visualizer draws behind it. Shadows only: no outlines, no boxes, the look stays clean. */
:root { --page-ink: #fff; --page-halo: 0 1px 2px rgba(0,0,0,.9), 0 0 6px rgba(0,0,0,.55); }
html[data-mode="light"] { --page-ink: #000; --page-halo: 0 1px 1px rgba(255,255,255,.95), 0 0 6px rgba(255,255,255,.7); }
.beat .coprod, .beat .sub, .beat .made { color: var(--page-ink); opacity: 1; text-shadow: var(--page-halo); }
.beat h1, html[data-mode="light"] .beat h1 { color: var(--page-ink); text-shadow: var(--page-halo); }

/* Visualizer switch on beat and loop pages: a quiet chip a little below the back key, full strength on hover or
   focus, so it is always one tap away without sitting in the picture. */
.beat-tools { align-items: flex-start; }
.beat-tools :is(#p-vizstyle, #p-switchup) { margin-top: 8px; padding: 3px 9px; font-size: 10px; min-width: 6.2em; border-radius: 10px; }
html.viz-live .beat-tools :is(#p-vizstyle, #p-switchup) { opacity: .5; }
html.viz-live .beat-tools :is(#p-vizstyle, #p-switchup):is(:hover, :focus-visible) { opacity: 1; }
html.viz-live .beat-tools :is(#p-vizstyle, #p-switchup)[aria-pressed="false"]:not(:hover, :focus-visible) { opacity: .22; } /* switched off */
@media (hover: none) { html.viz-live .beat-tools :is(#p-vizstyle, #p-switchup) { opacity: .65; } }

/* Now-playing cover turns like a record while playing (app.js spinCover drives a transform-only animation). */
.lcd img { will-change: transform; backface-visibility: hidden; }
/* Loop rows link to their page like beat rows do. */
.table.loops .row .t:hover { text-decoration: underline; }
/* Phones only: one compact row under the search box, so the visualizer keeps more of the screen: the visualizer
   button on the left, Beats / Loops centred between it and Player on the right (on loops, All / Solo / Collab
   centred under them). Both side buttons are icons here, spectrum bars and the note (the full labels stay on bigger
   screens; the visualizer button names the current style in its tooltip and to screen readers). The visualizer
   button keeps its place while hidden (before anything plays), so Beats / Loops never moves when it appears. */
@media (max-width: 600px) {
  .filter-right { flex: 1 1 100%; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 6px; }
  .filter-right > :is(#p-vizstyle, #p-switchup) { grid-area: 1 / 1; justify-self: start; align-self: stretch; min-width: 0; width: auto; padding-inline: 11px; font-size: 0; }
  .filter-right > :is(#p-vizstyle, #p-switchup)::before { content: ""; display: block; width: 12px; height: 12px; background: currentColor;
    -webkit-mask: var(--viz-icon) center / contain no-repeat; mask: var(--viz-icon) center / contain no-repeat; }
  .filter-right > :is(#p-vizstyle, #p-switchup) { --viz-icon: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 12 12%27%3E%3Cpath fill-rule=%27evenodd%27 d=%27M6 2.2C3.4 2.2 1.3 4.1.2 6c1.1 1.9 3.2 3.8 5.8 3.8s4.7-1.9 5.8-3.8C10.7 4.1 8.6 2.2 6 2.2zm0 1.1c2 0 3.6 1.3 4.5 2.7C9.6 7.4 8 8.7 6 8.7S2.4 7.4 1.5 6C2.4 4.6 4 3.3 6 3.3z%27/%3E%3Ccircle cx=%276%27 cy=%276%27 r=%271.6%27/%3E%3C/svg%3E"); display: inline-flex; align-items: center; justify-content: center; }
  .filter-right > .player-link .label { display: none; }
  .filter-right > #count { grid-area: 1 / 2; justify-self: center; }
  .filter-right > .player-link { grid-area: 1 / 3; justify-self: end; align-self: stretch; display: inline-flex; align-items: center; padding-inline: 11px; }
  .filter-right > #loop-kind { grid-area: 2 / 1 / 3 / 4; justify-self: center; }
  .list-mode span { padding-inline: 9px; }
}
@media (max-width: 360px) { .list-mode span { padding-inline: 7px; } }
/* Phones: the toolbar's buttons (transport, light/dark, cart) sit centred above the now-playing display. */
@media (max-width: 760px) {
  .toolbar { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; }
  .toolbar .lcd { flex: 1 1 100%; order: 3; }
}

/* ---------- covers are round ----------
   Every cover is a dish cut to a circle with a transparent surround (engine/site.py cutouts), so its frame follows
   the circle: no square border, backing or box shadow around it, and on the big covers a shadow that follows the
   disc's own shape. While a big cover loads, a dark disc the size of the dish (43% radius, engine/dish.py DISH_R)
   holds its place, so a page never shows an empty white square. */
.row img, .lcd img, .beat .art img, #feature img,
html[data-mode="light"] :is(.row img, .lcd img, .beat .art img, #feature img) {
  border: 0; border-radius: 50%; background-color: transparent; box-shadow: none; }
.beat .art img, #feature img { filter: drop-shadow(0 12px 20px rgba(0,0,0,.55)); }
html[data-mode="light"] :is(.beat .art img, #feature img) { filter: drop-shadow(0 10px 18px rgba(60,80,95,.3)); }
.beat .art { position: relative; isolation: isolate; }
.beat .art::before { content: ""; position: absolute; left: 7%; top: 7%; width: 86%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, #1c1f22, #050506); z-index: -1; }

.cart-tab { display: none; } /* the phone bar's cart (below) */

/* ---------- phones: one now-playing panel along the bottom (thumb reach), nothing on top ----------
   The toolbar moves to the bottom edge as a single panel: the now-playing display (cover, title, seek, Buy) and
   under it the transport in five even slots (shuffle, previous, play / pause, next, and the cart in the store or
   repeat in the Player), so play / pause is always dead centre. The top of the screen is left to the search and
   Beats / Loops bar alone. The panel fades with the rest of the UI in immersive mode and sits under the cart drawer.
   Sizes are before the UI zoom (x1.25): 38px buttons are 48px on screen, play 58px. The light / dark switch and the
   wordmark are not shown here (touch screens follow the device's setting: viz-core.js). */
@media (max-width: 760px) {
  .toolbar { position: fixed; top: auto; bottom: 0; left: 0; right: 0; z-index: 10;
    display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 6px;
    padding: 7px max(10px, env(safe-area-inset-right)) calc(5px + env(safe-area-inset-bottom) / 1.25) max(10px, env(safe-area-inset-left));
    border-bottom: 0; border-top: 1px solid #000; box-shadow: inset 0 1px 0 var(--edge), 0 -6px 20px rgba(0,0,0,.55); }
  .toolbar { background: linear-gradient(180deg, rgba(255,255,255,.07), rgba(255,255,255,0) 40%), linear-gradient(180deg, #202326, #08090a); } /* solid: the list never shows through */
  html[data-mode="light"] .toolbar { background: linear-gradient(180deg, #fafcfd, #d9e0e5); }
  html[data-mode="light"] .toolbar { border-top-color: #a3adb5; box-shadow: inset 0 1px 0 #fff, 0 -2px 12px rgba(60,80,95,.18); }
  .toolbar .lcd { order: 0; flex: none; width: 100%; max-width: none; grid-column: auto; }
  .toolbar .right { display: none; }
  .toolbar .transport { order: 1; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); justify-items: center;
    align-items: center; gap: 0; touch-action: manipulation; }
  .transport #p-shuffle { grid-column: 1; grid-row: 1; }
  .transport #p-prev { grid-column: 2; grid-row: 1; }
  .transport #p-toggle { grid-column: 3; grid-row: 1; }
  .transport #p-next { grid-column: 4; grid-row: 1; }
  .transport #p-repeat, .transport .cart-tab { grid-column: 5; grid-row: 1; }
  .transport .tbtn { width: 38px; height: 38px; font-size: 13px; }
  .transport .tbtn.big { width: 46px; height: 46px; font-size: 16px; }
  .transport #p-shuffle, .transport #p-repeat { font-size: 15px; }
  .transport .cart-tab { display: inline-grid; place-items: center; }
  :is(.transport, .np-tools) .cart-tab::before { /* also on Now Playing, beside the dots (phone.js) */ content: ""; width: 17px; height: 17px; background: currentColor;
    -webkit-mask: var(--bag) center / contain no-repeat; mask: var(--bag) center / contain no-repeat;
    --bag: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%27-.45 .45 24 24%27 fill=%27none%27 stroke=%27%23000%27 stroke-width=%272%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3E%3Cpath d=%27M2.5 4h2.6l2.3 11h10.9l2.2-7.8H6.2%27/%3E%3Ccircle cx=%279.5%27 cy=%2719.5%27 r=%271.4%27/%3E%3Ccircle cx=%2717%27 cy=%2719.5%27 r=%271.4%27/%3E%3C/svg%3E");; }
  .cart-tab b { position: absolute; top: -3px; right: -4px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
    font: 700 9px/16px var(--ui); color: #fff; text-shadow: none; background: linear-gradient(180deg, #e8453c, #a31a14);
    border: 1px solid #000; box-shadow: 0 1px 2px rgba(0,0,0,.6); }
  /* The search / Beats / Loops bar takes the top edge; the list scrolls clear of the panel. */
  .filterbar { top: 0; }
  .window { margin-top: 0; }
  body { padding-bottom: calc(170px + env(safe-area-inset-bottom)); }
  .to-top { bottom: calc(126px + env(safe-area-inset-bottom)); }
  .sitefoot { bottom: calc(128px + env(safe-area-inset-bottom)); } /* above the player panel */
}
/* Phones and tablets follow the device's light / dark setting (the head script and app.js / player.js): no switch. */
@media (hover: none) and (pointer: coarse) { .mode-btn { display: none; } }

/* ---------- phones: a cleaner list and beat page ----------
   List rows read as two lines: the name, and under it BPM and key in small type (so you can choose without opening
   every beat), with a slightly bigger cover and the price on the right. The column header goes (nothing to label).
   Beat and loop pages lead with the music: a smaller cover so the name and play button are on the first screen,
   the play button big and level with the name, and the licence buttons sized for thumbs. */
@media (max-width: 600px) {
  .thead { display: none; }
  .table .row { grid-template-columns: 30px 36px auto minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: 10px; row-gap: 1px;
    min-height: 54px; padding-block: 7px; }
  .list .row { contain-intrinsic-size: auto 54px; }
  .table .row > .play { grid-area: 1 / 1 / 3 / 2; }
  .table .row > img, .table .row > span:empty { grid-area: 1 / 2 / 3 / 3; width: 36px; height: 36px; }
  .table .row > .t-wrap { grid-area: 1 / 3 / 2 / 5; align-self: end; flex-wrap: wrap; column-gap: 2px; }
  /* Whole words: a name only breaks between words (the owner's edit buttons drop under it instead of squeezing it
     into "EARTHQUA / KE"); only a single word longer than the whole line is broken. */
  .table .row .t { overflow-wrap: break-word; word-break: normal; }
  .table .row > .num { display: block; grid-area: 2 / 3; align-self: start; font-size: 10px; color: var(--muted); text-align: left; }
  .table .row > .key { display: block; grid-area: 2 / 4; margin-left: -6px; align-self: start; font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .table .row > .num:not(:empty)::after { content: " BPM"; }
  .table .row > .num:not(:empty) + .key:not(:empty)::before { content: "· "; }
  .table .row > .listen-tag { grid-area: 1 / 5 / 3 / 6; align-self: center; }
  .table .row > .price-btn { grid-area: 1 / 5 / 3 / 6; padding: 6px 10px; font-size: 11px; border-radius: 12px; }
  .table .row > .idx { display: none; }

  .beat .art { max-width: min(300px, 78vw); }
  .beat .info { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 14px; align-items: center; }
  .beat .info > * { grid-column: 1 / -1; }
  .beat .info > :is(h1, .coprod, .sub, .made) { grid-column: 1; }
  .beat .info > #beat-play { grid-column: 2; grid-row: 2 / span 4; align-self: center; width: 58px; height: 58px; font-size: 20px; }
  .beat .sub { margin-bottom: 6px; }
  .beat .made { margin: 0 0 4px; }
  .beat .tiers { margin-top: 16px; }
  .tier { padding: 12px; row-gap: 10px; }
  .tier .add { padding: 8px 20px; font-size: 12px; margin-left: auto; min-width: 128px; text-align: center; display: inline-flex; align-items: center; justify-content: center; }
  /* "Make an offer" is a link, not a cart button: same size as Add, readable text instead of the embossed grey. */
  .tier .add.ghost { color: #e6edf1; text-shadow: none; }
  html[data-mode="light"] .tier .add.ghost { color: #2a3238; }
  /* The now-playing panel: room under the time row, and a Buy button that matches the other rounded buttons. */
  .lcd { padding-bottom: 9px; }
  .lcd-buy { border-radius: 12px; padding: 8px 14px; }
}

/* ---------- vibe (engine/vibe.py): descriptor chips and "sounds like" on beat and loop pages ---------- */
.vibe-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 2px; }
.beat .vibe-row + .made { margin-top: 6px; } /* the year sat tucked under the tempo line; with the vibe words between, it gets its own space */
.vibe-chip { font-size: 11px; letter-spacing: .04em; text-transform: lowercase; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--edge); background: var(--shine), rgba(20,22,24,.7); opacity: var(--c, .8); }
.similar { margin: 16px 0 4px; text-align: center; }
.similar h2 { font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin: 0 0 8px; }
.similar-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; justify-items: center; }
.similar-item { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 10px; padding: 6px; border-radius: 8px; border: 1px solid transparent;
  min-width: 0; transition: background .15s ease, border-color .15s ease; }
.similar-item:hover, .similar-item:focus-visible { background: rgba(255,255,255,.06); border-color: var(--edge); }
.similar-item img { width: 44px; height: 44px; border-radius: 50%; flex: none; }
.similar-item span { font-size: 12px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-mode="light"] .vibe-chip { background: var(--shine), rgba(255,255,255,.7); }
@media (pointer: coarse) { .similar-item { min-height: 52px; } }
/* "Sounds like" over the moving visualizer: the same treatment as the heading block above it (full white with a dark
   halo on dark, full black with a soft white halo on light), so the heading and the track names read over any look. */
.similar h2, .similar-item span { color: var(--page-ink); text-shadow: var(--page-halo); }
.similar h2 { opacity: .9; }
.similar-item img { filter: drop-shadow(0 2px 4px rgba(0,0,0,.35)); }
/* Small covers (Similar, the cart): the cover's disc is cut at 41.8% of the picture with a clear margin round it, so
   the picture is scaled up until the disc fills the circle (scale, not transform: the cart's playing cover turns with a
   transform) and no dark ring shows round the CD. */
.similar-item img, .drawer .line-cover { scale: calc(1 / .836); background: none; }
html[data-mode="light"] .similar-item:hover, html[data-mode="light"] .similar-item:focus-visible { background: rgba(255,255,255,.55); }

/* Touch screens: every control at least 44 px tall (Apple / WCAG target size); desktop sizes unchanged. */
@media (pointer: coarse) {
  .cart-btn, .tiers .add, .tiers .add.ghost { min-height: 44px; }
  .lcd-buy { min-height: 38px; }
  .lcd-title { display: inline-block; padding: 12px 8px; margin: -12px -8px; } /* bigger hit area, same look */
}

/* ---------- records ----------
   The big cover on a beat / loop page is the plain round artwork and stays still. The now-playing cover at the top
   turns while sound is coming out and stops on the spot when it stops (vinyl.js). A click on either is play / pause. */
.vinyl { position: relative; display: block; aspect-ratio: 1; border-radius: 50%; isolation: isolate; contain: layout paint;
  cursor: pointer; -webkit-tap-highlight-color: transparent; -webkit-user-select: none; user-select: none; }
.vinyl:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
.vinyl::before { content: ""; position: absolute; inset: 0; border-radius: 50%; z-index: -1; box-shadow: 0 14px 30px rgba(0,0,0,.5), 0 2px 4px rgba(0,0,0,.4); }
.vinyl-disc { position: absolute; inset: 0; border-radius: 50%; overflow: hidden; background: #0d0d0f;
  -webkit-mask-image: -webkit-radial-gradient(white, black); } /* Safari: a turning, round-clipped picture shows square corners and flickers unless the round shape is a mask */
/* The artwork's transparent surround is cut off by the disc's round edge, so the image is larger than the disc and
   centred absolutely (a grid centres an overflowing item from the top, which left the art hanging off the bottom). */
.vinyl-disc img, html[data-mode="light"] .vinyl-disc img { position: absolute; left: calc(50% - 50% / .836); top: calc(50% - 50% / .836); /* centred by offsets, not translate(-50%): Safari lost that offset and left the picture in a corner of the disc */
  width: calc(100% / .836) !important; /* the cover circle (cut at radius .418 of the image, engine/site.py) fills the disc */ height: auto !important; aspect-ratio: 1; max-width: none; object-fit: cover; border: 0 !important;
  box-shadow: none !important; filter: none !important; -webkit-box-reflect: none; background-color: transparent !important; pointer-events: none; }
/* A record's picture fades in once decoded (vinyl.js); no blurry thumbnail stand-in behind it on a turning disc. */
.vinyl-disc img { opacity: 0; transition: opacity .25s ease; background-image: none !important; }
.vinyl-disc img.ready { opacity: 1; }
/* The picture is what turns (vinyl.js), on its own layer inside the still round frame. */
.vinyl-disc img, .m-card.playing .m-card-art img { will-change: transform; backface-visibility: hidden; }
.vinyl.no-art .vinyl-disc img { visibility: hidden; }
.vinyl.no-art .vinyl-disc { background: radial-gradient(circle, #2a2d31 0 20%, #1d1f22 21% 100%); }
/* Sized as the covers always were: the disc takes 86% of the cover column, centred (the cut-out's transparent surround
   used to give it that margin). */
.beat .art.vinyl { width: 86%; margin: 7%; touch-action: none; } /* a finger on it scratches (app.js), it doesn't scroll */
.beat .art.vinyl::before { inset: 0; left: 0; top: 0; width: auto; height: auto; aspect-ratio: auto; background: none; }
.art.vinyl .vinyl-disc img { will-change: auto; }
.vinyl { transition: transform .08s ease-out; }
.vinyl:active { transform: scale(.96); } /* pressed: shows at once, before the audio answers */
/* Now-playing bar: just the round artwork, no record dressing, and nothing at all until a track with art plays. */
.vinyl.mini { width: 34px; height: 34px; margin: 3px; flex: none; } /* the disc as it sat in the 40px cover */
.vinyl.mini::before { box-shadow: 0 1px 3px rgba(0,0,0,.5); }
/* Hidden only until a track is loaded; a track without a picture (or whose picture failed) gets the plain dark
   record, which can still be clicked to play or pause. */
.vinyl.mini.empty { visibility: hidden; }
@media (max-width: 600px) { .vinyl.mini { width: 29px; height: 29px; margin: 2.5px; } }
@media (prefers-reduced-motion: reduce) { .vinyl-disc img, .m-card-art img { will-change: auto; } }

/* ---------- visualizer button: one look on every page ----------
   The spectrum-bars symbol plus the style's name on bigger screens, the symbol alone on phones; the same size,
   spacing and states on the home page, beat and loop pages and the player. It shows while something plays. */
:is(#p-vizstyle, #p-switchup) { --viz-icon: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 12 12%27%3E%3Cpath fill-rule=%27evenodd%27 d=%27M6 2.2C3.4 2.2 1.3 4.1.2 6c1.1 1.9 3.2 3.8 5.8 3.8s4.7-1.9 5.8-3.8C10.7 4.1 8.6 2.2 6 2.2zm0 1.1c2 0 3.6 1.3 4.5 2.7C9.6 7.4 8 8.7 6 8.7S2.4 7.4 1.5 6C2.4 4.6 4 3.3 6 3.3z%27/%3E%3Ccircle cx=%276%27 cy=%276%27 r=%271.6%27/%3E%3C/svg%3E");
  display: inline-flex; align-items: center; justify-content: center; gap: 7px; }
:is(#p-vizstyle, #p-switchup)::before { content: ""; display: block; flex: none; width: 12px; height: 12px; background: currentColor;
  -webkit-mask: var(--viz-icon) center / contain no-repeat; mask: var(--viz-icon) center / contain no-repeat; }
.beat-tools :is(#p-vizstyle, #p-switchup) { margin-top: 0; padding: 4px 12px; font-size: 11px; border-radius: 12px; min-width: 7.2em; align-self: center; margin-bottom: 12px; }
html.viz-live .beat-tools :is(#p-vizstyle, #p-switchup) { opacity: 1; }
@media (max-width: 600px) {
  :is(#p-vizstyle, #p-switchup), .beat-tools :is(#p-vizstyle, #p-switchup), .open-btns :is(#p-vizstyle, #p-switchup) { font-size: 0; gap: 0; min-width: 0; padding-inline: 11px; }
}



.beat h1 { overflow-wrap: anywhere; } .beat .info { min-width: 0; } /* a long one-word title (MOUNTAINSIDE) wraps instead of pushing the page sideways */

/* ---------- visualizer button: the icon alone, everywhere ----------
   The spectrum-bars symbol on every page and screen size; the style showing is named in its tooltip and to screen
   readers (viz-switch.js). Same size and place as before, so nothing around it moves. */
:is(#p-vizstyle, #p-switchup), .beat-tools :is(#p-vizstyle, #p-switchup), .filter-right > :is(#p-vizstyle, #p-switchup), .open-btns :is(#p-vizstyle, #p-switchup) {
  font-size: 0; gap: 0; min-width: 0; padding-inline: 11px; }
:is(#p-vizstyle, #p-switchup)::before { width: 13px; height: 13px; }
.beat-tools { align-items: center; }
.beat-tools :is(#p-vizstyle, #p-switchup) { align-self: stretch; margin: 0; } /* level with the back button: same height, centred on its line */

#drawer .muted:empty, #drawer .muted:empty + br { display: none; }
#drawer .sum { display: flex; justify-content: space-between; align-items: baseline; }
.drawer .line-end { display: inline-flex; align-items: center; gap: 4px; flex: none; } /* no store tagline set */

/* AVS Easter egg phases (viz-egg.js): the words' dots draw over the AVS picture, which dims underneath meanwhile. */
#viz-egg { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
#viz.avs.on.egg { opacity: .4; transition: opacity .6s ease; }

/* ---------- Beats / Loops and All / Solo / Collab: segmented switches ----------
   A recessed groove with the chosen half as a raised, glossy key that lights up, the others plain labels; the
   counts sit beside each label in lighter type. Same size and place as before, so nothing around them moves. */
.cart-btn.list-mode, .cart-btn.list-mode:hover, .cart-btn.list-mode:active {
  padding: 2px; gap: 2px; align-items: stretch; border-radius: 999px; transform: none;
  background: linear-gradient(180deg, rgba(0,0,0,.62), rgba(22,24,27,.78));
  border: 1px solid rgba(0,0,0,.85);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.85), inset 0 -1px 0 rgba(255,255,255,.04), 0 1px 0 rgba(255,255,255,.07);
}
.list-mode > span, .kind-switch > button {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 12px; border-radius: 999px; opacity: 1;
  color: #9aa3aa; font-weight: 600; letter-spacing: .02em; border: 0 !important; box-shadow: none !important; background: none;
  transition: color .15s, background .2s, box-shadow .2s;
}
.list-mode > span b, .kind-switch > button b { color: inherit; font-weight: 400; opacity: .7; min-width: 0; font-size: .92em; }
.list-mode > span:not(.on):hover, .kind-switch > button:not(.on):hover { color: #e8eef2; }
.list-mode > span.on, .kind-switch > button.on {
  color: #fff; text-shadow: 0 1px 1px rgba(0,0,0,.6);
  background: var(--shine), linear-gradient(180deg, #626b73 0%, #30363b 55%, #1f2326 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), inset 0 0 0 1px rgba(0,0,0,.5), 0 1px 3px rgba(0,0,0,.6), 0 0 12px rgba(150,205,255,.22) !important;
}
.list-mode > span.on b, .kind-switch > button.on b { opacity: .85; }
.kind-switch > button:focus-visible { outline: 1px dotted #fff; outline-offset: -3px; }
html[data-mode="light"] .cart-btn.list-mode, html[data-mode="light"] .cart-btn.list-mode:hover {
  background: linear-gradient(180deg, rgba(0,0,0,.12), rgba(0,0,0,.05)); border-color: rgba(0,0,0,.2);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.25), 0 1px 0 rgba(255,255,255,.8);
}
html[data-mode="light"] .list-mode > span, html[data-mode="light"] .kind-switch > button { color: #56616a; }
html[data-mode="light"] .list-mode > span:not(.on):hover, html[data-mode="light"] .kind-switch > button:not(.on):hover { color: #1b2126; }
html[data-mode="light"] .list-mode > span.on, html[data-mode="light"] .kind-switch > button.on {
  color: #1b2126; text-shadow: 0 1px 0 rgba(255,255,255,.8);
  background: var(--shine), linear-gradient(180deg, #ffffff 0%, #e4ebf0 55%, #d3dde4 100%);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.25), 0 0 10px rgba(80,150,210,.25) !important;
}

/* ---------- legal pages and links (engine/legal.py) ----------
   Terms / Privacy / Refunds / Credits: a quiet line under every page, and plain readable text on their own pages. */
/* The policy links: a thin line under the end of the list (and of every other page), never over it. */
.sitefoot { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; text-align: center; padding: 14px 12px 12px; /* always at the very bottom: of the screen on a short page, of the content on a long one */ font-size: 10px; letter-spacing: .03em; color: var(--muted); }
.sitefoot a { color: var(--muted); text-decoration: none; padding: 2px 4px; display: inline-block; }
.sitefoot a:hover, .sitefoot a:focus-visible { color: var(--text); text-decoration: underline; }
/* Mouse users: the line stays hidden until the pointer is over it (or a link is tabbed to). Touch screens have no hover, so it shows there. */
@media (hover: hover) {
  .sitefoot:not(:hover):not(:focus-within) { opacity: 0; transition: none; }
  .sitefoot:is(:hover, :focus-within) { transition: none; } /* instant both ways, not the .3s list fade further down */
}
#drawer .agree { font-size: 10.5px; line-height: 1.45; color: var(--muted); margin: 8px 0 0; }
#drawer .agree a { color: inherit; text-decoration: underline; display: inline-block; padding: 3px 0; }
.page.legal { font-size: 13px; line-height: 1.6; margin-top: 14px; border-radius: 10px; border: 1px solid rgba(255,255,255,.06);
  background: rgba(8,9,10,.82); box-shadow: 0 10px 40px rgba(0,0,0,.45); }
html[data-mode="light"] .page.legal { background: rgba(255,255,255,.88); border-color: rgba(0,0,0,.08); box-shadow: 0 10px 30px rgba(60,80,95,.18); }
.page.legal h2.part { font-size: 15px; margin-top: 40px; padding-top: 14px; border-top: 1px solid rgba(127,127,127,.25); scroll-margin-top: 90px; }
.page.legal h2.part:first-of-type { margin-top: 18px; border-top: 0; padding-top: 0; }
.page.legal h2 { font: 600 13px var(--ui); letter-spacing: .08em; text-transform: uppercase; margin: 26px 0 6px; }
.page.legal a { color: var(--text); }
.page.legal .authors { color: var(--muted); font-size: 11.5px; overflow-wrap: anywhere; }
.legal-table { width: 100%; border-collapse: collapse; margin: 6px 0; font-size: 12px; }
.legal-table th, .legal-table td { text-align: left; vertical-align: top; padding: 6px 8px; border-bottom: 1px solid rgba(255,255,255,.12); }
html[data-mode="light"] .legal-table th, html[data-mode="light"] .legal-table td { border-bottom-color: rgba(0,0,0,.12); }
@media (max-width: 520px) { .legal-table td:nth-child(2) { white-space: nowrap; } .legal-table th, .legal-table td { padding: 6px 4px; } }
.payee-form label { display: block; margin: 12px 0 4px; }
.payee-form input.search { width: 100%; box-sizing: border-box; min-height: 40px; font-size: 16px; } /* 16px: no zoom-in on iPhone */
.payee-form label.check { display: flex; gap: 10px; align-items: flex-start; line-height: 1.5; margin: 16px 0; }
.payee-form label.check input { margin-top: 3px; width: 18px; height: 18px; flex: none; }
.payee-form .btn { min-height: 40px; padding-inline: 18px; }
@media (pointer: coarse) { /* bigger invisible touch area for the row buttons; they look the same */
  .row .play, .row .price-btn { position: relative; }
  .row .play::after, .row .price-btn::after { content: ""; position: absolute; inset: -8px -6px; }
}

/* The free-download copy of the store (app.js setFree): no cart, prices or checkout; Download buttons instead. */
html.free :is(#cart-open, #cart-tab, #drawer, .agree, .deal) { display: none !important; }
.price-btn.dl { text-decoration: none; }

/* ---------- switch-up button (turntable): beside the visualizer button, same look and states ---------- */
#p-switchup { --viz-icon: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 12 12%27%3E%3Cpath fill-rule=%27evenodd%27 d=%27M5 1.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zm0 3.4a1.1 1.1 0 1 1 0 2.2 1.1 1.1 0 0 1 0-2.2z%27/%3E%3Cpath d=%27M9.7.5l1.2.7-2.3 4-1.1-.6z%27/%3E%3Ccircle cx=%279.9%27 cy=%271%27 r=%27.95%27/%3E%3C/svg%3E") !important; }
#p-switchup[aria-pressed="false"] { opacity: .4; }
@media (max-width: 600px) {
  .filter-right { grid-template-columns: auto auto minmax(0, 1fr) auto; }
  .filter-right > #p-switchup { display: none; } /* phones: the list toggle takes its place */
  .filter-right > #p-listtoggle { display: inline-flex; grid-area: 1 / 2; justify-self: start; align-self: stretch; align-items: center; padding-inline: 11px; }
  .filter-right > #count { grid-area: 1 / 3; }
  .filter-right > .player-link { grid-area: 1 / 4; }
  .filter-right > #loop-kind { grid-area: 2 / 1 / 3 / 5; }
}

/* ---------- drawn transport icons (no emoji glyphs): sized from the button's font size, coloured by its text ---------- */
svg.ic { width: 1.15em; height: 1.15em; fill: currentColor; stroke: none; vertical-align: -.2em; pointer-events: none; }
svg.ic.st { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
/* Transport and list play buttons: the icon box is centred exactly (the text-baseline drop of svg.ic left it 2px low). */
.tbtn:not([hidden], .cart-tab), .play:not([hidden]) { display: inline-flex; align-items: center; justify-content: center; }
.tbtn svg.ic, .play svg.ic { display: block; vertical-align: baseline; }

/* ---------- visualizer / switch-up buttons: the look says on or off, and hovering never changes which ---------- */
:is(#p-vizstyle, #p-switchup)[aria-pressed="true"] { box-shadow: inset 0 1px 0 var(--edge), 0 0 10px var(--cool), 0 0 0 1px rgba(160,220,255,.35); }
html[data-mode="light"] :is(#p-vizstyle, #p-switchup)[aria-pressed="true"] { box-shadow: inset 0 1px 0 #fff, 0 0 0 1px rgba(60,110,160,.45); }
html.viz-live :is(#p-vizstyle, #p-switchup)[aria-pressed="false"]:is(:hover, :focus-visible) { opacity: .55; background: var(--shine), linear-gradient(180deg, #3a3f44 0%, #16181a 100%); box-shadow: none; }
html[data-mode="light"].viz-live :is(#p-vizstyle, #p-switchup)[aria-pressed="false"]:is(:hover, :focus-visible) { background: var(--shine), linear-gradient(180deg, #ffffff 0%, #d9e0e5 100%); }

/* ---------- phones: the track list toggle (#p-listtoggle, app.js), in the switch-up button's place ----------
   Hides the list and footer so the visualizer has the screen; search, Beats / Loops and the player stay. */
#p-listtoggle { display: none; }
#p-listtoggle::before { content: ""; display: block; width: 12px; height: 12px; background: currentColor;
  -webkit-mask: var(--list-icon) center / contain no-repeat; mask: var(--list-icon) center / contain no-repeat;
  --list-icon: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 12 12%27%3E%3Cpath d=%27M1 2h10v1.5H1zM1 5.25h10v1.5H1zM1 8.5h10V10H1z%27/%3E%3C/svg%3E"); }
#p-listtoggle[aria-pressed="false"] { opacity: .5; }
.window .table, .sitefoot { transition: opacity .3s ease, visibility 0s; }
html.viz-live:not(.viz-off).list-hidden :is(.window .table, .sitefoot, .to-top) { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .3s ease, visibility 0s .3s; }
/* Phones: fading layers are composited, so the fades never stutter over a long list. */
@media (pointer: coarse) { .window, .toolbar, .sitefoot { will-change: opacity; } }

/* Fast scrolling: each row lays out and paints on its own, so building or changing one never reflows the list. */
.list .row { contain: layout style; }

/* Taps act at once: no waiting to see whether it is a double-tap zoom. */
html { touch-action: manipulation; }
/* The list toggle shows only while a visualizer is on and playing (keeping its place, so nothing shifts); with the
   visualizer off or nothing playing, the list always shows. */
.filter-right > #p-listtoggle { visibility: hidden; opacity: 0; pointer-events: none; transition: opacity .25s ease, visibility 0s .25s; }
html.viz-live:not(.viz-off) .filter-right > #p-listtoggle { visibility: visible; opacity: 1; pointer-events: auto; transition: opacity .25s ease; }
html.viz-live:not(.viz-off) .filter-right > #p-listtoggle[aria-pressed="false"] { opacity: .5; }
/* Back to top stays a circle everywhere: phones give every button a 44px minimum height and side padding, which
   stretched it into an oval; there it sits in its own corner, never placed over the list's price column. */
.to-top { box-sizing: border-box; min-width: 0; min-height: 0; padding: 0; aspect-ratio: 1; }
@media (max-width: 760px) {
  .to-top { left: auto !important; width: 36px; height: 36px; right: max(10px, env(safe-area-inset-right)); }
}


/* Desktop: Beats / Loops (and the All / Solo / Collab filter on loops) sit right beside the search; the visualizer and
   Player buttons stay at the right edge. The group is dissolved here only; phones keep their own grid (above). */
@media (min-width: 601px) {
  .filterbar { justify-content: flex-start; }
  .filter-right { display: contents; }
  .search { order: 0; }
  #count { order: 1; }
  #loop-kind { order: 2; }
  #p-vizstyle { order: 3; margin-left: auto; }
  #p-switchup, #p-listtoggle, .filter-right > .player-link { order: 4; }
  .filterbar { gap: 8px; }
  #p-vizstyle ~ * { margin-left: 0; }
}

/* Taps, double-taps, long presses and swipes never select page text (the blue selection boxes over the list, the
   toolbar and the cart). Fields, the editor and the policy pages stay selectable. */
body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
input, textarea, select, [contenteditable], .editor, .editor *, .legal, .legal * { -webkit-user-select: text; user-select: text; }

/* ---------- admin: add to the store by dropping files on the track list (admin/add.js) ---------- */
html.dropping main { position: relative; }
html:not(.admin) :is(.add-panel, .drop-over) { display: none !important; } /* admin mode only */
.drop-over { position: absolute; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center; pointer-events: none;
  border: 2px dashed rgba(160,220,255,.85); border-radius: 10px; background: rgba(6,10,14,.72); box-shadow: inset 0 0 40px rgba(120,190,255,.25); }
.drop-over > div { display: flex; flex-direction: column; gap: 6px; align-items: center; text-align: center; padding: 18px 24px; position: sticky; top: 40vh; }
.drop-over strong { font-size: 16px; letter-spacing: .03em; }
.drop-over small { color: var(--muted); font-size: 11.5px; }
.add-panel { position: fixed; right: 16px; bottom: 16px; z-index: 60; width: min(380px, calc(100vw - 32px)); box-sizing: border-box; padding: 10px 12px;
  border-radius: 10px; border: 1px solid rgba(255,255,255,.12); background: rgba(10,11,12,.94); box-shadow: 0 10px 40px rgba(0,0,0,.55); font-size: 12px; }
.add-panel[hidden] { display: none; }
.add-panel .drop-head { display: flex; align-items: center; gap: 8px; }
.add-panel .drop-head strong { flex: 1; }
.add-panel .kind, .add-panel .x { font: inherit; font-size: 11px; padding: 3px 9px; border-radius: 999px; border: 1px solid rgba(255,255,255,.18); background: transparent; color: var(--text); cursor: pointer; }
.add-panel .x { padding: 0 8px; font-size: 14px; line-height: 20px; }
.add-panel .drop-list { list-style: none; margin: 8px 0 0; padding: 0; max-height: 40vh; overflow: auto; }
.add-panel .drop-row { display: flex; gap: 8px; padding: 5px 0; font-size: 11.5px; border-top: 1px solid rgba(255,255,255,.06); }
.add-panel .drop-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.add-panel .drop-kind { flex: none; color: var(--muted); }
.add-panel .drop-status { flex: none; max-width: 50%; text-align: right; color: var(--muted); }
.add-panel .drop-row.busy .drop-status { color: var(--text); }
.add-panel .drop-row.done .drop-status { color: #8fd6a0; }
.add-panel .drop-row.done a { color: inherit; }
.add-panel .drop-row.failed .drop-status { color: #ff9a8a; }
html[data-mode="light"] .add-panel { background: rgba(250,251,252,.96); border-color: rgba(0,0,0,.15); color: #1b2126; }
html[data-mode="light"] .add-panel .kind, html[data-mode="light"] .add-panel .x { color: #1b2126; border-color: rgba(0,0,0,.25); }
html[data-mode="light"] .drop-over { background: rgba(240,244,247,.8); }

/* ================= phones: music-app layout (phone.js) =================
   Store pages only (html.store; the Player keeps its own bar). A mini player floats along the bottom and opens into
   a full-screen Now Playing sheet; rows play on a tap with their options behind a dots button; the list page has a
   header and shelves of covers above the list. Same glass, record and visualizer as everywhere else. Sizes are
   before the UI zoom (x1.25). Desktop: none of these parts show. */
.np-head, .more, .m-top, .m-shelves, .m-cart { display: none; }
@media (max-width: 760px) {
  /* ---- mini player ---- */
  html.store .toolbar {
    left: 6px; right: 6px; bottom: calc(6px + env(safe-area-inset-bottom) / 1.25);
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto auto; grid-template-areas: "art title prev play next" "art sub prev play next";
    gap: 0 8px; align-items: center; padding: 8px 8px 8px 6px; border: 1px solid #000; border-radius: 10px; overflow: hidden; cursor: pointer;
    box-shadow: inset 0 1px 0 var(--edge), 0 8px 24px rgba(0,0,0,.6), var(--np-backing); }
  /* A backing drawn by the floating player itself (so it always matches its size): solid in the gaps beside and below it
     (down past the home bar), a soft fade above, so the page scrolling by never shows around it or seems to load over it. */
  html.store { --np-backing: 0 40px 0 6px #000, 0 -6px 18px 6px rgba(0,0,0,.85); }
  html.store[data-mode="light"] { --np-backing: 0 40px 0 6px #e9eef2, 0 -6px 18px 6px rgba(233,238,242,.9); }
  /* The mini player is its own compositor layer, so page scrolling and the address bar sliding never repaint or shift it. */
  html.store .toolbar { transform: translateZ(0); will-change: transform, opacity; contain: layout paint; }
  html.store { overscroll-behavior-y: none; } /* no rubber-band pulling the page away from the fixed player */
  html.store .toolbar:not(.show) { visibility: hidden; } /* nothing played yet: no empty player */
  html.store[data-mode="light"] .toolbar { border-color: #a3adb5; box-shadow: inset 0 1px 0 #fff, 0 6px 18px rgba(60,80,95,.25), var(--np-backing); }
  html.store .toolbar :is(.transport, .lcd, .lcd-text) { display: contents; }
  html.store .toolbar :is(#p-prev, #p-shuffle, #p-cur, #p-dur) { display: none; }
  html.store:not(.np-open) .toolbar #p-next { grid-area: next; width: 40px; height: 40px; font-size: 14px; } /* skip, right of play */
  html.store .toolbar :is(.cart-tab, .vol, .right, .np-head) { display: none; } /* apart from the ids: :is() takes its weightiest argument */
  html.store .toolbar #p-vinyl { grid-area: art; width: 38px; height: 38px; margin: 0; pointer-events: none; }
  html.store .toolbar .lcd-title-row { grid-area: title; justify-content: flex-start; align-self: end; }
  html.store .toolbar .lcd-title { pointer-events: none; padding: 0; margin: 0; font-size: 12px; text-shadow: none; }
  html.store .toolbar .lcd-sub { grid-area: sub; align-self: start; text-align: left; font-size: 10.5px; }
  html.store .toolbar .lcd-title-row .edit { display: none; }
  html.store .toolbar #p-buy { grid-area: buy; min-height: 0; padding: 10px 14px; font-size: 11.5px; border-radius: 16px; }
  html.store .toolbar #p-toggle { grid-area: play; width: 44px; height: 44px; font-size: 15px; }
  html.store .toolbar .lcd-row { position: absolute; left: 8px; right: 8px; bottom: 3px; display: block; margin: 0; pointer-events: none; }
  html.store .toolbar .lcd .bar { height: 2px; border: 0; border-radius: 1px; background: rgba(255,255,255,.14); box-shadow: none; }
  html.store .toolbar .lcd .bar::before { content: none; }
  html.store[data-mode="light"] .toolbar .lcd .bar { background: rgba(0,0,0,.12); }
  html.store body { padding-bottom: calc(124px + env(safe-area-inset-bottom)); }
  html.store .to-top { bottom: calc(78px + env(safe-area-inset-bottom)); }
  html.store .sitefoot { bottom: calc(80px + env(safe-area-inset-bottom)); }

  /* ---- Now Playing (the same toolbar, full screen) ---- */
  /* No overflow: hidden on the page while it is open: switching it on the root rebuilt and laid out the whole page (a
     quarter of a second on a phone, just as a swipe began or ended). The sheet covers the screen and keeps every touch
     on it to itself (touch-action below), so the page can't be scrolled under it anyway. */
  /* Only the visualizer behind the sheet (np-peek: it is sliding away, phone.js). The page is clipped away as one piece:
     hiding every element in it (visibility on main *) restyled thousands of rows the moment the sheet opened or a drag
     began, a 100 ms stall that made the swipe stutter. */
  html.store.np-open:not(.np-peek) main { clip-path: inset(0 0 100% 0); }
  html.store.np-open:not(.np-peek) :is(.sitefoot, .to-top) { visibility: hidden !important; }
  /* While the sheet moves (phone.js): a solid backing on the sheet, so the page under it never shows through, and a
     dimming layer over the page that darkens as the sheet rises. Both only fade (opacity), so a swipe never repaints the page. */
  html.store.np-open .toolbar::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: 0;
    background: linear-gradient(180deg, #16181b 0%, #0c0d0f 55%, #060607 100%); transition: opacity .22s ease-out; }
  html.store.np-open[data-mode="light"] .toolbar::before { background: linear-gradient(180deg, #f3f6f8 0%, #e6ebef 55%, #dde3e8 100%); }
  html.store.np-solid .toolbar::before { opacity: 1; transition: none; }
  html.store.np-solid.np-solid-fade .toolbar::before { transition: opacity .14s linear; } /* the open sheet going solid as a drag starts */
  .np-scrim { position: fixed; inset: 0; z-index: 13; background: #000; opacity: 0; pointer-events: none; will-change: opacity; }
  html:not(.np-peek) .np-scrim { visibility: hidden; }
  /* With the visualizer on, it slides with the sheet (phone.js): its canvases come up over the page and the dimming,
     under the sheet, on the page's own background (.np-under, so the page never shows through them), all moved by the
     sheet's travel. The sheet keeps its see-through look all the way. */
  html.np-vizmove :is(#viz, #viz-egg) { z-index: 14; will-change: transform; }
  .np-under { display: none; }
  html.np-vizmove .np-under { display: block; position: fixed; inset: 0; z-index: 13; pointer-events: none; background: rgb(6, 5, 8); will-change: transform; }
  html.np-vizmove[data-mode="light"] .np-under { background: #e9eef2; }
  html.store.np-open .toolbar {
    inset: 0; border: 0; border-radius: 0; cursor: auto; z-index: 15;
    grid-template-columns: repeat(2, minmax(0, 1fr)) minmax(0, 1.2fr) repeat(2, minmax(0, 1fr)); grid-template-rows: auto minmax(0, 1fr) auto auto auto auto; /* the play column a little wider: even gaps along the button row */
    grid-template-areas: "head head head head head" "art art art art art" "title title title title title" "sub sub sub sub sub" "bar bar bar bar bar" "shuf prev play next cart";
    --np-buy-w: 72px; /* Buy sits over the right end of the title and sub lines, which keep this lane (and a gap) clear */
    gap: 2px 0; padding: calc(8px + env(safe-area-inset-top) / 1.25) 18px calc(26px + env(safe-area-inset-bottom) / 1.25);
    background: linear-gradient(180deg, rgba(6,7,8,.55) 0%, rgba(6,7,8,.12) 22%, rgba(6,7,8,.12) 52%, rgba(6,7,8,.8) 78%, rgba(4,4,5,.92) 100%);
    box-shadow: none; } /* see-through: the visualizer plays around the record; darker under the text and buttons */
  html.store.np-open[data-mode="light"] .toolbar { background: linear-gradient(180deg, rgba(240,243,245,.6) 0%, rgba(240,243,245,.15) 22%, rgba(240,243,245,.15) 52%, rgba(240,243,245,.82) 78%, rgba(233,238,242,.94) 100%); }
  html.store.np-open .toolbar { backdrop-filter: none; -webkit-backdrop-filter: none; }
  html.store.np-open .toolbar .np-head { grid-area: head; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
  .np-head button { width: 44px; height: 44px; display: inline-grid; place-items: center; border-radius: 50%; color: var(--text); }
  .np-head button svg.ic { width: 20px; height: 20px; vertical-align: 0; }
  .np-head button { flex: none; }
  .np-from { flex: 1; text-align: center; line-height: 1.2; min-width: 0; }
  /* each line's tracking also trails its last letter: a matching indent keeps the text truly centred */
  /* The record as big as the column allows (short screens: as the row allows). Like a music app's artwork it eases
     back a little while paused and springs forward when the sound comes back (phone.js sets np-paused). */
  html.store.np-open .toolbar #p-vinyl { width: auto; height: auto; max-width: 100%; max-height: 100%; aspect-ratio: 1; justify-self: stretch; align-self: center;
    margin: 10px 0; pointer-events: auto; transition: transform .55s cubic-bezier(.3,1.35,.5,1); }
  html.store.np-open.np-paused .toolbar #p-vinyl { transform: scale(.84); transition-duration: .4s; transition-timing-function: cubic-bezier(.4,0,.2,1); }
  html.store.np-open .toolbar #p-vinyl::before { box-shadow: 0 22px 50px rgba(0,0,0,.7), 0 4px 10px rgba(0,0,0,.45), 0 0 46px rgba(150,205,255,.14); } /* no box-shadow transition: it scales with the record, and a 50px blur animated repainted every frame */
  html.store.np-open.np-paused .toolbar #p-vinyl::before { box-shadow: 0 10px 26px rgba(0,0,0,.55), 0 2px 6px rgba(0,0,0,.4); }
  html.store.np-open .toolbar #p-vinyl .vinyl-disc { box-shadow: inset 0 0 0 1px rgba(255,255,255,.07); }
  @media (prefers-reduced-motion: reduce) { html.store.np-open .toolbar #p-vinyl, html.store.np-open .toolbar #p-vinyl::before { transition: none; } }
  /* Touch on the player is all the player's own: a drag down on Now Playing follows the finger (and a swipe on the
     mini player opens it or skips) without the page also scrolling, rubber-banding or pulling to refresh under it. */
  html.store .toolbar { touch-action: none; overscroll-behavior: none; }
  html.store.np-open .toolbar .lcd-title { pointer-events: auto; font-size: 19px; line-height: 1.2; text-shadow: 0 0 10px rgba(190,225,255,.2); }
  html.store.np-open[data-mode="light"] .toolbar .lcd-title { text-shadow: none; }
  html.store.np-open .toolbar .lcd-title-row { margin-top: 10px; }
  /* No rule here may end on a class the list rows share (.admin-tools did): flipping np-open then restyled every row. */
  html.store.np-open .toolbar .lcd-sub { font-size: 11.5px; white-space: normal; }
  html.store.np-open .toolbar #p-buy { grid-area: 3 / 5 / 5 / 6; align-self: center; justify-self: end; width: var(--np-buy-w); padding: 12px 0; font-size: 12.5px; }
  html.store.np-open .toolbar :is(.lcd-title-row, .lcd-sub) { padding-right: calc(var(--np-buy-w) + 12px); } /* long names end in "…" before Buy, never under it */
  html.store.np-open .toolbar .lcd-row { position: static; grid-area: bar; display: grid; grid-template-columns: 1fr 1fr; grid-template-areas: "bar bar" "cur dur";
    gap: 6px 0; margin: 14px 0 6px; pointer-events: auto; }
  html.store.np-open .toolbar :is(#p-cur, #p-dur) { display: block; }
  html.store.np-open .toolbar #p-cur { grid-area: cur; text-align: left; }
  html.store.np-open .toolbar #p-dur { grid-area: dur; text-align: right; }
  html.store.np-open .toolbar .lcd .bar { grid-area: bar; height: 6px; border: 1px solid #000; border-radius: 3px; background: #15181a; box-shadow: inset 0 1px 2px rgba(0,0,0,.8), 0 1px 0 rgba(255,255,255,.06); }
  html.store.np-open[data-mode="light"] .toolbar .lcd .bar { background: #f7f8f5; border-color: #8b949b; box-shadow: inset 0 1px 2px rgba(0,0,0,.2); }
  html.store.np-open .toolbar .lcd .bar::before { content: ""; inset: -14px 0; }
  html.store.np-open .toolbar :is(#p-shuffle, #p-prev, #p-next, .cart-tab) { display: inline-flex; align-items: center; justify-content: center; width: 46px; height: 46px; font-size: 16px; place-self: center; }
  html.store.np-open .toolbar #p-shuffle { grid-area: shuf; }
  html.store.np-open .toolbar #p-prev { grid-area: prev; }
  html.store.np-open .toolbar #p-next { grid-area: next; }
  html.store.np-open .toolbar .cart-tab { grid-area: cart; display: inline-grid; place-items: center; }
  html.store.np-open .toolbar .cart-tab::before { width: 19px; height: 19px; } /* in step with the bigger buttons beside it */
  html.store.np-open .toolbar #p-toggle { grid-area: play; width: 64px; height: 64px; font-size: 23px; place-self: center; }
  html.free.store.np-open .toolbar .cart-tab { display: none !important; }

  /* ---- list page header ---- */
  html.store .m-top { display: flex; align-items: center; justify-content: space-between; padding: 12px 0 6px; }
  .m-brand { font-family: "Michroma", var(--ui); font-size: 17px; letter-spacing: .28em; text-transform: uppercase; color: var(--page-ink); text-shadow: var(--page-halo); }
  .m-top-btns { display: flex; gap: 12px; }
  html.store .m-icon { display: inline-grid; place-items: center; width: 42px; height: 42px; padding: 0; }
  html.store .m-icon svg.ic { width: 18px; height: 18px; vertical-align: 0; }
  html.store .m-cart { position: relative; }
  .m-badge { position: absolute; top: -3px; right: -4px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
    font: 700 9px/16px var(--ui); color: #fff; text-shadow: none; background: linear-gradient(180deg, #e8453c, #a31a14); border: 1px solid #000; }
  .m-badge[hidden] { display: none; }
  html.store .beat-tools .m-cart { display: inline-grid; margin-left: auto; align-self: center; margin-bottom: 12px; }
  html.store .filter-right > .player-link { display: none; } /* it's in the header */

  /* ---- search and Beats / Loops chips ---- */
  html.store .filterbar { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "search search" "chips viz" "kind kind";
    gap: 8px; align-items: center; top: 0; padding-top: calc(8px + env(safe-area-inset-top) / 1.25); }
  html.store .filterbar, html.store[data-mode] .filterbar { background: none; backdrop-filter: none; -webkit-backdrop-filter: none; } /* see-through: the visualizer shows behind the search (beats lowfx's fill) */
  html.store .filter-right { display: contents; }
  html.store .search { grid-area: search; width: 100%; padding: 12px 12px 12px 30px; border-radius: 8px; background-position: 10px 50%;
    background-color: transparent; border: 1px solid rgba(255,255,255,.18); box-shadow: none; }
  html.store[data-mode="light"] .search { background-color: transparent; border-color: rgba(0,0,0,.22); box-shadow: none; }
  html.store .search:focus { border-color: rgba(200,230,255,.45); box-shadow: 0 0 10px var(--cool); }
  html.store #count { grid-area: chips; justify-self: start; }
  /* Browse by mood (phone.js): in the page while the search box is in use, never in the pinned bar. */
  html.store .m-moods { display: block; margin: 6px 0 16px; }
  html.store .m-moods[hidden] { display: none; }
  .m-moods h2 { margin: 0 0 8px; font: 700 15px/1.2 var(--ui); color: var(--page-ink); text-shadow: var(--page-halo); }
  .m-moods ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; list-style: none; margin: 0; padding: 0; }
  .m-mood { position: relative; display: flex; flex-direction: column; justify-content: flex-start; width: 100%; height: 64px; padding: 9px 10px; overflow: hidden;
    text-align: left; border-radius: 8px; color: #f2f6f8; border: 1px solid #000; -webkit-tap-highlight-color: transparent;
    background: var(--shine), linear-gradient(180deg, #3a3f44 0%, #16181a 100%); box-shadow: inset 0 1px 0 var(--edge), 0 1px 2px rgba(0,0,0,.8);
    transition: transform .12s ease-out; }
  .m-mood:active { transform: scale(.97); }
  .m-mood-name { font-weight: 700; font-size: 13px; }
  .m-mood-n { font-size: 10px; opacity: .65; }
  .m-mood img { position: absolute; right: -10px; bottom: -12px; width: 56px; height: 56px; border-radius: 50%; transform: rotate(18deg); box-shadow: 0 4px 10px rgba(0,0,0,.5); }
  html[data-mode="light"] .m-mood { color: #1d2328; border-color: #8d979f; background: var(--shine), linear-gradient(180deg, #ffffff 0%, #d9e0e5 100%); box-shadow: inset 0 1px 0 #fff, 0 1px 2px rgba(60,80,95,.35); }
  html.store #loop-kind { grid-area: kind; justify-self: start; }
  html.store #loop-kind[hidden] { display: none; }
  html.store .m-top-btns > :is(#p-vizstyle, #p-switchup) { width: 42px; height: 42px; min-height: 0; padding: 0; border-radius: 50%; justify-content: center; } /* phone.js moves them into the header row */
  html.store .filter-right > #p-listtoggle { display: none; } /* shelves and Now Playing replace the fade-the-list button */
  html.store .filter-right > :is(#p-vizstyle, #p-listtoggle) { width: 42px; height: 42px; min-height: 0; padding: 0; border-radius: 50%; justify-content: center; }
  html.store .cart-btn.list-mode, html.store .cart-btn.list-mode:hover, html.store .cart-btn.list-mode:active { background: none; border: 0; box-shadow: none; padding: 0; gap: 8px; min-height: 0; }
  html.store .kind-switch { display: inline-flex; gap: 8px; }
  html.store :is(.list-mode > span, .kind-switch > button) { padding: 10px 18px; border-radius: 999px; color: #c9d1d6;
    border: 1px solid #000 !important; background: var(--shine), linear-gradient(180deg, #3a3f44 0%, #16181a 100%);
    box-shadow: inset 0 1px 0 var(--edge), 0 1px 2px rgba(0,0,0,.8) !important; }
  html.store[data-mode="light"] :is(.list-mode > span, .kind-switch > button) { color: #2a3238; border-color: #8d979f !important;
    background: var(--shine), linear-gradient(180deg, #ffffff 0%, #d9e0e5 100%); box-shadow: inset 0 1px 0 #fff, 0 1px 2px rgba(60,80,95,.35) !important; }
  html.store :is(.list-mode > span.on, .kind-switch > button.on) { color: #0b0d0e; text-shadow: none;
    background: var(--shine), linear-gradient(180deg, #f4f8fb 0%, #b9c8d3 100%); box-shadow: inset 0 1px 0 #fff, 0 0 12px rgba(150,205,255,.35) !important; }
  html.store[data-mode="light"] :is(.list-mode > span.on, .kind-switch > button.on) { color: #0b2233; text-shadow: none;
    background: var(--shine), linear-gradient(180deg, #ffffff 0%, #cfe6f7 100%); box-shadow: inset 0 0 0 1.5px #2f7fb8, 0 1px 3px rgba(60,80,95,.35) !important; }
  html.store[data-mode="light"] :is(.list-mode > span, .kind-switch > button):not(.on) { color: #33414b; text-shadow: none; }

  /* ---- rows: tap to play, dots for the rest ---- */
  html.store .table { border: 0; border-radius: 10px; box-shadow: none; background: rgba(6,7,8,.55); }
  html.store[data-mode="light"] .table { background: rgba(255,255,255,.6); box-shadow: none; }
  html.store .table .row, html.store .table .row.alt, html.store[data-mode="light"] .table .row { background: transparent; border-bottom: 0; }
  html.store .table .row { grid-template-columns: 42px auto minmax(0, 1fr) 44px; column-gap: 10px; min-height: 58px; padding: 7px 4px 7px 10px; }
  html.store .list .row { contain-intrinsic-size: auto 58px; }
  html.store .table .row > :is(.play, .price-btn, .idx) { display: none; }
  html.store .table .row > img, html.store .table .row > span:empty { grid-area: 1 / 1 / 3 / 2; width: 42px; height: 42px; }
  html.store .table .row > .t-wrap { grid-area: 1 / 2 / 2 / 4; }
  html.store .table .row > .num { grid-area: 2 / 2; }
  html.store .table .row > .key { grid-area: 2 / 3; margin-left: -9px; }
  html.store .table .row .t { font-size: 13px; font-weight: 600; }
  html.store .table .row .admin-tools { display: none; } /* in the dots sheet */
  html.store .table .row > .more { grid-area: 1 / 4 / 3 / 5; display: inline-grid; place-items: center; width: 44px; height: 44px; color: var(--muted); }
  .more > span { width: 3px; height: 3px; border-radius: 50%; background: currentColor; box-shadow: 0 -6px 0 currentColor, 0 6px 0 currentColor; }
  html.store .table .row.playing { background: var(--shine), linear-gradient(180deg, rgba(86,100,112,.92), rgba(40,46,52,.92)); border-radius: 8px; box-shadow: inset 3px 0 0 #a8dcff, inset 0 1px 0 rgba(255,255,255,.18); }
  html.store[data-mode="light"] .table .row.playing { background: var(--shine), linear-gradient(180deg, #d6e8f5, #aecbe0); box-shadow: inset 3px 0 0 #2f7fb8, inset 0 1px 0 #fff; }
  html.store .table .row.playing .t { color: #a8dcff; }
  html.store[data-mode="light"] .table .row.playing .t { color: #154e78; text-shadow: none; }

  /* ---- shelves ---- */
  html.store .m-shelves { display: block; margin: -8px 0 16px; } /* close under the Beats / Loops buttons */
  html.store .m-shelves[hidden] { display: none; }
  html.store .m-shelf[hidden] { display: none; }
  .m-shelf + .m-shelf { margin-top: 16px; }
  .m-shelf[hidden] + .m-shelf { margin-top: 0; } /* one shelf per tab (phone.js syncBrowse) */
  .m-shelf h2 { margin: 0 0 8px; font: 700 15px/1.2 var(--ui); color: var(--page-ink); text-shadow: var(--page-halo); }  .m-shelf-row { display: flex; gap: 12px; list-style: none; margin: -12px -12px -16px; padding: 12px 12px 20px; /* room for the shadows (blur 10px + offset): a scrolling row clips anything past its box */ overflow-x: auto; scroll-snap-type: x proximity; touch-action: pan-x pan-y; /* a swipe that starts on a shelf can still scroll the page (mandatory snapping with contained overscroll trapped it in Safari) */
    scroll-padding-inline: 12px; scrollbar-width: none; }
  .m-shelf-row::-webkit-scrollbar { display: none; }
  .m-shelf-row > li { flex: none; scroll-snap-align: start; }
  .m-card { display: flex; flex-direction: column; align-items: center; gap: 8px; width: 104px; padding: 0; text-align: center; -webkit-tap-highlight-color: transparent; }
  .m-card-art { position: relative; width: 104px; aspect-ratio: 1; border-radius: 50%; overflow: hidden; background: #0d0d0f var(--card-under, none) center / calc(100% / .836) no-repeat; -webkit-mask-image: -webkit-radial-gradient(white, black); isolation: isolate;
    box-shadow: 0 4px 10px rgba(0,0,0,.45); transition: transform .12s ease-out, box-shadow .2s; } /* no border ring, and a shadow that fits the row's padding */
  .m-card-art img { position: absolute; left: calc(50% - 50% / .836); top: calc(50% - 50% / .836); width: calc(100% / .836); max-width: none; aspect-ratio: 1; }
  .m-card:active .m-card-art { transform: scale(.96); }
  .m-card.playing .m-card-art { box-shadow: 0 4px 10px rgba(0,0,0,.45), 0 0 10px rgba(150,205,255,.55); }
  .m-card-t { display: block; width: 100%; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--page-ink); text-shadow: var(--page-halo); }
  .m-card-t { font-size: 12px; font-weight: 700; }
  .m-card.playing .m-card-t { color: #a8dcff; }
  html[data-mode="light"] .m-card.playing .m-card-t { color: #154e78; }

  /* ---- mini player: back, play and skip (Now Playing keeps Buy, the header the cart) ---- */
  html.store:not(.np-open) .toolbar #p-buy { display: none; }
  html.store:not(.np-open) .toolbar #p-prev { grid-area: prev; display: inline-flex; width: 40px; height: 40px; font-size: 14px; }
  /* free copy: its download button keeps that spot instead of back */
  html.free.store:not(.np-open) .toolbar #p-prev { display: none; }
  html.free.store:not(.np-open) .toolbar #p-buy { grid-area: prev; display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0; border-radius: 50%; font-size: 11px; }

  /* ---- beat and loop pages: album style ---- */
  html.store .beat { gap: 10px; padding-top: 0; }
  html.store .beat .info { order: 2; }
  html.store .beat .art { order: 1; max-width: min(280px, 64vw); margin-top: 52px; }
  html.store .beat-tools { position: absolute; top: 10px; left: 10px; right: 10px; margin: 0; flex-wrap: nowrap; }
  html.store .beat { position: relative; }
  html.store .beat-tools > * { margin-bottom: 0 !important; }
  html.store .beat-tools .back { width: 34px; height: 34px; min-height: 0; padding: 0; border-radius: 50%; font-size: 0; display: inline-flex; align-items: center; justify-content: center; gap: 0; letter-spacing: 0; } /* flex, not grid: grid put the chevron and the hidden label in separate rows, lifting the chevron above the middle */
  /* A round back button is flat like the cart beside it: the desktop key's stacked edge showed as a second disc under it. */
  html.store .beat-tools .cart-btn.back, html.store .beat-tools .cart-btn.back:hover, html.store .beat-tools .cart-btn.back:active,
  html.store[data-mode="light"] .beat-tools .cart-btn.back, html.store[data-mode="light"] .beat-tools .cart-btn.back:active {
    box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 2px 6px rgba(0,0,0,.45); transform: none; }
  html.store[data-mode="light"] .beat-tools .cart-btn.back { box-shadow: inset 0 1px 0 #fff, 0 2px 6px rgba(60,80,95,.3); }
  html.store .beat-tools .cart-btn.back:active { transform: scale(.94); }
  html.store .beat-tools .back::before { content: ""; width: 16px; height: 16px; background: currentColor;
    -webkit-mask: var(--chev) center / contain no-repeat; mask: var(--chev) center / contain no-repeat;
    --chev: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27none%27 stroke=%27%23000%27 stroke-width=%272.4%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3E%3Cpath d=%27M15 5l-7 7 7 7%27/%3E%3C/svg%3E"); }
  html.store .beat-tools #p-vizstyle { width: 34px; height: 34px; min-height: 0; padding: 0; border-radius: 50%; margin-left: auto !important; }
  html.store .beat-tools #p-switchup { width: 34px; height: 34px; min-height: 0; padding: 0; border-radius: 50%; } /* the same round size as the visualizer's beside it (phones used to hide it, so it never got one) */
  html.store .beat-tools .m-cart { margin-left: 10px; }
  html.store .beat .info > #beat-play { width: 56px; height: 56px; font-size: 20px; }
  html.store .beat h1 { font-size: 26px; margin-top: 6px; }
  html.store .beat .tiers { margin-top: 18px; border: 0; border-radius: 10px; box-shadow: none; background: rgba(6,7,8,.6); }
  html.store[data-mode="light"] .beat .tiers { background: rgba(255,255,255,.65); box-shadow: none; }
  html.store .tier, html.store .tier:nth-child(even), html.store[data-mode="light"] .tier { background: transparent; flex-wrap: nowrap; padding: 12px 14px; }
  html.store .tier + .tier { border-top: 1px solid rgba(127,127,127,.16); }
  html.store .tier .name { font-size: 13px; }
  html.store .tier .terms { font-size: 10.5px; line-height: 1.35; }
  html.store .tier .add { min-width: 0; padding: 8px 16px; flex: none; }
  html.store .similar { margin-top: 22px; }
  html.store .similar h2 { font: 700 15px/1.2 var(--ui); letter-spacing: 0; text-transform: none; }
  html.store .similar-list { display: flex; justify-content: safe center; gap: 12px; margin: -10px -10px -14px; padding: 10px 10px 18px; overflow-x: auto; scrollbar-width: none; scroll-snap-type: x mandatory; }
  html.store .similar-list::-webkit-scrollbar { display: none; }
  html.store .similar-item { flex: none; flex-direction: column; align-items: center; gap: 6px; width: 104px; padding: 0; border: 0; scroll-snap-align: start; }
  html.store .similar-item:hover, html.store .similar-item:focus-visible { background: none; }
  html.store .similar-item img { width: 104px; height: 104px; filter: drop-shadow(0 6px 10px rgba(0,0,0,.5)); }
  html.store .similar-item span { max-width: 100%; font-weight: 700; }

  /* ---- cart: a bottom sheet ---- */
  html.store .drawer { inset: auto 0 0 0; width: auto; max-height: 82vh; border-left: 0; border-top: 1px solid #000; border-radius: 14px 14px 0 0;
    padding-bottom: calc(env(safe-area-inset-bottom) / 1.25); transform: translateY(100%); box-shadow: inset 0 1px 0 var(--edge), 0 -10px 30px rgba(0,0,0,.6); }
  html.store .drawer.open { transform: none; }
  html.store .drawer.dragging { transition: none; }
  html.store .drawer header { flex-wrap: wrap; padding-top: 6px; }
  html.store .drawer header .m-grab { flex: 1 1 100%; margin-bottom: 4px; }
  /* The cart sheet in the phone's own look: round covers and 44px targets like the list rows, one raised pill to pay. */
  html.store .drawer header { align-items: center; padding: 6px 16px 10px; }
  html.store .drawer header strong { font-size: 15px; }
  html.store .drawer header .x { width: 44px; height: 44px; margin-right: -10px; display: inline-grid; place-items: center; border-radius: 50%; font-size: 22px; }
  html.store .drawer .items { padding: 4px 6px; overscroll-behavior: contain; }
  html.store .drawer .items > p { padding: 28px 10px; text-align: center; font-size: 13px; }
  html.store .drawer .line, html.store .drawer .line:nth-child(even) { gap: 12px; min-height: 58px; padding: 7px 4px 7px 10px; border: 0; border-radius: 8px; background: transparent; }
  html.store .drawer .line-cover { width: 44px; height: 44px; }
  html.store .drawer .line-title { font-size: 13px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
  html.store .drawer .line-title .muted { font-size: 11px; font-weight: 400; }
  html.store .drawer .line-price { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
  html.store .drawer .line .x { width: 44px; height: 44px; display: inline-grid; place-items: center; border-radius: 50%; font-size: 20px; }
  html.store .drawer footer { padding: 12px 16px 14px; border-top: 1px solid rgba(127,127,127,.22); box-shadow: none; }
  html.store .drawer footer p { margin: 0 0 8px; }
  html.store .drawer footer .deal { font-size: 11px; }
  html.store .drawer footer .sum { font-size: 14px; margin-bottom: 12px; }
  html.store .drawer footer .sum strong { font-size: 20px; font-variant-numeric: tabular-nums; }
  html.store .drawer .checkout { min-height: 50px; padding: 0 18px; border-radius: 999px; font-size: 14px; font-weight: 700; color: #0b0d0e; text-shadow: none;
    border: 1px solid #000; background: var(--shine), linear-gradient(180deg, #f4f8fb 0%, #b9c8d3 100%); box-shadow: inset 0 1px 0 #fff, 0 0 12px rgba(150,205,255,.35); }
  html.store .drawer .checkout:disabled { opacity: .6; }
  html.store[data-mode="light"] .drawer .checkout { color: #0b2233; border-color: #8d979f; background: var(--shine), linear-gradient(180deg, #ffffff 0%, #cfe6f7 100%);
    box-shadow: inset 0 0 0 1.5px #2f7fb8, 0 1px 3px rgba(60,80,95,.35); }
  html.store.cart-open body::after { content: ""; position: fixed; inset: 0; z-index: 19; background: rgba(0,0,0,.55); }
}

/* ---- the dots action sheet (phones; opened from a row or Now Playing) ---- */
.m-sheet { zoom: 1.25; position: fixed; inset: auto 0 0 0; width: auto; max-width: none; max-height: 80vh; margin: 0; overflow: auto;
  padding: 6px 0 calc(10px + env(safe-area-inset-bottom) / 1.25); border: 1px solid #000; border-bottom: 0; border-radius: 14px 14px 0 0; color: var(--text);
  background: var(--shine), linear-gradient(180deg, #2a2e32, #0e1011); box-shadow: inset 0 1px 0 var(--edge), 0 -10px 30px rgba(0,0,0,.6); }
.m-sheet::backdrop { background: rgba(0,0,0,.55); }
html[data-mode="light"] .m-sheet { background: var(--shine), linear-gradient(180deg, #ffffff, #dfe5e9); border-color: #9aa4ac; }
.m-grab { width: 36px; height: 4px; margin: 2px auto 10px; border-radius: 2px; background: rgba(127,127,127,.45); }
.m-sheet-head { display: flex; align-items: center; gap: 12px; padding: 2px 16px 12px; border-bottom: 1px solid rgba(127,127,127,.18); }
.m-sheet-head img, .m-noart { width: 44px; height: 44px; flex: none; border-radius: 50%; object-fit: cover; background: #0d0d0f; }
.m-sheet-head div { min-width: 0; }
.m-sheet-head b { display: block; font-size: 13px; overflow-wrap: anywhere; }
.m-sheet-head small { display: block; color: var(--muted); font-size: 11px; }
.m-acts { padding-top: 4px; }
.m-act { display: flex; align-items: center; gap: 14px; width: 100%; padding: 12px 16px; font-size: 13px; text-align: left; -webkit-tap-highlight-color: transparent; }
.m-act:active, .m-act:focus-visible { background: rgba(127,127,127,.12); outline: none; }
.m-act svg.ic { width: 20px; height: 20px; flex: none; vertical-align: 0; }
.m-act-note { margin-left: auto; color: var(--muted); font-variant-numeric: tabular-nums; }
@media (max-width: 380px) { .m-sheet { zoom: 1.1; } }


/* ---- cleaned-up glass: brighter, glossier buy buttons; even pill shapes; roomier list ---- */
.price-btn, .add:not(.ghost), .lcd-buy, .checkout {
  color: #0b0d0e; text-shadow: 0 1px 0 rgba(255,255,255,.6); border-color: #000;
  background: var(--shine), linear-gradient(180deg, #f4f8fb 0%, #b9c8d3 100%);
  box-shadow: inset 0 1px 0 #fff, 0 0 12px rgba(150,205,255,.3), 0 1px 2px rgba(0,0,0,.8); }
:is(.price-btn, .add:not(.ghost), .lcd-buy, .checkout):hover {
  background: var(--shine), linear-gradient(180deg, #ffffff 0%, #cbd8e1 100%);
  box-shadow: inset 0 1px 0 #fff, 0 0 16px rgba(150,205,255,.5), 0 1px 2px rgba(0,0,0,.8); }
html[data-mode="light"] :is(.price-btn, .add:not(.ghost), .lcd-buy, .checkout) {
  color: #0b2233; border-color: #5f7d93; background: var(--shine), linear-gradient(180deg, #ffffff 0%, #cfe6f7 100%);
  box-shadow: inset 0 0 0 1px rgba(47,127,184,.35), 0 1px 3px rgba(60,80,95,.35); }
.price-btn, .add, .lcd-buy, .cart-btn { border-radius: 999px; }
.add { padding: 6px 16px; }
@media (min-width: 601px) { .row { height: 40px; } .row img { width: 32px; height: 32px; } .row .t { font-size: 12.5px; } }
.table, .tiers { border-radius: 10px; }

/* ---- Stripe banner under the licences on beat and loop pages ---- */
.pay-banner { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; margin: 12px 0 0; padding: 9px 12px; border-radius: 10px;
  font-size: 11px; color: #c9d1d6; border: 1px solid #000; background: var(--shine), linear-gradient(180deg, rgba(40,44,48,.85), rgba(10,11,12,.92));
  box-shadow: inset 0 1px 0 var(--edge), 0 1px 2px rgba(0,0,0,.6); }
.pay-banner .lock { width: 13px; height: 13px; vertical-align: 0; }
.pay-banner .stripe { font: italic 800 15px/1 var(--ui); letter-spacing: -.03em; color: #9b94ff; }
.pay-banner .cards { display: inline-flex; gap: 4px; margin-left: auto; }
.pay-banner .cards .card { width: 34px; height: 22px; display: block; border-radius: 3px; box-shadow: 0 0 0 1px rgba(255,255,255,.15); }
html[data-mode="light"] .pay-banner { color: #2a3137; border-color: #9aa4ac; background: var(--shine), linear-gradient(180deg, #ffffff, #dfe5e9); box-shadow: inset 0 1px 0 #fff; }
html[data-mode="light"] .pay-banner .stripe { color: #635bff; }
html[data-mode="light"] .pay-banner .cards .card { box-shadow: 0 0 0 1px #c3cbd1; }

/* ---- buttons that feel physical: lift and brighten under the pointer, sink in at once when pressed (darker,
   shadow pulled in), spring back on release. Transform and shadow only, so it stays smooth. ---- */
:is(.tbtn, .lcd-buy, .cart-btn:not(.list-mode), .play, .price-btn, .add, .checkout, .btn, .mode-btn) {
  transition: transform .22s cubic-bezier(.34, 1.56, .64, 1), box-shadow .18s ease, background .18s ease, filter .18s ease; }
@media (hover: hover) {
  :is(.tbtn, .lcd-buy, .cart-btn:not(.list-mode), .play, .price-btn, .add, .checkout, .btn, .mode-btn):hover {
    transform: translateY(-1px); filter: brightness(1.12); }
  .row .play:hover, .row .price-btn:hover { transform: translateY(-1px); }
}
:is(.tbtn, .lcd-buy, .cart-btn:not(.list-mode), .play, .price-btn, .add, .checkout, .btn, .mode-btn):active,
.row :is(.play, .price-btn):active {
  transform: translateY(1px) scale(.95); filter: brightness(.9); transition-duration: .06s;
  box-shadow: inset 0 2px 4px rgba(0,0,0,.55), 0 0 0 rgba(0,0,0,0) !important; }
:is(.price-btn, .add:not(.ghost), .lcd-buy, .checkout):active { box-shadow: inset 0 2px 5px rgba(60,80,95,.45) !important; }
.cart-btn.back:hover { transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) {
  :is(.tbtn, .lcd-buy, .cart-btn, .play, .price-btn, .add, .checkout, .btn, .mode-btn):is(:hover, :active) { transform: none; }
}

/* the top player's disc stays hidden until a track is loaded (nothing to show on a fresh page) */
html:not(#_) .vinyl.mini.empty, html:not(#_) .vinyl.mini.empty * { visibility: hidden !important; }
/* ...and its Buy button too: nothing to buy until a track is picked (keeps its space, so nothing shifts when it appears) */
html:not(#_) .lcd:has(#p-vinyl.empty) #p-buy { visibility: hidden; }


/* ---- phone polish: a frosted pinned search bar, row press feedback, a tidy pay banner ---- */
@media (max-width: 760px) {
  /* Rows answer a tap at once; no grey system flash. */
  html.store .table .row { -webkit-tap-highlight-color: transparent; border-radius: 8px; }
  html.store .table .row.nav-going:not(.playing), html.store .m-card.nav-going .m-card-art { background-color: rgba(127,127,127,.16); }
  html.store .table .row > .more:active { background: rgba(127,127,127,.18); border-radius: 50%; }
  html.store :is(button, a, .m-card, .m-mood) { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
  /* Pay banner: the card marks sit centred on their own line, not hanging off the right. */
  html.store .pay-banner { justify-content: center; text-align: center; }
  html.store .pay-banner .cards { margin-left: 0; flex-basis: 100%; justify-content: center; }
}

/* A page on its way (app.js navPending): a thin bar slides along the top until it swaps in. Movement only, no flashing. */
html.nav-wait body::before { content: ""; position: fixed; top: 0; left: 0; z-index: 50; width: 40%; height: 2px; pointer-events: none;
  background: linear-gradient(90deg, transparent, #a8dcff, transparent); animation: nav-wait 1s linear infinite; }
html[data-mode="light"].nav-wait body::before { background: linear-gradient(90deg, transparent, #2f7fb8, transparent); }
@keyframes nav-wait { from { transform: translateX(-100%); } to { transform: translateX(250%); } }
@media (prefers-reduced-motion: reduce) { html.nav-wait body::before { animation: none; width: 100%; opacity: .6; } }
.similar-item.nav-going, .back.nav-going { opacity: .7; }

/* ---- proportions: the phone layout starts at 760px but some of its list rules only started at 600px, so between the
   two (small tablets, narrow windows) the column header showed over rows it no longer lined up with and BPM ran into
   the key ("151D minor"). They now apply wherever the phone layout does. ---- */
@media (max-width: 760px) {
  html.store .thead { display: none; }
  html.store .table .row > .num { display: block; font-size: 10.5px; color: var(--muted); text-align: left; }
  html.store .table .row > .num:not(:empty)::after { content: " BPM"; }
  html.store .table .row > .key { display: block; font-size: 10.5px; margin-left: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  html.store .table .row > .num:not(:empty) + .key:not(:empty)::before { content: "· "; }
  html.store .table .row > .t-wrap { align-self: end; }
  html.store .table .row > :is(.num, .key) { align-self: start; }
}
@media (max-width: 760px) {
  html.store .table .row > .key { margin-left: -6px; } /* "140 BPM · E minor" reads as one line, not two columns */
  /* the price on every row, beside the dots: what a beat costs, and buying it, without opening a menu */
  html.store .table .row { grid-template-columns: 42px auto minmax(0, 1fr) auto 36px; }
  html.store .table .row > .price-btn { display: inline-flex; align-items: center; grid-area: 1 / 4 / 3 / 5; align-self: center; padding: 6px 11px; font-size: 11px; min-height: 32px; }
  html.store .table .row > .listen-tag { grid-area: 1 / 4 / 3 / 5; align-self: center; }
  html.store .table .row > .t-wrap { grid-area: 1 / 2 / 2 / 4; }
  html.store .table .row > .more { grid-area: 1 / 5 / 3 / 6; width: 36px; }
}

/* ================= the feed (feed.js): one beat per screen, swipe for the next =================
   Wide screens: a full-height column down the left, the store beside it. Phones and smaller windows: a full-screen
   sheet opened from the Feed button. Each card snaps into place; the playing one's CD spins and a thin bar shows
   how far through the beat it is. */
.feed { display: none; flex-direction: column; color: var(--text); z-index: 16;
  background: var(--shine), linear-gradient(180deg, rgba(20,22,24,.96), rgba(4,5,6,.98)); border-right: 1px solid #000;
  box-shadow: inset -1px 0 0 rgba(255,255,255,.06), 8px 0 30px rgba(0,0,0,.5); }
html[data-mode="light"] .feed { background: var(--shine), linear-gradient(180deg, #f7f9fa, #dfe5e9); border-color: #9aa4ac; box-shadow: inset -1px 0 0 #fff, 6px 0 20px rgba(60,80,95,.15); }
.feed-head { display: flex; align-items: baseline; gap: 10px; padding: 14px 16px 10px; border-bottom: 1px solid rgba(127,127,127,.18); }
.feed-head b { font-family: "Michroma", var(--ui); font-size: 13px; letter-spacing: .24em; text-transform: uppercase; }
.feed-head small { color: var(--muted); font-size: 11.5px; flex: 1; }
.feed-close { display: none; width: 40px; height: 40px; margin: -8px -8px -8px 0; border-radius: 50%; font-size: 24px; line-height: 1; color: var(--muted); }
.feed-list { flex: 1; min-height: 0; overflow-y: auto; scroll-snap-type: y mandatory; overscroll-behavior: contain; scrollbar-width: none; outline: none; }
.feed-list::-webkit-scrollbar { display: none; }
.feed-card { position: relative; height: 100%; scroll-snap-align: start; scroll-snap-stop: always; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 22px; padding: 24px 22px 30px; cursor: pointer; box-sizing: border-box; outline: none;
  -webkit-tap-highlight-color: transparent; }
.feed-card + .feed-card { border-top: 1px solid rgba(127,127,127,.12); }
.feed-cd { width: min(78%, 46vh, 290px); flex: none; }
/* The playing card's record turns with every other record, on the same clock (app.js, vinyl.js). */
@media (prefers-reduced-motion: reduce) { .feed-card .feed-cd .vinyl-disc img { animation: none !important; } }
.feed-cd::before { box-shadow: 0 18px 40px rgba(0,0,0,.6), 0 3px 8px rgba(0,0,0,.45); }
.feed-info { width: 100%; text-align: center; }
.feed-title { margin: 0 0 4px; font: 700 26px/1.1 var(--ui); letter-spacing: -.01em; overflow-wrap: anywhere; }
.feed-by { margin: 0 0 2px; color: var(--muted); font-size: 12px; }
.feed-meta { margin: 0 0 16px; font-size: 12.5px; font-weight: 600; }
.feed-acts { display: flex; justify-content: center; gap: 10px; }
.feed-buy { padding: 10px 20px !important; font-size: 13px !important; min-height: 42px; }
.feed-open { padding: 10px 18px; font-size: 12.5px; display: inline-flex; align-items: center; min-height: 42px; }
.feed-progress { position: absolute; left: 22px; right: 22px; bottom: 14px; height: 3px; border-radius: 2px; background: rgba(127,127,127,.2); overflow: hidden; opacity: 0; transition: opacity .2s; }
.feed-progress i { display: block; height: 100%; background: currentColor; transform-origin: left; transform: scaleX(0); }
.feed-card.playing .feed-progress { opacity: .8; }
.feed-btn { display: none; }
/* Before the visitor starts it, the first card invites a tap. */
.feed:not(.live) .feed-card:first-child .feed-meta::after { content: "Tap to play · swipe for more"; display: block; margin-top: 6px; color: var(--muted); font-weight: 400; font-size: 11.5px; }

@media (max-width: 1199px) {
  .feed-btn { display: inline-flex; align-items: center; }
  html.feed-open .feed { display: flex; position: fixed; inset: 0; padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); }
  html.feed-open, html.feed-open body { overflow: hidden; }
  .feed-close { display: inline-grid; place-items: center; }
  .feed-cd { width: min(76vw, 46vh, 340px); }
  .feed-title { font-size: 28px; }
}
@media (min-width: 601px) and (max-width: 1199px) { .filterbar .feed-btn { order: 2; } }
@media (max-width: 760px) { html.store .filter-right > .feed-btn { grid-area: viz; justify-self: end; min-height: 40px; padding: 0 16px; border-radius: 999px; } }
/* the full-screen feed is solid: the list behind never shows through */
@media (max-width: 1199px) {
  html.feed-open .feed { background: var(--shine), linear-gradient(180deg, #16181a, #040506); }
  html.feed-open[data-mode="light"] .feed { background: var(--shine), linear-gradient(180deg, #f7f9fa, #dfe5e9); }
}

/* ---- the feed over the visualizer: see-through, so the music's visualizer plays behind every card; a dark wash only
   where the text and buttons sit keeps them readable over any picture. Full screen, the page under it is hidden, so
   it is just the visualizer, the disc and the beat. ---- */
.feed, html[data-mode="light"] .feed { background: linear-gradient(180deg, rgba(4,5,6,.55) 0%, rgba(4,5,6,.12) 18%, rgba(4,5,6,.12) 45%, rgba(4,5,6,.78) 72%, rgba(4,5,6,.9) 100%); }
html[data-mode="light"] .feed { background: linear-gradient(180deg, rgba(240,243,245,.6) 0%, rgba(240,243,245,.15) 18%, rgba(240,243,245,.15) 45%, rgba(240,243,245,.82) 72%, rgba(233,238,242,.92) 100%); }
@media (max-width: 1199px) {
  html.feed-open .feed { background: linear-gradient(180deg, rgba(4,5,6,.55) 0%, rgba(4,5,6,.1) 16%, rgba(4,5,6,.1) 46%, rgba(4,5,6,.8) 72%, rgba(4,5,6,.92) 100%); }
  html.feed-open[data-mode="light"] .feed { background: linear-gradient(180deg, rgba(240,243,245,.6) 0%, rgba(240,243,245,.12) 16%, rgba(240,243,245,.12) 46%, rgba(240,243,245,.84) 72%, rgba(233,238,242,.94) 100%); }
  html.feed-open :is(main, .sitefoot, .to-top, .toolbar) { visibility: hidden !important; }
}
.feed-title, .feed-meta { text-shadow: var(--page-halo); }
.feed-by { color: var(--page-ink); opacity: .75; text-shadow: var(--page-halo); }
/* each card is clear, so the visualizer shows through its middle; the card divider is dropped (it cut the picture) */
.feed-card + .feed-card { border-top: 0; }
html.immersive .feed { opacity: 1; } /* the feed is the visualizer's frame: it never fades with the rest of the page */
@media (max-width: 1199px) { html.feed-open:not(#_):not(#_) :is(main, .toolbar) :is(img, .vinyl, .vinyl-disc) { visibility: hidden !important; } } /* the list's discs are forced visible elsewhere */

/* ---- the feed by swipe (phones and smaller windows): it follows the finger in from the left while dragged
   (html.feed-dragging, feed.js). No tab on the edge. ---- */
@media (max-width: 1199px) {
  .feed-btn { display: none !important; }
  html.feed-dragging .feed { display: flex; position: fixed; inset: 0; will-change: transform; }
  html.feed-dragging:not(.feed-open) .feed { transform: translate3d(-100%, 0, 0); }
  html.feed-open .feed { animation: none; }
}

/* ---- glass buttons (dark mode): see-through frosted pills with a bright top edge and a soft drop shadow, so they sit
   in the 2000s glass of the page; the buy buttons a little brighter and bolder. The Beats / Loops switch keeps its own look. ---- */
html:not(#_):not(#_):not([data-mode="light"]) :is(.tbtn, .lcd-buy, .mode-btn, .cart-btn:not(.list-mode), .row .play, .row .price-btn, .add, .checkout) {
  background: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.04)) !important; color: #eef1f3 !important; text-shadow: none !important;
  border: 1px solid rgba(255,255,255,.14) !important; box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 2px 8px rgba(0,0,0,.35) !important;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
html:not(#_):not(#_):not([data-mode="light"]) :is(.row .price-btn, .lcd-buy, .add:not(.ghost), .checkout) {
  background: linear-gradient(180deg, rgba(255,255,255,.3), rgba(255,255,255,.1)) !important; font-weight: 700; }
html:not(#_):not(#_):not([data-mode="light"]) :is(.tbtn, .lcd-buy, .mode-btn, .cart-btn:not(.list-mode), .row .play, .row .price-btn, .add, .checkout):hover {
  background: linear-gradient(180deg, rgba(255,255,255,.24), rgba(255,255,255,.08)) !important; }
html:not(#_):not(#_):not([data-mode="light"]) :is(.tbtn, .lcd-buy, .mode-btn, .cart-btn:not(.list-mode), .row .play, .row .price-btn, .add, .checkout):active {
  background: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.12)) !important; box-shadow: inset 0 2px 4px rgba(0,0,0,.45) !important; }

/* ---- pressing a button: it dips with a soft inner shadow, a warm glow spreads from the spot pressed (--px / --py, set by
   app.js) and fades, and the button settles back with a small spring. Gentle and short, no bright flash. ---- */
:is(.glassbtn, .tbtn, .lcd-buy, .cart-btn, .play, .price-btn, .add, .checkout, .btn, .files a, .mode-btn) { position: relative; }
html:not(#_):not(#_) :is(.glassbtn, .tbtn, .lcd-buy, .cart-btn:not(.list-mode), .play, .price-btn, .add, .checkout, .btn, .files a, .mode-btn) {
  transition: transform .38s cubic-bezier(.3, 1.6, .5, 1), box-shadow .2s ease, background .2s ease, filter .2s ease; }
html:not(#_):not(#_) :is(.glassbtn, .tbtn, .lcd-buy, .cart-btn:not(.list-mode), .play, .price-btn, .add, .checkout, .btn, .files a, .mode-btn):active {
  transform: translateY(1px) scale(.94); filter: brightness(.92); transition: transform .07s ease-out, box-shadow .07s ease-out, filter .07s ease-out; }
html:not(#_) .pop::after { inset: 0; box-shadow: none; transform-origin: var(--px, 50%) var(--py, 50%);
  background: radial-gradient(circle at var(--px, 50%) var(--py, 50%), rgba(255, 232, 205, .38), rgba(255, 232, 205, .12) 45%, transparent 70%);
  animation: press-flash-glow .55s cubic-bezier(.2, .7, .3, 1) forwards; }
html:not(#_)[data-mode="light"] .pop::after { animation-name: press-flash-glow;
  background: radial-gradient(circle at var(--px, 50%) var(--py, 50%), rgba(120, 90, 60, .22), rgba(120, 90, 60, .06) 45%, transparent 70%); }
@keyframes press-flash-glow {
  0%   { opacity: 1; transform: scale(.4); }
  100% { opacity: 0; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  html:not(#_) .pop::after { animation: none; }
  html:not(#_):not(#_) :is(.glassbtn, .tbtn, .lcd-buy, .cart-btn, .play, .price-btn, .add, .checkout, .btn, .files a, .mode-btn):active { transform: none; }
}

/* ---------- covers: one clean CD ----------
   Each cover is shown as printed (engine/cdprint.py), cut to its disc. The records carry one still glass highlight
   and rim above the turning picture: it never turns, so the light stays put like on a real CD. The small covers are
   the plain disc. No blend modes or colour flips, so nothing repaints while a disc spins. */
.vinyl:not(.no-art)::after, .m-card-art::after { content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none; z-index: 2;
  background: linear-gradient(135deg, rgba(255,255,255,.32) 0%, rgba(255,255,255,0) 42%, rgba(255,255,255,0) 70%, rgba(255,255,255,.1) 100%);
  box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.45), inset 0 0 0 3px rgba(0,0,0,.18); }
.vinyl.mini:not(.no-art)::after { box-shadow: inset 0 0 0 1px rgba(255,255,255,.4); }
/* the small ones: the disc (radius .418 of the picture) scaled to fill a clean circle */
:is(.row img, .similar-item img, .drawer .line-cover, .m-sheet-head img, .m-mood img) {
  scale: calc(1 / .836); clip-path: circle(41.8%); border-radius: 0; background: none; filter: none; box-shadow: none; }
/* See-through centres: the spindle hole is clear on every disc (a still mask on the record's frame, the picture
   turns inside it), so plain photo covers read as CDs too. 12.5% of the disc, like a real CD (15 mm of 120). */
:root { --cd-hole-mask: radial-gradient(circle closest-side, transparent 12.5%, #000 13.1%); }
.vinyl:not(.no-art) .vinyl-disc, .vinyl:not(.no-art)::after, .m-card-art, .m-card-art::after { -webkit-mask-image: var(--cd-hole-mask); mask-image: var(--cd-hole-mask); }
.vinyl:not(.no-art)::after, .m-card-art::after { background:
  radial-gradient(circle closest-side, transparent 12.6%, rgba(255,255,255,.55) 13.4%, rgba(255,255,255,0) 15.5%),
  linear-gradient(135deg, rgba(255,255,255,.32) 0%, rgba(255,255,255,0) 42%, rgba(255,255,255,0) 70%, rgba(255,255,255,.1) 100%); }
/* the small ones: the hole on the picture itself (disc radius .418 of the picture, so 12.5% of it is 10.45%) */
:is(.row img, .similar-item img, .drawer .line-cover, .m-sheet-head img, .m-mood img) {
  -webkit-mask-image: radial-gradient(circle closest-side, transparent 10.45%, #000 11.2%); mask-image: radial-gradient(circle closest-side, transparent 10.45%, #000 11.2%); }

/* A cover that would not load after its retries (app.js img-failed): a plain dark CD in its place, never a stand-in
   picture, until it loads on a later try. Also covers the moment between a failure and its retry. */
img.img-failed { object-position: -9999px 0; background: radial-gradient(circle closest-side, transparent 0 25%, rgba(255,255,255,.18) 26%, transparent 28%, transparent 96%, rgba(255,255,255,.25) 98%, transparent 100%),
  conic-gradient(from 30deg, #1d1f22, #2c2f33 25%, #1a1c1f 50%, #2a2d31 75%, #1d1f22) !important; }
/* The disc shelf's scroll room ran 2px past the screen's edge, so the whole page could be dragged sideways. */
html.store, html.store body { overflow-x: clip; }

/* ================= Beats / Loops and All / Solo / Collab: segmented switches with a sliding thumb =================
   One recessed glass groove per switch; a glossy silver thumb slides under the chosen option (switches.js places it
   with --sx / --sw) and springs a little as it lands. The chosen label goes dark on the silver; the others are light
   on the glass and brighten under the pointer. The count beside each label is lighter. Same on every screen size. */
html:not(#_) .seg, html:not(#_) .seg:hover, html:not(#_) .seg:active,
html.store:not(#_) .seg, html.store:not(#_) .seg:hover, html.store:not(#_) .seg:active {
  position: relative; isolation: isolate; display: inline-flex; align-items: stretch; gap: 0; padding: 3px; border-radius: 999px; transform: none; filter: none;
  background: linear-gradient(180deg, rgba(0,0,0,.55), rgba(24,26,29,.7)); border: 1px solid rgba(0,0,0,.85);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.85), inset 0 -1px 0 rgba(255,255,255,.05), 0 1px 0 rgba(255,255,255,.07); }
html[data-mode="light"]:not(#_) .seg { background: linear-gradient(180deg, rgba(0,0,0,.12), rgba(0,0,0,.05)); border-color: rgba(0,0,0,.2);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.25), 0 1px 0 rgba(255,255,255,.8); }
/* phones: no dark groove, the visualizer shows behind the tabs like it does behind the search */
@media (max-width: 760px) {
  html.store:not(#_):not(#_) .seg { background: none; border-color: rgba(255,255,255,.18); box-shadow: none; }
  html.store[data-mode="light"]:not(#_):not(#_) .seg { border-color: rgba(0,0,0,.22); }
}
html:not(#_) .seg::before { content: ""; position: absolute; z-index: -1; top: 3px; bottom: 3px; left: 0; width: var(--sw, 0); border-radius: 999px;
  transform: translateX(var(--sx, 0)); opacity: 0;
  background: linear-gradient(180deg, rgba(255,255,255,.55), rgba(255,255,255,.12) 49%, transparent 50%), linear-gradient(180deg, #f4f8fb, #b9c8d3);
  box-shadow: inset 0 1px 0 #fff, 0 1px 3px rgba(0,0,0,.6), 0 0 12px rgba(150,205,255,.28); }
html:not(#_) .seg.seg-ready::before { opacity: 1; }
html:not(#_) .seg.seg-slides::before { transition: transform .32s cubic-bezier(.3, 1.35, .5, 1), width .32s cubic-bezier(.3, 1.35, .5, 1); }
html[data-mode="light"]:not(#_) .seg::before { background: linear-gradient(180deg, rgba(255,255,255,.9), rgba(255,255,255,.3) 49%, transparent 50%), linear-gradient(180deg, #ffffff, #cfe6f7);
  box-shadow: inset 0 0 0 1px rgba(47,127,184,.35), 0 1px 3px rgba(60,80,95,.35); }
@media (prefers-reduced-motion: reduce) { html:not(#_) .seg.seg-slides::before { transition: none; } }
/* the options: no backgrounds of their own (the thumb is the highlight), the same height and padding everywhere */
html:not(#_) .seg > :is(span, button), html.store:not(#_) .seg > :is(span, button), html[data-mode]:not(#_) .seg > :is(span, button) {
  position: relative; display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 0 15px; border-radius: 999px; cursor: pointer;
  background: none !important; border: 0 !important; box-shadow: none !important; text-shadow: none; opacity: 1;
  color: #c9d1d6; font-weight: 650; letter-spacing: .01em; transition: color .2s ease; -webkit-tap-highlight-color: transparent; }
html:not(#_) .seg > :is(span, button):not(.on):hover { color: #f2f6f8; }
html:not(#_) .seg > :is(span, button).on, html.store:not(#_) .seg > :is(span, button).on { color: #0b0d0e; }
html[data-mode="light"]:not(#_) .seg > :is(span, button) { color: #56616a; }
html[data-mode="light"]:not(#_) .seg > :is(span, button):is(.on, :not(.on):hover) { color: #0b2233; }
html:not(#_) .seg > :is(span, button) b { font-weight: 500; opacity: .6; font-size: .9em; min-width: 0; }
html:not(#_) .seg > :is(span, button).on b { opacity: .7; }
html:not(#_) .seg > :is(span, button) + :is(span, button) { border-left: 0 !important; }
html:not(#_) .seg > :is(span, button):active { transform: scale(.96); transition: transform .08s; }
html:not(#_) .seg > button:focus-visible { outline: 2px solid rgba(160,220,255,.7); outline-offset: -2px; }
@media (pointer: coarse) { html:not(#_) .seg > :is(span, button) { min-height: 40px; padding: 0 18px; } }

/* Beat/loop page on web: Back pinned to the top-left corner, and the small print a size up. Phones are unchanged. */
@media (min-width: 701px) {
  html.store main.beat { position: relative; padding-top: 58px; }
  html.store main.beat .beat-tools .back { position: absolute; top: 10px; left: 14px; }
  html.store main.beat :is(.coprod, .sub) { font-size: 15px; }
  html.store main.beat .made { font-size: 12.5px; }
  html.store main.beat .tier .name { font-size: 15px; }
  html.store main.beat .tier .terms { font-size: 13px; line-height: 1.45; }
  html.store :is(main.beat, .np-info) .pay-banner { font-size: 12.5px; }
}

/* ---- the CDs' rims: a still silver edge band and a polished ring round the clear hub, over every record's printed
   art (pages, Now Playing, the top player, the feed, the shelf cards). Nothing lies over the print itself: a grey
   soft-light "metal" cast and white light streaks used to, so the same cover looked paler and greyer here than on
   the list's small discs (which show the plain picture), and the blend repainted the disc on every frame it turned.
   The metal is printed into the covers already (engine/cdprint.py). ---- */
html:not(#_):not(#_) :is(.vinyl:not(.no-art), .m-card-art)::after {
  mix-blend-mode: normal;
  background:
    radial-gradient(circle closest-side, transparent 12.6%, rgba(255,255,255,.75) 13.2%, rgba(150,158,166,.55) 14.6%, rgba(235,240,244,.6) 16%, rgba(255,255,255,0) 17.5%,
      transparent 95.2%, rgba(205,212,220,.55) 96.4%, rgba(255,255,255,.9) 97.8%, rgba(120,128,136,.7) 99.2%, rgba(0,0,0,.45) 100%);
  box-shadow: none; }

/* ---- visualizer and DJ mode buttons: on and off at a glance ----
   On: the button lights up glossy silver (like the buy buttons), its icon dark, with a small glowing light in the
   corner. Off: dark glass, the icon dimmed and crossed by a diagonal slash, so off reads as off without comparing
   shades. The state comes from aria-pressed (viz-switch.js, app.js). */
html:not(#_):not(#_).viz-live :is(#p-vizstyle, #p-switchup) { opacity: 1; position: relative; overflow: visible; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="true"] {
  color: #0b0d0e; border-color: #000; text-shadow: none;
  background: linear-gradient(180deg, rgba(255,255,255,.55), rgba(255,255,255,.12) 49%, transparent 50%), linear-gradient(180deg, #f4f8fb, #b9c8d3);
  box-shadow: inset 0 1px 0 #fff, 0 0 12px rgba(150,205,255,.35), 0 1px 2px rgba(0,0,0,.8); }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="true"]::after {
  content: ""; position: absolute; top: 3px; right: 3px; width: 6px; height: 6px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #ffffff, #bfe6ff 45%, #5fa8d8 100%);
  box-shadow: 0 0 6px 1px rgba(150,210,255,.85); }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"] {
  color: #8b949b; opacity: 1;
  background: linear-gradient(180deg, rgba(255,255,255,.06), transparent 50%), linear-gradient(180deg, #1e2124, #0c0d0f);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.8), 0 1px 0 rgba(255,255,255,.05); }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"]::before { opacity: .55; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"]::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 18px; height: 2px; border-radius: 1px; pointer-events: none;
  background: #8b949b; box-shadow: 0 0 0 1px #0c0d0f; transform: translate(-50%, -50%) rotate(-45deg); }
html[data-mode="light"]:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"] { color: #7d8790; background: linear-gradient(180deg, #e3e8ec, #cfd6db); box-shadow: inset 0 1px 2px rgba(0,0,0,.2); }
html[data-mode="light"]:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"]::after { background: #7d8790; box-shadow: 0 0 0 1px #dfe5e9; }
html[data-mode="light"]:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="true"] { color: #0b2233;
  background: linear-gradient(180deg, rgba(255,255,255,.9), rgba(255,255,255,.3) 49%, transparent 50%), linear-gradient(180deg, #ffffff, #cfe6f7);
  box-shadow: inset 0 0 0 1px rgba(47,127,184,.45), 0 1px 3px rgba(60,80,95,.35); }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup):is(:hover, :focus-visible) { filter: brightness(1.08); }

/* ---- Stripe banner: real card brand badges and the Stripe wordmark (the plain text labels are hidden) ---- */
html:not(#_) .pay-banner .stripe { font: italic 800 17px/1 "Segoe UI", system-ui, sans-serif; letter-spacing: -.045em; color: #8e86ff; }
html[data-mode="light"]:not(#_) .pay-banner .stripe { color: #635bff; }
html:not(#_) .pay-banner .cards { gap: 6px; }
html:not(#_) .pay-banner .cards span { width: 38px; height: 24px; padding: 0; font-size: 0; color: transparent; border-radius: 4px; border: 0;
  background: #fff center / 100% 100% no-repeat; box-shadow: 0 0 0 1px rgba(0,0,0,.35), 0 1px 2px rgba(0,0,0,.4); }
html:not(#_) .pay-banner .cards span.c-visa { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 38 24'%3E%3Crect width='38' height='24' rx='3' fill='%23fff'/%3E%3Ctext x='19' y='16.2' text-anchor='middle' font-family='Arial Black,Arial,sans-serif' font-weight='900' font-style='italic' font-size='11' letter-spacing='-.3' fill='%231a1f71'%3EVISA%3C/text%3E%3C/svg%3E"); }
html:not(#_) .pay-banner .cards span.c-mc { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 38 24'%3E%3Crect width='38' height='24' rx='3' fill='%23fff'/%3E%3Ccircle cx='15' cy='12' r='7' fill='%23eb001b'/%3E%3Ccircle cx='23' cy='12' r='7' fill='%23f79e1b'/%3E%3Cpath d='M19 6.3a7 7 0 0 1 0 11.4a7 7 0 0 1 0-11.4z' fill='%23ff5f00'/%3E%3C/svg%3E"); }
html:not(#_) .pay-banner .cards span.c-amex { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 38 24'%3E%3Crect width='38' height='24' rx='3' fill='%23016fd0'/%3E%3Ctext x='19' y='15.6' text-anchor='middle' font-family='Arial,sans-serif' font-weight='900' font-size='9' letter-spacing='.4' fill='%23fff'%3EAMEX%3C/text%3E%3C/svg%3E"); }

/* ---- beat and loop pages: a plain round back arrow top-left (no "All beats" text), and the visualizer and DJ mode
   buttons together in the top-right corner, on every screen size; the page starts below them. ---- */
html:not(#_):not(#_) main.beat { position: relative; padding-top: 58px; }
html:not(#_):not(#_) .beat-tools { position: absolute; top: 10px; left: 0; right: 0; margin: 0; padding: 0 14px; display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; z-index: 2; }
html:not(#_):not(#_) .beat-tools > * { margin: 0 !important; }
html:not(#_):not(#_) .beat-tools .back, html:not(#_):not(#_) .beat-tools .back:hover, html:not(#_):not(#_) .beat-tools .back:active {
  width: 38px; height: 38px; min-height: 0; padding: 0; border-radius: 50%; font-size: 0; gap: 0; letter-spacing: 0; text-transform: none;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 2px 6px rgba(0,0,0,.45); }
html:not(#_):not(#_) .beat-tools .back > span { display: none; }
html:not(#_):not(#_) .beat-tools .back svg.back-ic { display: none; }
html:not(#_):not(#_) .beat-tools .back::before { content: ""; width: 17px; height: 17px; background: currentColor;
  -webkit-mask: var(--chev) center / contain no-repeat; mask: var(--chev) center / contain no-repeat;
  --chev: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27none%27 stroke=%27%23000%27 stroke-width=%272.4%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3E%3Cpath d=%27M15 5l-7 7 7 7%27/%3E%3C/svg%3E"); }
html[data-mode="light"]:not(#_):not(#_) .beat-tools .back { box-shadow: inset 0 1px 0 #fff, 0 2px 6px rgba(60,80,95,.3); }
html:not(#_):not(#_) .beat-tools :is(#p-vizstyle, #p-switchup) { width: 38px; height: 38px; min-width: 0; padding: 0; border-radius: 50%; align-self: center; justify-content: center; }
html:not(#_):not(#_) .beat-tools #p-vizstyle { margin-left: auto !important; }
html:not(#_):not(#_) .beat-tools .m-cart { margin-left: 4px !important; }
/* simpler: on is the lit silver button, off is plain dark with a dimmed icon; no corner light, no slash */
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)::after { content: none; display: none; }
/* on / off, as distinct as it gets and instant: on is solid bright silver with a dark icon; off is no fill at all, a thin
   outline and a faint icon. No glow, no light, no fade or press animation on these two. */
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup) { transition: none !important; animation: none !important; transform: none !important; filter: none !important; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)::after { content: none !important; display: none !important; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup).pop::after { content: none !important; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="true"] { color: #000; border: 1px solid #fff;
  background: #eef2f5; box-shadow: none; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="true"]::before { opacity: 1; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"] { color: #c3cbd1; border: 1px solid rgba(255,255,255,.28);
  background: transparent; box-shadow: none; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"]::before { opacity: .4; }
html[data-mode="light"]:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="true"] { color: #fff; border-color: #1b2126; background: #1b2126; }
html[data-mode="light"]:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"] { color: #1b2126; border-color: rgba(0,0,0,.3); background: transparent; }
/* the icons say it too: the visualizer's eye is open when on and shut (with lashes) when off; DJ mode's record has the
   tonearm resting on it when on and lifted off to the side when off. These styles outrank the glass-button rules. */
html:not(#_):not(#_) #p-vizstyle[aria-pressed="true"] { --viz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill-rule='evenodd' d='M6 2.2C3.4 2.2 1.3 4.1.2 6c1.1 1.9 3.2 3.8 5.8 3.8s4.7-1.9 5.8-3.8C10.7 4.1 8.6 2.2 6 2.2zm0 1.1c2 0 3.6 1.3 4.5 2.7C9.6 7.4 8 8.7 6 8.7S2.4 7.4 1.5 6C2.4 4.6 4 3.3 6 3.3z'/%3E%3Ccircle cx='6' cy='6' r='1.6'/%3E%3C/svg%3E") !important; }
html:not(#_):not(#_) #p-vizstyle[aria-pressed="false"] { --viz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='1.2' stroke-linecap='round'%3E%3Cpath d='M.9 5.2C2.3 6.9 4 7.7 6 7.7s3.7-.8 5.1-2.5'/%3E%3Cpath d='M2.6 6.8 1.7 8.1M6 7.7v1.6M9.4 6.8l.9 1.3'/%3E%3C/svg%3E") !important; }
html:not(#_):not(#_) #p-switchup[aria-pressed="true"] { --viz-icon: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 12 12%27%3E%3Cpath fill-rule=%27evenodd%27 d=%27M5 1.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zm0 3.4a1.1 1.1 0 1 1 0 2.2 1.1 1.1 0 0 1 0-2.2z%27/%3E%3Cpath d=%27M9.7.5l1.2.7-2.3 4-1.1-.6z%27/%3E%3Ccircle cx=%279.9%27 cy=%271%27 r=%27.95%27/%3E%3C/svg%3E") !important; }
html:not(#_):not(#_) #p-switchup[aria-pressed="false"] { --viz-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill-rule='evenodd' d='M4.6 2.1a4.3 4.3 0 1 0 0 8.6 4.3 4.3 0 0 0 0-8.6zm0 3.2a1.1 1.1 0 1 1 0 2.2 1.1 1.1 0 0 1 0-2.2z'/%3E%3Crect x='10.3' y='1.4' width='1.2' height='5.6' rx='.6'/%3E%3Ccircle cx='10.9' cy='1.4' r='.95'/%3E%3C/svg%3E") !important; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="true"] { border: 1px solid #fff !important; background: #eef2f5 !important; box-shadow: none !important; color: #000 !important; }
html:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"] { border: 1px solid rgba(255,255,255,.28) !important; background: transparent !important; box-shadow: none !important; color: #c3cbd1 !important; }
html[data-mode="light"]:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="true"] { border-color: #1b2126 !important; background: #1b2126 !important; color: #fff !important; }
html[data-mode="light"]:not(#_):not(#_) :is(#p-vizstyle, #p-switchup)[aria-pressed="false"] { border-color: rgba(0,0,0,.3) !important; background: transparent !important; color: #1b2126 !important; }
/* the card badges: the real Visa, Mastercard and American Express logos (payment-icons 1.2.1, MPL-2.0,
   vendor/cards/LICENSE-payment-icons.txt), in place of the hand-drawn ones */
html:not(#_) .pay-banner .cards span { width: 38px; height: 24px; background: transparent center / contain no-repeat; box-shadow: 0 1px 2px rgba(0,0,0,.45); border-radius: 3px; }
html:not(#_) .pay-banner .cards span.c-visa { background-image: url(/vendor/cards/visa.svg); }
html:not(#_) .pay-banner .cards span.c-mc { background-image: url(/vendor/cards/mastercard.svg); }
html:not(#_) .pay-banner .cards span.c-amex { background-image: url(/vendor/cards/amex.svg); }
/* Visa and Mastercard on white cards, the logo centred on each (payment-icons' "single" logos); Amex keeps its blue box */
html:not(#_) .pay-banner .cards span:is(.c-visa, .c-mc) { background-color: #fff; background-position: center; background-repeat: no-repeat; }
html:not(#_) .pay-banner .cards span.c-visa { background-image: url(/vendor/cards/visa-single.svg); background-size: 78% auto; }
html:not(#_) .pay-banner .cards span.c-mc { background-image: url(/vendor/cards/mastercard-single.svg); background-size: auto 82%; }

/* ================= the cart: a cleaner, more professional drawer =================
   A clear header with a count, roomy item rows (bigger disc, bold name, the licence as a small tag, the price right-
   aligned, a quiet remove), a summary with a big total, one bright padlocked Checkout button with who takes the payment
   and the cards under it, and a real empty state. Same glass as the rest of the store. */
html:not(#_) .drawer header { padding: 16px 16px 14px; border-bottom: 1px solid rgba(255,255,255,.08); box-shadow: none; }
html:not(#_) .drawer header strong { display: inline-flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 700; letter-spacing: .01em; }
.cart-n { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; display: inline-grid; place-items: center; font-size: 11px; font-weight: 800;
  color: #0b0d0e; background: linear-gradient(180deg, #f4f8fb, #b9c8d3); }
html:not(#_) .drawer header .x { width: 32px; height: 32px; border-radius: 50%; display: inline-grid; place-items: center; font-size: 20px; line-height: 1;
  color: var(--text); background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.1); }
html:not(#_) .drawer header .x:hover { background: rgba(255,255,255,.12); }
html:not(#_) .drawer .items { padding: 6px 8px; }
html:not(#_) :is(.drawer .line, .drawer .line:nth-child(even)) { gap: 12px; padding: 12px 8px; background: transparent; border-bottom: 1px solid rgba(255,255,255,.06); align-items: center; }
html:not(#_) .drawer .line:last-child { border-bottom: 0; }
html:not(#_) .drawer .line-cover { width: 48px; height: 48px; }
html:not(#_) .drawer .line-title { font-size: 13.5px; font-weight: 700; line-height: 1.3; }
html:not(#_) .drawer .line-link:hover { text-decoration: none; color: #fff; }
.line-tier { display: inline-block; margin-top: 4px; padding: 2px 8px; border-radius: 999px; font-size: 10.5px; font-weight: 600; color: #b9c2c8;
  background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.1); }
html:not(#_) .drawer .line-end { gap: 10px; }
html:not(#_) .drawer .line-price { font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; }
/* Remove from cart: a clear round button (it was a faint grey glyph whose white hover vanished in light mode). */
html:not(#_) .drawer .line .x { width: 30px; height: 30px; padding: 0; border-radius: 50%; display: inline-grid; place-items: center; font-size: 18px; line-height: 1;
  color: var(--text); background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.14); cursor: pointer; }
html:not(#_) .drawer .line .x:hover { color: #ffd6d6; background: rgba(255,80,80,.22); border-color: rgba(255,110,110,.45); }
html:not(#_) .drawer .line .x:focus-visible { outline: 2px solid rgba(160,220,255,.7); outline-offset: 2px; }
html[data-mode="light"]:not(#_) .drawer .line .x { color: #1b2126; background: rgba(0,0,0,.04); border-color: rgba(0,0,0,.16); }
html[data-mode="light"]:not(#_) .drawer .line .x:hover { color: #a61b1b; background: rgba(220,40,40,.1); border-color: rgba(200,40,40,.4); }
html:not(#_) .drawer footer { padding: 16px; border-top: 1px solid rgba(255,255,255,.08); box-shadow: none; background: rgba(0,0,0,.18); }
html:not(#_) .drawer footer .deal { font-size: 12px; color: #c9d1d6; }
html:not(#_) #drawer .sum { margin: 2px 0 14px; align-items: baseline; }
html:not(#_) #drawer .sum span { font-size: 13px; color: #c9d1d6; font-weight: 600; }
html:not(#_) #drawer .sum strong { font-size: 24px; font-weight: 800; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
html:not(#_) .drawer .checkout { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 48px; border-radius: 999px;
  font-size: 15px; font-weight: 800; color: #0b0d0e; text-shadow: none; border: 1px solid #000;
  background: linear-gradient(180deg, rgba(255,255,255,.55), rgba(255,255,255,.12) 49%, transparent 50%), linear-gradient(180deg, #f4f8fb, #b9c8d3);
  box-shadow: inset 0 1px 0 #fff, 0 0 14px rgba(150,205,255,.3), 0 1px 2px rgba(0,0,0,.8); }
html:not(#_) .drawer .checkout::before { content: ""; width: 14px; height: 14px; background: currentColor;
  -webkit-mask: var(--lock) center / contain no-repeat; mask: var(--lock) center / contain no-repeat;
  --lock: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 10V7a5 5 0 0 1 10 0v3h1.5v11h-13V10zm2 0h6V7a3 3 0 0 0-6 0z'/%3E%3C/svg%3E"); }
html:not(#_) .drawer .checkout:disabled { opacity: .7; }
html:not(#_) .drawer.is-empty footer :is(.sum, .checkout, .cart-trust, .deal) { display: none; }
html:not(#_) .cart-trust.pay-banner { margin: 10px 0 0; padding: 0; border: 0; background: none; box-shadow: none; justify-content: center; gap: 6px 8px; font-size: 11.5px; color: #c9d1d6; }
html:not(#_) .cart-trust .cards { margin-left: 0; }
html:not(#_) .cart-trust .cards span { width: 32px; height: 20px; }
html:not(#_) #drawer .agree { margin-top: 12px; text-align: center; font-size: 10.5px; }
.cart-empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px; padding: 48px 16px; }
.cart-empty-disc { width: 64px; height: 64px; margin-bottom: 8px; border-radius: 50%; opacity: .5;
  background: radial-gradient(circle closest-side, transparent 0 22%, rgba(255,255,255,.35) 23%, transparent 26%, transparent 95%, rgba(255,255,255,.4) 97%, transparent 100%),
    conic-gradient(from 30deg, #2a2d31, #6c737a 15%, #2a2d31 35%, #5d636a 60%, #2a2d31 80%, #5d636a 92%, #2a2d31); }
.cart-empty b { font-size: 15px; }
.cart-empty small { color: #8b949b; font-size: 12px; margin-bottom: 10px; }
.cart-empty .cart-btn { padding: 9px 20px; }
html[data-mode="light"]:not(#_) .drawer :is(header, footer) { border-color: rgba(0,0,0,.1); }
html[data-mode="light"]:not(#_) .drawer footer { background: rgba(255,255,255,.4); }
html[data-mode="light"]:not(#_) .drawer .line { border-color: rgba(0,0,0,.08); }
html[data-mode="light"] .line-tier { color: #44505a; background: rgba(0,0,0,.05); border-color: rgba(0,0,0,.1); }
html[data-mode="light"]:not(#_) .drawer header .x { color: #1b2126; background: rgba(0,0,0,.05); border-color: rgba(0,0,0,.12); }
html[data-mode="light"]:not(#_) .drawer .checkout { color: #0b2233; border-color: #5f7d93; background: linear-gradient(180deg, rgba(255,255,255,.9), rgba(255,255,255,.3) 49%, transparent 50%), linear-gradient(180deg, #ffffff, #cfe6f7); }
/* the Checkout button is the bright one (outranks the glass-button rules) */
html:not(#_):not(#_):not(#_) #drawer .checkout { color: #0b0d0e !important; border: 1px solid #000 !important;
  background: linear-gradient(180deg, rgba(255,255,255,.55), rgba(255,255,255,.12) 49%, transparent 50%), linear-gradient(180deg, #f4f8fb, #b9c8d3) !important;
  box-shadow: inset 0 1px 0 #fff, 0 0 14px rgba(150,205,255,.3), 0 1px 2px rgba(0,0,0,.8) !important; }
html:not(#_):not(#_) .drawer .checkout:hover { filter: brightness(1.05); }
html[data-mode="light"]:not(#_):not(#_) .drawer .checkout { color: #0b2233 !important; border-color: #5f7d93 !important;
  background: linear-gradient(180deg, rgba(255,255,255,.9), rgba(255,255,255,.3) 49%, transparent 50%), linear-gradient(180deg, #ffffff, #cfe6f7) !important; }
html:not(#_) .drawer.is-empty footer { display: none; } /* empty: nothing to pay for, so no total, buttons or terms */

/* PayPal's own yellow on its cart button, over the bright Checkout rule above (any mode, any view). */
html:not(#_):not(#_):not(#_) #drawer .checkout.paypal { color: #111 !important; border: 1px solid #c99a1c !important; text-shadow: none;
  background: linear-gradient(180deg, rgba(255,255,255,.5), rgba(255,255,255,.12) 49%, transparent 50%), linear-gradient(180deg, #ffd35c, #f5b82a) !important;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 0 14px rgba(255,196,57,.25), 0 1px 2px rgba(0,0,0,.6) !important; }
html:not(#_):not(#_):not(#_) #drawer .checkout.paypal:active { box-shadow: inset 0 2px 5px rgba(120,80,0,.4) !important; }
/* Apple Pay: Apple's black button with the Apple mark (the U+F8FF glyph only Apple fonts draw; the button only shows on
   Apple devices), glossed like the others; no padlock in front of the mark. */
html:not(#_):not(#_):not(#_) #drawer .checkout.applepay { margin-bottom: 10px; color: #fff !important; border: 1px solid #000 !important; text-shadow: none;
  background: linear-gradient(180deg, rgba(255,255,255,.22), rgba(255,255,255,.05) 49%, transparent 50%), linear-gradient(180deg, #2b2e31, #000) !important;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.8) !important; }
html:not(#_):not(#_):not(#_) #drawer .checkout.applepay:active { box-shadow: inset 0 2px 5px rgba(0,0,0,.9) !important; }
html:not(#_) .drawer .checkout.applepay::before { content: none; }
.checkout.applepay .ap-logo { font: 600 19px/1 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", sans-serif; letter-spacing: -.01em; }
/* The official Amex art (beat / loop page banner) is a touch wider than the badge: fill the badge, centred. */
.pay-banner .cards img.card { object-fit: cover; object-position: center; background: #2557d6; }

/* Beat / loop page pay banner: secure checkout and the card logos, then why to buy now (instant download, license). */
html:not(#_) :is(main, .np-info) .pay-banner { gap: 8px 10px; padding: 11px 14px; }
html:not(#_) :is(main, .np-info) .pay-banner .pay-dot { color: #6f787f; margin: 0 -3px; }
html:not(#_) :is(main, .np-info) .pay-banner .pay-promise { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 4px 16px; padding-top: 8px;
  border-top: 1px solid rgba(255,255,255,.08); font-size: 12px; color: #a9b2b8; }
html:not(#_) :is(main, .np-info) .pay-banner .pay-promise span { display: inline-flex; align-items: center; gap: 5px; }
html:not(#_) :is(main, .np-info) .pay-banner .pay-promise .ic { width: 14px; height: 14px; fill: currentColor; color: #c3cbd1; }
html[data-mode="light"]:not(#_) :is(main, .np-info) .pay-banner .pay-promise { color: #44505a; border-color: rgba(0,0,0,.1); }
html[data-mode="light"]:not(#_) :is(main, .np-info) .pay-banner .pay-promise .ic { color: #2a3137; }
@media (max-width: 760px) { html.store:not(#_) :is(main, .np-info) .pay-banner .pay-promise { justify-content: center; } }

/* Home: the search row's dark band runs to both edges of the window; the list keeps its column. */
@media (min-width: 761px) {
  html:not(#_):not(#_) main.window .filterbar { margin-left: calc(50% - 50vw / 1.25); margin-right: calc(50% - 50vw / 1.25); padding-left: calc(50vw / 1.25 - 50% + 4px); padding-right: calc(50vw / 1.25 - 50% + 4px); }
}

/* Beat/loop page between phone and desktop (701-900px): stacked like the phone, so the price boxes keep their
   width instead of squeezing to a word or two per line beside the disc. */
@media (min-width: 701px) and (max-width: 900px) {
  html.store main.beat { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  html.store main.beat .art { width: 100%; max-width: 320px; }
}

/* Licensing page: the licenses side by side (scrolls sideways on its own on narrow phones), then the FAQ. */
.tier-help { display: flex; gap: 8px; justify-content: center; margin: 10px 0 0; font-size: 12px; color: var(--muted); }
.tier-help a { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.tier-help a:hover { color: var(--text); }
.lic-compare-wrap { overflow-x: auto; margin: 14px 0 10px; border-radius: 10px; border: 1px solid rgba(255,255,255,.1);
  background: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.015)); box-shadow: inset 0 1px 0 rgba(255,255,255,.08); }
.lic-compare { width: 100%; min-width: 440px; border-collapse: collapse; font-size: 12.5px; }
.lic-compare th, .lic-compare td { padding: 9px 12px; text-align: center; border-bottom: 1px solid rgba(255,255,255,.08); }
.lic-compare tbody tr:last-child > * { border-bottom: 0; }
.lic-compare thead th { font: 600 12px var(--ui); letter-spacing: .06em; text-transform: uppercase; background: rgba(255,255,255,.05); }
.lic-compare tbody th { text-align: left; font-weight: 500; color: var(--muted); white-space: nowrap; }
.lic-compare .yes { color: #6fc28b; font-weight: 700; }
.lic-compare .no { color: var(--muted); }
.faq { display: grid; gap: 8px; margin-top: 8px; }
.faq-q { border: 1px solid rgba(255,255,255,.1); border-radius: 10px; background: rgba(255,255,255,.03); }
.faq-q summary { cursor: pointer; padding: 11px 14px; font-weight: 600; list-style-position: inside; }
.faq-q p { margin: 0; padding: 0 14px 12px; color: var(--muted); }
.about-playlist { display: block; width: 100%; max-width: 660px; height: 450px; border: 0; border-radius: 12px; overflow: hidden; background: transparent; margin: 0 0 14px; }
.about-links { display: flex; flex-wrap: wrap; gap: 8px; }
.about-links .cart-btn { text-decoration: none; }
.heard-on { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; padding: 0; }
.heard-on li { padding: 6px 12px; border-radius: 999px; border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.05); font-size: 12px; }
html[data-mode="light"] .lic-compare-wrap { border-color: rgba(0,0,0,.12); background: linear-gradient(180deg, #fff, #f1f4f7); }
html[data-mode="light"] .lic-compare th, html[data-mode="light"] .lic-compare td { border-bottom-color: rgba(0,0,0,.08); }
html[data-mode="light"] .lic-compare thead th { background: rgba(0,0,0,.04); }
html[data-mode="light"] .lic-compare .yes { color: #1f7a3e; }
html[data-mode="light"] :is(.faq-q, .heard-on li) { border-color: rgba(0,0,0,.12); background: rgba(255,255,255,.7); }
.cart-nudge { margin: 4px 0 8px; padding: 7px 12px; border-radius: 999px; font-size: 12px; font-weight: 600; text-align: center;
  color: #d9f2e1; border: 1px solid rgba(111,194,139,.35); background: linear-gradient(180deg, rgba(111,194,139,.18), rgba(111,194,139,.06)); }
html[data-mode="light"] .cart-nudge { color: #185c30; border-color: rgba(31,122,62,.3); background: linear-gradient(180deg, #e9f7ee, #d8efe0); }

/* 404: a glass panel with a spinning-free disc, the way back to the beats first. */
.page.notfound { max-width: 520px; margin: 40px auto 60px; padding: 34px 26px 30px; text-align: center; border-radius: 14px;
  border: 1px solid rgba(255,255,255,.1); background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.02));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.12), 0 18px 40px rgba(0,0,0,.45); }
.page.notfound h1 { margin: 18px 0 6px; }
.nf-disc { width: 132px; height: 132px; margin: 0 auto; border-radius: 50%; display: grid; place-items: center;
  background: radial-gradient(circle, #0b0c0d 0 13%, #9aa3aa 14% 16%, transparent 17%),
              repeating-radial-gradient(circle, rgba(255,255,255,.06) 0 1px, transparent 1px 4px),
              conic-gradient(from 30deg, #2a2f33, #6d757b, #2a2f33, #565e64, #2a2f33);
  box-shadow: 0 0 0 1px rgba(255,255,255,.1), 0 10px 26px rgba(0,0,0,.6); }
.nf-disc span { transform: translateY(42px); font: 600 11px var(--ui); letter-spacing: .3em; color: rgba(255,255,255,.7); }
.nf-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 20px; }
.nf-actions .cart-btn { text-decoration: none; padding: 0 18px; min-height: 38px; display: inline-flex; align-items: center; }
html[data-mode="light"] .page.notfound { border-color: rgba(0,0,0,.08); background: linear-gradient(180deg, #ffffff, #eef2f5); box-shadow: 0 14px 34px rgba(60,80,95,.2); }
body:has(main[data-page="licensing"]) .to-top { display: none !important; } /* a short page: no back-to-top button */

/* Text pages (Terms, Licensing, About...): the same round back button as the beat pages. */
main.page.legal { position: relative; }
html:not(#_):not(#_) main.page.legal > .beat-tools { position: static; margin: 0 0 14px; }
/* Back-to-top floats bottom-right on every page and stays hidden until scrolled down: the glass buttons' own
   "position: relative" (and opacity) outranked .to-top, dropping it into the page's end half off the left edge. */
html:not(#_):not(#_) .cart-btn.to-top { position: fixed !important; left: auto; }
html:not(#_):not(#_) .cart-btn.to-top:not(.show) { opacity: 0; visibility: hidden; pointer-events: none; }

/* ---- Buy and Add to cart: bigger and brighter, so buying is what stands out. ---- */
html:not(.free) :is(.price-btn, .lcd-buy, .btn.buy):not([hidden]), .add:not(.ghost) {
  display: inline-flex; align-items: center; justify-content: center; letter-spacing: .02em; }
.btn.buy { color: #0b0d0e; text-shadow: 0 1px 0 rgba(255,255,255,.6);
  background: var(--shine), linear-gradient(180deg, #f4f8fb 0%, #b9c8d3 100%); }
html[data-mode="light"] .btn.buy { color: #0b2233; border-color: #5f7d93; background: var(--shine), linear-gradient(180deg, #ffffff 0%, #cfe6f7 100%); }
:is(.price-btn, .add:not(.ghost), .lcd-buy, .btn.buy) { box-shadow: inset 0 1px 0 #fff, 0 0 18px rgba(150,205,255,.45), 0 1px 2px rgba(0,0,0,.8); }
:is(.price-btn, .add:not(.ghost), .lcd-buy, .btn.buy):hover { box-shadow: inset 0 1px 0 #fff, 0 0 24px rgba(150,205,255,.7), 0 1px 2px rgba(0,0,0,.8); }
/* dark mode: the same frosted glass as the other buttons, but brighter and glowing, so buying is what stands out */
html:not(#_):not(#_):not([data-mode="light"]) :is(.price-btn, .lcd-buy, .add:not(.ghost), .btn.buy) {
  background: linear-gradient(180deg, rgba(255,255,255,.44), rgba(255,255,255,.15)) !important; color: #fff !important; text-shadow: 0 1px 2px rgba(0,0,0,.35) !important;
  border: 1px solid rgba(255,255,255,.34) !important; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 0 14px rgba(170,215,255,.3), 0 2px 8px rgba(0,0,0,.35) !important; }
html:not(#_):not(#_):not([data-mode="light"]) :is(.price-btn, .lcd-buy, .add:not(.ghost), .btn.buy):hover {
  background: linear-gradient(180deg, rgba(255,255,255,.54), rgba(255,255,255,.22)) !important;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 0 20px rgba(170,215,255,.48), 0 2px 8px rgba(0,0,0,.35) !important; }
html:not(#_):not(#_):not([data-mode="light"]) :is(.price-btn, .lcd-buy, .add:not(.ghost), .btn.buy):active {
  background: linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.24)) !important; box-shadow: inset 0 2px 4px rgba(0,0,0,.45) !important; }
.price-btn { font-size: 13px; padding: 6px 16px; }
.btn.buy { font-size: 14px; padding: 10px 24px; border-radius: 999px; }
.add:not(.ghost) { font-size: 12.5px; padding: 8px 18px; }
.lcd-buy { font-size: 12.5px; padding: 5px 14px; }
@media (max-width: 760px) { html.store .table .row > .price-btn { padding: 7px 12px; font-size: 12px; min-height: 34px; } }

/* ================= the cart on phones: a solid, tidy bottom sheet =================
   Measured on a 390px phone: the sheet was see-through (the beat page's title read through the total), the drag
   handle stretched the full width as a grey bar, the close button sat on the screen edge, and the two pay buttons
   touched. Now: an opaque sheet, a small centred handle, the close button inside the margin, the pay buttons spaced
   with "or" between them, and room for the phone's home bar. */
@media (max-width: 760px) {
  html.store:not(#_):not(#_) .drawer { background: linear-gradient(180deg, #1c1f22, #0d0f10); border-top: 1px solid rgba(255,255,255,.1); border-radius: 18px 18px 0 0;
    box-shadow: 0 -12px 40px rgba(0,0,0,.7); padding-bottom: 0; }
  html.store[data-mode="light"]:not(#_):not(#_) .drawer { background: linear-gradient(180deg, #fbfcfd, #e9eef1); border-top-color: #c3cbd1; box-shadow: 0 -12px 40px rgba(0,0,0,.25); }
  html.store:not(#_):not(#_) .drawer header { flex-wrap: wrap; padding: 8px 16px 12px; }
  html.store:not(#_):not(#_) .drawer header .m-grab { flex: 0 0 100%; width: auto; height: 5px; margin: 0 0 10px; border-radius: 0; background: none; position: relative; }
  html.store:not(#_):not(#_) .drawer header .m-grab::after { content: ""; position: absolute; left: 50%; top: 0; width: 40px; height: 5px; margin-left: -20px; border-radius: 3px; background: rgba(160,168,174,.45); }
  html.store:not(#_):not(#_) .drawer header strong { font-size: 17px; }
  html.store:not(#_):not(#_) .drawer header .x { width: 36px; height: 36px; margin: 0; font-size: 18px; }
  html.store:not(#_):not(#_) .drawer .items { padding: 4px 8px; }
  html.store:not(#_):not(#_) .drawer footer { padding: 14px 16px calc(14px + env(safe-area-inset-bottom) / 1.1); background: rgba(0,0,0,.22); }
  html.store[data-mode="light"]:not(#_):not(#_) .drawer footer { background: rgba(255,255,255,.55); }
  html.store:not(#_):not(#_) #drawer .sum { margin: 0 0 12px; }
  html.store:not(#_):not(#_) #drawer .sum strong { font-size: 22px; }
  html.store:not(#_):not(#_) #drawer .pay-or { margin: 10px 0; }
  html.store:not(#_):not(#_) #drawer .cart-trust { margin-top: 12px; }
}
/* A pay button the store has switched off (PayPal before its keys are set) stays hidden: the bright Checkout rules
   above set display and showed it anyway, a PayPal button that could only fail. */
html:not(#_):not(#_):not(#_):not(#_) #drawer .checkout[hidden] { display: none !important; }
/* The PayPal badge beside the cards under Checkout, once the store takes PayPal (app.js). */
html:not(#_) .cart-trust .cards span.pp { display: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 38 24'%3E%3Crect width='38' height='24' rx='3' fill='%23fff'/%3E%3Ctext x='19' y='15.6' text-anchor='middle' font-family='Verdana,Arial,sans-serif' font-size='8.6' font-weight='700' font-style='italic' letter-spacing='-.3'%3E%3Ctspan fill='%23003087'%3EPay%3C/tspan%3E%3Ctspan fill='%23009cde'%3EPal%3C/tspan%3E%3C/text%3E%3C/svg%3E"); }
html.paypal:not(#_) .cart-trust .cards span.pp { display: block; }

/* The big records (a beat / loop page, the feed's cards) cast a soft shadow on the page. The record's paint
   containment (.vinyl above) clipped its own shadow away, so it never showed: the big ones paint outside their box. */
:is(.beat .art.vinyl, .feed-cd) { contain: layout; }
html:not(#_) :is(.beat .art.vinyl, .feed-cd)::before { box-shadow: 0 28px 60px rgba(0,0,0,.62), 0 10px 22px rgba(0,0,0,.42), 0 2px 5px rgba(0,0,0,.35); }
html[data-mode="light"]:not(#_) :is(.beat .art.vinyl, .feed-cd)::before { box-shadow: 0 26px 50px rgba(40,55,70,.28), 0 8px 18px rgba(40,55,70,.2), 0 2px 4px rgba(40,55,70,.18); }

/* Shuffle on: the arrows turn green (off stays as it was). */
html:not(#_):not(#_):not(#_) #p-shuffle.on { color: #4fd67f !important; box-shadow: inset 0 1px 0 var(--edge), 0 0 10px rgba(79,214,127,.35), 0 0 0 1px rgba(79,214,127,.4); }
html[data-mode="light"]:not(#_):not(#_):not(#_) #p-shuffle.on { color: #17924a !important; box-shadow: inset 0 1px 0 #fff, 0 0 8px rgba(23,146,74,.25), 0 0 0 1px rgba(23,146,74,.45); }

/* The phone's mini player sits right on the bottom edge, full width (it floated 6px in, with rounded corners): the
   home bar's space is inside it, under its buttons. The open Now Playing sheet is unchanged. */
@media (max-width: 760px) {
  html.store:not(.np-open):not(#_) .toolbar { left: 0; right: 0; bottom: 0; border-width: 1px 0 0; border-radius: 0;
    padding-bottom: calc(8px + env(safe-area-inset-bottom) / 1.25); box-shadow: inset 0 1px 0 var(--edge), 0 -8px 24px rgba(0,0,0,.45); }
  html.store[data-mode="light"]:not(.np-open):not(#_) .toolbar { box-shadow: inset 0 1px 0 #fff, 0 -6px 18px rgba(60,80,95,.18); }
  html.store:not(.np-open):not(#_) .toolbar .lcd-row { left: 0; right: 0; top: 0; bottom: auto; } /* the progress line along its top edge */
  html.store:not(#_) .to-top { bottom: calc(72px + env(safe-area-inset-bottom)); }
}
/* The drag-down button takes focus when the sheet opens (so a keyboard or screen reader starts there); a tap must not
   leave it lit, so the focus ring only shows for keyboard focus, and a touch screen has no stuck hover on it. */
.np-head button:focus:not(:focus-visible) { outline: none; box-shadow: none; background: none; }
@media (hover: none) { .np-head button:hover { background: none; box-shadow: none; } }
/* The Now Playing sheet's record takes a finger like a page's big record (app.js scratch): no scrolling under it. */
html.store.np-open .toolbar #p-vinyl { touch-action: none; }
/* The sheet's record shrinks a little when paused (np-paused). Drawn once as its own layer and scaled by the GPU: redrawn
   at each step of the shrink (with its large soft shadow and glow), it dropped two frames at the start of every tape stop. */
html.store.np-open .toolbar #p-vinyl { will-change: transform; }
/* Paused, it settles (shrinks) only once a tape stop has wound down (viz-audio.js TAPE_MS): shrinking that large
   record while it still turned dropped two frames at the start of every stop, and a turntable doesn't sink while spinning. */
html.store.np-open.np-paused:not(#_) .toolbar #p-vinyl { transition-delay: .7s; }

/* ================= phones: fewer missed taps =================
   Measured on a 375px phone: a row's name was an 18px-tall link in the middle of the tap-to-play row, so a tap meant
   to play often opened the beat's page instead; the + sat 5px from the dots; and a tap in the 9px gaps between the
   mini player's buttons opened Now Playing. Now the whole row plays (its page is in the dots menu, and the player's
   title), the + and dots have room between them, and the player's buttons take taps that land just beside them. */
@media (max-width: 760px) {
  html.store .table .row .t { pointer-events: none; }
  html.store .table .row { grid-template-columns: 42px auto minmax(0, 1fr) auto 44px; column-gap: 8px; }
  html.store:not(#_) .table .row > .price-btn { min-height: 38px; padding-inline: 14px; margin-right: 4px; }
  html.store .table .row > .more { width: 44px; height: 48px; }
  html.store:not(.np-open) .toolbar :is(#p-prev, #p-toggle, #p-next) { position: relative; }
  html.store:not(.np-open) .toolbar :is(#p-prev, #p-toggle, #p-next)::after { content: ""; position: absolute; inset: -12px -5px; }
  /* A bigger bottom player: a larger record, title and buttons, and more room round them (about 80px tall, was 67). */
  html.store:not(.np-open):not(#_) .toolbar { gap: 0 10px; padding: 10px 10px calc(10px + env(safe-area-inset-bottom) / 1.25) 8px; }
  html.store:not(.np-open) .toolbar #p-vinyl { width: 46px; height: 46px; }
  html.store:not(.np-open) .toolbar .lcd-title { font-size: 13.5px; }
  html.store:not(.np-open) .toolbar .lcd-sub { font-size: 11.5px; }
  html.store:not(.np-open) .toolbar :is(#p-prev, #p-next) { width: 44px; height: 44px; font-size: 15px; }
  html.store:not(.np-open) .toolbar #p-toggle { width: 50px; height: 50px; font-size: 17px; }
  /* Play and skip only (back stays in Now Playing): more room for the name, and no back pressed for skip. The free
     copy keeps its download button in back's place. */
  html.store:not(.free):not(.np-open) .toolbar { grid-template-columns: auto minmax(0, 1fr) auto auto; grid-template-areas: "art title play next" "art sub play next"; }
  html.store:not(.free):not(.np-open) .toolbar #p-prev { display: none; }
  /* Its progress line along the top: thicker (3px on screen, was 2) and the played part bright on a dim track, so how
     far in a song is reads at a glance. Display only: seeking is on Now Playing's bar. */
  html.store:not(.np-open):not(#_) .toolbar .lcd .bar { height: 3px; border-radius: 0; background: rgba(255,255,255,.1); }
  html.store:not(.np-open):not(#_) .toolbar .lcd .fill { border-radius: 0 2px 2px 0; background: linear-gradient(90deg, #a8dcff, #ffffff); box-shadow: 0 0 6px rgba(168,220,255,.55); }
  html.store[data-mode="light"]:not(.np-open):not(#_) .toolbar .lcd .bar { background: rgba(0,0,0,.1); }
  html.store[data-mode="light"]:not(.np-open):not(#_) .toolbar .lcd .fill { background: #2f7fb8; box-shadow: none; }
  html.store body { padding-bottom: calc(140px + env(safe-area-inset-bottom)); }
  html.store:not(#_) .to-top { bottom: calc(86px + env(safe-area-inset-bottom)); }
}
@media (pointer: coarse) {
  .sitefoot a { padding: 10px 8px; }
  .drawer .line-link { display: inline-block; padding: 10px 0; margin: -10px 0; }
}
/* The search box's hint in the store's own grey (it was the browser's default #757575, the dimmest text on the page). */
.search::placeholder { color: var(--muted); opacity: 1; }

/* ---- records show their covers exactly as printed ----
   The cover pictures carry their own CD rim, hub and metal (engine/cdprint.py; the list's small discs show just
   that). Anything laid over them on the bigger records (a bright edge band, foil streaks, a grey soft-light metal cast)
   showed as a white ring round the cover and made the same cover paler and greyer than in the list. ---- */
html:not(#_):not(#_):not(#_) :is(.vinyl:not(.no-art), .m-card-art)::after { background: none; }
html:not(#_):not(#_):not(#_) :is(.vinyl:not(.no-art), .m-card-art) .vinyl-disc::after,
html:not(#_):not(#_):not(#_) .m-card-art::before { display: none; }

/* The list's titles are plain text (app.js): a tap on one plays its row, so no link underline on hover. */
html:not(#_) .row .t:hover, html:not(#_) .table.loops .row .t:hover { text-decoration: none; }

/* Now Playing's visualizer and DJ switches (phone.js .np-tools): plain icons in the header beside the dots. */
.np-tools, .np-dj { display: none; } /* desktop never shows them (phone.js adds them to the player bar on every device) */
@media (max-width: 760px) {
  html.store.np-open .toolbar .np-tools { display: flex; flex: none; pointer-events: auto; }
  html.store.np-open:not(.viz-live) .toolbar .np-viz { visibility: hidden; pointer-events: none; } /* only while a track plays, like the page's own button (viz-switch.js); its space kept, so nothing shifts */
  /* DJ mode at the end of the controls, where the cart was; the cart up top beside the visualizer. */
  html.store.np-open:not(#_) .toolbar { grid-template-areas: "head head head head head" "art art art art art" "title title title title title" "sub sub sub sub sub" "bar bar bar bar bar" "shuf prev play next dj"; }
  html.store:not(.np-open) .toolbar .np-dj { display: none; }
  html.store.np-open .toolbar .np-dj { display: inline-grid; grid-area: dj; place-self: center; width: 46px; height: 46px; pointer-events: auto; }
  html.store.np-open .toolbar .np-dj::before { width: 21px; height: 21px; }
  html.store.np-open:not(#_):not(#_):not(#_) .toolbar .np-tools .cart-tab { width: 44px; height: 44px; margin: 0; }
  /* The same pictures as the page's own buttons (an open or shut eye; the record with its arm on or lifted), drawn plain
     and white like Now Playing's other icons, a little dimmer when off. */
  .np-switch { width: 44px; height: 44px; display: inline-grid; place-items: center; padding: 0; border: 0; border-radius: 50%; background: none; color: #fff; -webkit-tap-highlight-color: transparent; }
  .np-switch[hidden] { display: none; }
  .np-switch::before { content: ""; width: 19px; height: 19px; background: currentColor;
    -webkit-mask: var(--np-icon) center / contain no-repeat; mask: var(--np-icon) center / contain no-repeat; }
  .np-viz[aria-pressed="true"] { --np-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill-rule='evenodd' d='M6 2.2C3.4 2.2 1.3 4.1.2 6c1.1 1.9 3.2 3.8 5.8 3.8s4.7-1.9 5.8-3.8C10.7 4.1 8.6 2.2 6 2.2zm0 1.1c2 0 3.6 1.3 4.5 2.7C9.6 7.4 8 8.7 6 8.7S2.4 7.4 1.5 6C2.4 4.6 4 3.3 6 3.3z'/%3E%3Ccircle cx='6' cy='6' r='1.6'/%3E%3C/svg%3E"); }
  .np-viz[aria-pressed="false"] { --np-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='1.2' stroke-linecap='round'%3E%3Cpath d='M.9 5.2C2.3 6.9 4 7.7 6 7.7s3.7-.8 5.1-2.5'/%3E%3Cpath d='M2.6 6.8 1.7 8.1M6 7.7v1.6M9.4 6.8l.9 1.3'/%3E%3C/svg%3E"); }
  .np-dj[aria-pressed="true"] { --np-icon: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 12 12%27%3E%3Cpath fill-rule=%27evenodd%27 d=%27M5 1.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zm0 3.4a1.1 1.1 0 1 1 0 2.2 1.1 1.1 0 0 1 0-2.2z%27/%3E%3Cpath d=%27M9.7.5l1.2.7-2.3 4-1.1-.6z%27/%3E%3Ccircle cx=%279.9%27 cy=%271%27 r=%27.95%27/%3E%3C/svg%3E"); }
  .np-dj[aria-pressed="false"] { --np-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill-rule='evenodd' d='M4.6 2.1a4.3 4.3 0 1 0 0 8.6 4.3 4.3 0 0 0 0-8.6zm0 3.2a1.1 1.1 0 1 1 0 2.2 1.1 1.1 0 0 1 0-2.2z'/%3E%3Crect x='10.3' y='1.4' width='1.2' height='5.6' rx='.6'/%3E%3Ccircle cx='10.9' cy='1.4' r='.95'/%3E%3C/svg%3E"); }
  .np-switch[aria-pressed="false"] { opacity: .6; }
  .np-switch:active { transform: scale(.92); opacity: .75; }
  html.store[data-mode="light"] .np-switch { color: #121416; }
}
/* Now Playing's buttons, half Spotify: shuffle, back, skip and the cart are plain icons (no glass circles), the glass
   play button stays the one big button, and the + is a thin outline. Layout and sizes as before: only the look changes. */
@media (max-width: 760px) {
  html.store.np-open:not(#_):not(#_):not(#_) .toolbar :is(#p-shuffle, #p-prev, #p-next, .cart-tab) {
    background: none !important; border: 0 !important; box-shadow: none !important; color: #fff; }
  html.store.np-open[data-mode="light"]:not(#_):not(#_):not(#_) .toolbar :is(#p-shuffle, #p-prev, #p-next, .cart-tab) { color: #121416; }
  html.store.np-open:not(#_):not(#_):not(#_) .toolbar #p-buy { background: none !important; border: 1.5px solid #b3b3b3 !important; box-shadow: none !important; color: #e6e6e6; }
  html.store.np-open[data-mode="light"]:not(#_):not(#_):not(#_) .toolbar #p-buy { border-color: #5d666d !important; color: #5d666d; }
  html.store.np-open:not(#_):not(#_):not(#_) .toolbar :is(#p-shuffle, #p-prev, #p-next, .cart-tab, #p-buy):active { transform: scale(.92); opacity: .75; }
}
/* Now Playing's top-right buttons (visualizer, cart, dots): one size and one look. The same box, a 20px icon in the
   page's text colour, no glass, no fade; the visualizer says off by its shut eye alone. */
@media (max-width: 760px) {
  html.store.np-open:not(#_):not(#_):not(#_) .toolbar .np-head :is(.np-viz, .cart-tab, .np-more) {
    width: 44px; height: 44px; padding: 0; margin: 0; border: 0 !important; border-radius: 50%; background: none !important; box-shadow: none !important;
    color: var(--text) !important; opacity: 1; filter: none; transition: none; display: inline-grid; place-items: center; }
  html.store.np-open:not(#_):not(#_):not(#_) .toolbar .np-head :is(.np-viz, .cart-tab)::before { width: 20px; height: 20px; }
  html.store.np-open:not(#_):not(#_):not(#_) .toolbar .np-head .np-more svg.ic { width: 20px; height: 20px; }
  html.store.np-open:not(#_):not(#_):not(#_) .toolbar .np-head :is(.np-viz, .cart-tab, .np-more):active { transform: scale(.92); opacity: .75; }
}
/* Phones: DJ mode is switched from Now Playing only (phone.js .np-dj, which drives this button). The page's own one is
   hidden, header and beat / loop pages alike. */
@media (max-width: 760px) { html.store #p-switchup { display: none !important; } }

/* ---- phones: the visualizer lives in Now Playing only, like Spotify's Canvas ----
   Behind the list it competed with the list and cost a phone its battery; now it shows in the sheet and slides with it
   (phone.js). While the sheet is closed it is hidden and drawn only a few times a second (viz-core.js), so it is ready
   the moment the sheet comes up. Its switches are Now Playing's own, so the page's visualizer, list-hide and DJ buttons
   are hidden, and the page never hides its list for a visualizer it no longer shows (nor fades into immersive mode:
   viz-idle.js leaves it be while Now Playing is closed). */
@media (max-width: 760px) {
  html.store:not(.np-open) :is(#viz, #viz-egg) { visibility: hidden; }
  html.store :is(#p-vizstyle, #p-listtoggle) { display: none !important; }
  html:not(#_):not(#_) .beat-tools .m-cart { margin-left: auto !important; } /* the visualizer button that pushed it to the right is hidden */
  html.store.list-hidden:not(#_):not(#_) :is(.window .table, .sitefoot, .to-top) { opacity: 1; visibility: visible; pointer-events: auto; }
}

/* ---- The exposed player (player-deck.js): html.deck-on unless switched off for this browser (?deck=off) ---- */
/* Beat/loop page on web: the back button up in the corner, its top in line with the round buttons on the right. */
@media (min-width: 701px) { html.store.deck-on main.beat .beat-tools .back { top: 0; left: 14px; } }
/* In DJ mode (html.deck-dj) the page's big record sits in the player: the record itself shows and spins as ever,
   the player's own disc shadow standing in for the record's. */
html.deck-on.deck-dj:not(#_):not(#_) .art.vinyl.deck-under::before { box-shadow: none; background: none; }
/* The deck's two layers round the record (player-deck.js): under it (placed just before the page, so painted beneath
   it and above the visualizer behind it) and over it (after the page); both below the toolbar (10). Their own
   view-transition groups, so a page change leaves them where they are. They fade with the page in idle mode
   (html.immersive: out over 1.8 s, back over .4 s), and hide under a fully open phone Now Playing sheet. */
html.deck-on canvas.deck { position: absolute; z-index: 1; pointer-events: none; border-radius: 2.5%; transition: opacity .4s ease; }
html.deck-on canvas.deck-below { box-shadow: 0 24px 50px rgba(0,0,0,.5), 0 6px 14px rgba(0,0,0,.35); view-transition-name: harz-deck-below; }
html.deck-on canvas.deck-above { view-transition-name: harz-deck-above; }
html.deck-on canvas.deck-sled { view-transition-name: harz-deck-sled; will-change: transform; border-radius: 0; } /* slid by player-deck.js */
html.deck-on canvas.deck-shade { view-transition-name: harz-deck-shade; border-radius: 0; }
html.deck-on.immersive canvas.deck { opacity: 0; transition: opacity 1.8s ease; }
html.deck-on.np-open:not(.np-peek) canvas.deck { visibility: hidden; }
::view-transition-group(harz-deck-below), ::view-transition-group(harz-deck-sled), ::view-transition-group(harz-deck-shade), ::view-transition-group(harz-deck-above) { animation: none; }
::view-transition-old(harz-deck-below), ::view-transition-old(harz-deck-sled), ::view-transition-old(harz-deck-shade), ::view-transition-old(harz-deck-above) { display: none; }
::view-transition-new(harz-deck-below), ::view-transition-new(harz-deck-sled), ::view-transition-new(harz-deck-shade), ::view-transition-new(harz-deck-above) { animation: none; }

/* ?np=scroll (phone.js): the track's page inside Now Playing. The sheet scrolls; the player keeps the first screen
   and the details sit just under it (positioned at 100%, so they add to the scroll without squeezing the player). */
@media (max-width: 760px) {
  html.store.np-scroll.np-open .toolbar { overflow: hidden auto; touch-action: pan-y; overscroll-behavior: none; scrollbar-width: none; }
  html.store.np-scroll.np-open .toolbar::-webkit-scrollbar { display: none; }
  html.store.np-scroll.np-open .toolbar #p-vinyl { touch-action: none; }
  .np-info { display: none; }
  html.store.np-scroll.np-open .np-info { display: block; position: absolute; top: 100%; left: 0; right: 0; min-height: 70svh;
    padding: 26px 18px calc(28px + env(safe-area-inset-bottom)); border-top: 1px solid #000; border-radius: 16px 16px 0 0;
    background: linear-gradient(180deg, rgba(34,37,41,.97) 0%, rgba(12,13,15,.98) 160px, rgba(6,7,8,.99) 100%);
    box-shadow: inset 0 1px 0 var(--edge), 0 -10px 30px rgba(0,0,0,.5); }
  html.store.np-scroll.np-open .np-info::before { content: ""; position: absolute; top: 8px; left: 50%; width: 36px; height: 4px; margin-left: -18px;
    border-radius: 2px; background: rgba(255,255,255,.22); } /* a grab handle, as on the phone's other sheets */
  html.store.np-scroll.np-open[data-mode="light"] .np-info::before { background: rgba(0,0,0,.2); }
  html.store.np-scroll.np-open[data-mode="light"] .np-info { border-color: #8d979f;
    background: linear-gradient(180deg, rgba(250,251,252,.98) 0%, rgba(233,238,242,.98) 140px, rgba(224,230,235,.99) 100%);
    box-shadow: inset 0 1px 0 #fff, 0 -8px 24px rgba(60,80,95,.2); }
  /* the track page's own layout (main.beat .info, above) inside the panel: just its spacing undone */
  .np-info .beat { display: block; padding: 0; }
  .np-info .beat .info { display: block; }
  .np-info .beat .sub { white-space: pre; }
  .np-info .beat .made { margin: 4px 0 0; }
  .np-info .np-dl { display: flex; justify-content: center; padding: 12px; margin-top: 16px; }
  .np-info-acts { display: flex; gap: 10px; margin-top: 16px; }
  .np-info-acts .cart-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 11px 8px; }
  .np-info-acts .ic { width: 16px; height: 16px; }
}

/* Express wallets beside the cards (Apple Pay, Link, Amazon Pay: vendor/wallets) and, under them, the pay-later line
   for Stripe's Klarna, Affirm and Cash App Pay. */
html:not(#_) .cart-trust .cards span.w-ap { background-image: url(/vendor/wallets/applepay.svg); }
html:not(#_) .cart-trust .cards span.w-link { background-image: url(/vendor/wallets/link.svg); }
html:not(#_) .cart-trust .cards span.w-amzn { background-image: url(/vendor/wallets/amazonpay.svg); }
.pay-banner .pay-later { flex-basis: 100%; text-align: right; font-size: 11.5px; color: #c9d1d6; }
.cart-trust .pay-later, html.store .pay-banner .pay-later { text-align: center; }
html[data-mode="light"] .pay-banner .pay-later { color: #44505a; }
@media (min-width: 761px) { html.store :is(main, .np-info) .pay-banner .pay-later { text-align: right; } }
/* Seven badges: they keep their size and wrap, centred, on a narrow phone rather than squeezing. */
html:not(#_) .pay-banner .cards { flex-wrap: wrap; row-gap: 6px; }
html:not(#_) .pay-banner .cards > * { flex-shrink: 0; }
html:not(#_) .cart-trust .cards span.w-cash { background-image: url(/vendor/wallets/cashapp.svg); }
/* Eight badges on one centred row on a phone (whose track page is zoomed 110%): a touch smaller there. */
@media (max-width: 760px) {
  html:not(#_) .pay-banner:not(.cart-trust) .cards { gap: 4px; }
  html:not(#_) .pay-banner:not(.cart-trust) .cards .card { width: 32px; height: 20px; }
  html:not(#_) .cart-trust .cards { gap: 4px; }
}
/* The pay-later line carries Klarna's and Affirm's own badges, a little smaller than the row above. */
.pay-banner .pay-later { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 5px; }
.cart-trust .pay-later, html.store .pay-banner .pay-later { justify-content: center; }
@media (min-width: 761px) { html.store :is(main, .np-info) .pay-banner .pay-later { justify-content: flex-end; } }
.pay-banner .pay-later .bnpl { width: 32px; height: 20px; flex-shrink: 0; border-radius: 3px; box-shadow: 0 0 0 1px rgba(255,255,255,.15), 0 1px 2px rgba(0,0,0,.45); }
html[data-mode="light"] .pay-banner .pay-later .bnpl { box-shadow: 0 0 0 1px #c3cbd1; }
