/*
 * Heardlists webbsidor. Samma färger som appen (src/theme/colors.ts), för
 * att sidan ska kännas som en del av den och inte som en mall: mörkt, guld
 * för det som går att trycka på, systemtypsnittet.
 *
 * BARA MÖRKT LÄGE, med flit. Appen har userInterfaceStyle "dark" och ingen
 * ljus variant, och sidan är till för den som redan har appen framför sig.
 * color-scheme talar om det för webbläsaren, så att rullister och
 * formulärdelar också blir mörka.
 *
 * INGA WEBBTYPSNITT OCH INGA SKRIPT. Sidan ska kunna publiceras med en
 * innehållspolicy som stänger allt utom egna filer (se _headers), och en
 * integritetspolicy som laddar typsnitt från en annan värd hade lämnat ut
 * besökarens IP-adress till just den.
 */

:root {
  color-scheme: dark;

  /* Namnen följer appens tema så att en ändrad ton går att följa hit. */
  --grouped-bg: #000000;
  --card: #1c1c1e;
  --card-raised: #2c2c2e;
  --border: #2a2a32;
  --separator: #38383a;
  --text: #f4f3f0;
  /* 8,9:1 mot svart. */
  --text-muted: #a5a5ae;
  /* 5,31:1 mot svart och 4,60:1 mot kortytan, samma skäl som i appen. */
  --text-faint: #84848e;
  --link: #f5c542;
  --on-link: #141414;

  --radius: 14px;
  --measure: 42rem;
  --gutter: 20px;

  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* Hindrar iOS från att förstora texten på egen hand vid vridning; den som
   * själv zoomar eller har större systemtext får fortfarande det. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--grouped-bg);
  color: var(--text);
  font-family: var(--font);
  /* 17 px är iOS brödtext. Rem och inte px överallt annars, så att
   * webbläsarens egen textstorlek slår igenom. */
  font-size: 1.0625rem;
  line-height: 1.6;
  overflow-wrap: break-word;
}

/* ---------------------------------------------------------------------- */
/* Länkar och fokus                                                         */
/* ---------------------------------------------------------------------- */

/* Guld betyder tryckbart, som i appen. Understrykningen står kvar i löptext:
 * färgen ensam räcker inte för den som inte skiljer guld från vitt. */
a {
  color: var(--link);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: 3px solid var(--link);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: var(--gutter);
  top: -100px;
  z-index: 10;
  padding: 10px 16px;
  border-radius: 10px;
  background: var(--link);
  color: var(--on-link);
  font-weight: 600;
  text-decoration: none;
}

.skip-link:focus {
  top: 12px;
}

/* ---------------------------------------------------------------------- */
/* Sidhuvud och sidfot                                                      */
/* ---------------------------------------------------------------------- */

.site-header,
.site-footer,
main {
  width: 100%;
  max-width: calc(var(--measure) + 2 * var(--gutter));
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  padding-top: 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--border);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  font-weight: 700;
  font-size: 1.125rem;
  letter-spacing: -0.2px;
  text-decoration: none;
}

.brand img {
  width: 32px;
  height: 32px;
  border-radius: 8px;
}

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Navigeringen är tryckytor, inte löptext: ingen understrykning, men
 * minst 44 px hög som appens MIN_TOUCH. */
.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  font-weight: 500;
}

.site-nav a[aria-current="page"] {
  color: var(--text);
}

.site-footer {
  margin-top: 56px;
  padding-top: 24px;
  padding-bottom: 40px;
  border-top: 1px solid var(--border);
  color: var(--text-faint);
  font-size: 0.875rem;
}

.site-footer ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  margin: 0 0 12px;
  padding: 0;
  list-style: none;
}

.site-footer a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.site-footer p {
  margin: 0;
}

/* ---------------------------------------------------------------------- */
/* Text                                                                     */
/* ---------------------------------------------------------------------- */

main {
  padding-top: 32px;
}

h1,
h2,
h3 {
  line-height: 1.2;
  text-wrap: balance;
}

h1 {
  margin: 0 0 8px;
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.8px;
}

h2 {
  margin: 44px 0 12px;
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.4px;
  /* Ankarlänkarna i innehållsförteckningen ska inte landa med rubriken
   * klistrad mot skärmkanten. */
  scroll-margin-top: 16px;
}

h3 {
  margin: 28px 0 8px;
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.2px;
}

p,
ul,
ol,
dl,
table {
  margin: 0 0 16px;
}

ul,
ol {
  padding-left: 1.3em;
}

li {
  margin-bottom: 8px;
}

li > ul {
  margin-top: 8px;
}

strong {
  font-weight: 600;
}

.updated {
  margin-bottom: 28px;
  color: var(--text-muted);
  font-size: 0.9375rem;
}

.lede {
  color: var(--text-muted);
  font-size: 1.1875rem;
  line-height: 1.5;
}

.muted {
  color: var(--text-muted);
}

/* Knappen till TestFlight i toppen: appens guldknapp, med minst 44 px
 * träffyta och en synlig fokusram för tangentbordet. */
.cta {
  margin: 28px 0 0;
}

.knapp {
  display: inline-block;
  min-height: 44px;
  padding: 12px 22px;
  border-radius: var(--radius);
  background: var(--link);
  color: var(--on-link);
  font-weight: 600;
  text-decoration: none;
}

.knapp:hover {
  filter: brightness(1.06);
}

.knapp:focus-visible {
  outline: 3px solid var(--text);
  outline-offset: 3px;
}

.cta-not {
  margin-top: 12px;
  font-size: 0.9375rem;
}

/* Appens knappnamn och menyvägar, så att "Profile, then Delete account"
 * läses som ett ställe i appen och inte som vanliga ord. */
.ui {
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------- */
/* Kort, som appens card-yta på den svarta grunden                          */
/* ---------------------------------------------------------------------- */

.card {
  margin: 0 0 16px;
  padding: 20px;
  border-radius: var(--radius);
  background: var(--card);
}

.card > :last-child {
  margin-bottom: 0;
}

.card h2,
.card h3 {
  margin-top: 0;
}

.toc {
  margin: 0 0 8px;
}

.toc h2 {
  margin: 0 0 8px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: 0;
}

.toc ol {
  margin: 0;
}

.toc li {
  margin-bottom: 4px;
}

/* ---------------------------------------------------------------------- */
/* Tabeller                                                                 */
/* ---------------------------------------------------------------------- */

/* En bred tabell får rulla i sidled inuti sin egen ruta, aldrig hela sidan. */
.table-wrap {
  margin: 0 0 16px;
  overflow-x: auto;
  border-radius: var(--radius);
  background: var(--card);
}

table {
  width: 100%;
  margin: 0;
  border-collapse: collapse;
  font-size: 0.9375rem;
  line-height: 1.5;
}

th,
td {
  padding: 12px 16px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--separator);
}

tr:last-child > th,
tr:last-child > td {
  border-bottom: 0;
}

thead th {
  color: var(--text-muted);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.2px;
}

tbody th {
  font-weight: 600;
}

/* På en telefon blir en tabell med tre kolumner en smal remsa per kolumn.
 * Där staplas varje rad i stället, och kolumnens namn står framför värdet. */
@media (max-width: 560px) {
  .stack thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .stack tr {
    display: block;
    padding: 12px 16px;
    border-bottom: 1px solid var(--separator);
  }

  .stack tr:last-child {
    border-bottom: 0;
  }

  .stack th,
  .stack td {
    display: block;
    padding: 0;
    border: 0;
  }

  .stack tbody th {
    margin-bottom: 6px;
  }

  .stack td + td {
    margin-top: 6px;
  }

  .stack td[data-label]::before {
    content: attr(data-label) ": ";
    color: var(--text-muted);
    font-weight: 600;
  }
}

/* ---------------------------------------------------------------------- */
/* Platshållare                                                             */
/* ---------------------------------------------------------------------- */

/* DET SOM INTE ÄR IFYLLT SKA SYNAS PÅ LÅNGT HÅLL. En platshållare som ser ut
 * som vanlig text publiceras förr eller senare av misstag.
 *
 * Kontaktadressen markeras via sitt href och inte via en klass: när
 * [CONTACT EMAIL] byts mot den riktiga adressen i en enda sökning blir
 * länken fungerande och markeringen försvinner av sig själv, eftersom en
 * riktig adress aldrig börjar med en hakparentes. */
.ph,
a[href^="mailto:["] {
  padding: 0 0.3em;
  border: 1px dashed var(--link);
  border-radius: 5px;
  background: rgba(245, 197, 66, 0.14);
  color: var(--link);
  font-weight: 600;
  text-decoration: none;
  white-space: normal;
}

/* ---------------------------------------------------------------------- */
/* Länklistan (404 och support)                                             */
/* ---------------------------------------------------------------------- */

.links {
  display: grid;
  gap: 1px;
  margin: 24px 0 16px;
  padding: 0;
  overflow: hidden;
  list-style: none;
  border-radius: var(--radius);
  background: var(--separator);
}

.links li {
  margin: 0;
}

/* Raderna ser ut som appens grupperade listor: hela raden är tryckytan. */
.links a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 56px;
  padding: 14px 20px;
  background: var(--card);
  color: var(--text);
  font-weight: 600;
  text-decoration: none;
}

.links a::after {
  content: "›";
  color: var(--link);
  font-size: 1.5rem;
  line-height: 1;
}

.links a:hover {
  background: var(--card-raised);
}

.credit {
  color: var(--text-faint);
  font-size: 0.875rem;
}

/* ---------------------------------------------------------------------- */
/* Startsidan                                                               */
/* ---------------------------------------------------------------------- */

/* STARTSIDAN ÄR EN KVÄLL. Först står man i publiken när scenljuset tänds,
 * sedan scrollar man genom bandets historia tills ens egen kväll ringas in,
 * får setlistan tejpad på scengolvet bockad låt för låt, och slutar med
 * extranumret när ljuset kommer tillbaka. Allt är CSS: sajten har inga
 * skript (se _headers och integritetspolicyns "This website").
 *
 * Varje rörelse ligger under prefers-reduced-motion: no-preference, och
 * de scrollstyrda dessutom under @supports (animation-timeline: view()).
 * Utan dem står varje scen färdig och stilla, i sitt slutläge, så att en
 * webbläsare utan stöd visar samma innehåll. Skriv alltså grundregeln som
 * slutläget och animationen som en väg dit. */
.home {
  --wide: 72rem;
  --grail: #d4a017;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  overflow-x: clip;
}

@media (min-width: 900px) {
  .home {
    --gutter: 40px;
  }
}

/* Scenerna går kant i kant, så main släpper sin bredd; .ram håller texten
 * på plats inuti dem. */
.home main {
  max-width: none;
  padding: 0;
}

.ram {
  width: 100%;
  max-width: calc(var(--wide) + 2 * var(--gutter));
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

.home .site-header {
  position: absolute;
  inset: 0 0 auto;
  z-index: 2;
  max-width: calc(var(--wide) + 2 * var(--gutter));
  border-bottom: 0;
}

.home .site-footer {
  max-width: calc(var(--wide) + 2 * var(--gutter));
  margin-top: 0;
}

.site-footer p + p {
  margin-top: 4px;
}

.home h2 {
  margin: 0;
  font-size: clamp(2.25rem, 1.2rem + 4vw, 4.5rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.035em;
}

/* Knappen ger efter under fingret, som appens knappar. Den enda
 * hovringseffekten är ljusheten i .knapp ovan. */
.knapp {
  transition: transform 160ms var(--ease-out, ease-out);
}

.knapp:active {
  transform: scale(0.97);
}

.knapp-stor {
  min-height: 56px;
  padding: 16px 28px;
  border-radius: 16px;
  font-size: 1.0625rem;
}

.home .cta {
  margin-top: 36px;
}

.home .cta-not {
  color: var(--text-muted);
}

.home .visuellt-dold {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------- */
/* Scenljuset                                                               */
/* ---------------------------------------------------------------------- */

/* Tre strålkastare i riggen ovanför scenen: guld, varmvitt och blått, ur
 * appens färger. Varje stråle är en smal kil i en konisk gradient med
 * spetsen i elementets överkant, så att den kan svepa genom att bara
 * vridas runt spetsen. Masken tonar ut strålen nedåt, som i rök. */
.ljus {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.stralk {
  position: absolute;
  top: -6%;
  width: 160vmax;
  height: 120%;
  translate: -50% 0;
  transform-origin: 50% 0;
  background: conic-gradient(
    at 50% 0%,
    transparent 0deg 172deg,
    var(--stralfarg) 177.5deg,
    var(--stralkarna) 180deg,
    var(--stralfarg) 182.5deg,
    transparent 188deg 360deg
  );
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 35%, transparent 92%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 35%, transparent 92%);
}

.stralk.s1 {
  left: 18%;
  rotate: 14deg;
  --stralfarg: rgb(245 197 66 / 0.09);
  --stralkarna: rgb(245 197 66 / 0.16);
}

.stralk.s2 {
  left: 50%;
  rotate: -3deg;
  --stralfarg: rgb(255 240 210 / 0.08);
  --stralkarna: rgb(255 240 210 / 0.15);
}

.stralk.s3 {
  left: 82%;
  rotate: -15deg;
  --stralfarg: rgb(108 176 243 / 0.08);
  --stralkarna: rgb(108 176 243 / 0.15);
}

/* Scenen ligger bakom publiken: ett ljust band i höjd med huvudena, så att
 * de syns i siluett, och rök som strålarna landar i. */
.dis {
  position: absolute;
  inset: auto 0 0;
  height: 75%;
  background:
    radial-gradient(70% 34% at 50% 80%, rgb(245 197 66 / 0.34), transparent 72%),
    radial-gradient(28% 26% at 16% 84%, rgb(245 197 66 / 0.16), transparent 70%),
    radial-gradient(28% 26% at 84% 84%, rgb(108 176 243 / 0.18), transparent 70%),
    radial-gradient(90% 60% at 50% 100%, rgb(212 160 23 / 0.12), transparent 75%);
}

@media (prefers-reduced-motion: no-preference) {
  .stralk {
    animation: svep 11s var(--ease-in-out) infinite alternate;
  }

  .stralk.s1 {
    animation-duration: 9s;
    animation-delay: -4s;
  }

  .stralk.s3 {
    animation-name: svep-motsatt;
    animation-duration: 13s;
    animation-delay: -7s;
  }
}

@keyframes svep {
  from {
    rotate: 16deg;
  }
  to {
    rotate: -12deg;
  }
}

@keyframes svep-motsatt {
  from {
    rotate: -18deg;
  }
  to {
    rotate: 10deg;
  }
}

/* ---------------------------------------------------------------------- */
/* Första skärmen: publiken                                                 */
/* ---------------------------------------------------------------------- */

.scen-intro {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  min-height: 100svh;
  padding: 112px var(--gutter) clamp(170px, 34vh, 360px);
  overflow: hidden;
  text-align: center;
}

.intro-text {
  max-width: 64rem;
}

.intro-text h1 {
  margin: 0;
  font-size: clamp(3rem, 12.5vw, 8.5rem);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.045em;
  text-wrap: wrap;
}

.intro-text h1 .rad {
  display: block;
}

/* "you've heard live." ska stå på en rad när det får plats: tio
 * teckenstorlekar ungefär, så storleken följer bredden. På en telefon får
 * raden brytas före "live." i stället för att krympa rubriken, och utan
 * balance, som annars lämnar "you've" ensamt på en rad. */
@media (min-width: 700px) {
  .intro-text h1 {
    font-size: min(8.5rem, (100vw - 2 * var(--gutter)) / 9.6);
  }
}

.intro-text .lede {
  max-width: 34rem;
  margin: 28px auto 0;
  font-size: clamp(1.125rem, 1rem + 0.45vw, 1.375rem);
}

/* Publiken i siluett mot röken. preserveAspectRatio="xMidYMax slice" i
 * SVG:n håller huvudena lika stora på en telefon och skär bort sidorna. */
.publik {
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: -1;
  width: 100%;
  height: clamp(170px, 34vh, 360px);
}

.publik .langt {
  fill: #261f12;
  color: #261f12;
}

.publik .bak {
  fill: #130f09;
  color: #130f09;
}

.publik .fram {
  fill: #000;
  color: #000;
}

.publik .arm {
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
}

.publik .skarm rect {
  fill: #f4f3f0;
}

.publik .skarm.s3 rect {
  fill: #f5c542;
}

/* Laddningen: salongen är mörk, ljuset tänds, rubriken kommer fram och
 * mobilerna åker upp en i taget. Det enda som händer av sig självt på
 * sidan, utöver strålarnas svep. */
@media (prefers-reduced-motion: no-preference) {
  .scen-intro .ljus {
    animation: tand 1800ms var(--ease-out) 150ms both;
  }

  .intro-text > * {
    animation: upp 700ms var(--ease-out) both;
  }

  .intro-text h1 {
    animation-delay: 350ms;
  }

  .intro-text .lede {
    animation-delay: 430ms;
  }

  .intro-text .cta {
    animation-delay: 510ms;
  }

  .intro-text .cta-not {
    animation-delay: 570ms;
  }

  .publik .skarm {
    animation: tand 500ms var(--ease-out) 1400ms both;
  }

  .publik .skarm.s2 {
    animation-delay: 1900ms;
  }

  .publik .skarm.s3 {
    animation-delay: 1600ms;
  }

  .publik .skarm.s4 {
    animation-delay: 2250ms;
  }

  .publik .skarm.s5 {
    animation-delay: 1750ms;
  }
}

@keyframes tand {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes upp {
  from {
    opacity: 0;
    translate: 0 16px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

/* Publiken sjunker långsammare än sidan när man scrollar, så att den
 * ligger närmare än scenen. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .publik {
      animation: sjunk linear both;
      animation-timeline: scroll(root);
      animation-range: 0 100svh;
    }
  }
}

@keyframes sjunk {
  to {
    translate: 0 22%;
  }
}

/* ---------------------------------------------------------------------- */
/* Kvällen: appens avslöjande                                               */
/* ---------------------------------------------------------------------- */

/* Appens kort "Rarest of the night" (src/components/Avslojandekort.tsx) i
 * stort format, med Lotteriet: kvällens låtar snurrar förbi och saktar in
 * tills den sällsyntaste stannar, pricken tänds, ringen ritas och pulserar,
 * procenten räknar upp och nivån poppar in. Tiderna är appens
 * (src/lib/efterLoggningen.ts och src/theme/rorelse.ts). Det spelas när
 * kortet kommit in i bild, som i appen, och om igen om man scrollar tillbaka
 * förbi det och ner igen. Grundreglerna är slutläget. */
.natten {
  padding-top: clamp(96px, 14vw, 176px);
}

.natten .scen {
  display: grid;
  gap: 40px;
  align-items: center;
}

@media (min-width: 900px) {
  .natten .scen {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    gap: 72px;
  }
}

.kvall-text .lede {
  max-width: 30rem;
  margin: 24px 0 0;
  font-size: clamp(1.125rem, 1rem + 0.45vw, 1.3125rem);
}

.kvall-kalla {
  margin: 16px 0 0;
  color: var(--text-faint);
  font-size: 0.9375rem;
}

.avslojande {
  padding: clamp(20px, 3.4vw, 32px);
  border-radius: 28px;
  background: var(--card);
  box-shadow:
    0 0 0 1px rgb(255 255 255 / 0.04),
    0 50px 100px -40px rgb(0 0 0 / 0.9);
}

.kort-etikett {
  margin: 0;
  color: var(--text-faint);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.prickar {
  display: block;
  width: 100%;
  height: auto;
  margin: 14px 0 0;
  overflow: visible;
}

.prickar .av {
  fill: var(--card-raised);
}

.prickar .tand {
  fill: var(--grail);
}

/* Ringen i textens vita, som i appen, och pulsen som växer ut ur den. */
.prickar .ring,
.prickar .puls {
  fill: none;
  stroke: var(--text);
  transform-box: fill-box;
  transform-origin: center;
}

.prickar .ring {
  stroke-width: 1.6;
  stroke-dasharray: 100;
  rotate: -90deg;
}

.prickar .puls {
  stroke-width: 1.2;
  opacity: 0;
}

.kort-forklaring {
  margin: 10px 0 0;
  color: var(--text-faint);
  font-size: 0.875rem;
  line-height: 1.45;
}

/* Låten till vänster och myntet till höger, som i appen. */
.kort-lat {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  margin-top: 18px;
}

.latnamn {
  margin: 0;
  font-size: clamp(1.25rem, 1rem + 1vw, 1.625rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.3;
}

/* Rullen: en klippt ruta en rad hög med ett band av namn i, som flyttas en
 * rad i taget. Slutläget står på det sista namnet, den sällsyntaste låten. */
.rulle {
  display: block;
  height: 1.3em;
  overflow: hidden;
}

.rulle-band {
  --rad: 1.3em;
  display: block;
  translate: 0 calc(-19 * var(--rad));
}

.rulle-band span {
  display: block;
  height: var(--rad);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.latrad {
  display: grid;
  margin: 2px 0 0;
  color: var(--text-muted);
  font-size: 0.9375rem;
}

.latrad > span {
  grid-area: 1 / 1;
}

.latrad .soker {
  visibility: hidden;
}

.mynt {
  display: grid;
  justify-items: end;
  gap: 4px;
  margin: 0;
}

/* På en smal skärm står myntet under låten, vänsterställt, som i appen vid
 * stor text: annars får rullens namn för lite plats medan de snurrar. */
@media (max-width: 519px) {
  .kort-lat {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
  }

  .mynt {
    justify-items: start;
  }

  .mynt-niva {
    text-align: left;
    transform-origin: 0 50%;
  }
}

/* Graalens mynt: helrunt, medaljguld, mörk text. */
.mynt-tal {
  min-width: 70px;
  padding: 4px 14px;
  border-radius: 999px;
  background: var(--grail);
  color: #141414;
  font-size: 1.0625rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.mynt-niva {
  max-width: 16em;
  color: var(--grail);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-align: right;
  text-transform: uppercase;
  transform-origin: 100% 50%;
}

/* --spela blir 1 när kortet kommit in i bild, och då startar Lotteriet
 * (stilfrågorna nedan läser det). Tidslinjen är scrollen, men själva
 * förloppet går på tid, som i appen. */
@property --spela {
  syntax: "<integer>";
  inherits: true;
  initial-value: 0;
}

/* Procenten räknas i tiondelar. "0." står fast i texten, eftersom kvällens
 * låt ligger under 1 %. */
@property --tiondelar {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .avslojande {
      animation: utlos linear both;
      animation-timeline: view();
      animation-range: entry 80% entry 90%;
    }

    /* Utgångsläget: grått fält, tom namnrad och inget mynt. */
    .rulle-band {
      opacity: 0;
      translate: 0 0;
    }

    .latrad .soker {
      visibility: visible;
      opacity: 0;
    }

    .latrad .spelad {
      opacity: 0;
    }

    .prickar .tand {
      fill: var(--card-raised);
    }

    .prickar .ring {
      stroke-dashoffset: 100;
    }

    .mynt-tal,
    .mynt-niva {
      opacity: 0;
    }

    .mynt-tal {
      counter-reset: tiondel var(--tiondelar);
    }

    .mynt-tal .siffra {
      display: none;
    }

    .mynt-tal::after {
      content: "0." counter(tiondel) "%";
    }

    @container style(--spela: 1) {
      /* 1. Rullen, 0 till 1,9 s, med "Finding your rarest song…" under. */
      .rulle-band {
        opacity: 1;
        animation: rulla 1990ms var(--ease-out) both;
      }

      .latrad .soker {
        animation: soka 2050ms linear both;
      }

      /* 2. Stoppet, 1,9 s: raden under byts. */
      .latrad .spelad {
        animation: tand 200ms var(--ease-out) 1900ms both;
      }

      /* 3. Pricken tänds, 250 ms. */
      .prickar .tand {
        animation: bli-guld 250ms var(--ease-out) 2020ms both;
      }

      /* 4. Ringen ritas på 200 ms och pulsen växer ut på 600 ms, 2,35 s. */
      .prickar .ring {
        animation: rita 200ms var(--ease-out) 2350ms both;
      }

      /* forwards och inte both: under väntan ska pulsen vara osynlig,
       * inte stå kvar i sin första bildruta. */
      .prickar .puls {
        animation: puls 600ms var(--ease-out) 2350ms forwards;
      }

      /* 5. Procenten räknar upp på 700 ms från 2,55 s, och nivån poppar in
       * när den står still. */
      .mynt-tal {
        animation:
          tand 150ms var(--ease-out) 2550ms both,
          rakna-procent 700ms cubic-bezier(0.33, 1, 0.68, 1) 2550ms both;
      }

      .mynt-niva {
        animation: niva 280ms linear 3250ms both;
      }
    }
  }
}

@keyframes utlos {
  to {
    --spela: 1;
  }
}

/* Lotteriets rulle (LOTTERI i src/lib/efterLoggningen.ts): första bytet vid
 * 45 ms, varje mellanrum 1,09 gånger det förra, stopp på den sällsyntaste
 * vid 1,9 s. Vid varje byte glider bandet en rad uppåt på högst 90 ms. 19
 * byten och 20 namn i bandet i index.html; räknat med samma formel som
 * appen och utskrivet här. */
@keyframes rulla {
  0% {
    translate: 0 0;
  }
  2.26% {
    translate: 0 0;
  }
  4.23% {
    translate: 0 calc(-1 * var(--rad));
  }
  4.73% {
    translate: 0 calc(-1 * var(--rad));
  }
  6.88% {
    translate: 0 calc(-2 * var(--rad));
  }
  7.41% {
    translate: 0 calc(-2 * var(--rad));
  }
  9.76% {
    translate: 0 calc(-3 * var(--rad));
  }
  10.34% {
    translate: 0 calc(-3 * var(--rad));
  }
  12.89% {
    translate: 0 calc(-4 * var(--rad));
  }
  13.53% {
    translate: 0 calc(-4 * var(--rad));
  }
  16.32% {
    translate: 0 calc(-5 * var(--rad));
  }
  17.01% {
    translate: 0 calc(-5 * var(--rad));
  }
  20.05% {
    translate: 0 calc(-6 * var(--rad));
  }
  20.81% {
    translate: 0 calc(-6 * var(--rad));
  }
  24.11% {
    translate: 0 calc(-7 * var(--rad));
  }
  24.94% {
    translate: 0 calc(-7 * var(--rad));
  }
  28.54% {
    translate: 0 calc(-8 * var(--rad));
  }
  29.44% {
    translate: 0 calc(-8 * var(--rad));
  }
  33.37% {
    translate: 0 calc(-9 * var(--rad));
  }
  34.36% {
    translate: 0 calc(-9 * var(--rad));
  }
  38.64% {
    translate: 0 calc(-10 * var(--rad));
  }
  39.71% {
    translate: 0 calc(-10 * var(--rad));
  }
  44.23% {
    translate: 0 calc(-11 * var(--rad));
  }
  45.54% {
    translate: 0 calc(-11 * var(--rad));
  }
  50.07% {
    translate: 0 calc(-12 * var(--rad));
  }
  51.9% {
    translate: 0 calc(-12 * var(--rad));
  }
  56.43% {
    translate: 0 calc(-13 * var(--rad));
  }
  58.84% {
    translate: 0 calc(-13 * var(--rad));
  }
  63.36% {
    translate: 0 calc(-14 * var(--rad));
  }
  66.39% {
    translate: 0 calc(-14 * var(--rad));
  }
  70.92% {
    translate: 0 calc(-15 * var(--rad));
  }
  74.63% {
    translate: 0 calc(-15 * var(--rad));
  }
  79.15% {
    translate: 0 calc(-16 * var(--rad));
  }
  83.61% {
    translate: 0 calc(-16 * var(--rad));
  }
  88.13% {
    translate: 0 calc(-17 * var(--rad));
  }
  93.39% {
    translate: 0 calc(-17 * var(--rad));
  }
  95.06% {
    translate: 0 calc(-18 * var(--rad));
  }
  95.48% {
    translate: 0 calc(-18 * var(--rad));
  }
  100% {
    translate: 0 calc(-19 * var(--rad));
  }
}

@keyframes soka {
  0%,
  92.68% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes bli-guld {
  from {
    fill: #2c2c2e;
  }
  to {
    fill: #d4a017;
  }
}

@keyframes rita {
  from {
    stroke-dashoffset: 100;
  }
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes puls {
  from {
    opacity: 0.7;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(3);
  }
}

@keyframes rakna-procent {
  to {
    --tiondelar: 2;
  }
}

/* Nivån slår över som appens fjäder (NIVA_FJADER, dämpning 0,55): från
 * skala 1,6, förbi 1 och tillbaka. */
@keyframes niva {
  0% {
    opacity: 0;
    scale: 1.6;
  }
  40% {
    opacity: 1;
    scale: 0.94;
  }
  70% {
    scale: 1.03;
  }
  100% {
    opacity: 1;
    scale: 1;
  }
}

/* ---------------------------------------------------------------------- */
/* Setlistan                                                                */
/* ---------------------------------------------------------------------- */

.setlist-scen {
  display: grid;
  gap: 56px;
  padding-top: clamp(112px, 16vw, 200px);
}

@media (min-width: 900px) {
  .setlist-scen {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
    gap: 80px;
  }

  .steg-text {
    position: sticky;
    top: 18svh;
  }
}

.steg-lista {
  display: grid;
  gap: 18px;
  margin: 36px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: steg;
}

.steg-lista li {
  display: flex;
  gap: 16px;
  align-items: baseline;
  margin: 0;
  max-width: 26rem;
  color: var(--text-muted);
  font-size: 1.1875rem;
  line-height: 1.45;
  counter-increment: steg;
}

.steg-lista li::before {
  content: counter(steg);
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--card);
  color: var(--text);
  font-size: 1rem;
  font-weight: 700;
  translate: 0 -2px;
}

/* Setlistan tejpad på scengolvet: tryckt i versaler på vitt papper, med
 * svart gaffatejp i hörnen. Det ljusaste på hela sidan. */
/* Bredden lämnar plats för tejpen, som sticker ut utanför pappret. */
.lapp {
  position: relative;
  max-width: min(440px, 100% - 44px);
  margin: 0 auto;
  padding: 44px 28px 32px;
  border-radius: 2px;
  background:
    linear-gradient(180deg, transparent 49.7%, rgb(0 0 0 / 0.05) 50%, transparent 50.3%),
    linear-gradient(160deg, #f1eee6, #e4e0d6);
  color: #141414;
  rotate: -1.5deg;
  box-shadow:
    0 1px 0 rgb(0 0 0 / 0.25),
    0 40px 80px -24px rgb(0 0 0 / 0.9);
}

.tejp {
  position: absolute;
  top: -14px;
  width: 104px;
  height: 32px;
  background: #26262a;
  clip-path: polygon(3% 2%, 97% 0, 100% 28%, 96% 52%, 100% 80%, 96% 100%, 3% 97%, 0 72%, 4% 46%, 0 20%);
}

.tejp.t1 {
  left: -22px;
  rotate: -9deg;
}

.tejp.t2 {
  right: -22px;
  rotate: 7deg;
}

.lapp-artist {
  margin: 0;
  font-size: 1.875rem;
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.01em;
  text-transform: uppercase;
}

.lapp-kvall {
  margin: 6px 0 22px;
  color: #55524c;
  font-size: 0.875rem;
  font-weight: 600;
}

.latar {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Varje låt får appens bock: en guldcirkel med mörk bock. */
.latar li {
  position: relative;
  margin: 0;
  padding: 6px 0 6px 36px;
  font-size: 1.0625rem;
  font-weight: 800;
  line-height: 1.2;
  text-transform: uppercase;
}

.latar li::before,
.latar li::after {
  content: "";
  position: absolute;
  top: 50%;
}

.latar li::before {
  left: 0;
  width: 22px;
  height: 22px;
  margin-top: -11px;
  border-radius: 50%;
  background: #f5c542;
}

.latar li::after {
  left: 8px;
  width: 6px;
  height: 11px;
  margin-top: -7px;
  border: solid #141414;
  border-width: 0 2.5px 2.5px 0;
  rotate: 45deg;
}

/* Extranumren efter ett streck, som på en riktig lapp. */
.latar .extranummer {
  margin-top: 14px;
  padding-top: 18px;
  border-top: 2px solid #141414;
}

.latar .extranummer::before,
.latar .extranummer::after {
  margin-top: -5px;
}

/* Den sällsynta låten, inringad med guldpenna som av någon i publiken. */
.latar .sallsynt {
  isolation: isolate;
}

.ringa {
  position: absolute;
  top: -8px;
  left: 26px;
  z-index: -1;
  width: calc(100% - 22px);
  height: calc(100% + 16px);
  overflow: visible;
}

.ringa path {
  fill: none;
  stroke: var(--grail);
  stroke-width: 3;
  stroke-linecap: round;
}

/* Graalens mynt, som i kortet ovanför, i liten storlek bredvid låten. */
.latar .bricka {
  display: inline-block;
  margin: 0 0 0 10px;
  padding: 4px 9px;
  border-radius: 999px;
  background: var(--grail);
  color: #141414;
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
  vertical-align: 2px;
  font-variant-numeric: tabular-nums;
}

.raknare {
  margin: 24px 0 0;
  padding-top: 18px;
  border-top: 2px solid #141414;
  font-size: 0.9375rem;
  font-weight: 600;
}

.raknare .tal {
  font-size: 1.5rem;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

/* Scrollar man förbi låtarna bockas de av en i taget, när de passerar
 * mitten av skärmen. Varje rad är sin egen tidslinje, så ordningen kommer
 * av sig själv. Räknaren under följer med upp till hela setlistan. */
@property --latar {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .latar li {
      view-timeline: --rad block;
    }

    .latar li::before {
      animation: bock-cirkel linear both;
      animation-timeline: --rad;
      animation-range: cover 30% cover 40%;
    }

    .latar li::after {
      animation: bock linear both;
      animation-timeline: --rad;
      animation-range: cover 34% cover 42%;
    }

    .ringa path {
      stroke-dasharray: 100;
      animation: rita linear both;
      animation-timeline: --rad;
      animation-range: cover 36% cover 52%;
    }

    .lapp {
      view-timeline: --lapp block;
    }

    .raknare .tal {
      counter-reset: latar var(--latar);
      animation: rakna linear both;
      animation-timeline: --lapp;
      animation-range: cover 20% cover 62%;
    }

    .raknare .tal .siffra {
      display: none;
    }

    .raknare .tal::after {
      content: counter(latar);
    }
  }
}

@keyframes bock-cirkel {
  from {
    background: transparent;
    box-shadow: inset 0 0 0 2px rgb(0 0 0 / 0.2);
    transform: scale(0.9);
  }
  60% {
    transform: scale(1.12);
  }
  to {
    background: #f5c542;
    box-shadow: inset 0 0 0 2px transparent;
    transform: scale(1);
  }
}

@keyframes bock {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Slutsiffran är antalet låtar på lappen i index.html. Byts setlistan ska
 * talet här bytas med den. */
@keyframes rakna {
  to {
    --latar: 18;
  }
}

/* ---------------------------------------------------------------------- */
/* Skärmbilderna                                                            */
/* ---------------------------------------------------------------------- */

.skarmar {
  padding-top: clamp(112px, 16vw, 200px);
}

.skarmar h2 {
  max-width: 14ch;
}

.galleri {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: min(76vw, 300px);
  gap: 20px;
  margin: 44px calc(50% - 50vw) 0;
  padding: 16px calc((100vw - min(76vw, 300px)) / 2) 8px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  list-style: none;
  overscroll-behavior-x: contain;
}

.galleri::-webkit-scrollbar {
  display: none;
}

.galleri:focus-visible {
  outline: 3px solid var(--link);
  outline-offset: -3px;
}

.galleri li {
  margin: 0;
  scroll-snap-align: center;
}

.telefon {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 13.5% / 6.2%;
  box-shadow:
    0 0 0 6px var(--card),
    0 0 0 7px var(--separator),
    0 48px 80px -36px rgb(0 0 0 / 0.95);
}

.galleri h3 {
  margin: 32px 0 8px;
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.galleri p {
  margin: 0;
  color: var(--text-muted);
}

@media (min-width: 900px) {
  .galleri {
    grid-auto-flow: row;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 48px;
    margin: 64px 0 0;
    padding: 0;
    overflow: visible;
  }
}

/* På en telefon blir bilden i mitten störst och de bredvid mindre, efter
 * var de står i raden man sveper. På en dator står de tre bredvid varandra
 * på olika djup och glider isär när man scrollar förbi. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    @media (max-width: 899px) {
      .telefon {
        animation: fokus linear both;
        animation-timeline: view(inline);
      }
    }

    @media (min-width: 900px) {
      .galleri li {
        animation: djup-nara linear both;
        animation-timeline: view();
      }

      .galleri li:nth-child(2) {
        animation-name: djup-fjarran;
      }
    }
  }
}

@keyframes fokus {
  0%,
  100% {
    opacity: 0.45;
    scale: 0.88;
  }
  50% {
    opacity: 1;
    scale: 1;
  }
}

@keyframes djup-nara {
  from {
    translate: 0 40px;
  }
  to {
    translate: 0 -40px;
  }
}

@keyframes djup-fjarran {
  from {
    translate: 0 120px;
  }
  to {
    translate: 0 -40px;
  }
}

/* ---------------------------------------------------------------------- */
/* Mer i appen                                                              */
/* ---------------------------------------------------------------------- */

/* Tre kort, vart och ett med en vy ur appen överst: notisen när en låt man
 * vill höra spelas, topplistan och kortet efter en import. Vyerna spelar en
 * kort rörelse när kortet kommer in i bild, med samma utlösare som
 * kvällskortet (--spela). Grundreglerna är slutläget. */
.mer {
  padding-top: clamp(96px, 12vw, 160px);
}

.funktioner {
  display: grid;
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 900px) {
  .funktioner {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
  }
}

.funktion {
  margin: 0;
  padding: 14px 14px 26px;
  border-radius: 26px;
  background: var(--card);
}

.funktion h3 {
  margin: 22px 10px 6px;
  font-size: 1.1875rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.funktion > p {
  margin: 0 10px;
  color: var(--text-muted);
}

/* Lika hög i alla tre korten, efter topplistan som är högst. */
.vy {
  display: grid;
  align-content: center;
  min-height: 256px;
  padding: 18px;
  border-radius: 18px;
  background: #111113;
  overflow: hidden;
}

/* :where håller regeln svag, så att varje vys egna marginaler vinner. */
:where(.vy) p {
  margin: 0;
}

/* Notisen på en låsskärm, med scenljus som bakgrundsbild. */
.vy-notis {
  background:
    radial-gradient(60% 70% at 15% 100%, rgb(245 197 66 / 0.35), transparent 70%),
    radial-gradient(55% 65% at 90% 90%, rgb(108 176 243 / 0.3), transparent 70%),
    radial-gradient(80% 60% at 50% 0%, rgb(255 240 210 / 0.08), transparent 70%),
    #0c0c0e;
}

.notis {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 12px 14px;
  border-radius: 20px;
  background: rgb(58 58 62 / 0.88);
  box-shadow: 0 14px 30px -12px rgb(0 0 0 / 0.8);
}

.notis-ikon {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 9px;
}

.notis-text {
  flex: 1;
  min-width: 0;
}

.notis-huvud {
  display: flex;
  justify-content: space-between;
  color: var(--text-muted);
  font-size: 0.75rem;
}

.notis-titel {
  margin-top: 1px;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.3;
}

.notis-rad {
  color: var(--text);
  font-size: 0.875rem;
  line-height: 1.3;
  opacity: 0.85;
}

/* Topplistan: rubrik, väljare och rader som i appen. Den egna raden står på
 * den ljusare ytan med YOU i guld och utan personmärke. */
.topp-rubrik {
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.segment {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 10px 0 12px;
  padding: 2px;
  border-radius: 10px;
  background: var(--card-raised);
  color: var(--text-muted);
  font-size: 0.8125rem;
  font-weight: 600;
  text-align: center;
}

.segment span {
  padding: 5px 0;
  border-radius: 8px;
}

.segment .vald {
  background: var(--link);
  color: var(--on-link);
}

.topp {
  margin: 0;
  padding: 0;
  overflow: hidden;
  border-radius: 12px;
  background: var(--card);
  list-style: none;
}

.topp li {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  column-gap: 10px;
  align-items: center;
  margin: 0;
  padding: 8px 12px;
}

.topp li + li {
  border-top: 1px solid var(--separator);
}

.topp .jag {
  background: var(--card-raised);
}

.marke {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: 0.75rem;
  font-weight: 700;
}

.marke.p1 {
  box-shadow: inset 0 0 0 2px #5066b8;
}

.marke.p2 {
  box-shadow: inset 0 0 0 2px #3a792b;
}

.topp-namn {
  overflow: hidden;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.topp-namn span {
  margin-left: 4px;
  color: var(--text-faint);
  font-size: 0.75rem;
  font-weight: 400;
}

.topp-matt {
  grid-column: 2;
  color: var(--text-muted);
  font-size: 0.75rem;
  line-height: 1.3;
}

.du {
  grid-column: 3;
  grid-row: 1 / span 2;
  color: var(--link);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Kortet efter en import: först "imported" och stapeln medan artisternas
 * historik laddas, sedan det klara läget. */
.vy-import {
  background:
    radial-gradient(70% 60% at 50% 110%, rgb(212 160 23 / 0.22), transparent 70%),
    #111113;
}

.import {
  padding: 16px;
  border-radius: 16px;
  background: var(--card);
}

.import-titel,
.import-rad {
  display: grid;
}

.import-titel > span,
.import-rad > span {
  grid-area: 1 / 1;
}

.import-titel {
  font-size: 1.0625rem;
  font-weight: 700;
}

.import-rad {
  margin-top: 4px;
  color: var(--text-muted);
  font-size: 0.875rem;
  line-height: 1.4;
}

.stapel {
  height: 6px;
  margin-top: 14px;
  overflow: hidden;
  border-radius: 3px;
  background: var(--card-raised);
}

.stapel span {
  display: block;
  height: 100%;
  background: var(--link);
  transform-origin: 0 50%;
}

.import-not {
  margin-top: 8px;
  color: var(--text-faint);
  font-size: 0.8125rem;
}

.import .laddar {
  visibility: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .funktion {
      animation: utlos linear both;
      animation-timeline: view();
      animation-range: entry 80% entry 90%;
    }

    /* Utgångslägena: ingen notis, inga rader, importen precis gjord. */
    .notis {
      opacity: 0;
    }

    .topp li {
      opacity: 0;
    }

    .import .laddar {
      visibility: visible;
    }

    .import .klar {
      opacity: 0;
    }

    .stapel span {
      scale: 0 1;
    }

    @container style(--spela: 1) {
      .notis {
        animation: notis-in 500ms var(--ease-out) 250ms both;
      }

      .topp li {
        animation: upp 350ms var(--ease-out) 200ms both;
      }

      .topp li:nth-child(2) {
        animation-delay: 270ms;
      }

      .topp li:nth-child(3) {
        animation-delay: 340ms;
      }

      .stapel span {
        animation: fyll 1600ms var(--ease-in-out) 300ms both;
      }

      .import .laddar {
        animation: ga-ut 200ms var(--ease-out) 1950ms both;
      }

      .import .klar {
        animation: tand 200ms var(--ease-out) 2000ms both;
      }
    }
  }
}

/* Notisen kommer ovanifrån, som på en iPhone. */
@keyframes notis-in {
  from {
    opacity: 0;
    translate: 0 -28px;
    scale: 0.96;
  }
  to {
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }
}

@keyframes fyll {
  from {
    scale: 0 1;
  }
  to {
    scale: 1 1;
  }
}

@keyframes ga-ut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

/* ---------------------------------------------------------------------- */
/* Extranumret                                                              */
/* ---------------------------------------------------------------------- */

.slut {
  position: relative;
  isolation: isolate;
  margin-top: clamp(112px, 16vw, 200px);
  padding: clamp(140px, 22vw, 260px) var(--gutter) clamp(96px, 12vw, 140px);
  overflow: hidden;
  text-align: center;
}

.slut h2 {
  max-width: 13ch;
  margin: 0 auto;
  font-size: clamp(2.75rem, 1rem + 7vw, 6.5rem);
  letter-spacing: -0.045em;
  line-height: 0.95;
}

/* Ljuset tänds igen när extranumret kommer in i bild. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .slut .ljus {
      animation: tand linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 45%;
    }
  }
}
