/* Direction A, César's pick (12 Nov 2026): one numbered list on black, the flyer alone in the
   middle, the logo small at the top, and C's bar at the bottom. Cream and black only. */

/* Home only. The shared parts (links, logo, roster list, bar, panels) are in /css/shell.css. */
/* ---------- the list ---------- */

.page { min-height: 100vh; min-height: 100svh; }

.list {
  list-style: none;
  margin: 0;
  padding: 5.75rem 0 0;
  width: var(--list-w);
}

/* The ending, as on the live site's footer: the slogan, in Spanish in both languages. */
.a-end {
  margin: 0;
  padding: 10vh 0 28vh var(--gutter);
  color: var(--cream);
  width: var(--list-w);
}

.row {
  display: grid;
  grid-template-columns: var(--gutter) minmax(0, 1fr);
  align-items: start;
  padding: 0 0 1.1rem;
}

.row__n {
  padding: 0.1rem 0 0 1.5rem;
  color: var(--cream-dim);
  opacity: var(--faint);
  font-variant-numeric: tabular-nums;
}

.row__hit {
  display: block;
  width: 100%;
  color: var(--cream-dim);
  text-align: left;
  transform-origin: left center;
  transition: color 200ms var(--ease-out), transform var(--release);
}
.row__hit:active { transform: scale(0.97); transition: color 200ms var(--ease-out), transform var(--press); }

.row__name {
  display: block;
  font-size: 0.8125rem;
  line-height: 1.35;
  color: var(--cream);
}

.row__arrow {
  display: inline-block;
  width: 0.62em;
  height: 0.62em;
  margin-left: 0.08em;
  vertical-align: 0.05em;
  opacity: 0;
  transform: translate(-0.12em, 0.12em);
  transition: opacity 200ms var(--ease-out), transform 260ms var(--ease-out);
}

.row__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.1rem 0.9rem;
  align-items: center;
  margin-top: 0.15rem;
  line-height: 1.5;
}
.row__tag--next {
  background: var(--cream);
  color: var(--ink);
  padding: 0.05rem 0.45rem 0;
}

.row--next .row__hit { color: var(--cream); }
.row--soon .row__name { opacity: 0.32; }
.row--soon .row__n { opacity: 0.32; }

@media (hover: hover) {
  /* Every row lights when its flyer comes up, page or not; only rows with a page show the arrow. */
  .row:not(.row--soon):hover .row__hit { color: var(--cream); }
  .row:not(.row--soon):hover .row__n { opacity: 1; color: var(--cream); }
  .row__hit--link:hover { color: var(--cream); }
  .row__hit--link:hover .row__arrow { opacity: 1; transform: none; }
}
.row__hit--link:focus-visible, .row.is-lit .row__hit { color: var(--cream); }
.row__hit--link:focus-visible .row__arrow,
.row.is-lit .row__arrow { opacity: 1; transform: none; }
.row.is-lit .row__n { opacity: 1; color: var(--cream); }
.row--next .row__arrow { opacity: 0.55; transform: none; }

.list__error { padding: 0 1.5rem; line-height: 1.8; }

/* Names dissolve into black as they scroll under the logo. */
.page::before {
  content: "";
  position: fixed;
  z-index: 25;
  top: 0;
  left: 0;
  right: 0;
  height: var(--top-r);
  background: linear-gradient(var(--ink) 45%, transparent);
  pointer-events: none;
}

/* ---------- the flyer in the middle: just the picture, edge to edge ---------- */

.sq {
  position: fixed;
  z-index: 5;
  left: 50%;
  top: calc(var(--top-r) + (100svh - var(--top-r) - var(--bot-r) - var(--fh)) / 2);
  width: var(--fw);
  transform: translateX(-50%);
}
.sq__link {
  display: block;
  width: var(--fw);
  transition: transform var(--release);
}
.sq__link:active { transform: scale(0.985); transition: transform var(--press); }
/* Hovering the flyer underlines its caption, the way every other link warms. */
.sq__cap { text-decoration: underline transparent; text-underline-offset: 3px; transition: text-decoration-color 200ms var(--ease-out), opacity 240ms ease-in-out; }
@media (hover: hover) { .sq:has(.sq__link[href]:hover) .sq__cap { text-decoration-color: currentColor; } }
/* An open panel sits over the frame on laptops, so the frame steps back behind it. */
.sq__frame { transition: opacity 240ms ease-in-out; }
.has-panel .sq__frame, .has-panel .sq__cap { opacity: 0.18; }
/* The slogan waits for the list, so a slow load never shows it alone. */
.page:has(.list:empty) .a-end { visibility: hidden; }
.sq__frame { position: relative; display: block; width: var(--fw); height: var(--fh); }
.sq__clip { position: absolute; inset: 0; overflow: hidden; box-shadow: var(--frame-edge); transition: box-shadow 200ms ease-in-out; }
/* A residency's cards stand on their own: the light look's hairline round the empty frame goes. */
.sq__frame:has(> .sq__stack.is-on) > .sq__clip { box-shadow: none; }
.sq__flyer {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 200ms ease-in-out;
}
.sq__flyer.is-on { opacity: 1; }
/* A DJ's photo, in black and white, the person centred (per-photo points in app.js). */
.sq__flyer--photo { filter: grayscale(1); }
.sq__cap {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin: 0.7rem 0 0;
  color: var(--cream-dim);
  line-height: 1.5;
  min-height: 1.5em;
}

/* A residency's flyers, stacked like cards ("todos encimados"). */
.sq__stack {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease-in-out;
}
.sq__stack.is-on { opacity: 1; }
.sq__card {
  position: absolute;
  left: 9%;
  top: 9%;
  width: 82%;
  height: 82%;
  object-fit: cover;
  box-shadow: var(--card-shadow);
  transition: transform 420ms var(--ease-out);
}
.sq__stack.is-on .sq__card { transform: translate(var(--x, 0), var(--y, 0)) rotate(var(--r, 0deg)); }

/* ---------- preloader: flyers stack in the centre, the front one grows into the flyer spot ---------- */

.pre { display: none; }
.is-preloading .pre {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 70;
  /* Black in both looks: the room opens like lights coming up, as on the inner pages. */
  background: #000;
  transition: background-color 420ms ease-in-out;
  /* If the script is late or never runs, the black lifts by itself at 1.8s. */
  animation: pre-bail 0s linear 1.8s forwards;
}
.pre.is-lifting { background-color: transparent; pointer-events: none; }
.pre__stack { position: absolute; inset: 0; }
.pre__img {
  position: absolute;
  left: 50%;
  top: 50%;
  aspect-ratio: 4 / 5;
  height: auto;
  object-fit: cover;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.92);
  transition: opacity 180ms ease-in-out, transform 300ms var(--ease-out);
}
.pre__img.is-on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.pre.is-lifting .pre__img:not(.is-hero) { opacity: 0; transition: opacity 220ms ease-in-out; }
.is-preloading .bar, .is-preloading .top-logo, .is-preloading .theme-btn { opacity: 0; }
.is-preloading.is-lift .bar, .is-preloading.is-lift .top-logo, .is-preloading.is-lift .theme-btn { opacity: 1; transition: opacity 400ms ease-in-out; }
.is-preloading .page, .is-preloading .roster, .is-preloading .sq__cap { visibility: hidden; }
.is-preloading.is-lift .page, .is-preloading.is-lift .roster, .is-preloading.is-lift .sq__cap { visibility: visible; }
.is-preloading .sq__frame { visibility: hidden; }
@keyframes pre-bail { to { visibility: hidden; } }
/* ...and the page under it shows at the same moment, so a late script never leaves it blank. */
.is-preloading .page, .is-preloading .roster, .is-preloading .sq__cap, .is-preloading .sq__frame,
.is-preloading .bar, .is-preloading .top-logo, .is-preloading .theme-btn { animation: pre-show 0s linear 1.8s forwards; }
@keyframes pre-show { to { visibility: visible; opacity: 1; } }

/* ---------- phones and tablets ---------- */

@media (max-width: 959px) {
  .a-body {
    --gutter: 2.6rem;
    --top-r: 3.4rem;
    /* The flyer card: about half the screen wide, so eight rows still show under it. */
    --pw: min(52vw, 15rem, calc((100svh - 11rem) * 0.36));
    display: flex;
    flex-direction: column;
  }
  .list { width: 100%; padding: 0.5rem 0 0; }
  /* Room at the end so the last rows can reach the reading line under the card. */
  .a-end { width: 100%; padding: 2.5rem 0.75rem calc(100svh - 24rem) var(--gutter); }
  .row__n { padding: 0.15rem 0 0 0.9rem; }
  .row__hit { padding-right: 0.75rem; }
  .row__name { font-size: 0.9375rem; }
  /* On a phone the lit row is the one that put its flyer in the card, so the others step back. */
  .row .row__hit, .row .row__n { opacity: var(--unlit); transition: opacity 200ms ease-in-out; }
  .row.is-lit .row__hit, .row.is-lit .row__n { opacity: 1; }
  /* PRÓXIMAMENTE's word sits at 0.62 x 0.32; its "??" matches instead of staying at 0.62. */
  .row--soon .row__n { opacity: 0.2; }

  /* Solid here: names scrolling up out from under the card must not show behind the logo. */
  .page::before { background: var(--ink); }
  .top-logo { top: 0.7rem; }
  .top-logo img { height: 22px; }
  .theme-btn { top: calc(0.7rem - 7px); right: 0.4rem; }

  .roster { display: none; }

  /* The card sticks under the logo, and the row passing just under it swaps its flyer in. */
  .sq {
    order: -1;
    position: sticky;
    z-index: 6;
    top: var(--top-r);
    left: auto;
    transform: none;
    width: 100%;
    margin: 3.4rem 0 0;
    padding: 0.25rem 0 1.6rem;
    background: linear-gradient(var(--ink) calc(100% - 1.6rem), transparent);
  }
  .sq__link { width: var(--pw); margin: 0 auto; }
  .sq__frame { width: var(--pw); height: calc(var(--pw) * 1.25); }
  .sq__cap { position: static; margin: 0.55rem 0 0; text-align: center; }


}

@media (prefers-reduced-motion: reduce) {
  .a-body *, .a-body *::before, .a-body *::after {
    transition-duration: 0s !important;
    transition-delay: 0s !important;
    animation: none !important;
  }
  .rv { opacity: 1; transform: none; }
  .row__hit:active, .sq__link:active, .a-link:active, .roster__link:active,
  .panel__artist:active, .top-logo:active { transform: none; }
  .panel, .panel.is-open { transform: translate(-50%, 0); }
}

/* An English visitor: the HTML's Spanish words stay hidden until app.js has put the English in. */
html.i18n-wait [data-i18n], html.i18n-wait .lang-btn { visibility: hidden; }
