/* DeepCrates: Staff Pick. A dusty-pink record-shop wall with the sleeve
   pinned up slightly askew, the track on a lined staff-pick card with the
   year pencilled in, and earlier plays as cards back in the bin. Light
   only, like the paper it imitates; it does not follow the viewer's
   colour scheme. */

/* Self-hosted so the installed app renders offline and the page makes no
   third-party request. optional (not swap): a font that misses first
   paint is skipped rather than reflowed into, the CLS trade the other
   stations make too. Bricolage carries only the wordmark's letters and
   Caveat only digits, so both are a couple of KB. */
@font-face {
  font-family: "Courier Prime";
  src: url("fonts/courier-prime-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-display: optional;
}
@font-face {
  font-family: "Courier Prime";
  src: url("fonts/courier-prime-700-latin.woff2") format("woff2");
  font-weight: 700;
  font-display: optional;
}
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("fonts/bricolage-deepcrates.woff2") format("woff2");
  font-weight: 800;
  font-stretch: 75%;
  font-display: optional;
}
@font-face {
  font-family: "Caveat";
  src: url("fonts/caveat-digits.woff2") format("woff2");
  font-weight: 700;
  font-display: optional;
}

:root {
  --wall: #d9a7a0; /* the shop wall; theme-color */
  --card: #f6eedd; /* index cards and sleeves */
  --ink: #1a1714; /* 15.46:1 on card, 8.49:1 on wall */
  --oxblood: #7a2e2e; /* 8.06:1 on card; 4.42:1 on wall, so large only */
  --maroon: #5a2222; /* 5.92:1 on wall: small text on the wall */
  --faded: #5a4a3a; /* 7.35:1 on card */
  --teal: #2f6464; /* 5.82:1 on card */
  --rule: #c9d3d6; /* the card's printed lines; decorative */
  --shadow: rgba(122, 46, 46, 0.2);

  /* House sleeve, shared by the cover and the history thumbnails. Shows
     before real art arrives and stays for tracks with no cover. Lives in
     CSS so it paints before player.js runs. The icon's milk crate, in
     oxblood on card stock so it stands off the wall. */
  --house-sleeve: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/\
svg' viewBox='0 0 1200 1200'><rect width='1200' height='1200' fill='%23f6eedd'\
/><g fill='%237a2e2e' fill-rule='evenodd'><path d='m271.73 357.3 324.53-56.445\
v144l-38.832-10.477-0.003906-0.35547-17.742-18.926-7.7812 12.395-11.688-3.1523\
 11.316-17.941-20.926-22.32-20.32 31.879 0.40625 0.41797-28.789-7.7656-11.539-\
11.562-4.6562 7.1914-13.207-3.5625 4.1641-6.3984-15.605 3.3125zm142.83-6.9414c\
-1.8438 0.33203-3.1602 1.9805-3.0742 3.8555l1.0781 23.398c0.10938 2.2969 2.242\
2 3.957 4.4922 3.4961l63.723-13.059c1.7734-0.36328 3.0352-1.9453 2.9922-3.7578\
l-0.52734-21.984c-0.054688-2.2969-2.1484-4.0039-4.4102-3.5938zm108.3 25.641 32\
.113-6.8125-15.598 24.742zm34.348 37.293-0.25781-25.727-9.5 15.133zm-93.754-24\
.699 34.461-7.3086-16.445 25.688z'/><path d='m778.95 397.58 149.32-40.281-324.\
53-56.449v144l38.832-10.477 0.003906-0.35547 17.742-18.926 7.7812 12.395 11.68\
4-3.1523-11.309-17.941 20.922-22.32 20.32 31.879-0.40625 0.41797 28.789-7.7656\
 11.539-11.562 4.6562 7.1914 13.207-3.5625-4.1641-6.3984zm-57.66-58.863c-2.261\
7-0.41016-4.3555 1.293-4.4141 3.5938l-0.52344 21.977c-0.042969 1.8125 1.2148 3\
.3945 2.9922 3.7578l63.707 13.059c2.2539 0.46094 4.3867-1.1992 4.4922-3.4961l1\
.0781-23.395c0.085938-1.8711-1.2266-3.5234-3.0742-3.8555zm-19.215 42.562 34.46\
5 7.3086-18.016 18.379zm-57.055-12.098 32.113 6.8125-16.516 17.93zm-1.9805 18.\
379 9.5039 15.133-9.7578 10.594z'/><path d='m936.71 362.78-27.91 360.34-305.05\
 169.23v-439.75zm-118.97 56.348c0.14062-2.5625-2.2773-4.5-4.75-3.8086l-53.109 \
14.898c-3.1445 0.88281-5.3555 3.7031-5.4609 6.9688l-0.74609 22.965c-0.082031 2\
.582 2.4102 4.4688 4.8711 3.6914l52.816-16.688c2.9727-0.9375 5.0547-3.6211 5.2\
227-6.7344zm44.871 71.059-21.727 39.09-18.656-24.734 22.371-39.809zm-101.33 36\
.023 20.938 25.316 23.145-40.992-20.207-26.105zm-43.191 49.641 24.746-43.082-2\
2.75-26.781-25.57 43.957zm78.598 112.1-19.535-20.867-22.898 41.379 20.207 20.0\
86zm60.492-110.47-21.316 38.926-18.371-22.219 21.938-39.641zm-26.129 122.5 20.\
918-38.742-17.5-20.598-21.516 39.457zm-61.965-41.516-20.852-22.273-23.902 42.5\
27 21.574 21.449zm31.848-57.301-22.68 40.801-20.562-22.598 23.375-41.59zm8.972\
7-16.148 22.195-39.934-18.918-24.441-22.871 40.684zm-1.2812 25.199 18.625 21.9\
26-21.766 39.75-19.27-21.176zm-35.77-42.102-23.668 41.914-21.996-24.168 24.43-\
42.742zm31.402 127.93 13.281 14.188-29.059 14.742zm-64.645-69.062-24.207 42.86\
7-23.094-22.953 25-43.742zm-78.879-11.477 22.016 21.887 25.328-44.102-23.914-2\
5.547-23.316 40.082zm53.926 80.422-24.449 43.496 22.629 20.242 23.695-42.633zm\
-52.863-152.08-0.52734 35.508 12.984-22.199zm43.715-40.145-40.926 13.363 20.16\
 22.148zm66.48-21.699-37.227 12.152 17.852 21.582zm60.672-19.805-34.004 11.102\
 15.859 21.027zm24.41-7.9648 14.137 20.488 17.043-30.668zm-196.75 189.25-0.5 3\
3.836 12.68-22.082zm-1.0117 68.301 21.539 19.266 24.766-43.855-23.414-22.598-2\
2.785 39.863zm-0.875 58.961 12.395-21.953-11.918-10.328zm38.504 0.68359-16.617\
-14.402-17.957 31.949zm31.254-15.859 31.637-16.055-14.832-14.312zm142.49-72.30\
1-11.926-14.035-14.855 27.621zm4.3359-19.508 1.9258-28.344-9.9961 18.582zm3.94\
92-58.129-14.906-19.254-21.074 38.645 17.266 20.879 18.281-33.859zm3.6211-53.2\
23-10.18 18.668 8.1719 10.836zm2.1055-31.012-15.102-21.344-21.477 38.809 17.50\
4 23.215 18.621-34.008zm3.7695-55.449-10.371 18.742 8.2812 12z'/><path d='m263\
.3 362.78 27.906 360.34 305.05 169.23v-439.75zm122.48 51.648c-2.4727-0.69141-4\
.8906 1.25-4.75 3.8086l1.1562 21.293c0.16797 3.1133 2.25 5.7969 5.2227 6.7344l\
52.816 16.691c2.4609 0.77734 4.9531-1.1133 4.8711-3.6914l-0.74609-22.965c-0.10\
547-3.2656-2.3164-6.0859-5.4609-6.9688zm39.77 314.12 20.207-20.082-22.902-41.3\
79-19.535 20.867zm-88.152-238.36 21.727 39.09 18.656-24.738-22.375-39.805zm80.\
395 61.34 20.938-25.316-23.879-41.781-20.203 26.105zm64.91 51.625 24.996 43.73\
8-23.094 22.953-24.207-42.867zm-0.78125-27.301 23.574-25.906-25.57-43.953-22.7\
5 26.777zm5.25 183.81 22.629-20.242-24.449-43.5-21.875 21.109zm-92.648-87.773 \
19.273-21.176-22.41-40.496-18.625 21.926zm47.797-52.523-23.375-41.586-19.867 2\
3.383 22.68 40.805zm8.5039-9.3398 21.996-24.168-24.43-42.742-21.234 24.996zm3.\
2812 90.141 21.574-21.449-23.902-42.527-20.852 22.273zm-44.41-138.84-22.867-40\
.684-18.918 24.441 22.195 39.938zm30.488 178.19 31.637 16.055-16.805-30.367zm-\
57.664-145.32-21.938-39.641-17.75 22.93 21.316 38.93zm-67.199-72.797 0.45312 6\
.668 18.621 34.012 17.504-23.215-21.477-38.809zm50.223 119.24-17.5 20.602 20.9\
18 38.742 18.098-19.883zm-53.992-174.69 2.0898 30.742 8.2812-12zm0.20703-21.89\
5 17.043 30.668 14.137-20.488zm73.73 50.273-18.141-32.129 34.004 11.102zm79.75\
4-0.17187-37.223-12.152 19.375 33.734zm50.023 45.059-20.766-35.512 40.926 13.3\
63zm-195.83 42.699 8.1719-10.836-10.176-18.668zm2.0469 30.129 18.281 33.859 17\
.266-20.879-21.078-38.645-14.902 19.254zm3.5156 51.719 8.0703-9.7617-9.9961-18\
.582zm31.117 33.094-14.855-27.621-11.926 14.035zm55.418 28.121-15.777-28.93-13\
.281 14.188zm126.12 64-17.957-31.949-16.617 14.402zm3.4531-50.512-11.918 10.32\
8 12.395 21.953zm-0.50391-34.004-22.785-39.863-23.414 22.598 24.766 43.855 21.\
539-19.266zm-0.90625-60.977-12.18 11.754 12.684 22.082zm-0.52734-35.656-23.32-\
40.082-23.91 25.547 25.328 44.102 22.016-21.887zm-13.406-50.672 12.984 22.199-\
0.52734-35.508z'/></g></svg>");

  --line: 1.45rem; /* the card's ruling; text in the card sits on it */
  --display: "Bricolage Grotesque", "Arial Narrow", sans-serif;
  --type: "Courier Prime", "Courier New", monospace;
  --hand: "Caveat", "Segoe Print", cursive;
}

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

body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  justify-items: center;
  padding: 1.2rem 1rem 2rem;
  background: var(--wall);
  /* A faint halftone, as if the wall were printed. */
  background-image: radial-gradient(
    rgba(122, 46, 46, 0.09) 1px,
    transparent 1px
  );
  background-size: 5px 5px;
  color: var(--ink);
  font-family: var(--type);
  -webkit-font-smoothing: antialiased;
}

.player {
  width: min(26rem, 100%);
}

.masthead {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
}

.badge,
.spec,
.section-heading {
  margin: 0;
  font-size: 0.68rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--maroon);
}

.badge::before {
  content: "\25CF\00A0";
  color: var(--oxblood);
}

.badge.off::before {
  content: "\25CB\00A0";
}

.name {
  margin: 0.35rem 0 1rem;
  font-family: var(--display);
  font-weight: 800;
  font-stretch: 75%;
  font-size: 2.6rem;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--oxblood);
}

/* The sleeve, pinned up a little crooked. A loaded cover is opaque and
   object-fit: cover, so it paints over the house sleeve entirely. */
.art {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 3px;
  background: var(--card) var(--house-sleeve) center / cover no-repeat;
  box-shadow: 4px 6px 0 rgba(122, 46, 46, 0.22);
  transform: rotate(-1.2deg);
}

/* The staff-pick card. Every line of text is one ruling tall, and the
   ruling starts below the top padding, so text sits on the printed
   lines however the title wraps. */
.meta {
  margin-top: 1.2rem;
  padding: 0.75rem 1rem 0.95rem;
  border-radius: 3px;
  background:
    repeating-linear-gradient(
      transparent 0 calc(var(--line) - 1px),
      var(--rule) calc(var(--line) - 1px) var(--line)
    )
    0 0.75rem / 100% calc(100% - 1.7rem) no-repeat,
    var(--card);
  box-shadow: 3px 4px 0 var(--shadow);
  transform: rotate(0.6deg);
}

.meta > * {
  margin: 0;
  line-height: var(--line);
}

/* Pencilled in. AzuraCast's original year, hidden when there isn't one. */
.year {
  font-family: var(--hand);
  font-weight: 700;
  font-size: 1.4rem;
  color: var(--oxblood);
}

.title {
  font-size: 1.3rem;
  font-weight: 700;
  text-wrap: balance;
}

.artist {
  font-size: 0.95rem;
}

.album {
  font-size: 0.82rem;
  color: var(--faded);
}

.toggle {
  display: block;
  width: 100%;
  margin-top: 1.3rem;
  padding: 0.85rem 1rem;
  border: 0;
  border-radius: 4px;
  background: var(--oxblood);
  color: var(--card);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-indent: 0.3em; /* offsets the trailing letter-space */
  text-transform: uppercase;
  box-shadow: 3px 4px 0 rgba(26, 23, 20, 0.25);
  cursor: pointer;
}

.toggle:hover {
  background: #8a3535;
}

.toggle:active {
  transform: translate(2px, 3px);
  box-shadow: 1px 1px 0 rgba(26, 23, 20, 0.25);
}

.toggle:focus-visible,
.stream-copy:focus-visible,
.stream-url:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.status {
  margin: 0.7rem 0 0;
  text-align: center;
  font-size: 0.75rem;
  color: var(--maroon);
}

.hidden {
  display: none;
}

/* Motion: a slow needle drop. The card slides into place and the cover
   fades up. The fade starts above zero opacity so the cover still counts
   as painted for LCP. */
@keyframes slide-in {
  from {
    opacity: 0;
    transform: translateY(0.5rem) rotate(0.6deg);
  }
}
@keyframes fade-up {
  from {
    opacity: 0.35;
  }
}

.meta.enter {
  animation: slide-in 0.6s ease-out both;
}
.art.enter {
  animation: fade-up 0.8s ease-out both;
}

@media (prefers-reduced-motion: reduce) {
  .meta.enter,
  .art.enter {
    animation: none;
  }
  .toggle:active {
    transform: none;
  }
}

.history,
.streams {
  margin-top: 1.8rem;
}

.section-heading {
  margin-bottom: 0.55rem;
  padding-bottom: 0.4rem;
  border-bottom: 2px dashed var(--oxblood);
}

.history-list,
.stream-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Rows have a fixed height and single-line text so the list's settled
   height is known before the first poll fills it: reserve it up front
   rather than shifting everything below (the API returns 5 entries). */
.history-list {
  min-height: calc(5 * (4.6rem + 0.45rem));
}

/* Cards back in the bin, each a little off true. */
.history-row {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr);
  column-gap: 0.75rem;
  align-content: center;
  height: 4.6rem;
  margin-bottom: 0.45rem;
  padding: 0.5rem 0.6rem;
  border-radius: 3px;
  background: var(--card);
  box-shadow: 2px 3px 0 var(--shadow);
}

.history-row:nth-child(odd) {
  transform: rotate(-0.4deg);
}
.history-row:nth-child(even) {
  transform: rotate(0.3deg);
}

.history-art {
  grid-row: span 4;
  align-self: center;
  width: 3.5rem;
  height: 3.5rem;
  object-fit: cover;
  border-radius: 2px;
  background: var(--card) var(--house-sleeve) center / cover no-repeat;
}

.history-title,
.history-artist,
.history-album,
.history-time {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 0.74rem;
  line-height: 1.3;
}

.history-title {
  font-size: 0.84rem;
  font-weight: 700;
}

.history-album {
  color: var(--faded);
}

.history-time {
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
  color: var(--teal);
}

.stream-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 0.7rem;
  align-items: center;
  margin-bottom: 0.45rem;
  padding: 0.6rem 0.7rem;
  border-radius: 3px;
  background: var(--card);
  box-shadow: 2px 3px 0 var(--shadow);
}

.stream-format {
  grid-column: 1;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
}

.stream-note {
  font-weight: 400;
  text-transform: none;
  color: var(--faded);
}

.stream-url {
  grid-column: 1;
  font-size: 0.7rem;
  color: var(--teal);
  overflow-wrap: anywhere;
}

.stream-url:hover {
  color: var(--ink);
}

.stream-copy {
  grid-column: 2;
  grid-row: 1 / span 2;
  padding: 0.4rem 0.7rem;
  border: 2px solid var(--oxblood);
  border-radius: 4px;
  background: transparent;
  color: var(--oxblood);
  font: inherit;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  cursor: pointer;
}

.stream-copy:hover {
  background: var(--oxblood);
  color: var(--card);
}
