@charset "utf-8";
/* ==========================================================================
   Muno design system — "شب و شیار" (Night & Groove)
   Persian-first, RTL, dark. Hand-authored, no framework, no build step.
   Sections: 1 fonts · 2 tokens · 3 reset · 4 type · 5 layout · 6 rail
             7 topbar · 8 search · 9 sections · 10 cards · 11 rows
             12 hero/sleeve · 13 track page · 14 artist page · 15 player
             16 footer · 17 utilities · 18 responsive · 19 motion/a11y
   ========================================================================== */

/* -- 1 . Fonts ----------------------------------------------------------- */
/* One family, real weights. The vendor sheet declared every weight as its own
   family at weight:normal, which made `font-weight` inert. */
@font-face{font-family:Peyda;font-style:normal;font-weight:300;font-display:swap;
  src:url(/Peyda/PeydaWeb/woff2/peydaWeblight.woff2) format("woff2")}
@font-face{font-family:Peyda;font-style:normal;font-weight:400;font-display:swap;
  src:url(/Peyda/PeydaWeb/woff2/PeydaWebRegular.woff2) format("woff2")}
@font-face{font-family:Peyda;font-style:normal;font-weight:500;font-display:swap;
  src:url(/Peyda/PeydaWeb/woff2/PeydaWebMedium.woff2) format("woff2")}
@font-face{font-family:Peyda;font-style:normal;font-weight:600;font-display:swap;
  src:url(/Peyda/PeydaWeb/woff2/PeydaWebSemiBold.woff2) format("woff2")}
@font-face{font-family:Peyda;font-style:normal;font-weight:700;font-display:swap;
  src:url(/Peyda/PeydaWeb/woff2/PeydaWebBold.woff2) format("woff2")}

/* -- 2 . Tokens ---------------------------------------------------------- */
/* Everything that is not a colour: identical in both themes, declared once. */
:root{
  /* The brand stops. Fixed in both themes on purpose — a warm gradient is the
     one thing on the site that should look the same wherever it appears, and a
     button that changes colour with the theme stops reading as a brand mark. */
  --brand-1:#FF8A1F;
  --brand-2:#FF4D2E;
  --warm:linear-gradient(135deg,var(--brand-1),var(--brand-2));
  /* Ink for text sitting on that gradient. Dark in both themes, because the
     gradient is light in both themes. */
  --on-warm:#17110A;

  /* A vinyl record is black in daylight too. The disc, the veils over cover art
     and the labels on a poster stay dark in both themes because they sit on
     artwork, not on the page. */
  --art-veil:rgba(10,8,14,.85);
  --art-chip:rgba(10,8,14,.62);
  --art-chip-solid:rgba(8,6,12,.88);
  --on-art:#F3EDE4;

  --rail:248px;
  --player-h:88px;
  --topbar-h:68px;

  /* The notch, the home indicator and the rounded corners. Named once and added
     to every edge a fixed element touches. The status bar style is
     black-translucent, which means iOS draws the page *under* the status bar
     and leaves it to us to make room — without these the topbar sat behind the
     clock and the player behind the home indicator. */
  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
  --safe-l:env(safe-area-inset-left,0px);
  --safe-r:env(safe-area-inset-right,0px);
  --gutter:clamp(16px,3vw,40px);
  --maxw:1440px;

  --r-sm:8px;
  --r:12px;
  --r-lg:18px;

  --mono:ui-monospace,"SF Mono","JetBrains Mono","Roboto Mono",Menlo,Consolas,Peyda,sans-serif;
  --sans:Peyda,"Vazirmatn","Segoe UI",system-ui,-apple-system,sans-serif;

  --ease:cubic-bezier(.2,.7,.3,1);
}

/* ---------------------------------------------------------------------------
   Themes
   ---------------------------------------------------------------------------
   Three states, not two. An explicit choice stamps data-theme on <html>; with
   no stamp the system decides. The default with no stamp and no system
   preference is dark, because dark is what this site is — the palette is named
   "شب و شیار" and the identity does not survive being served light by accident.

   Every colour is declared in both blocks. A token that exists in only one of
   them is the classic unreadable-page bug: one theme's text on the other
   theme's ground.
   --------------------------------------------------------------------------- */

/* -- dark: the default -- */
:root,
:root[data-theme="dark"]{
  color-scheme:dark;

  /* Ink — a deep plum-black, not neutral #000: it keeps warm cover art from
     looking pasted onto a void. */
  --ink:#0E0C14;
  --ink-2:#15121D;
  --ink-3:#1D1928;
  --ink-4:#262133;

  /* Bone — warm off-white for display type. Pure #fff reads clinical here. */
  --bone:#F3EDE4;
  --text:#E4DED6;
  --muted:#948CA3;
  --faint:#8A8199;

  --line:rgba(243,237,228,.09);
  --line-2:rgba(243,237,228,.16);

  /* The accent as text and icons. On this ground the brand orange is legible
     as it is, so the two are the same value here and diverge on light. */
  --amber:#FF8A1F;
  --ember:#FF4D2E;

  --focus:#FFC34D;
  --scrim:rgba(6,5,10,.72);
  --sheen:rgba(243,237,228,.07);
  --glow:rgba(255,110,30,.9);
  --shadow:0 24px 60px -20px rgba(0,0,0,.75);

  --ok:#8FE3B8;
  --ok-bg:rgba(80,200,140,.09);
  --ok-line:rgba(80,200,140,.28);
  --bad:#FF9B9E;
  --bad-bg:rgba(229,72,77,.09);
  --bad-line:rgba(229,72,77,.3);
  --bad-edge:#E5484D;
}

/* -- light -- */
:root[data-theme="light"]{
  color-scheme:light;

  /* The same plum bias, read from the other end. A neutral grey here would
     make the amber look like a warning rather than a brand. */
  --ink:#FAF8FB;
  --ink-2:#FFFFFF;
  --ink-3:#F2EFF5;
  --ink-4:#E7E2EC;

  --bone:#17131F;
  --text:#332D3F;
  --muted:#565061;
  --faint:#6B6379;

  --line:rgba(23,19,31,.10);
  --line-2:rgba(23,19,31,.20);

  /* Not the brand orange: #FF8A1F on white is 2.3:1 and fails as text. This is
     the same hue carried down to a step that reads at 4.9:1, so links and
     labels stay legible while the gradient above keeps the brand colour. */
  --amber:#C2410C;
  --ember:#A5350A;

  --focus:#B23E0B;
  --scrim:rgba(23,19,31,.44);
  --sheen:rgba(23,19,31,.06);
  --glow:rgba(255,110,30,.42);
  --shadow:0 18px 44px -20px rgba(23,19,31,.28);

  --ok:#186A3F;
  --ok-bg:rgba(24,106,63,.08);
  --ok-line:rgba(24,106,63,.26);
  --bad:#B4232A;
  --bad-bg:rgba(180,35,42,.07);
  --bad-line:rgba(180,35,42,.26);
  --bad-edge:#C4262D;
}

/* The system decides when nothing is stamped. :not() keeps an explicit dark
   choice winning over a light OS, which a bare media query would not. */
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]){
    color-scheme:light;

    --ink:#FAF8FB;
    --ink-2:#FFFFFF;
    --ink-3:#F2EFF5;
    --ink-4:#E7E2EC;

    --bone:#17131F;
    --text:#332D3F;
    --muted:#565061;
    --faint:#6B6379;

    --line:rgba(23,19,31,.10);
    --line-2:rgba(23,19,31,.20);

    --amber:#C2410C;
    --ember:#A5350A;

    --focus:#B23E0B;
    --scrim:rgba(23,19,31,.44);
    --sheen:rgba(23,19,31,.06);
    --glow:rgba(255,110,30,.42);
  --shadow:0 18px 44px -20px rgba(23,19,31,.28);

    --ok:#186A3F;
    --ok-bg:rgba(24,106,63,.08);
    --ok-line:rgba(24,106,63,.26);
    --bad:#B4232A;
    --bad-bg:rgba(180,35,42,.07);
    --bad-line:rgba(180,35,42,.26);
    --bad-edge:#C4262D;
  }
}

/* -- 3 . Reset ----------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--ink);color:var(--text);
  font-family:var(--sans);font-size:.9375rem;line-height:1.9;font-weight:400;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}

/* A second line of defence, not the fix — the fix is that nothing is too wide,
   and tests/browser/overflow.mjs is what keeps that true. `hidden` still builds
   a scroll container, and WebKit will pan it with a finger even with no
   scrollbar drawn, which is how one over-wide footer let the whole page slide
   sideways on a phone. `clip` builds no scroll container, so there is nothing
   to pan. Only the x axis: the y axis has to stay scrollable, and vertical
   scrolling is asserted in tests/browser/mobile.mjs so this can never quietly
   take the page's scrolling with it. */
html,body{overflow-x:clip}
img,svg,video{display:block;max-width:100%}
img{height:auto}
a{color:inherit;text-decoration:none}
button,input,select{font:inherit;color:inherit}
button{background:none;border:0;padding:0;cursor:pointer}
ul,ol{margin:0;padding:0;list-style:none}
h1,h2,h3,h4,p{margin:0}
:focus-visible{outline:2px solid var(--focus);outline-offset:3px;border-radius:4px}
::selection{background:var(--amber);color:#12100c}

/* -- 4 . Type ------------------------------------------------------------ */
/* Persian carries the prose; Latin mono carries the data. Numbers, durations
   and counts are a different language here, and they are set like one. */
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums;letter-spacing:.04em}

/* Small labels: eyebrows, badges, section links. These used to borrow the
   monospace stack for its technical texture, which is fine for digits and
   wrong for words -- every one of them holds Persian. */
.lbl{font-family:var(--sans);font-weight:600;letter-spacing:normal;text-transform:none}

.d1{
  font-size:clamp(2rem,5.4vw,3.9rem);font-weight:700;line-height:1.14;text-wrap:balance;
  letter-spacing:-.022em;color:var(--bone);
}
.d2{font-size:clamp(1.5rem,3.2vw,2.3rem);font-weight:700;line-height:1.25;text-wrap:balance;letter-spacing:-.018em;color:var(--bone)}
.eyebrow{
  font-family:var(--sans);font-size:.75rem;font-weight:600;letter-spacing:normal;
  color:var(--amber);
}
.lead{font-size:1.0625rem;line-height:2;color:var(--muted);font-weight:300}

/* -- 5 . Layout shell ---------------------------------------------------- */
.main{
  padding:0 calc(var(--gutter) + var(--safe-r)) calc(var(--player-h) + var(--safe-b) + 56px) calc(var(--gutter) + var(--safe-l));
  margin-inline-start:0;
}
.wrap{max-width:var(--maxw);margin:0 auto;width:100%}
.skip{
  position:absolute;inset-inline-start:-9999px;top:0;z-index:200;
  /* The brand gradient, not the flat accent. On the light theme --amber is the
     deepened step that keeps links legible, and near-black on it came to
     3.67:1 — a skip link is the one control a keyboard user has to be able to
     read. On the gradient the same ink reads 7.9:1 and 5.7:1. */
  background:var(--warm);color:var(--on-warm);padding:10px 18px;border-radius:0 0 var(--r) 0;font-weight:600;
}
.skip:focus{inset-inline-start:0}

/* -- 6 . Rail (primary navigation) --------------------------------------- */
.rail{
  position:fixed;inset-block:0;inset-inline-start:0;width:var(--rail);z-index:90;
  background:var(--ink-2);border-inline-end:1px solid var(--line);
  padding:calc(26px + var(--safe-t)) 18px calc(var(--player-h) + var(--safe-b) + 24px);
  display:flex;flex-direction:column;gap:28px;overflow-y:auto;
  transition:transform .34s var(--ease);
}
.rail__brand{display:flex;align-items:center;gap:10px;padding-inline:6px}
.rail__brand img{height:30px;width:auto}
.rail__ver{font-family:var(--mono);font-size:.625rem;color:var(--faint);letter-spacing:.1em}

.nav{display:flex;flex-direction:column;gap:2px}
.nav__label{
  font-family:var(--sans);font-size:.6875rem;font-weight:600;color:var(--muted);
  padding:0 12px 8px;
}
.nav__link{
  display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:var(--r);
  color:var(--muted);font-size:.9375rem;font-weight:500;line-height:1.4;
  transition:background .18s var(--ease),color .18s var(--ease);position:relative;
}
.nav__link svg{width:19px;height:19px;flex:none;fill:currentColor;opacity:.85}
.nav__link:hover{background:var(--ink-3);color:var(--text)}
.nav__link[aria-current=page]{color:var(--bone);background:var(--ink-3)}
.nav__link[aria-current=page]::before{
  content:"";position:absolute;inset-inline-start:0;top:50%;translate:0 -50%;
  width:3px;height:20px;border-radius:0 3px 3px 0;background:var(--warm);
}
.nav__link.is-soon{opacity:.45;pointer-events:none}
.nav__soon{font-family:var(--sans);font-size:.6875rem;font-weight:500;color:var(--faint);margin-inline-start:auto}

/* Library counters — the rail states the size of the catalogue, which is the
   one fact that earns a permanent slot in the chrome. */
.rail__stats{margin-top:auto;padding:16px 12px;border-top:1px solid var(--line);display:grid;gap:12px}
.stat{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.stat__n{font-family:var(--mono);font-size:1.0625rem;color:var(--bone);font-variant-numeric:tabular-nums}
.stat__k{font-size:.75rem;color:var(--faint)}

.rail__close{display:none}
.scrim{
  position:fixed;inset:0;background:var(--scrim);z-index:85;opacity:0;visibility:hidden;
  transition:opacity .3s var(--ease),visibility .3s var(--ease);
}
body.rail-open .scrim{opacity:1;visibility:visible}

/* -- 7 . Topbar ---------------------------------------------------------- */
.topbar{
  position:sticky;top:0;z-index:50;height:calc(var(--topbar-h) + var(--safe-t));padding-top:var(--safe-t);
  display:flex;align-items:center;gap:14px;
  margin-inline:calc(var(--gutter) * -1);padding-inline:var(--gutter);
  background:var(--ink);
  background:color-mix(in srgb,var(--ink) 82%,transparent);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid transparent;transition:border-color .2s var(--ease);
}
.topbar.is-stuck{border-bottom-color:var(--line)}
.topbar__inner{display:flex;align-items:center;gap:14px;width:100%;max-width:var(--maxw);margin:0 auto}
.topbar__burger{display:none;width:40px;height:40px;border-radius:var(--r);align-items:center;justify-content:center;color:var(--text)}
.topbar__burger:hover{background:var(--ink-3)}
.topbar__burger svg{width:20px;height:20px;fill:currentColor}
.topbar__logo{display:none}
.topbar__spacer{flex:1}
.topbar__actions{display:flex;align-items:center;gap:8px}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:42px;padding:0 18px;border-radius:999px;font-size:.875rem;font-weight:600;
  transition:transform .18s var(--ease),background .18s var(--ease),color .18s var(--ease);
  white-space:nowrap;
}
.btn svg{width:17px;height:17px;fill:currentColor;flex:none}
.btn--warm{background:var(--warm);color:var(--on-warm);box-shadow:0 8px 24px -10px rgba(255,110,30,.85)}
.btn--warm:hover{transform:translateY(-1px)}
.btn--quiet{background:var(--ink-3);color:var(--text);border:1px solid var(--line)}
.btn--quiet:hover{background:var(--ink-4);color:var(--bone)}
.btn--ghost{color:var(--muted)}
.btn--ghost:hover{color:var(--bone)}
.btn--lg{height:52px;padding:0 26px;font-size:.9375rem}
.btn--icon{width:42px;padding:0}
.btn--icon.btn--lg{width:52px}

/* -- 8 . Search ---------------------------------------------------------- */
/* min-width:0 is not decoration. A flex item defaults to min-width:auto, which
   refuses to shrink below its content, so `flex:1` alone let this field hold the
   topbar 32px wider than a phone the moment a fourth control joined the row. */
.search{position:relative;flex:1 1 0;min-width:0;max-width:520px}
.search__field{display:flex;align-items:center;gap:10px;height:44px;padding:0 14px;
  background:var(--ink-2);border:1px solid var(--line);border-radius:999px;
  transition:border-color .2s var(--ease),background .2s var(--ease)}
.search__field:focus-within{border-color:var(--line-2);background:var(--ink-3)}
.search__field svg{width:17px;height:17px;fill:var(--faint);flex:none}
.search__input{flex:1;min-width:0;background:none;border:0;outline:none;font-size:.875rem;color:var(--text)}
.search__input::placeholder{color:var(--faint)}
.search__clear{color:var(--faint)}
.search__clear svg{width:15px;height:15px;fill:currentColor}

.results{
  position:absolute;inset-inline:0;top:calc(100% + 10px);z-index:70;
  background:var(--ink-2);border:1px solid var(--line-2);border-radius:var(--r-lg);
  box-shadow:var(--shadow);overflow:hidden;max-height:min(70vh,560px);overflow-y:auto;
}
.results__head{
  font-family:var(--sans);font-size:.6875rem;font-weight:600;
  color:var(--muted);padding:12px 16px 6px;
}
.results__item{display:flex;align-items:center;gap:12px;padding:9px 16px;transition:background .15s var(--ease)}
.results__item:hover{background:var(--ink-3)}
.results__item img{width:40px;height:40px;border-radius:var(--r-sm);object-fit:cover;flex:none;background:var(--ink-4)}
.results__item img.is-round{border-radius:50%}
.results__item>span{min-width:0;display:flex;flex-direction:column;line-height:1.6}
.results__t{font-size:.875rem;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.results__s{font-size:.75rem;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
[x-cloak]{display:none!important}
.results__empty{padding:22px 16px;text-align:center;color:var(--faint);font-size:.875rem}
.results__loading{padding:18px;display:flex;justify-content:center}

.spinner{width:18px;height:18px;border:2px solid var(--line-2);border-top-color:var(--amber);border-radius:50%;animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* -- 9 . Sections -------------------------------------------------------- */
.section{margin-top:clamp(40px,6vw,72px)}
.section__head{display:flex;align-items:center;gap:16px;margin-bottom:22px}
.section__title{font-size:1.1875rem;font-weight:600;color:var(--bone);letter-spacing:-.01em;white-space:nowrap}
.section__rule{flex:1;height:1px;background:var(--line)}
.section__more{
  font-family:var(--sans);font-size:.8125rem;font-weight:600;
  color:var(--muted);display:inline-flex;align-items:center;gap:6px;transition:color .18s var(--ease);
}
.section__more:hover{color:var(--amber)}

/* -- 10 . Track cards ---------------------------------------------------- */
.grid{display:grid;gap:clamp(14px,1.6vw,22px);grid-template-columns:repeat(auto-fill,minmax(148px,1fr))}

.card{min-width:0}
.card__art{
  position:relative;display:block;aspect-ratio:1;border-radius:var(--r);overflow:hidden;
  background:var(--ink-3);isolation:isolate;
}
.card__art img{width:100%;height:100%;object-fit:cover;transition:scale .5s var(--ease),filter .3s var(--ease)}
.card:hover .card__art img{scale:1.045;filter:brightness(.62)}
.card__art::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,var(--art-veil),transparent 55%);
  opacity:0;transition:opacity .3s var(--ease);
}
.card:hover .card__art::after{opacity:1}
.card__link{position:absolute;inset:0;z-index:1}

.card__play{
  position:absolute;inset-block-end:10px;inset-inline-start:10px;z-index:2;
  width:42px;height:42px;border-radius:50%;background:var(--warm);color:var(--on-warm);
  display:grid;place-items:center;
  opacity:0;translate:0 8px;transition:opacity .25s var(--ease),translate .25s var(--ease),scale .15s var(--ease);
  box-shadow:0 10px 26px -8px var(--glow);
}
.card__play svg{width:16px;height:16px;fill:currentColor}
.card:hover .card__play,.card__play:focus-visible{opacity:1;translate:0}
.card__play:hover{scale:1.07}

.card__plays{
  position:absolute;inset-block-end:16px;inset-inline-end:12px;z-index:2;
  font-family:var(--mono);font-size:.6875rem;color:var(--bone);
  opacity:0;transition:opacity .25s var(--ease);display:flex;align-items:center;gap:5px;
}
.card:hover .card__plays{opacity:.85}
.card__plays svg{width:12px;height:12px;fill:currentColor}

.card__title{
  margin-top:11px;font-size:.875rem;font-weight:500;color:var(--text);line-height:1.5;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:color .18s var(--ease);
}
.card:hover .card__title{color:var(--bone)}
.card__artist{
  font-size:.75rem;color:var(--faint);line-height:1.6;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.card__artist a:hover{color:var(--amber)}

/* Active track — the card that is currently loaded in the player. */
.card.is-current .card__title{color:var(--amber)}
.card.is-current .card__play{opacity:1;translate:0}

/* -- 11 . Track rows (discography) --------------------------------------- */
.rows{display:flex;flex-direction:column}
.row{
  display:grid;align-items:center;gap:14px;padding:9px 12px;border-radius:var(--r);
  grid-template-columns:32px 48px minmax(0,1fr) auto auto;
  transition:background .16s var(--ease);
}
.row:hover{background:var(--ink-2)}
/* Index and play control share one 32px cell: the number is the resting state,
   the control replaces it on hover or focus. */
.row__lead{position:relative;width:32px;height:32px;display:grid;place-items:center}
.row__i{font-family:var(--mono);font-size:.75rem;color:var(--faint);transition:opacity .16s var(--ease)}
.row:hover .row__i{opacity:0}
.row__play{position:absolute;inset:0;border-radius:50%;display:grid;place-items:center;color:var(--bone);
  opacity:0;transition:opacity .16s var(--ease)}
.row__play svg{width:14px;height:14px;fill:currentColor}
.row:hover .row__play,.row__play:focus-visible{opacity:1}
.row__play:focus-visible+.row__i,.row:hover .row__i{opacity:0}
.row__art{width:48px;height:48px;border-radius:var(--r-sm);object-fit:cover;background:var(--ink-3)}
.row__meta{min-width:0}
.row__t{font-size:.875rem;font-weight:500;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
.row:hover .row__t{color:var(--bone)}
.row__s{font-size:.75rem;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
.row__n{font-family:var(--mono);font-size:.75rem;color:var(--faint)}
.row__dl{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;color:var(--faint);transition:color .16s var(--ease),background .16s var(--ease)}
.row__dl svg{width:15px;height:15px;fill:currentColor}
.row__dl:hover{color:var(--bone);background:var(--ink-3)}
.row.is-current{background:var(--ink-2)}
.row.is-current .row__t{color:var(--amber)}
.row.is-current .row__i{opacity:0}
.row.is-current .row__play{opacity:1;color:var(--amber)}

/* -- 12 . Hero + the sleeve/disc signature ------------------------------- */
/* The disc is not decoration: it turns only while audio is playing, so every
   page shows its own transport state without a second indicator. */
.hero{
  display:grid;gap:clamp(28px,5vw,64px);align-items:center;
  grid-template-columns:minmax(0,1fr) auto;
  padding:clamp(32px,5vw,64px) 0 clamp(8px,2vw,20px);
}
.hero__body{min-width:0;display:flex;flex-direction:column;gap:16px;align-items:flex-start}
.hero__title{max-width:16ch}
.hero__title a{transition:color .18s var(--ease)}
.hero__title a:hover{color:var(--amber)}
.hero__artist{font-size:1.125rem;color:var(--muted);font-weight:400}
.hero__artist a{transition:color .18s var(--ease)}
.hero__artist a:hover{color:var(--bone)}
.hero__actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:6px}
.hero__data{display:flex;align-items:center;gap:26px;flex-wrap:wrap;margin-top:4px}
.hero__datum{display:flex;flex-direction:column;gap:1px}
.hero__datum b{font-family:var(--mono);font-size:1rem;font-weight:500;color:var(--bone);font-variant-numeric:tabular-nums}
.hero__datum span{font-size:.6875rem;color:var(--faint);letter-spacing:.02em}

.sleeve{position:relative;width:clamp(200px,26vw,320px);aspect-ratio:1;flex:none}
.sleeve__art{
  position:relative;z-index:2;width:100%;height:100%;object-fit:cover;
  border-radius:var(--r-lg);box-shadow:var(--shadow);background:var(--ink-3);
}
.sleeve__disc{
  position:absolute;z-index:1;inset-block:7%;inset-inline-end:-30%;aspect-ratio:1;height:86%;
}
.disc{
  position:relative;width:100%;height:100%;border-radius:50%;
  /* The one graphic that keeps its own colours in both themes: this is a vinyl
     record, an object rather than a surface, and a record is black in daylight
     too. Theming it would turn the site's signature into a white coaster. */
  background:
    repeating-radial-gradient(circle at 50% 50%,
      rgba(243,237,228,.05) 0 1px, rgba(0,0,0,0) 1px 5px),
    radial-gradient(circle at 34% 30%, rgba(243,237,228,.13), rgba(0,0,0,0) 46%),
    radial-gradient(circle at 50% 50%, #16121d 0 30%, #0c0912 30% 100%);
  box-shadow:0 22px 46px -18px rgba(0,0,0,.9), inset 0 0 0 1px rgba(243,237,228,.06);
  animation:groove 9s linear infinite;animation-play-state:paused;
}
body.is-playing .disc{animation-play-state:running}
@keyframes groove{to{transform:rotate(360deg)}}
.disc__label{position:absolute;inset:33%;border-radius:50%;overflow:hidden;box-shadow:inset 0 0 0 1px rgba(243,237,228,.14)}
.disc__label img{width:100%;height:100%;object-fit:cover;filter:saturate(1.1)}
.disc__hole{position:absolute;inset:47.6%;border-radius:50%;background:var(--ink);box-shadow:0 0 0 1px rgba(243,237,228,.18)}

/* Up-next queue beside the hero — a release feed genuinely is ordered, so the
   numbering here carries information rather than decorating. */
.queue{display:flex;flex-direction:column;gap:2px;margin-top:14px;width:100%;max-width:460px}
.queue__head{font-family:var(--sans);font-size:.6875rem;font-weight:600;color:var(--muted);padding:0 10px 8px}
.queue__item{display:grid;grid-template-columns:26px minmax(0,1fr) auto;align-items:center;gap:12px;padding:7px 10px;border-radius:var(--r-sm);transition:background .16s var(--ease)}
.queue__item:hover{background:var(--ink-2)}
.queue__i{font-family:var(--mono);font-size:.6875rem;color:var(--faint)}
.queue__t{font-size:.8125rem;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.queue__item:hover .queue__t{color:var(--text)}
.queue__s{font-family:var(--mono);font-size:.6875rem;color:var(--faint)}

/* -- 13 . Track page ----------------------------------------------------- */
.crumbs{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding-top:26px;font-size:.75rem;color:var(--faint)}
.crumbs a{transition:color .18s var(--ease)}
.crumbs a:hover{color:var(--amber)}
.crumbs li{display:flex;align-items:center;gap:8px}
.crumbs li+li::before{content:"/";color:var(--line-2);font-family:var(--mono)}
.crumbs [aria-current]{color:var(--muted)}

.lyrics{
  max-width:62ch;margin-inline:auto;padding:clamp(24px,4vw,44px);
  background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r-lg);
  font-size:1.0625rem;line-height:2.4;color:var(--text);text-align:center;font-weight:300;
}
.lyrics p{margin:0 0 1.4em}
.lyrics p:last-child{margin-bottom:0}

.panel{background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r-lg);padding:clamp(18px,3vw,28px)}
.dl-note{font-size:.8125rem;color:var(--faint);margin-top:10px}

/* -- 14 . Artist page ---------------------------------------------------- */
.artist{display:grid;grid-template-columns:auto minmax(0,1fr);gap:clamp(22px,4vw,44px);align-items:center;padding:clamp(28px,4vw,52px) 0}
.artist__photo{
  width:clamp(132px,16vw,190px);aspect-ratio:1;border-radius:var(--r-lg);object-fit:cover;
  background:var(--ink-3);box-shadow:var(--shadow);
}
.artist__body{min-width:0;display:flex;flex-direction:column;gap:14px;align-items:flex-start}
.artist__bio{max-width:68ch;color:var(--muted);font-size:.9375rem;line-height:2.05;font-weight:300}
.artist__bio p{margin:0 0 .9em}
.bio-toggle{font-family:var(--sans);font-size:.8125rem;font-weight:600;color:var(--amber)}
.clamp-6{display:-webkit-box;-webkit-line-clamp:6;line-clamp:6;-webkit-box-orient:vertical;overflow:hidden}

/* -- 15 . Player --------------------------------------------------------- */
.player{
  position:fixed;inset-block-end:0;inset-inline:0;z-index:80;
  height:calc(var(--player-h) + var(--safe-b));
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr) minmax(0,1fr);
  align-items:center;gap:20px;
  /* One shorthand, with the home-indicator inset in it. Written as a separate
     padding-bottom above this line it was silently thrown away, because the
     shorthand that follows resets every side. */
  padding:0 calc(clamp(14px,2.4vw,26px) + var(--safe-r)) var(--safe-b) calc(clamp(14px,2.4vw,26px) + var(--safe-l));
  background:var(--ink-2);
  background:color-mix(in srgb,var(--ink-2) 94%,transparent);
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  border-top:1px solid var(--line);
  transform:translateY(100%);transition:transform .4s var(--ease);
}
.player.is-ready{transform:none}

.player__now{display:flex;align-items:center;gap:12px;min-width:0}
.player__art{width:54px;height:54px;border-radius:var(--r-sm);object-fit:cover;background:var(--ink-3);flex:none}
.player__meta{min-width:0}
.player__t{font-size:.875rem;font-weight:500;color:var(--bone);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
.player__s{font-size:.75rem;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}

.player__center{display:flex;flex-direction:column;align-items:center;gap:6px;min-width:0;width:100%}
.player__buttons{display:flex;align-items:center;gap:6px}
.pbtn{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;color:var(--muted);transition:color .16s var(--ease),background .16s var(--ease),scale .16s var(--ease)}
.pbtn svg{width:17px;height:17px;fill:currentColor}
.pbtn:hover{color:var(--bone);background:var(--ink-3)}
.pbtn.is-on{color:var(--amber)}
.pbtn--play{width:44px;height:44px;background:var(--bone);color:#12100c}
.pbtn--play svg{width:18px;height:18px}
.pbtn--play:hover{background:var(--bone);color:var(--ink);scale:1.04}
.pbtn[disabled]{opacity:.35;pointer-events:none}

.player__seek{display:flex;align-items:center;gap:10px;width:100%;max-width:620px}
.time{font-family:var(--mono);font-size:.6875rem;color:var(--faint);font-variant-numeric:tabular-nums;width:40px;text-align:center;flex:none}

.range{
  -webkit-appearance:none;appearance:none;width:100%;height:14px;background:none;cursor:pointer;
}
.range::-webkit-slider-runnable-track{height:4px;border-radius:99px;
  background:linear-gradient(to right,var(--amber) var(--pct,0%),var(--ink-4) var(--pct,0%))}
.range::-moz-range-track{height:4px;border-radius:99px;background:var(--ink-4)}
.range::-moz-range-progress{height:4px;border-radius:99px;background:var(--amber)}
.range::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:12px;height:12px;border-radius:50%;
  background:var(--bone);margin-top:-4px;opacity:0;transition:opacity .16s var(--ease)}
.range::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:var(--bone);opacity:0}
.range:hover::-webkit-slider-thumb,.range:focus-visible::-webkit-slider-thumb{opacity:1}
.range:hover::-moz-range-thumb,.range:focus-visible::-moz-range-thumb{opacity:1}

/* Audio time runs left-to-right even inside an RTL page. */
.player__seek,.player__volume{direction:ltr}

.player__side{display:flex;align-items:center;justify-content:flex-end;gap:4px}
.player__volume{display:flex;align-items:center;gap:6px;width:104px}

/* Mobile progress hairline sits on the player's top edge. */
.player__hair{display:none;position:absolute;inset-inline:0;top:-1px;height:2px;background:var(--ink-4)}
.player__hair span{display:block;height:100%;width:0;background:var(--warm)}

/* -- 16 . Footer --------------------------------------------------------- */
.footer{margin-top:clamp(56px,8vw,110px);border-top:1px solid var(--line);padding:44px 0 20px}
/* The 240px is a floor, not a preference: a minmax minimum cannot shrink, so
   this grid demanded 240 + 36 gap + 150 = 426px. On a 390px phone the content
   box is 358px, and the whole page scrolled sideways because of these numbers.
   min() lets each track collapse when the container is narrower than its floor,
   and the ladder in section 18 drops the columns before it ever gets that far. */
.footer__grid{display:grid;gap:36px;
  grid-template-columns:minmax(min(240px,100%),1.6fr) repeat(auto-fit,minmax(min(150px,100%),1fr))}
.footer__brand img{height:30px;width:auto;margin-bottom:14px}
.footer__about{font-size:.875rem;color:var(--faint);line-height:2;max-width:44ch}
.footer__h{font-size:.8125rem;font-weight:600;color:var(--bone);margin-bottom:14px}
.footer__nav{display:flex;flex-direction:column;gap:9px}
.footer__nav a,.footer__contact a{font-size:.8125rem;color:var(--muted);transition:color .18s var(--ease)}
.footer__nav a:hover,.footer__contact a:hover{color:var(--amber)}
.footer__contact{display:flex;flex-direction:column;gap:9px}
.footer__contact a{display:flex;align-items:center;gap:9px}
.footer__contact svg{width:15px;height:15px;fill:currentColor;color:var(--faint);flex:none}
.footer__bar{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
  margin-top:34px;padding-top:18px;border-top:1px solid var(--line);font-size:.75rem;color:var(--faint)}
.footer__social{display:flex;gap:8px}
.footer__social a{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:var(--ink-2);border:1px solid var(--line);transition:border-color .18s var(--ease)}
.footer__social a:hover{border-color:var(--line-2)}
.footer__social svg{width:15px;height:15px;fill:var(--muted)}

/* -- 17 . Utilities ------------------------------------------------------ */
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.empty{padding:60px 20px;text-align:center;color:var(--faint);font-size:.9375rem}
.ltr{direction:ltr;unicode-bidi:isolate}

/* -- 18 . Responsive ----------------------------------------------------- */
@media (min-width:1024px){
  .main{margin-inline-start:var(--rail)}
}
@media (max-width:1023px){
  .rail{transform:translateX(-100%);box-shadow:var(--shadow)}
  [dir=rtl] .rail{transform:translateX(100%)}
  body.rail-open .rail{transform:none}
  .rail__close{display:grid;place-items:center;width:38px;height:38px;border-radius:var(--r);
    position:absolute;top:20px;inset-inline-end:16px;color:var(--muted)}
  .rail__close svg{width:18px;height:18px;fill:currentColor}
  .topbar__burger{display:grid}
  .topbar__logo{display:block}
  .topbar__logo img{height:26px;width:auto}
  .hero{grid-template-columns:1fr;justify-items:center;text-align:center}
  .hero__body{align-items:center}
  .hero__title{max-width:none}
  .sleeve{order:-1;width:min(280px,64vw)}
  .sleeve__disc{inset-inline-end:-26%}
  .artist{grid-template-columns:1fr;justify-items:center;text-align:center}
  .artist__body{align-items:center}
}
@media (max-width:760px){
  :root{--player-h:64px;--topbar-h:60px}
  .search{position:static}
  .results{inset-inline:var(--gutter)}
  .player{grid-template-columns:minmax(0,1fr) auto;gap:10px}
  .player__center{flex-direction:row;width:auto}
  .player__seek{display:none}
  .player__side{display:none}
  .player__art{width:44px;height:44px}
  .player__hair{display:block}
  .pbtn--prev{display:none}
  .grid{grid-template-columns:repeat(auto-fill,minmax(126px,1fr));gap:14px}
  .row{grid-template-columns:28px minmax(0,1fr) auto;gap:11px}
  .row__art{display:none}
  .row__n{display:none}
  .lyrics{padding:20px 16px;font-size:1rem;line-height:2.2}
  .hero__data{justify-content:center;gap:18px}
}
@media (max-width:900px){
  /* Below this the brand column and three link columns stop fitting on one
     row. Dropping its floor lets auto-fit choose the count and wrap the rest,
     instead of forcing a row wider than the screen. */
  .footer__grid{gap:28px;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr))}
}
@media (max-width:560px){
  .footer__grid{grid-template-columns:1fr;gap:26px}
}
@media (max-width:420px){
  .grid{grid-template-columns:repeat(2,1fr)}
  /* A section heading is nowrap so the rule beside it reads as one line, which
     is right until the heading is "بهترین آهنگ‌های محسن چاوشی" on a 320px
     screen — then an unbreakable line widens the whole page. Below this width
     the heading may wrap; two lines cost nothing and truncating a heading with
     an ellipsis would lose the artist's name. */
  .section__head{gap:12px}
  .section__title{white-space:normal}
  .section__rule{flex:1 1 16px;min-width:10px}
  .section__more{flex:none;white-space:nowrap}
}

/* -- 19 . Motion & accessibility ----------------------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
  .disc{animation:none}
}
/* A reader who asks for more contrast gets it in whichever theme they are in.
   The old single block pushed the secondary text pale, which is right on the
   dark ground and unreadable on the light one. */
@media (prefers-contrast:more){
  :root,
  :root[data-theme="dark"]{
    --muted:#C9C2D4;--faint:#A79FB5;
    --line:rgba(243,237,228,.22);--line-2:rgba(243,237,228,.34);
  }
  :root[data-theme="light"]{
    --muted:#4A4356;--faint:#5E5670;
    --line:rgba(23,19,31,.26);--line-2:rgba(23,19,31,.42);
  }
}
@media (prefers-contrast:more) and (prefers-color-scheme:light){
  :root:not([data-theme="dark"]){
    --muted:#4A4356;--faint:#5E5670;
    --line:rgba(23,19,31,.26);--line-2:rgba(23,19,31,.42);
  }
}

/* ==========================================================================
   20 . Accounts, library, playlists, PWA, skeletons
   Appended as one block so the original system above stays readable.
   ========================================================================== */

/* -- 20.1 . Forms --------------------------------------------------------- */
.form{max-width:420px;margin-inline:auto;padding:clamp(28px,6vw,56px) 0}
.form__head{margin-bottom:26px}
.form__head h1{margin-bottom:8px}
.form__head p{color:var(--muted);font-size:.9375rem}
.field{display:flex;flex-direction:column;gap:7px;margin-bottom:16px}
.field label{font-size:.8125rem;color:var(--muted);font-weight:500}
.input{
  height:48px;padding:0 15px;border-radius:var(--r);
  background:var(--ink-2);border:1px solid var(--line);color:var(--text);
  font-size:.9375rem;outline:none;width:100%;
  transition:border-color .18s var(--ease),background .18s var(--ease);
}
.input:focus{border-color:var(--line-2);background:var(--ink-3)}
.input::placeholder{color:var(--faint)}
.input[aria-invalid=true]{border-color:var(--bad-edge)}
textarea.input{height:auto;min-height:96px;padding:12px 15px;line-height:1.9;resize:vertical}
.field__error{font-size:.75rem;color:var(--bad)}
.field__hint{font-size:.75rem;color:var(--faint)}
.form .btn{width:100%}
.form__alt{margin-top:20px;padding-top:18px;border-top:1px solid var(--line);
  font-size:.875rem;color:var(--muted);text-align:center}
.form__alt a{color:var(--amber)}

.check{display:flex;align-items:center;gap:10px;cursor:pointer;font-size:.875rem;color:var(--muted)}
.check input{
  appearance:none;-webkit-appearance:none;width:20px;height:20px;flex:none;border-radius:6px;
  background:var(--ink-2);border:1px solid var(--line-2);cursor:pointer;
  display:grid;place-items:center;transition:background .16s var(--ease),border-color .16s var(--ease);
}
.check input:checked{background:var(--amber);border-color:var(--amber)}
.check input:checked::after{content:"";width:5px;height:9px;border:solid var(--on-warm);border-width:0 2px 2px 0;rotate:45deg;translate:0 -1px}

.alert{padding:12px 15px;border-radius:var(--r);font-size:.875rem;margin-bottom:18px;border:1px solid}
.alert--ok{background:var(--ok-bg);border-color:var(--ok-line);color:var(--ok)}
.alert--bad{background:var(--bad-bg);border-color:var(--bad-line);color:var(--bad)}

/* -- 20.2 . Account chip in the rail -------------------------------------- */
.account{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:var(--r);
  background:var(--ink-3);border:1px solid var(--line)}
.account img{width:32px;height:32px;border-radius:50%;object-fit:cover;flex:none;background:var(--ink-4)}
.account__name{font-size:.8125rem;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.account__out{margin-inline-start:auto;color:var(--faint);flex:none}
.account__out svg{width:16px;height:16px;fill:currentColor}
.account__out:hover{color:var(--bone)}

/* -- 20.3 . Favourite and add-to-playlist --------------------------------- */
.heart{
  width:36px;height:36px;border-radius:50%;display:grid;place-items:center;
  color:var(--muted);transition:color .16s var(--ease),background .16s var(--ease),scale .16s var(--ease);
}
.heart svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.9}
.heart:hover{color:var(--bone);background:var(--ink-3)}
.heart.is-on{color:var(--ember);animation:pop .28s var(--ease)}
.heart.is-on svg{fill:currentColor;stroke:currentColor}
@keyframes pop{40%{scale:1.22}100%{scale:1}}

/* Card overlay actions sit opposite the play control. */
.card__fav{position:absolute;inset-block-start:8px;inset-inline-end:8px;z-index:2;
  width:34px;height:34px;border-radius:50%;background:var(--art-chip);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  display:grid;place-items:center;color:var(--bone);opacity:0;transition:opacity .25s var(--ease)}
.card__fav svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.9}
.card:hover .card__fav,.card__fav:focus-visible,.card__fav.is-on{opacity:1}
.card__fav.is-on{color:var(--ember)}
.card__fav.is-on svg{fill:currentColor}

/* -- 20.4 . Menus --------------------------------------------------------- */
.menu{position:relative}
.menu__btn{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;color:var(--faint)}
.menu__btn svg{width:16px;height:16px;fill:currentColor}
.menu__btn:hover{color:var(--bone);background:var(--ink-3)}
.menu__pop{
  position:absolute;inset-inline-end:0;top:calc(100% + 6px);z-index:75;min-width:212px;
  background:var(--ink-2);border:1px solid var(--line-2);border-radius:var(--r);
  box-shadow:var(--shadow);padding:6px;display:none;max-height:320px;overflow-y:auto;
}
.menu.is-open .menu__pop{display:block}
.menu__label{font-family:var(--sans);font-size:.6875rem;font-weight:600;
  color:var(--muted);padding:8px 10px 4px}
.menu__item{display:flex;align-items:center;gap:9px;width:100%;padding:9px 10px;border-radius:var(--r-sm);
  font-size:.8125rem;color:var(--text);text-align:start;transition:background .14s var(--ease)}
.menu__item:hover{background:var(--ink-3)}
.menu__item svg{width:15px;height:15px;fill:currentColor;color:var(--faint);flex:none}
.menu__item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.menu__sep{height:1px;background:var(--line);margin:5px 0}

/* -- 20.5 . Playlist cards ------------------------------------------------ */
.plist{display:block;min-width:0}
.plist__art{position:relative;aspect-ratio:1;border-radius:var(--r);overflow:hidden;background:var(--ink-3);
  display:grid;place-items:center}
.plist__art img{width:100%;height:100%;object-fit:cover}
.plist__art svg{width:34%;height:34%;fill:var(--ink-4)}
.plist__badge{position:absolute;inset-block-start:8px;inset-inline-start:8px;
  font-family:var(--sans);font-size:.6875rem;font-weight:600;
  padding:3px 8px;border-radius:5px;background:rgba(10,8,14,.8);color:var(--bone);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.plist__title{margin-top:11px;font-size:.875rem;font-weight:500;color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.plist:hover .plist__title{color:var(--bone)}
.plist__meta{font-size:.75rem;color:var(--faint)}

/* -- 20.6 . Skeletons ----------------------------------------------------- */
/* One shimmer definition, applied to whatever shape is waiting. */
.sk{position:relative;overflow:hidden;background:var(--ink-3);border-radius:var(--r)}
.sk::after{
  content:"";position:absolute;inset:0;translate:-100% 0;
  background:linear-gradient(90deg,transparent,var(--sheen),transparent);
  animation:sweep 1.35s infinite;
}
@keyframes sweep{100%{translate:100% 0}}
.sk--text{height:.72em;border-radius:5px;margin:.32em 0}
.sk--art{aspect-ratio:1;border-radius:var(--r)}
.sk--round{border-radius:50%}
.sk--w70{width:70%}
.sk--w45{width:45%}

/* Covers fade in once decoded, which removes the grey flash on a slow
   connection without adding a byte of markup per card. */
.card__art img{opacity:0;transition:opacity .3s var(--ease)}
.card__art img.is-loaded{opacity:1}
html.no-js .card__art img{opacity:1}

@media (prefers-reduced-motion:reduce){
  .sk::after{animation:none}
}

/* -- 20.7 . Toast --------------------------------------------------------- */
.toasts{position:fixed;inset-block-end:calc(var(--player-h) + var(--safe-b) + 16px);inset-inline:0;z-index:95;
  display:flex;flex-direction:column;align-items:center;gap:8px;pointer-events:none;padding:0 16px}
.toast{
  background:var(--ink-3);border:1px solid var(--line-2);color:var(--text);
  padding:11px 18px;border-radius:999px;font-size:.8125rem;box-shadow:var(--shadow);
  pointer-events:auto;display:flex;align-items:center;gap:9px;max-width:min(92vw,420px);
  animation:rise .28s var(--ease);
}
.toast svg{width:15px;height:15px;fill:currentColor;flex:none;color:var(--amber)}
.toast a{color:var(--amber);white-space:nowrap}
@keyframes rise{from{opacity:0;translate:0 10px}to{opacity:1;translate:0}}

/* -- 20.8 . Install prompt ------------------------------------------------ */
/* Shown once the browser says the app is installable, and never again after a
   dismissal. The player already owns the bottom edge, so this sits above it. */
.install{
  position:fixed;inset-block-end:calc(var(--player-h) + var(--safe-b) + 14px);inset-inline:14px;z-index:96;
  max-width:440px;margin-inline:auto;
  display:none;align-items:center;gap:14px;padding:14px 16px;
  background:var(--ink-2);border:1px solid var(--line-2);border-radius:var(--r-lg);
  box-shadow:var(--shadow);animation:rise .32s var(--ease);
}
.install.is-on{display:flex}
.install__icon{width:44px;height:44px;border-radius:12px;flex:none;background:var(--ink-3)}
.install__body{min-width:0;flex:1}
.install__body b{display:block;font-size:.875rem;color:var(--bone);font-weight:600}
.install__body span{display:block;font-size:.75rem;color:var(--muted);line-height:1.7}
.install__go{height:38px;padding:0 16px;border-radius:999px;background:var(--warm);color:var(--on-warm);
  font-size:.8125rem;font-weight:600;flex:none}
.install__x{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;color:var(--faint);flex:none}
.install__x svg{width:14px;height:14px;fill:currentColor}
.install__x:hover{color:var(--bone);background:var(--ink-3)}

/* A quieter permanent entry point for people who dismissed the banner. */
.nav__link--install{color:var(--amber)}
.nav__link--install svg{opacity:1}

/* In standalone mode the app is already installed; hide every trace of it. */
@media (display-mode:standalone){
  .install,.nav__link--install{display:none!important}
}

/* -- 20.9 . Library ------------------------------------------------------- */
.lib__head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:clamp(26px,4vw,44px) 0 4px}
.empty__cta{margin-top:16px;display:flex;gap:10px;justify-content:center;flex-wrap:wrap}

/* -- 20.10 . Dialog ------------------------------------------------------- */
.dialog{border:0;padding:0;background:none;max-width:min(92vw,420px);width:100%}
.dialog::backdrop{background:var(--scrim);backdrop-filter:blur(3px)}
.dialog__box{background:var(--ink-2);border:1px solid var(--line-2);border-radius:var(--r-lg);
  padding:22px;box-shadow:var(--shadow)}
.dialog__box h2{font-size:1.0625rem;font-weight:600;color:var(--bone);margin-bottom:16px}
.dialog__row{display:flex;gap:10px;margin-top:18px}
.dialog__row .btn{flex:1}
.row__actions{display:flex;align-items:center;gap:2px}
.row__actions .heart{width:32px;height:32px}
.row__actions .heart svg{width:16px;height:16px}
.pager{display:flex;align-items:center;justify-content:center;gap:12px}
.pager__btn{height:40px;padding:0 18px;border-radius:999px;display:inline-flex;align-items:center;
  background:var(--ink-2);border:1px solid var(--line);color:var(--text);font-size:.875rem;
  transition:background .18s var(--ease),color .18s var(--ease)}
.pager__btn:hover{background:var(--ink-3);color:var(--bone)}
.pager__btn.is-off{opacity:.38;pointer-events:none}
.pager__count{font-size:.75rem;color:var(--faint)}

/* ==========================================================================
   21 . Concerts
   Posters are portrait (2:3) where covers are square, so events get their own
   grid rather than being forced into the card system.
   ========================================================================== */

.hero--flat{grid-template-columns:1fr;padding-bottom:0}
.hero--flat .hero__body{align-items:flex-start;max-width:none}

.ev-grid{display:grid;gap:clamp(14px,1.8vw,24px);grid-template-columns:repeat(auto-fill,minmax(178px,1fr))}

.ev{min-width:0}
.ev__art{position:relative;display:block;aspect-ratio:5/7;border-radius:var(--r);overflow:hidden;
  background:var(--ink-3)}
.ev__art img{width:100%;height:100%;object-fit:cover;transition:scale .5s var(--ease)}
.ev:hover .ev__art img{scale:1.04}
.ev__noart{position:absolute;inset:0;display:grid;place-items:center}
.ev__noart svg{width:34%;height:34%;fill:var(--ink-4)}

/* The countdown chip is the one piece of colour on the card: it is the reason
   the visitor is looking at it. */
.ev__flag{
  position:absolute;inset-block-end:8px;inset-inline-start:8px;
  font-family:var(--sans);font-size:.75rem;font-weight:600;letter-spacing:normal;
  font-variant-numeric:tabular-nums;
  padding:5px 10px;border-radius:7px;background:var(--art-chip-solid);color:#FFB259;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.ev__flag--off{color:var(--bad)}

.ev__title{margin-top:11px;font-size:.875rem;font-weight:500;color:var(--text);line-height:1.5;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ev:hover .ev__title{color:var(--bone)}
.ev__meta{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:.75rem;color:var(--faint);line-height:1.7}
.ev__meta .mono{font-size:.6875rem}

.ev__filter{display:flex;gap:10px;width:100%;max-width:520px;margin-top:8px}
.ev__filter .search__field{flex:1}

/* -- city chips ----------------------------------------------------------- */
.chips{display:flex;flex-wrap:wrap;gap:8px;margin:26px 0 6px}
.chip{display:inline-flex;align-items:center;height:34px;padding:0 14px;border-radius:999px;
  background:var(--ink-2);border:1px solid var(--line);color:var(--muted);font-size:.8125rem;
  transition:border-color .18s var(--ease),color .18s var(--ease),background .18s var(--ease)}
.chip:hover{color:var(--bone);border-color:var(--line-2)}
.chip.is-on{background:var(--ink-3);color:var(--bone);border-color:var(--line-2)}

/* -- artist photo credit --------------------------------------------------
   Small and quiet, but not hidden: the licence on a Wikimedia photograph is
   conditional on the credit being visible. */
/* The figure is the grid's auto-width first column, so it takes the photo's
   width and the caption wraps inside it rather than widening the column. */
.artist__figure{margin:0;display:flex;flex-direction:column;gap:8px;width:clamp(132px,16vw,190px)}
.artist__photo{width:100%}
.artist__credit{font-size:.6875rem;color:var(--faint);line-height:1.6}
.artist__credit a{color:var(--muted);text-decoration:underline;text-underline-offset:2px}
.artist__credit a:hover{color:var(--bone)}

/* -- navigation progress --------------------------------------------------
   Swapping content is fast enough that a spinner would flash, but not so fast
   that a slow connection should look like a dead click. A hairline is enough. */
.nav-bar{
  position:fixed;inset-block-start:0;inset-inline-start:0;z-index:120;
  height:2px;width:0;background:var(--warm);
  opacity:0;pointer-events:none;
}
.nav-bar.is-on{width:78%;opacity:1;transition:width 7s cubic-bezier(.1,.9,.2,1),opacity .1s}
.nav-bar.is-done{width:100%;opacity:0;transition:width .18s var(--ease),opacity .32s .12s}

@media (prefers-reduced-motion:reduce){
  .nav-bar,.nav-bar.is-on,.nav-bar.is-done{transition:opacity .1s}
}

/* -- countdown ------------------------------------------------------------ */
.cd{display:flex;gap:8px;margin:6px 0 4px}
.cd__cell{
  min-width:64px;padding:10px 12px;border-radius:var(--r);text-align:center;
  background:var(--ink-2);border:1px solid var(--line);
}
.cd__cell b{display:block;font-size:1.375rem;font-weight:500;color:var(--bone);
  font-variant-numeric:tabular-nums;line-height:1.2}
.cd__cell span{display:block;font-size:.6875rem;color:var(--faint);margin-top:2px}
.cd.is-live .cd__cell{border-color:color-mix(in srgb,var(--brand-1) 40%,transparent)}
.cd.is-live .cd__cell b{color:var(--amber)}

/* -- poster beside the hero ----------------------------------------------- */
.ev__poster{flex:none;width:clamp(190px,24vw,300px)}
.ev__poster img{width:100%;height:auto;aspect-ratio:5/7;object-fit:cover;
  border-radius:var(--r-lg);box-shadow:var(--shadow);background:var(--ink-3)}

@media (max-width:1023px){
  .ev__poster{order:-1;width:min(260px,58vw)}
}
@media (max-width:760px){
  .ev-grid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:14px}
  .cd__cell{min-width:0;flex:1;padding:9px 6px}
  .cd__cell b{font-size:1.125rem}
  .ev__filter{flex-direction:column}
}
@media (max-width:420px){
  .ev-grid{grid-template-columns:repeat(2,1fr)}
}

/* -- concerts strip on an artist page ------------------------------------- */
.ev-strip{display:flex;flex-direction:column;gap:2px}
.ev-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:14px;
  padding:11px 12px;border-radius:var(--r);transition:background .16s var(--ease)}
.ev-row:hover{background:var(--ink-2)}
.ev-row__date{text-align:center;min-width:56px}
.ev-row__date b{display:block;font-family:var(--mono);font-size:1.0625rem;color:var(--bone);line-height:1.15}
.ev-row__date span{display:block;font-size:.6875rem;color:var(--faint)}
.ev-row__meta{min-width:0}
.ev-row__t{display:block;font-size:.875rem;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ev-row:hover .ev-row__t{color:var(--bone)}
.ev-row__s{display:block;font-size:.75rem;color:var(--faint)}
.ev-row__go{font-family:var(--sans);font-size:.8125rem;font-weight:600;color:var(--amber)}

/* ==========================================================================
   22 . Editorial — news and long-form
   ========================================================================== */

.post-grid{display:grid;gap:clamp(18px,2.4vw,30px);grid-template-columns:repeat(auto-fill,minmax(280px,1fr));margin-top:26px}

.post{min-width:0}
.post__art{display:block;aspect-ratio:16/9;border-radius:var(--r);overflow:hidden;background:var(--ink-3)}
.post__art img{width:100%;height:100%;object-fit:cover;transition:scale .5s var(--ease)}
.post:hover .post__art img{scale:1.04}
.post__noart{display:block;width:100%;height:100%;
  background:linear-gradient(135deg,var(--ink-3),var(--ink-4))}
.post__cat{margin-top:12px;font-family:var(--sans);font-size:.75rem;font-weight:600;
  color:var(--amber)}
.post__title{margin-top:6px;font-size:1.0625rem;font-weight:600;color:var(--bone);line-height:1.55;
  letter-spacing:-.01em;text-wrap:balance}
.post:hover .post__title{color:var(--bone)}
.post__sum{margin-top:7px;font-size:.875rem;color:var(--muted);line-height:1.9;
  display:-webkit-box;-webkit-line-clamp:3;line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.post__meta{margin-top:9px;font-size:.6875rem;color:var(--faint)}

/* -- article -------------------------------------------------------------- */
/* A single column at a readable measure; the site chrome stays out of the way
   of the one thing on the page that is meant to be read start to finish. */
.article{max-width:70ch;margin-inline:auto;padding-top:clamp(20px,3vw,36px)}
.article__head{margin-bottom:26px}
.article__head .d1{font-size:clamp(1.75rem,4vw,2.9rem);margin-top:8px}
.article__meta{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:14px;
  font-size:.8125rem;color:var(--faint)}
.article__cover{width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;
  border-radius:var(--r-lg);margin-bottom:30px;background:var(--ink-3)}
.article__body{font-size:1.0625rem;line-height:2.2;color:var(--text);font-weight:300}
.article__body p{margin:0 0 1.3em}
.article__body h2{font-size:1.375rem;font-weight:600;color:var(--bone);margin:1.8em 0 .6em;
  letter-spacing:-.01em}
.article__body h3{font-size:1.125rem;font-weight:600;color:var(--bone);margin:1.5em 0 .5em}
.article__body a{color:var(--amber);text-decoration:underline;text-underline-offset:3px}
.article__body ul,.article__body ol{margin:0 0 1.3em;padding-inline-start:1.4em}
.article__body ul{list-style:disc}
.article__body ol{list-style:decimal}
.article__body li{margin-bottom:.5em}
.article__body blockquote{margin:1.5em 0;padding-inline-start:18px;
  border-inline-start:2px solid var(--amber);color:var(--muted)}
.article__body img{border-radius:var(--r);margin:1.4em 0}
.article__body strong{font-weight:600;color:var(--bone)}

/* ==========================================================================
   23 . Search
   The field is the page: on a search surface the first thing a visitor should
   meet is somewhere to type, at a size that says so.
   ========================================================================== */

.find{padding:clamp(30px,6vw,64px) 0 4px;max-width:760px;margin-inline:auto}

.find__form{
  position:relative;display:flex;align-items:center;gap:10px;
  height:64px;padding:0 8px 0 8px;padding-inline-start:52px;
  background:var(--ink-2);border:1px solid var(--line-2);border-radius:999px;
  transition:border-color .2s var(--ease),background .2s var(--ease);
}
.find__form:focus-within{border-color:var(--amber);background:var(--ink-3)}
.find__icon{
  position:absolute;inset-inline-start:20px;top:50%;translate:0 -50%;
  width:20px;height:20px;fill:var(--faint);pointer-events:none;
}
.find__form:focus-within .find__icon{fill:var(--amber)}
.find__input{
  flex:1;min-width:0;background:none;border:0;outline:none;
  font-size:1.0625rem;color:var(--bone);font-family:inherit;
}
.find__input::placeholder{color:var(--faint)}
.find__input::-webkit-search-cancel-button{display:none}
.find__clear{
  width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  color:var(--faint);flex:none;transition:color .16s var(--ease),background .16s var(--ease);
}
.find__clear svg{width:15px;height:15px;fill:currentColor}
.find__clear:hover{color:var(--bone);background:var(--ink-4)}
.find__go{
  height:48px;padding:0 22px;border-radius:999px;background:var(--warm);color:var(--on-warm);
  font-size:.875rem;font-weight:600;flex:none;
  transition:transform .18s var(--ease);
}
.find__go:hover{transform:translateY(-1px)}

.find__tabs{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px;justify-content:center}
.find__tabs .chip b{margin-inline-start:6px;color:var(--faint);font-size:.6875rem;font-weight:400}
.find__tabs .chip.is-on b{color:var(--amber)}

/* -- artist faces --------------------------------------------------------- */
/* Round, because a person is not an album. */
.face-grid{display:grid;gap:clamp(14px,2vw,24px);grid-template-columns:repeat(auto-fill,minmax(124px,1fr))}
.face{display:flex;flex-direction:column;align-items:center;text-align:center;min-width:0}
.face img{
  width:100%;height:auto;aspect-ratio:1;object-fit:cover;border-radius:50%;
  background:var(--ink-3);border:1px solid var(--line);
  transition:border-color .2s var(--ease),scale .3s var(--ease);
}
.face:hover img{border-color:var(--line-2);scale:1.03}
.face__name{
  margin-top:11px;font-size:.875rem;font-weight:500;color:var(--text);line-height:1.5;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.face:hover .face__name{color:var(--bone)}
.face__meta{font-size:.6875rem;color:var(--faint)}

.chips .chip b{margin-inline-start:6px;color:var(--faint);font-size:.6875rem;font-weight:400}

.empty__hint{display:block;font-size:.8125rem;color:var(--faint);margin-top:8px}

@media (max-width:760px){
  .find__form{height:56px;padding-inline-start:46px}
  .find__icon{inset-inline-start:16px;width:18px;height:18px}
  .find__input{font-size:1rem}
  .find__go{height:42px;padding:0 16px;font-size:.8125rem}
  .face-grid{grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:14px}
}

/* -- news attribution ----------------------------------------------------- */
/* Rewritten reporting always shows where it came from. */
.credit{
  display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;
  margin-top:32px;padding:14px 16px;border-radius:var(--r);
  background:var(--ink-2);border:1px solid var(--line);
  font-size:.8125rem;color:var(--muted);line-height:1.8;
}
.credit b{color:var(--text);font-weight:600}
.credit a{color:var(--amber);white-space:nowrap}
.post__badge{
  display:inline-block;margin-inline-start:6px;padding:1px 7px;border-radius:5px;
  font-family:var(--sans);font-size:.6875rem;font-weight:500;
  background:var(--ink-3);color:var(--muted);vertical-align:middle;
}

/* -- 20 . Editorial prose, FAQ and discovery ------------------------------ */
/* Added when the track page stopped being a title and a play button. The prose
   block carries the sentences a page can honestly say about a recording, and
   the FAQ answers the questions people type; both need to read as text, not as
   interface, so they get a wider measure and a quieter colour than the chrome. */
.prose{max-width:74ch;color:var(--text);font-size:.9375rem;line-height:2.05}
.prose p{margin:0 0 14px}
.prose p:last-child{margin-bottom:0}
.prose a{color:var(--amber);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;text-decoration-color:color-mix(in srgb,var(--amber) 45%,transparent)}
.prose a:hover{text-decoration-color:var(--amber)}

.faq{display:flex;flex-direction:column;gap:10px;max-width:74ch}
.faq__item{background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;transition:border-color .18s var(--ease)}
.faq__item[open]{border-color:var(--line-2)}
.faq__q{display:flex;align-items:center;gap:10px;padding:14px 18px;cursor:pointer;
  font-weight:600;color:var(--bone);font-size:.9375rem;line-height:1.7;list-style:none}
.faq__q::-webkit-details-marker{display:none}
/* The marker is drawn rather than typed: a rotated caret survives RTL, where a
   typographic arrow would point the wrong way. */
.faq__q::before{content:"";flex:none;width:8px;height:8px;border-inline-start:2px solid var(--amber);
  border-block-end:2px solid var(--amber);transform:rotate(45deg);transition:transform .2s var(--ease)}
.faq__item[open] .faq__q::before{transform:rotate(-135deg) translate(-2px,-2px)}
.faq__q:hover{color:var(--bone)}
.faq__a{padding:0 18px 16px 44px;color:var(--muted);line-height:2}

.chips--tight{margin:14px 0 0}

/* Four ways in, above the taxonomy itself. */
.tiles{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.tile{display:flex;flex-direction:column;gap:4px;padding:20px;border-radius:var(--r-lg);
  background:var(--ink-2);border:1px solid var(--line);
  transition:border-color .18s var(--ease),transform .18s var(--ease)}
.tile:hover{border-color:var(--line-2);transform:translateY(-2px)}
.tile__k{font-size:.6875rem;color:var(--amber);letter-spacing:.04em}
.tile__t{font-size:1.0625rem;font-weight:600;color:var(--bone)}
.tile__s{font-size:.8125rem;color:var(--faint);line-height:1.7}

.cats{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(210px,1fr))}
.cat{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:13px 16px;border-radius:var(--r);background:var(--ink-2);
  border:1px solid var(--line);transition:border-color .18s var(--ease),background .18s var(--ease)}
.cat:hover{background:var(--ink-3);border-color:var(--line-2)}
.cat__t{color:var(--text);font-size:.875rem}
.cat:hover .cat__t{color:var(--bone)}
.cat__n{flex:none;font-size:.75rem;color:var(--faint)}

/* -- radio ---------------------------------------------------------------- */
.stations{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}
.station{display:flex;align-items:center;gap:14px;padding:12px;border-radius:var(--r-lg);
  background:var(--ink-2);border:1px solid var(--line);
  transition:border-color .18s var(--ease),background .18s var(--ease)}
.station:hover{background:var(--ink-3);border-color:var(--line-2)}
.station__art{flex:none;width:64px;height:64px;border-radius:var(--r);object-fit:cover}
.station__art--none{background:var(--ink-4)}
.station__body{display:flex;flex-direction:column;gap:2px;min-width:0}
.station__t{font-weight:600;color:var(--bone);font-size:.9375rem}
.station__s{font-size:.8125rem;color:var(--faint);line-height:1.7;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.station__go{flex:none;display:grid;place-items:center;width:36px;height:36px;border-radius:999px;
  background:var(--warm);margin-inline-start:auto}
.station__go svg{width:15px;height:15px;fill:var(--on-warm);margin-inline-start:1px}

@media (max-width:760px){
  .faq__a{padding-inline-start:18px}
  .cats{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
  .stations{grid-template-columns:1fr}
}

/* -- 21 . Theme switch ---------------------------------------------------- */
/* Three states in one control, because the default is "follow the system" and a
   two-position switch cannot say that. Every icon is hidden until the script
   resolves the state, so the button never shows a symbol that contradicts the
   page around it. */
.theme{
  flex:none;display:grid;place-items:center;width:38px;height:38px;
  border-radius:var(--r);color:var(--muted);
  border:1px solid transparent;
  transition:color .18s var(--ease),background .18s var(--ease),border-color .18s var(--ease);
}
.theme:hover{color:var(--bone);background:var(--ink-3)}
.theme__i{width:18px;height:18px;fill:currentColor;grid-area:1/1;display:none}
.theme[data-state="system"] .theme__i--sys,
.theme[data-state="light"] .theme__i--sun,
.theme[data-state="dark"] .theme__i--moon{display:block}

@media (max-width:760px){
  /* Four controls in one row on a phone: the gap gives back what the
     fourth one takes, so the search field keeps a usable width. */
  .topbar__inner{gap:10px}
  .theme{width:34px;height:34px}
  .theme__i{width:17px;height:17px}
}

/* -- 22 . Wordmark -------------------------------------------------------- */
/* The wordmark is white in the source file, which is invisible on the light
   ground. It is drawn as a background rather than an <img> so the theme can
   choose the file: the browser fetches only the one that applies, where two
   <img> tags with one hidden would download both. role and aria-label carry the
   name that alt used to. */
.brand{
  display:block;
  background:url(/images/munow.svg) center/contain no-repeat;
}
.brand--lg{width:104px;height:30px}
.brand--sm{width:90px;height:26px}

:root[data-theme="light"] .brand{background-image:url(/images/munow-ink.svg)}

@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) .brand{background-image:url(/images/munow-ink.svg)}
}

/* ==========================================================================
   23 . Touch
   --------------------------------------------------------------------------
   Everything here is keyed on `pointer:coarse` rather than a width, because
   none of it is about how wide the screen is — it is about whether the thing
   pointing at it is a finger. A narrow desktop window keeps the desktop
   behaviour; a large tablet gets the touch behaviour.
   ========================================================================== */

@media (pointer:coarse){

  /* -- 23.1 . The zoom on focus ------------------------------------------
     Safari zooms the whole viewport when a focused field renders under 16px,
     and then leaves the page zoomed. The only honest fix is to make the field
     16px: the alternative, `maximum-scale=1` on the viewport, works by banning
     pinch-zoom for everyone, which takes a real accessibility tool away to
     paper over a type-size problem. 16px only where a finger is. */
  input,select,textarea,
  .search__input,.input,.find__input{font-size:16px}

  /* -- 23.2 . Thumb-sized targets ----------------------------------------
     44px is the smallest a control can be before a thumb starts missing it.
     Anything already block-shaped just grows; the small round icon buttons
     keep the size they were drawn at and gain the missing area invisibly, so
     the layout does not loosen to accommodate a rule nobody can see. */
  .btn,.nav__link,.queue__item,.row,.ev-row,.footer__nav a{min-height:44px}

  /* Breadcrumbs and inline form links are short words, and a word is not a
     button — growing them would space the trail out. They get the area
     instead, the same way the icon buttons do. */
  .crumbs a,.field__hint,.field a,.foot a{position:relative}
  .crumbs a::after,.field__hint::after,.field a::after,.foot a::after{
    content:;position:absolute;top:50%;left:50%;translate:-50% -50%;
    width:max(100%,44px);height:44px;
  }
  .chip,.cat{min-height:40px}

  .card__fav{width:40px;height:40px}

  .theme,.card__play,.pbtn,.rail__close,.topbar__burger,
  .search__clear,.section__more,.topbar__logo,.rail__brand,.player__meta,
  .menu__btn,.card__more,.chip{position:relative}

  .theme::after,.card__play::after,.pbtn::after,
  .rail__close::after,.topbar__burger::after,.search__clear::after,
  .section__more::after,.topbar__logo::after,.rail__brand::after,
  .menu__btn::after,.card__more::after,.chip::after{
    content:"";position:absolute;top:50%;left:50%;translate:-50% -50%;
    width:max(100%,44px);height:max(100%,44px);
  }

  /* The transport is the most-tapped thing on the site; it gets real size, not
     an invisible extension. */
  .pbtn{width:44px;height:44px}
  .pbtn--play{width:56px;height:56px}

  /* Hover does not exist here. The play and favourite buttons on a card fade in
     on hover, which on a phone left them invisible and still tappable — an
     unmarked 42px control on every cover, and two of them from neighbouring
     cards close enough to steal each other's corner. If there is no hover to
     reveal them, they are simply shown. */
  .card__play,.card__fav{opacity:1;translate:0}

  /* Breadcrumbs and short form links are a line of text tall. They have room
     above and below, so they take real padding rather than reaching into the
     control above them — an invisible area that overlaps a neighbour does not
     win the tap anyway. */
  .crumbs{gap:4px 10px}
  .crumbs a{padding:12px 6px}
  .field__hint,.form__alt a{display:inline-block;padding:11px 2px}
  .footer__contact{gap:2px}
  .footer__contact a{padding:10px 0}
  .footer__nav{gap:2px}

  /* -- 23.3 . How a tap should feel ---------------------------------------
     touch-action removes the wait for a possible double-tap zoom, which is the
     whole of the old "300ms delay". The grey flash goes, and a real :active
     state replaces it — removing the highlight without giving the press its
     own feedback makes a control feel broken rather than native. */
  a,button,[role=button],summary,label,input,select,.chip,.row,.card{
    touch-action:manipulation;
  }
  html{-webkit-tap-highlight-color:transparent}

  .btn:active,.pbtn:active,.chip:active,.nav__link:active,.theme:active,
  .card__play:active,.card__fav:active,.topbar__burger:active{scale:.96}

  /* Long-pressing a control should not offer to select its label or save its
     icon. Content — titles, lyrics, prose — stays selectable, because copying
     a lyric is something people actually do. */
  .rail,.topbar,.player,.btn,.chip,.pbtn,.theme,.nav__link,
  .card__play,.card__fav,.section__more{
    -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;
  }
  .card__art img,.hero__art img,.player__art{-webkit-touch-callout:none}
}

/* -- 23.4 . Scrolling ------------------------------------------------------
   A scroll that reaches the end of a panel should stop there instead of
   handing the gesture to the page behind it. In a browser tab the page itself
   keeps pull-to-refresh, which people expect there; installed as an app it
   does not, because an app does not reload when you scroll up at the top. */
html,body{overscroll-behavior-y:contain}
.rail,.results,.menu__list{overscroll-behavior:contain;-webkit-overflow-scrolling:touch}

@media (display-mode:standalone){
  html,body{overscroll-behavior-y:none}
}

/* -- 23.5 . The drawer holds the page still --------------------------------
   Set by script, which also remembers the scroll offset: `overflow:hidden` on
   its own is enough on a desktop and useless on iOS, where the page behind
   scrolls anyway and then jumps to the top when the drawer closes. */
body.is-locked{position:fixed;inset-inline:0;overflow:hidden;width:100%}
