/* perun.house, Voltage language. The long-form reasoning behind most of these
   rules lives in onepager/index.html; this file keeps the decisions, not the
   history. Values and palettes live in tokens.css; this file is the components.
   The page stays in its palette from top to bottom (the act-2 flip was
   dropped 2026-10-06; the dark look is the black / red palette). */
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;scroll-padding-top:64px}
body{background:var(--vo-paper);color:var(--vo-ink);font-family:var(--mono);
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
  transition:background-color .5s cubic-bezier(.4,0,.2,1),color .5s cubic-bezier(.4,0,.2,1)}
a{color:inherit}
img{display:block;max-width:100%}
button,input,textarea{font:inherit;color:inherit}
button{background:none;border:0;cursor:pointer}
:focus-visible{outline:var(--line) solid var(--vo-ink);outline-offset:3px}
.skip{position:absolute;left:-9999px}
.skip:focus{left:var(--gut);top:8px;z-index:60;background:var(--vo-ink);color:var(--vo-paper);padding:var(--s-2) var(--s-3)}
.wrap{max-width:1240px;margin:0 auto;padding:0 var(--gut)}  /* 1240 is repeated in .bar */
h2,h3{font-size:var(--t-s);letter-spacing:var(--tr-3);text-transform:uppercase;font-weight:700;margin-bottom:var(--s-3)}
p,li{font-size:var(--t-body);line-height:1.85}
ul,ol{list-style:none}

/* ---------- top bar ---------- */
.bar{position:fixed;z-index:50;top:0;left:0;right:0;display:flex;align-items:center;gap:var(--s-5);
  /* Side padding puts the mark and the colour button on the edges of the
     content column (max 1240px, centred), not the window's, so the bar
     lines up with every block under it on wide screens. */
  padding:10px max(var(--gut), calc((100% - 1240px) / 2 + var(--gut)));
  background:var(--vo-paper);border-bottom:var(--line) solid var(--vo-ink);
  font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase;
  transition:background-color .5s,color .5s}
.bar-mark{font-family:var(--cond);font-size:24px;letter-spacing:0;text-decoration:none;line-height:1}
.bar-nav{display:flex;gap:var(--s-4);margin-left:auto;overflow-x:auto;scrollbar-width:none}
.bar-nav::-webkit-scrollbar{display:none}
.bar-nav a{text-decoration:none;white-space:nowrap}
.bar-nav a:hover{text-decoration:underline;text-underline-offset:4px}
/* EN / PL. The current language is filled, the other is a plain link. */
.lang{display:flex;border:var(--line) solid var(--vo-ink)}
.lang a{padding:var(--s-1) var(--s-2);text-decoration:none;font-size:var(--t-xs);letter-spacing:var(--tr-2)}
.lang a + a{border-left:var(--line) solid var(--vo-ink)}
.lang a[aria-current]{background:var(--vo-ink);color:var(--vo-paper)}
.lang a:not([aria-current]):hover{background:var(--vo-ink);color:var(--vo-paper)}
.pal{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-1) var(--s-2) var(--s-1) var(--s-1);border:var(--line) solid var(--vo-ink);
  font-size:var(--t-xs);letter-spacing:var(--tr-2);text-transform:uppercase;white-space:nowrap}
.pal:hover{background:var(--vo-ink);color:var(--vo-paper)}
.pal-chip{width:18px;height:18px;background:linear-gradient(135deg,var(--vo-a) 0 50%,var(--vo-b) 50% 100%);
  box-shadow:inset 0 0 0 2px currentColor}
@media(max-width:820px){
  .bar{flex-wrap:wrap;gap:var(--s-2) var(--s-3)}
  .bar-nav{order:3;width:100%;margin-left:0;gap:var(--s-3)}
  .lang{margin-left:auto}
  .pal-name{display:none}
  html[data-bar="top"]{scroll-padding-top:92px}
}

/* ---------- hero ---------- */
.hero{padding:var(--s-8) 0 var(--s-7)}
/* Phones have no top bar (the menu is at the bottom), so the hero starts near the top. */
@media(max-width:820px){.hero{padding-top:var(--s-6)}html[data-bar="top"] .hero{padding-top:118px}}
.hero h1{font-family:var(--cond);font-size:clamp(90px,26vw,340px);line-height:.78;
  text-transform:uppercase;letter-spacing:-.02em;font-weight:700}
/* While it scrambles, a wide random letter must not push the page sideways. */
.hero h1.scr{overflow-x:clip}
.rule{border-top:var(--line) solid currentColor;margin:var(--s-5) 0}
/* Each sentence is its own balanced block, so one that does not fit splits
   into even lines instead of leaving a word alone on the last one. 22ch
   keeps "DARK, VOCAL-FREE." on one line; the Polish first sentence is wider
   and splits evenly in two. */
.say{font-family:var(--cond);font-size:clamp(30px,7.5vw,90px);line-height:.95;text-transform:uppercase;max-width:22ch}
.say .s{display:block;text-wrap:balance}
.say .nb{white-space:nowrap}
/* A separator shows only once the words on both sides are there: not while the
   content is loading, and not when a CMS field is left empty. */
.sep:has(+ :empty),:empty + .sep{visibility:hidden}
.role{margin-top:var(--s-5);font-size:var(--t-m);letter-spacing:var(--tr-3);text-transform:uppercase}

/* ---------- boxes: shared 3px borders by overlap ---------- */
.box{border:var(--line) solid var(--vo-ink);padding:var(--s-6);margin-bottom:calc(var(--line) * -1);
  transition:background-color .16s,color .16s}
.two{grid-template-columns:repeat(2,minmax(0,1fr))}
.three{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-6)}
.chapter{margin-top:37px}
@media(max-width:700px){
  .two,.three{grid-template-columns:1fr}
}

/* ---------- featured mix ---------- */
/* Halves, so the player/visual line is the same line as every other half. */
.mix{grid-template-columns:repeat(2,minmax(0,1fr))}
.mix-main{display:flex;flex-direction:column}
.mix-title{font-family:var(--cond);font-size:clamp(34px,5vw,64px);line-height:.95;text-transform:uppercase;text-wrap:balance}
.mix-meta{margin-top:var(--s-3);font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase;opacity:var(--fade-3)}
.mix-desc{margin-top:var(--s-3)}
/* What pressing Play costs in data: phones only, where it is usually paid for. */
.mix-data{display:none;margin-top:var(--s-3);font-size:var(--t-s);opacity:var(--fade-3)}
@media(max-width:820px){.mix-data:not(:empty){display:block}}
/* The Play button sits alone at the foot of the player box, larger since the
   timeline moved to its own full-width box under the mix (2026-10-11). */
.player{margin-top:auto;padding-top:var(--s-6);display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-4) var(--s-5)}
/* On a narrow phone the clock drops under Play rather than pushing the box wider. */
/* The clock beside Play, in the display face like the title: the elapsed time
   big, the total smaller after the slash, both on the same baseline. */
.player .seek-time{justify-content:flex-start;align-items:baseline;gap:var(--s-2);font-family:var(--cond);
  font-size:clamp(34px,4.4vw,52px);line-height:1;letter-spacing:0;font-variant-numeric:tabular-nums}
.player .t-end{font-size:.45em}
.player .t-end::before{content:"/";margin-right:var(--s-2)}
.player .t-end:empty::before{content:none}
/* At this size the space kept for the longest time (player.js sets it) reads
   as a gap, so the elapsed time takes its own width; with tabular digits it
   only moves when it gains a digit, twice in a long mix. */
.player .t-now{min-width:0!important}
.play{flex:0 0 auto;display:flex;align-items:center;gap:var(--s-3);padding:0 var(--s-6);min-height:80px;
  background:var(--vo-ink);color:var(--vo-paper);font-size:var(--t-l);letter-spacing:var(--tr-3);text-transform:uppercase}
.play:hover{background:var(--vo-paper);color:var(--vo-ink);box-shadow:inset 0 0 0 var(--line) var(--vo-ink)}
.play-icon{width:0;height:0;border-style:solid;border-width:9px 0 9px 15px;border-color:transparent transparent transparent currentColor}
.play[aria-pressed="true"] .play-icon{width:15px;height:18px;border:0;
  background:linear-gradient(90deg,currentColor 0 35%,transparent 35% 65%,currentColor 65%)}
/* The timeline across the whole width of the mix, the clock under it, so the
   track names have the full page to crawl through. */
.mix-seek{padding:0;display:grid}
/* Edge to edge, and one line bigger at each end, so the strip's own top and
   bottom lines land on the box's lines instead of doubling them. */
.mix-seek .tl-wrap{height:78px;margin:calc(var(--line) * -1) 0}
/* The voltage line (timeline.js) is drawn on the canvas; the range input is
   laid over it, invisible, so a click, a drag, the arrow keys and screen
   readers all seek as with any slider. Focus shows as a frame. */
.tl-wrap{position:relative;height:56px;cursor:pointer;touch-action:none}
.tl-wrap canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
.tl-wrap input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
.tl-wrap:has(input:focus-visible){outline:var(--line) solid var(--vo-ink);outline-offset:4px}
.tl-hover{position:absolute;bottom:calc(100% + 6px);left:0;transform:translateX(-50%);white-space:nowrap;pointer-events:none;
  background:var(--vo-ink);color:var(--vo-paper);font-size:var(--t-s);letter-spacing:var(--tr-0);padding:var(--s-1) var(--s-2);z-index:2;
  max-width:60vw;overflow:hidden;text-overflow:ellipsis}
.tl-hover.is-right{transform:translateX(-100%)}
.tl-hover[hidden]{display:none}
.seek-time{display:flex;justify-content:space-between;gap:var(--s-3);font-size:var(--t-s);letter-spacing:var(--tr-1)}
.mix-visual{position:relative;padding:0;min-height:280px;overflow:hidden}
.vis{position:absolute;inset:0;width:100%;height:100%;display:block}
.vis-idle,.vis-pick{position:absolute;font-size:var(--t-xs);letter-spacing:var(--tr-2);text-transform:uppercase;
  background:var(--vo-paper);color:var(--vo-ink);border:var(--line) solid var(--vo-ink);padding:var(--s-1) var(--s-2)}
.vis-idle{left:12px;bottom:12px}
/* A 3D visual's licence credit (the bust is CC-BY), small in the corner. */
.vis-credit{position:absolute;right:12px;bottom:12px;max-width:60%;text-align:right;text-wrap:balance;font-size:var(--t-s);opacity:var(--fade-3);pointer-events:none}
.mix.is-on .vis-idle{display:none}
/* The picker only shows on hover or focus with a pointer, so the field reads
   clean; on touch it stays visible because there is no hover. */
.vis-pick{top:12px;right:12px;transition:opacity .16s}
.vis-pick:hover{background:var(--vo-ink);color:var(--vo-paper)}
@media(hover:hover) and (pointer:fine){
  .vis-pick{opacity:0}
  .mix-visual:hover .vis-pick,.vis-pick:focus-visible{opacity:1}
}
.tracklist,.more,.mix-seek{grid-column:1 / -1}
.tracklist summary,.readmore summary{cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center}
.tracklist summary::-webkit-details-marker,.readmore summary::-webkit-details-marker{display:none}
.tracklist summary h2,.readmore summary h2{margin:0}
.tracklist summary::after,.readmore summary::after{content:"+";font-size:20px;line-height:1}
.tracklist[open] summary::after,.readmore[open] summary::after{content:"-"}
.tl{margin-top:var(--s-4);columns:2;column-gap:var(--s-7)}
.tl li{break-inside:avoid;display:flex;gap:var(--s-3)}
.tl button{display:flex;gap:var(--s-3);text-align:left;width:100%;line-height:1.85}
.tl button:hover .tl-name{text-decoration:underline;text-underline-offset:3px}
.tl time{flex:0 0 5.5ch;opacity:var(--fade-2);font-variant-numeric:tabular-nums}
.tl li.is-now{background:var(--vo-ink);color:var(--vo-paper)}
/* The "All mixes" fold-out: one row per mix, the current one filled like the playing track. */
.ml{margin-top:var(--s-4)}
.ml button{display:grid;grid-template-columns:3ch minmax(0,1fr) auto;gap:var(--s-3);width:100%;text-align:left;line-height:1.85;text-transform:uppercase;letter-spacing:var(--tr-1)}
.ml button:hover .ml-name{text-decoration:underline;text-underline-offset:3px}
.ml-n,.ml time{opacity:var(--fade-2);font-variant-numeric:tabular-nums}
.ml li.is-now{background:var(--vo-ink);color:var(--vo-paper)}
.more{display:block;text-decoration:none;font-size:var(--t-m);letter-spacing:var(--tr-3);text-transform:uppercase}
.more:hover,.box:is(a):hover{background:var(--vo-ink);color:var(--vo-paper)}
@media(max-width:820px){
  .mix{grid-template-columns:1fr}
  .mix-visual{min-height:220px;transition:min-height .3s}
  /* Stacked, the idle field is a short strip; it opens up on play. */
  .mix:not(.is-on) .mix-visual{min-height:120px}
  .tl{columns:1}
}


/* ---------- about ---------- */
.readmore .three{margin-top:var(--s-5)}
.readmore h3{margin-bottom:var(--s-2)}

/* ---------- photos and posters ---------- */
/* Quarters, always: auto-fit used to drop to three columns on mid widths
   and wrap the fourth photo onto a row of its own. */
.shots{grid-template-columns:repeat(4,minmax(0,1fr))}
.shots img,.roll img,.grid img{width:100%;object-fit:cover;filter:var(--shot-filter);mix-blend-mode:var(--shot-blend)}
.shots img{aspect-ratio:1}
@media(hover:hover) and (pointer:fine){
  .shots img:hover,.roll img:hover,.grid img:hover{filter:none;mix-blend-mode:normal}
}
@media(max-width:700px){
  .shots{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none}
  .shots::-webkit-scrollbar{display:none}
  .shots .cell{flex:0 0 78%;min-width:0;scroll-snap-align:start}
}

/* ---------- crate ---------- */
.nums{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-5) var(--s-5)}
.nums b{display:block;font-family:var(--cond);font-size:clamp(34px,4.6vw,56px);line-height:1;font-weight:700}
.nums span{font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase}
.bars li{display:grid;grid-template-columns:11ch 1fr 4ch;gap:var(--s-3);align-items:center;font-size:var(--t-m)}
.bars i{display:block;height:12px;background:var(--vo-ink);width:var(--w);transform-origin:left;
  transition:transform .8s cubic-bezier(.2,.8,.3,1)}
.bars:not(.is-in) i{transform:scaleX(0)}
.bars em{font-style:normal;text-align:right;opacity:var(--fade-3);font-variant-numeric:tabular-nums}
.fp{font-size:var(--t-m);letter-spacing:var(--tr-0)}
.orbit{position:relative;overflow:hidden;border:var(--line) solid var(--vo-ink);margin-bottom:calc(var(--line) * -1)}
.orbit-roll{display:flex;width:max-content;animation:roll 42s linear infinite}
.orbit-roll span,.orbit-roll i{font-family:var(--cond);font-size:clamp(26px,3.6vw,44px);line-height:1.2;white-space:nowrap}
.orbit-roll span{padding:var(--s-3) var(--s-5);text-transform:uppercase}
.orbit-roll i{font-style:normal;padding:var(--s-3) 0;opacity:var(--fade-1)}
.orbit:hover .orbit-roll,.is-out .orbit-roll,.is-out .roll,.posters:hover .roll{animation-play-state:paused}
@keyframes roll{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ---------- shows ---------- */
.cols{columns:2;column-gap:var(--s-7)}
.cols li{break-inside:avoid}
.note{display:block;padding-left:var(--s-3);opacity:var(--fade-2)}
.posters{position:relative;overflow:hidden;border:var(--line) solid var(--vo-ink);margin-bottom:calc(var(--line) * -1)}
/* The running transform makes the track its own isolated layer, so the
   posters can only blend with what is inside it. Painting the track in the
   page colour gives them that backdrop; without it they blended with nothing
   and showed as plain greyscale, untinted. */
.roll{display:flex;width:max-content;animation:roll 56s linear infinite;
  background:var(--vo-paper);transition:background-color .5s cubic-bezier(.4,0,.2,1)}
.roll img{flex:0 0 auto;width:clamp(148px,20vw,258px);aspect-ratio:4/5;border-right:var(--line) solid var(--vo-ink)}
@media(max-width:700px){.cols{columns:1}}

/* ---------- gallery ---------- */
.grid{grid-template-columns:repeat(4,minmax(0,1fr))}
.cell{display:block}
.grid .cell:first-child{grid-column:span 2;grid-row:span 2}
.grid img{aspect-ratio:1;height:100%}
@media(max-width:700px){.grid{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* ---------- contact ---------- */
.book label{display:block;font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase;margin-bottom:var(--s-3)}
.book input,.book textarea{display:block;width:100%;margin-top:var(--s-2);padding:var(--s-3);background:transparent;
  border:var(--line) solid var(--vo-ink);border-radius:0;font-size:var(--t-body);text-transform:none;letter-spacing:0;resize:vertical}
.book input:focus,.book textarea:focus{outline:0;background:var(--vo-ink);color:var(--vo-paper)}
.book .hp{position:absolute;left:-9999px}
.book button{padding:var(--s-3) var(--s-6);background:var(--vo-ink);color:var(--vo-paper);font-size:var(--t-m);letter-spacing:var(--tr-3);text-transform:uppercase}
.book button:hover{background:var(--vo-paper);color:var(--vo-ink);box-shadow:inset 0 0 0 var(--line) var(--vo-ink)}
.book-msg{margin-top:var(--s-3);min-height:1.85em}
.links a{text-decoration:none}
.links a:hover{text-decoration:underline;text-underline-offset:3px}
.cta{display:block;background:var(--vo-ink);color:var(--vo-paper);text-decoration:none;text-align:center;
  font-family:var(--cond);font-size:clamp(34px,9vw,96px);text-transform:uppercase;padding:var(--s-6) var(--s-3);line-height:1}
.cta:hover{background:var(--vo-paper);color:var(--vo-ink);box-shadow:inset 0 0 0 var(--line) var(--vo-ink)}
.foot{display:flex;justify-content:space-between;padding:var(--s-5) 0 60px;font-size:var(--t-m)}

/* ---------- cursor: a block that inverts what is under it ---------- */
.cur{position:fixed;z-index:70;width:20px;height:20px;background:#fff;mix-blend-mode:difference;
  pointer-events:none;opacity:0;left:calc(var(--mx) * 100vw);top:calc(var(--my) * 100vh);
  transform:translate(-50%,-50%) scale(var(--cx,1),var(--cy,1));
  transition:transform .13s cubic-bezier(.2,.8,.3,1),opacity .16s}
@media(hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference){
  html.has-cur .cur{opacity:1}
  html.has-cur,html.has-cur a,html.has-cur button,html.has-cur summary{cursor:none}
}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .orbit-roll,.roll{animation:none}
  .orbit-roll [data-dup],.roll [data-dup]{display:none}
  .orbit,.posters{overflow-x:auto;scrollbar-width:none}
  .bars i{transition:none}
  .bars:not(.is-in) i{transform:none}
  body,.bar{transition:none}
}

/* =================== sound page =================== */
.nums-row{grid-template-columns:repeat(5,minmax(0,1fr))}
@media(max-width:820px){.nums-row{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* Genre filter. Pressed is filled, the rest are outlined cells. */
.chips{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-top:var(--s-1)}
.chips button{border:var(--line) solid var(--vo-ink);padding:var(--s-2) var(--s-3);font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase}
.chips button em{font-style:normal;opacity:var(--fade-2);margin-left:var(--s-1);font-variant-numeric:tabular-nums}
.chips button:hover,.chips button[aria-pressed="true"]{background:var(--vo-ink);color:var(--vo-paper)}
.filter-note{margin-top:var(--s-3);font-size:var(--t-m);opacity:var(--fade-3)}
.bars li.dim{opacity:var(--fade-1)}
.bars li{transition:opacity .25s}
.fp i{transition:width .4s cubic-bezier(.2,.8,.3,1),transform .8s cubic-bezier(.2,.8,.3,1)}
/* 17ch fits the longest label, Polish "Instrumentalność". */
.fp li{grid-template-columns:17ch 1fr 5ch}
.fp-text{margin-top:var(--s-4);font-size:var(--t-m)}
/* Ranked lists: name, a short bar, the count. Numbered by the <ol>. */
.rank{list-style:none;counter-reset:r}
.rank li{counter-increment:r;display:grid;grid-template-columns:3ch minmax(0,1fr) 64px 4ch;gap:var(--s-3);align-items:center;
  padding:var(--s-2) 0;border-top:1px solid color-mix(in srgb,var(--vo-ink) 25%,transparent);font-size:var(--t-m)}
.rank li::before{content:counter(r);opacity:var(--fade-2);font-variant-numeric:tabular-nums}
.rank .r-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank i{display:block;height:8px;background:var(--vo-ink);width:var(--w)}
.rank em{font-style:normal;text-align:right;opacity:var(--fade-3);font-variant-numeric:tabular-nums}
/* Facts: three boxes welded into one row, big number over a sentence. */
.facts{grid-template-columns:repeat(3,minmax(0,1fr))}
.facts b{display:block;font-family:var(--cond);font-size:clamp(48px,7vw,96px);line-height:.9;font-weight:700;margin-bottom:var(--s-3)}
@media(max-width:700px){.facts{grid-template-columns:1fr}}
/* Player facades: nothing loads from Spotify or Bandcamp until pressed. */
.embeds{grid-template-columns:repeat(3,minmax(0,1fr))}
@media(max-width:820px){.embeds{grid-template-columns:minmax(0,1fr)}}
.embed{display:flex;flex-direction:column;min-width:0}
/* The name is big in the display face, as in the hero; the box is only as tall
   as its words, and grows to the player's height when it loads. */
.embed-slot{padding:var(--s-4);display:flex;flex-direction:column;align-items:flex-start;gap:var(--s-2);flex:1}
.embed-t{font-family:var(--cond);font-size:clamp(30px,8vw,42px);line-height:.95;text-transform:uppercase;letter-spacing:-.01em;overflow-wrap:anywhere;text-wrap:balance}
.embed-sub{font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase;opacity:var(--fade-3);line-height:1.6}
.embed button{margin-top:var(--s-2);padding:var(--s-3) var(--s-4);background:var(--vo-ink);color:var(--vo-paper);font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase}
.embed button:hover{background:var(--vo-paper);color:var(--vo-ink);box-shadow:inset 0 0 0 var(--line) var(--vo-ink)}
.embed-note{padding:var(--s-3) var(--s-4);font-size:var(--t-s);opacity:var(--fade-3)}
.embed-out{display:block;padding:var(--s-2) var(--s-4);border-top:var(--line) solid var(--vo-ink);font-size:var(--t-s);letter-spacing:var(--tr-2);
  text-transform:uppercase;text-decoration:none}
.embed-out:hover{background:var(--vo-ink);color:var(--vo-paper)}
.embed-slot.is-player{padding:0;gap:0;align-items:stretch}
.embed iframe{display:block;width:100%;border:0}
/* The loaded player's name strip: constant crawl, still under reduced motion. */
.embed-tk{display:flex;overflow:hidden;white-space:nowrap;border-bottom:var(--line) solid var(--vo-ink)}
.embed-tk span{flex:none;font-family:var(--cond);font-size:40px;line-height:1.2;text-transform:uppercase;animation:tk-crawl 20s linear infinite}
@keyframes tk-crawl{to{transform:translateX(-100%)}}
@media(prefers-reduced-motion:reduce){.embed-tk span{animation:none}}
/* A short last row on wide screens: the last box takes the empty cells. */
@media(min-width:821px){
  .embeds>.embed:last-child:nth-child(3n+1){grid-column:1 / -1}
  .embeds>.embed:last-child:nth-child(3n+2){grid-column:span 2}
}
/* A head box with its heading on the left and a link on the right. */
.head-split{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-4);flex-wrap:wrap}
.head-split h2{margin:0}
.bc-follow{display:inline-block;font-size:var(--t-m);letter-spacing:var(--tr-2);text-transform:uppercase;text-decoration:none}
.bc-follow:hover{text-decoration:underline;text-underline-offset:4px}
.foot-back{text-decoration:none}
.foot-back:hover{text-decoration:underline;text-underline-offset:3px}

/* =================== fixed sizes =================== */
/* stack() in common.js: every possible text in one grid cell, one visible,
   so the element keeps the size of its longest text. */
.stack{display:inline-grid}
.stack>span{grid-area:1 / 1;visibility:hidden}
.stack>span.on{visibility:visible}
.t-now{font-variant-numeric:tabular-nums}
.t-end{font-variant-numeric:tabular-nums;text-align:right}
/* Text that changes with a choice reserves two lines, so a longer message
   in either language does not push the page down. */
.filter-note,.book-msg{min-height:calc(1.85em * 2)}
.filter-note{line-height:1.85}

/* =================== the grid =================== */
/* Every row of side-by-side cells draws its lines the same way: one outer
   border, a gap exactly one line wide between cells, and each cell paints
   that gap in ink with a box-shadow. A line at a given fraction of the
   width (a half, a third, a quarter) then lands on the same pixels in every
   row, whatever the number of columns, so halves line up with halves and
   quarters with quarters down the whole page.

   Before this, side-by-side boxes overlapped their own borders, the photo
   strip drew a border inside each photo and the gallery used gaps: three
   methods, three different places for "50%", 3px apart.

   The cells carry no background, so photos still blend with the page and
   an unfilled cell at the end of a row stays page colour. */
.two,.mix,.shots,.grid,.gal,.facts,.embeds{display:grid;gap:var(--line);
  border:var(--line) solid var(--vo-ink);margin-bottom:calc(var(--line) * -1)}
:is(.two,.mix,.shots,.grid,.gal,.facts,.embeds)>*{border:0;margin:0;box-shadow:0 0 0 var(--line) var(--vo-ink)}

/* =================== gallery page =================== */
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.gal{grid-template-columns:repeat(4,minmax(0,1fr))}
@media(max-width:820px){.gal{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:520px){.gal{grid-template-columns:repeat(2,minmax(0,1fr))}}
.gal .cell{padding:0;cursor:zoom-in}
.gal .cell[hidden]{display:none}
.gal img{width:100%;aspect-ratio:1;object-fit:cover;filter:var(--shot-filter);mix-blend-mode:var(--shot-blend)}
@media(hover:hover) and (pointer:fine){.gal .cell:hover img{filter:none;mix-blend-mode:normal}}
/* Touch screens: a tapped photo or poster shows its own colours (tapReveal in common.js). */
.rev img,img.rev{filter:none;mix-blend-mode:normal}
.gal .cell:focus-visible{outline:var(--line) solid var(--vo-ink);outline-offset:-9px;z-index:1}
/* The viewer fills the screen in the page colours and shows the photo as
   it is, without the duotone. */
.viewer{width:100vw;height:100dvh;max-width:none;max-height:none;margin:0;padding:0;border:0;
  background:var(--vo-paper);color:var(--vo-ink);font-family:var(--mono)}
.viewer::backdrop{background:var(--vo-paper)}
.viewer[open]{display:grid;grid-template-rows:auto minmax(0,1fr)}
.viewer-bar{display:flex;align-items:center;gap:var(--s-5);border-bottom:var(--line) solid var(--vo-ink);
  padding:10px max(var(--gut), calc((100% - 1240px) / 2 + var(--gut)));font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase}
.viewer-num{font-variant-numeric:tabular-nums;white-space:nowrap}
.viewer-cap{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:none;letter-spacing:var(--tr-0);font-size:var(--t-m)}
.viewer-close{border:var(--line) solid var(--vo-ink);padding:var(--s-2) var(--s-3);font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase}
.viewer-close:hover,.viewer-prev:hover,.viewer-next:hover{background:var(--vo-ink);color:var(--vo-paper)}
.viewer-stage{display:grid;grid-template-columns:72px minmax(0,1fr) 72px;min-height:0}
.viewer-prev,.viewer-next{font-size:28px}
.viewer-prev{border-right:var(--line) solid var(--vo-ink)}
.viewer-next{border-left:var(--line) solid var(--vo-ink)}
.viewer-img{width:100%;height:100%;object-fit:contain;padding:var(--s-5);min-height:0;user-select:none;-webkit-user-drag:none;cursor:zoom-out}
@media(max-width:700px){
  .viewer-stage{grid-template-columns:1fr 1fr;grid-template-rows:minmax(0,1fr) 64px}
  .viewer-img{grid-column:1 / -1;grid-row:1;padding:var(--s-3)}
  .viewer-prev,.viewer-next{grid-row:2;border:0;border-top:var(--line) solid var(--vo-ink)}
  .viewer-prev{border-right:var(--line) solid var(--vo-ink)}
  .viewer-cap{display:none}
}

/* =================== dock: the sticky player =================== */
/* Slides up from the bottom once the mix has started and the player has
   scrolled away; aligned to the content column like the menu bar. */
.dock{position:fixed;z-index:45;left:0;right:0;bottom:0;background:var(--vo-paper);color:var(--vo-ink);
  border-top:var(--line) solid var(--vo-ink);transform:translateY(105%);transition:transform .28s cubic-bezier(.2,.8,.3,1),background-color .5s,color .5s;
  padding:0 max(var(--gut), calc((100% - 1240px) / 2 + var(--gut)))}
.dock.is-on{transform:none}
.dock-in{display:grid;grid-template-columns:52px minmax(0,1fr) auto 44px 44px;align-items:center;gap:0 var(--s-4);height:64px}
.dock .play{min-height:0;height:52px;width:52px;padding:0;justify-content:center}
.dock .tl-wrap{height:40px}
.dock .tl-hover{bottom:calc(100% + 10px)}
.dock-time{font-size:var(--t-s);font-variant-numeric:tabular-nums}
.dock-up,.dock-x{height:44px;border:var(--line) solid var(--vo-ink);font-size:var(--t-l);line-height:1}
.dock-up:hover,.dock-x:hover{background:var(--vo-ink);color:var(--vo-paper)}
/* With the dock up, the page ends above it, so nothing is hidden under it. */
html.dock-on body{padding-bottom:70px}
/* Below 820px the timeline gets its own full-width row, so it is never
   squeezed by the track name. */
@media(max-width:820px){
  .dock-in{grid-template-columns:52px minmax(0,1fr) 44px 44px;grid-template-rows:auto 34px;height:auto;padding:var(--s-2) 0;gap:var(--s-2) var(--s-3)}
  .dock .tl-wrap{grid-column:1 / -1;grid-row:2;height:34px}
  html.dock-on body{padding-bottom:116px}
}
/* With the bar at the bottom (phones), the dock is one slim row standing on
   it: play, the ticker, back up, hide. The clock shows in the player. */
@media(max-width:820px){
  html:not([data-bar="top"]) .dock{bottom:var(--tabbar-h,55px)}
  html:not([data-bar="top"]) .dock-in{grid-template-columns:44px minmax(0,1fr) 44px 44px;grid-template-rows:none;height:56px;padding:0;gap:0 var(--s-3)}
  html:not([data-bar="top"]) .dock .play{height:44px;width:44px}
  html:not([data-bar="top"]) .dock .tl-wrap{grid-column:auto;grid-row:auto;height:40px}
  html:not([data-bar="top"]) .dock-time{display:none}
  html:not([data-bar="top"]).dock-on body{padding-bottom:calc(var(--tabbar-h,55px) + 59px)}
}
@media(prefers-reduced-motion:reduce){.dock{transition:none}}

/* =================== press page =================== */
/* A solid ink button for downloads. */
.btn{display:inline-block;padding:var(--s-3) var(--s-5);background:var(--vo-ink);color:var(--vo-paper);text-decoration:none;
  font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase}
.btn:hover{background:var(--vo-paper);color:var(--vo-ink);box-shadow:inset 0 0 0 var(--line) var(--vo-ink)}
.kit{display:flex;flex-direction:column;gap:var(--s-3)}
.kit h2{margin:0}
.kit-links{display:flex;flex-wrap:wrap;gap:var(--s-3);margin-top:auto}
.contact-mail{font-size:var(--t-l)}
/* Bios: one box each, heading and Copy on one line, the text under it. */
.bio h3{margin:0}
.bio-text{margin-top:var(--s-3);max-width:72ch}
.bio-text p + p{margin-top:var(--s-3)}
/* Single line breaks inside a bio are kept, as typed in the CMS. */
.bio-text p{white-space:pre-line}
.bio:first-child .bio-text{font-size:var(--t-l)}
/* Copy keeps one width: both labels share a cell, one visible (as stack()). */
.copy{display:inline-grid;border:var(--line) solid var(--vo-ink);padding:var(--s-2) var(--s-3);font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase}
.copy>span{grid-area:1 / 1}
.copy .copy-b,.copy.is-done .copy-a{visibility:hidden}
.copy.is-done .copy-b{visibility:visible}
.copy:hover,.copy.is-done{background:var(--vo-ink);color:var(--vo-paper)}
.note-line{font-size:var(--t-s);opacity:var(--fade-3);margin:0}
/* Posters keep their own 4:5 shape. */
.pgrid img{aspect-ratio:4 / 5}
.viewer-dl{border:var(--line) solid var(--vo-ink);padding:var(--s-2) var(--s-3);font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase;text-decoration:none;white-space:nowrap}
.viewer-dl:hover{background:var(--vo-ink);color:var(--vo-paper)}

/* ---------- phones and touch screens ---------- */
/* Safari on iPhone zooms the page into any form field under 16px and leaves it
   zoomed, so on touch screens the fields are 16px (an exception to the scale). */
@media(pointer:coarse){.book input,.book textarea{font-size:16px}}
/* Fingers need bigger targets than the controls look. An invisible ::before
   grows each hit area without moving or redrawing anything: to 44px where
   there is room, and only to the line pitch (about 24px) in stacked lists,
   where more would take taps meant for the next link. */
@media(pointer:coarse){
  .bar-nav a,.lang a,.pal,.links a,.foot-back,.bc-follow,.contact-mail,.tracklist summary,.readmore summary,
  .chips button,.copy,.embed button,.book button,.viewer-dl,.viewer-close{position:relative}
  :is(.bar-nav a,.lang a,.pal,.links a,.foot-back,.bc-follow,.contact-mail,.tracklist summary,.readmore summary,
  .chips button,.copy,.embed button,.book button,.viewer-dl,.viewer-close,.vis-pick)::before{content:"";position:absolute;inset:var(--hit,-4px) 0}
  .lang a,.foot-back,.bc-follow{--hit:-12px}
  /* The menu row scrolls sideways, which clips anything drawn outside it, so
     there the row and its links grow by padding that a negative margin takes
     back: same layout, 37px to tap. */
  .bar-nav{padding-block:12px;margin-block:-12px}
  .bar-nav a{padding-block:12px;margin-block:-12px}
  .bar-nav a::before{content:none}
  .tracklist summary,.readmore summary,.vis-pick{--hit:-10px}
  .pal{--hit:-6px}
  .links a,.contact-mail{--hit:-4px}
}
/* No text under 11px on a phone. */
@media(max-width:820px){.lang a,.pal-name,.vis-idle,.vis-pick{font-size:var(--t-s)}}

/* ---------- the phone menu (built in common.js, startMenu) ---------- */
/* Below 820px the top bar steps aside for one bar at the bottom: the name,
   the page you are on, and Menu, which opens the whole screen as a list. */
.tabbar,.sheet{display:none}
@media(max-width:820px){
  html:not([data-bar="top"]) .bar{display:none}
  html:not([data-bar="top"]) body{padding-bottom:var(--tabbar-h,55px)}
  .tabbar{display:grid;position:fixed;z-index:52;left:0;right:0;bottom:0;grid-template-columns:auto minmax(0,1fr) auto;
    background:var(--vo-paper);color:var(--vo-ink);border-top:var(--line) solid var(--vo-ink);padding-bottom:env(safe-area-inset-bottom);
    font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase;transition:background-color .5s,color .5s}
  .tabbar>*{display:flex;align-items:center;min-height:52px;padding:0 var(--s-4);text-decoration:none}
  .tabbar>*+*{border-left:var(--line) solid var(--vo-ink)}
  .tab-name{font-family:var(--cond);font-size:24px;letter-spacing:0;line-height:1}
  .tab-here{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
  .tab-menu{display:grid!important;place-items:center;background:var(--vo-ink);color:var(--vo-paper);padding:0 var(--s-5);text-transform:inherit;letter-spacing:inherit}
  .tab-menu>span{grid-area:1 / 1}
  .sheet{display:flex;position:fixed;z-index:51;left:0;right:0;top:0;bottom:var(--tabbar-h,55px);flex-direction:column;justify-content:flex-end;gap:var(--s-5);
    overflow:auto;padding:var(--s-4) var(--gut);background:var(--vo-paper);color:var(--vo-ink)}
  .sheet[hidden]{display:none}
  html.sheet-open{overflow:hidden}
  .sheet-pages,.sheet-sections{display:flex;flex-direction:column;border-top:var(--line) solid var(--vo-ink)}
  .sheet-pages:empty,.sheet-sections:empty{display:none}
  .sheet:focus{outline:0}
  :is(.sheet-pages,.sheet-sections) a{font-family:var(--cond);font-size:clamp(32px,10vw,44px);line-height:1.1;text-transform:uppercase;text-decoration:none;padding:var(--s-1) 0;border-bottom:var(--line) solid var(--vo-ink)}
  .sheet-pages a::after{content:" \2192"}
  .sheet-pages a[aria-current]{text-decoration:underline;text-underline-offset:6px;text-decoration-thickness:3px}
  .sheet-row{display:flex;gap:var(--s-3);align-items:center;font-size:var(--t-s);letter-spacing:var(--tr-2);text-transform:uppercase}
  .sheet-row .lang{margin:0}
  .sheet-row .pal-name{display:grid}
}
