/* ===== Edition system — shared print hardware (desktop-only) =====
   Extracted from the music-catalog concept so all main pages share one
   visual language: ink masthead, navy Buy Now, plate dots, glass overlay. */
@media (min-width: 1025px) {
  :root {
    --ee-ink: hsl(221, 39%, 13%);

    /* One cast-shadow scale. Every offset is square and unblurred — the whole
       system is printed sheets stacked on a page, and a blurred or lopsided
       cast breaks that read. Small elements carry more alpha because they
       cast over a much smaller area. Hover always steps up exactly one rung. */
    --ee-edge: rgba(2, 6, 23, 0.35);
    --ee-cast: rgba(2, 6, 23, 0.20);
    --ee-cast-deep: rgba(2, 6, 23, 0.28);
    --ee-cast-broad: rgba(2, 6, 23, 0.16);
    --ee-cast-broad-deep: rgba(2, 6, 23, 0.22);

    --ee-lift-sm: 2px 2px 0 var(--ee-cast);
    --ee-lift-sm-hover: 3px 3px 0 var(--ee-cast-deep);
    --ee-lift-md: 4px 4px 0 var(--ee-cast-broad);
    --ee-lift-md-hover: 6px 6px 0 var(--ee-cast-broad-deep);
    --ee-lift-lg: 8px 8px 0 var(--ee-cast-broad);
    --ee-lift-lg-hover: 11px 11px 0 var(--ee-cast-broad-deep);
    --ee-lift-plate: 10px 10px 0 var(--ee-cast-broad);
  }

      /* The masthead sits on its ink rule; a soft halo under it belongs to the
         old elevation language and fights that edge. */
      .header-base,
      .example-1 {
        box-shadow: none !important;
      }

      /* ===== Hover tiers ====================================================
         One motion for everything that responds: a 1px lift toward the light
         into a square unblurred cast. Only the depth of the cast changes, by
         how big the thing is. Use the class on new markup; the selector lists
         beside each class adopt the existing components.

           .ee-hover-control  buttons and small square controls   3px
           .ee-hover-tile     tiles, comp cards, result cards     6px
           .ee-hover-sheet    panels, folios, large cards         8px
           .ee-hover-plate    cover art and other big plates     10px

         Rest states are set per component (a seated button keeps its 1px seat,
         a cover card sits flat); the tier only owns the hover. Containers that
         merely hold controls are deliberately NOT given a tier — a backdrop
         that moves when you cross it reads as a glitch, and nesting two lifts
         makes both wobble. */

      .ee-hover-control,
      .ee-hover-tile,
      .ee-hover-sheet,
      .ee-hover-plate {
        transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
      }

      /* Components adopting the control tier. These were the stragglers: the
         filter chips and Clear all still used blurred glows (0 4px 6px and
         0 6px 20px), and the carousel arrows changed colour without deepening
         their cast. */
      #catalog-filters .button-group button,
      #catalog-filters .btn-group button,
      #catalog-filters .btn.u-btn,
      #catalog-filters .u-btn--pill,
      .filter-controls .multi-select-button,
      .nr-thumb-carousel .related-works-nav-btn,
      .video-carousel .related-works-nav-btn,
      .news-nr-audio-accordion .accordion-toggle,
      .collections-toggle {
        transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
      }
      #catalog-filters .button-group button:hover,
      #catalog-filters .btn-group button:hover,
      #catalog-filters .btn.u-btn:hover,
      #catalog-filters .u-btn--pill:hover,
      .filter-controls .multi-select-button:hover,
      .nr-thumb-carousel .related-works-nav-btn:hover,
      .video-carousel .related-works-nav-btn:hover,
      .news-nr-audio-accordion .accordion-toggle:hover {
        transform: translate(-1px, -1px) !important;
        box-shadow: var(--ee-lift-sm-hover) !important;
      }
      /* the arrows are absolutely positioned and already carry a centring
         transform, so they take the cast without the translate */
      .nr-thumb-carousel .related-works-nav-btn:hover,
      .video-carousel .related-works-nav-btn:hover {
        transform: none !important;
      }

      .ee-hover-control:hover { transform: translate(-1px, -1px); box-shadow: var(--ee-lift-sm-hover) !important; }
      .ee-hover-tile:hover    { transform: translate(-1px, -1px); box-shadow: var(--ee-lift-md-hover) !important; }
      .ee-hover-sheet:hover   { transform: translate(-1px, -1px); box-shadow: var(--ee-lift-lg) !important; }
      .ee-hover-plate:hover   { transform: translate(-1px, -1px); box-shadow: var(--ee-lift-plate) !important; }

      @media (prefers-reduced-motion: reduce) {
        .ee-hover-control:hover,
        .ee-hover-tile:hover,
        .ee-hover-sheet:hover,
        .ee-hover-plate:hover { transform: none !important; }
      }

      /* ---------- 11 · Masthead: press-bed rule + ink link states ---------- */
      /* Nav wordmark: same ink voice as the rest of the edition — genuinely thick */
      .brand-title {
        font-weight: 900 !important;
        -webkit-text-stroke: 0.8px currentColor;
        letter-spacing: -0.015em !important;
        color: var(--gray-950, var(--ee-ink)) !important;
      }
      .brand-roles .role-link,
      .brand-roles .role-sep {
        text-transform: uppercase;
        font-size: 11px !important;
        letter-spacing: 0.1em !important;
        font-weight: 600;
      }

      /* Crisp ink rule under the header — the page's plates hang from it */
      .header-base {
        border-bottom: 2px solid rgba(2, 6, 23, 0.85) !important;
        box-shadow: none !important;
      }
      /* Active page: ink text with a crisp underline rule (no pill, no glow) */
      .main-nav a.active {
        color: var(--gray-950, var(--ee-ink)) !important;
        font-weight: 700 !important;
        text-decoration: underline !important;
        text-underline-offset: 9px;
        text-decoration-thickness: 2px;
        text-decoration-color: var(--ee-ink);
      }
      .main-nav a:not(.active):hover {
        color: var(--gray-950, var(--ee-ink)) !important;
      }
      /* Dropdowns: white plates with ink edges and offset shadows, cream hover */
      .main-nav .dropdown-menu {
        border: 1px solid rgba(2, 6, 23, 0.45) !important;
        border-radius: 8px !important;
        box-shadow: var(--ee-lift-md) !important;
        padding: 6px !important;
      }
      .main-nav .dropdown-menu a {
        border-radius: 5px !important;
      }
      .main-nav .dropdown-menu a:hover {
        background: var(--secondary-100) !important;
        color: var(--gray-950, var(--ee-ink)) !important;
      }

      /* ---------- 10a · Side section dots: tiny plates, same hardware ---------- */
      .side-dot-nav .dot {
        width: 11px !important;
        height: 11px !important;
        border-radius: 3px !important;
        border: 1.5px solid rgba(2, 6, 23, 0.55) !important;
        background: #ffffff !important;
        box-shadow: var(--ee-lift-sm) !important;
      }
      .side-dot-nav .dot:hover {
        background: var(--secondary-100) !important;
        border-color: var(--ee-ink) !important;
        transform: scale(1.1) !important;
      }
      .side-dot-nav .dot.active {
        background: var(--primary-600) !important;
        border-color: var(--ee-ink) !important;
        box-shadow: 0 0 0 2px #ffffff, 1.5px 1.5px 0 2px rgba(2, 6, 23, 0.3) !important;
      }
      .side-dot-nav .dot-label {
        border: 1px solid rgba(2, 6, 23, 0.45) !important;
        border-radius: 5px !important;
        background: #ffffff !important;
        color: var(--ee-ink) !important;
        font-weight: 800 !important;
        font-size: 0.72rem !important;
        text-transform: uppercase !important;
        letter-spacing: 0.07em !important;
        box-shadow: var(--ee-lift-sm) !important;
      }

      /* Free / contact / toggle variants keep their own colour — that colour
         carries meaning — but the cast is material, not meaning, so they use
         the same square offset as everything else instead of a coloured glow. */
      .buy-now-btn.free,
      .buy-now-btn.free-download-btn,
      .buy-now-btn.contact-btn,
      .composition-buy-btn.free,
      .composition-buy-btn.free-download-btn,
      .composition-buy-btn.contact-btn,
      .u-toggle {
        box-shadow: 0 1px 0 var(--ee-cast) !important;
        transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
      }
      .buy-now-btn.free:hover,
      .buy-now-btn.free-download-btn:hover,
      .buy-now-btn.contact-btn:hover,
      .composition-buy-btn.free:hover,
      .composition-buy-btn.free-download-btn:hover,
      .composition-buy-btn.contact-btn:hover,
      .u-toggle:hover {
        transform: translate(-1px, -1px) !important;
        box-shadow: var(--ee-lift-sm-hover) !important;
      }

      /* ---------- 5 · Buy Now: solid ink, no more purple gradient ---------- */
      /* One confident palette-native CTA. Free-download and contact variants keep
         their own colors. */
      .buy-now-btn:not(.free):not(.free-download-btn):not(.contact-btn),
      .btn-buy:not(.free):not(.free-download-btn):not(.contact-btn),
      .buy-button:not(.free):not(.free-download-btn):not(.contact-btn),
      .composition-buy-btn:not(.free):not(.free-download-btn):not(.contact-btn),
      .enhanced-score-buy-btn:not(.free):not(.free-download-btn):not(.contact-btn),
      .new-releases-section .primary-actions-container .btn-buy.buy-now-btn:not(.free):not(.contact-btn) {
        background: hsl(221, 45%, 22%) !important;
        color: #ffffff !important;
        border: 0 !important;
        border-radius: 8px !important;
        font-weight: 800 !important;
        letter-spacing: 0.01em;
        box-shadow: 0 1px 0 var(--ee-cast) !important;
      }
      .buy-now-btn:not(.free):not(.free-download-btn):not(.contact-btn):hover,
      .btn-buy:not(.free):not(.free-download-btn):not(.contact-btn):hover,
      .buy-button:not(.free):not(.free-download-btn):not(.contact-btn):hover,
      .composition-buy-btn:not(.free):not(.free-download-btn):not(.contact-btn):hover,
      .enhanced-score-buy-btn:not(.free):not(.free-download-btn):not(.contact-btn):hover,
      .new-releases-section .primary-actions-container .btn-buy.buy-now-btn:not(.free):not(.contact-btn):hover {
        background: hsl(221, 45%, 17%) !important;
        filter: none !important;
        transform: translate(-1px, -1px) !important;
        box-shadow: var(--ee-lift-sm-hover) !important;
      }
      .buy-now-btn:not(.free):not(.free-download-btn):not(.contact-btn):active,
      .btn-buy:not(.free):not(.free-download-btn):not(.contact-btn):active {
        transform: translate(0, 0) !important;
        box-shadow: 0 1px 0 var(--ee-cast) !important;
      }

      /* ---------- 10 · Score overlay: keep the glass, speak the same language ---------- */
      .enhanced-score-overlay-content {
        border-radius: 12px !important;
        border: 1px solid rgba(255, 255, 255, 0.22) !important;
        /* The one deliberate exception to the square-cast rule: this is a modal
           floating over a dimmed page, not a sheet stacked on it, so it keeps
           an ambient shadow. */
        box-shadow: 0 0 0 1px rgba(2, 6, 23, 0.65), 0 24px 64px rgba(0, 0, 0, 0.45) !important;
      }
      /* Header: flat folio navy instead of a gradient */
      .enhanced-score-overlay-header {
        background: hsl(221, 45%, 17%) !important;
        border-radius: 12px 12px 0 0 !important;
        border-bottom: 1px solid rgba(255, 255, 255, 0.14) !important;
      }
      .enhanced-score-overlay-main-title {
        font-weight: 900 !important;
        letter-spacing: -0.02em !important;
      }
      .enhanced-score-overlay-instrumentation {
        font-style: italic !important;
        color: rgba(255, 255, 255, 0.8) !important;
      }
      .enhanced-score-overlay-close {
        background: #ffffff !important;
        color: var(--ee-ink) !important;
        border: 1px solid rgba(2, 6, 23, 0.45) !important;
        border-radius: 6px !important;
        font-size: 1.1rem !important;
        box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.35) !important;
      }
      .enhanced-score-overlay-close:hover { background: var(--secondary-100) !important; }
      /* Header actions on navy: Buy Now flips to white/ink (navy-on-navy would vanish),
         Learn More becomes a ghost button — same hardware, dark ground */
      .enhanced-score-overlay-actions .buy-now-btn:not(.free):not(.free-download-btn):not(.contact-btn),
      .enhanced-score-overlay-actions .composition-buy-btn:not(.free):not(.free-download-btn):not(.contact-btn),
      .enhanced-score-overlay-actions .buy-button:not(.free):not(.free-download-btn):not(.contact-btn),
      .enhanced-score-overlay-actions .enhanced-score-buy-btn:not(.free):not(.free-download-btn):not(.contact-btn) {
        background: #ffffff !important;
        color: var(--ee-ink) !important;
        border: 1px solid rgba(2, 6, 23, 0.45) !important;
        border-radius: 8px !important;
        font-weight: 800 !important;
        box-shadow: 0 1px 0 rgba(0, 0, 0, 0.3) !important;
      }
      .enhanced-score-overlay-actions .buy-now-btn:not(.free):not(.free-download-btn):not(.contact-btn):hover,
      .enhanced-score-overlay-actions .composition-buy-btn:not(.free):not(.free-download-btn):not(.contact-btn):hover,
      .enhanced-score-overlay-actions .buy-button:not(.free):not(.free-download-btn):not(.contact-btn):hover,
      .enhanced-score-overlay-actions .enhanced-score-buy-btn:not(.free):not(.free-download-btn):not(.contact-btn):hover {
        background: var(--secondary-100) !important;
        transform: translate(-1px, -1px) !important;
        box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.35) !important;
      }
      .enhanced-score-overlay-actions .learn-more-btn,
      .enhanced-score-overlay-actions .enhanced-score-learn-more-btn,
      .enhanced-score-overlay-actions .btn:not(.buy-now-btn):not(.composition-buy-btn):not(.buy-button) {
        background: transparent !important;
        color: #ffffff !important;
        border: 1px solid rgba(255, 255, 255, 0.45) !important;
        border-radius: 8px !important;
        font-weight: 800 !important;
      }
      .enhanced-score-overlay-actions .learn-more-btn:hover,
      .enhanced-score-overlay-actions .enhanced-score-learn-more-btn:hover,
      .enhanced-score-overlay-actions .btn:not(.buy-now-btn):not(.composition-buy-btn):not(.buy-button):hover {
        background: rgba(255, 255, 255, 0.12) !important;
        border-color: rgba(255, 255, 255, 0.7) !important;
      }
      /* Tabs: ghost segments on the glass; active tab is the white plate */
      .enhanced-score-overlay .score-media-toggle {
        padding: 10px 15px !important;
        border-bottom: 1px solid rgba(255, 255, 255, 0.16) !important;
      }
      .enhanced-score-overlay .media-toggle-btn {
        background: transparent !important;
        color: rgba(255, 255, 255, 0.88) !important;
        border: 1px solid rgba(255, 255, 255, 0.32) !important;
        border-radius: 6px !important;
        font-weight: 700 !important;
      }
      .enhanced-score-overlay .media-toggle-btn:hover {
        background: rgba(255, 255, 255, 0.12) !important;
        filter: none !important;
      }
      .enhanced-score-overlay .media-toggle-btn.active {
        background: #ffffff !important;
        color: var(--ee-ink) !important;
        border-color: #ffffff !important;
        box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.35) !important;
      }
}

/* ===== One loading-placeholder treatment ==================================
   The site had grown eight different shimmer keyframes across components
   (loading-shimmer, nrSk, pc-skeleton, sk-shimmer, skeleton, skeleton-shimmer,
   news-loading-shimmer, rc-shimmer) at four durations, two easings, both
   sweep directions, and five colour recipes — two of which were inverted
   relative to each other, so placeholders on the same page shimmered in
   opposite polarity at different speeds. Several also used cool slate greys
   on the warm cream surfaces, where they read as muddy and barely moved.

   This is one treatment for all of them. The fill is translucent ink rather
   than a fixed grey, so it tints whatever surface it sits on — cream stays
   cream, white stays white — and the contrast is high enough to actually read
   as "loading" without shouting. Deliberately outside the desktop-only media
   query: loading states matter at every width. */

/* Percentage background-position aligns X% of the image with X% of the box,
   so with a 200%-wide gradient only 0%..100% keeps the box fully covered —
   sweeping outside that range leaves an uncovered band with a hard edge. */
@keyframes ee-skeleton-sweep {
  from { background-position: 100% 0; }
  to   { background-position: 0% 0; }
}

.nr-sk,
.loading-gradient,
.streaming-skeleton,
.ld-line,
.ld-chip,
.sk,
.sk-thumb,
.nr-thumb.scaffold-thumb > div:first-child,
#featuredPrimaryPlayer > div[style],
.video-thumb[aria-hidden="true"] > div[style],
.table-header-cell[style*="shimmer"],
[style*="loading-shimmer"] {
  background-image: linear-gradient(
    100deg,
    rgba(2, 6, 23, 0.085) 20%,
    rgba(2, 6, 23, 0.035) 45%,
    rgba(2, 6, 23, 0.085) 70%
  ) !important;
  background-color: transparent !important;
  background-size: 200% 100% !important;
  background-repeat: no-repeat !important;
  animation: ee-skeleton-sweep 1.4s ease-in-out infinite !important;
  border-radius: 6px !important;
}

/* A cover plate whose image has not arrived.
   The scaffold covers the gap before the real cards render, but once they do,
   an <img> that has not loaded is just an empty box with its alt text sitting
   in it — which is what a slow connection actually shows, and it reads as
   broken rather than as loading. The plate holds the same sweep as every other
   placeholder until the image paints, and the alt text is hidden while it does,
   so the swap is plate-for-plate.

   Deliberately outside the desktop-only query: a slow connection is not a
   desktop problem. */
.nr-thumb:not(.ee-img-ready),
.composition-image:not(.ee-img-ready),
.nr-thumb:not(.ee-img-ready) img,
.composition-image:not(.ee-img-ready) img {
  color: transparent !important;
}
.nr-thumb:not(.ee-img-ready),
.composition-image:not(.ee-img-ready) {
  background-image: linear-gradient(
    100deg,
    rgba(2, 6, 23, 0.085) 20%,
    rgba(2, 6, 23, 0.035) 45%,
    rgba(2, 6, 23, 0.085) 70%
  ) !important;
  background-size: 200% 100% !important;
  background-repeat: no-repeat !important;
  animation: ee-skeleton-sweep 1.4s ease-in-out infinite !important;
}
@media (prefers-reduced-motion: reduce) {
  .nr-thumb:not(.ee-img-ready),
  .composition-image:not(.ee-img-ready) {
    animation: none !important;
  }
}

/* Blocks that stand in for a cover or a player read better with the same
   hairline the real plate will have, so the swap is edge-for-edge. */
.nr-thumb.scaffold-thumb > div:first-child,
#featuredPrimaryPlayer > div[style],
.video-thumb[aria-hidden="true"] > div[style],
.sk-thumb {
  box-shadow: inset 0 0 0 1px rgba(2, 6, 23, 0.16) !important;
  border-radius: 8px !important;
}

/* Text stand-ins keep a text-like height and a tighter radius. */
.ld-line,
.nr-sk-line,
.nr-sk-title {
  border-radius: 4px !important;
}

/* A sweeping gradient is exactly the kind of motion vestibular sensitivity
   guidance asks you to drop; hold a steady fill instead of removing the cue. */
@media (prefers-reduced-motion: reduce) {
  .nr-sk,
  .loading-gradient,
  .streaming-skeleton,
  .ld-line,
  .ld-chip,
  .sk,
  .sk-thumb,
  .nr-thumb.scaffold-thumb > div:first-child,
  #featuredPrimaryPlayer > div[style],
  .video-thumb[aria-hidden="true"] > div[style],
  [style*="loading-shimmer"] {
    animation: none !important;
    background-image: none !important;
    background-color: rgba(2, 6, 23, 0.06) !important;
  }
}

/* With the wrapper neutralised, the inner button sets the size — and it inherits
   a compact 32px rule while Learn More beside it is 44px. Match them: measured
   Learn More at 112x44, padding 7.68/12.8, 14.4px text. */
@media (min-width: 1025px) {
  #news-new-release-buy > button,
  #news-new-release-buy > a,
  .primary-actions-container .btn-buy.buy-now-btn > button,
  .primary-actions-container .buy-now-btn > button.buy-now-btn,
  .primary-actions-container .buy-now-btn > .composition-buy-btn {
    min-height: 44px !important;
    padding: 7.68px 12.8px !important;
    font-size: 0.9rem !important;
    line-height: 1.1 !important;
    border-radius: 8px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    box-sizing: border-box !important;
  }
}

/* Placed last on purpose, and deliberately specific: the navy button rule that
   paints these carries six classes, so a plain `.buy-now-btn:has(...)` (two)
   lost to it on specificity even though it matched. */
@media (min-width: 1025px) {
  /* PurchaseButton renders its <button> INTO a wrapper that already carries the
     same classes, so wrapper and button were both painted as plates — a button
     inside a button, with two casts stacking on hover. When a buy control
     contains another control, the outer is only a container. */
  #news-new-release-buy:has(button),
  #news-new-release-buy:has(a),
  .primary-actions-container .btn-buy.buy-now-btn:has(button):not(.free):not(.contact-btn):not(.free-download-btn),
  .primary-actions-container .buy-now-btn:has(.composition-buy-btn):not(.free):not(.contact-btn):not(.free-download-btn),
  .expanded-actions .buy-now-btn:has(button):not(.free):not(.contact-btn):not(.free-download-btn),
  .collection-actions-flex .buy-now-btn:has(button):not(.free):not(.contact-btn):not(.free-download-btn) {
    background: none !important;
    background-color: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
    padding: 0 !important;
    min-height: 0 !important;
    border-radius: 0 !important;
    transform: none !important;
  }
  #news-new-release-buy:has(button):hover,
  .primary-actions-container .btn-buy.buy-now-btn:has(button):not(.free):not(.contact-btn):not(.free-download-btn):hover,
  .primary-actions-container .buy-now-btn:has(.composition-buy-btn):not(.free):not(.contact-btn):not(.free-download-btn):hover,
  .expanded-actions .buy-now-btn:has(button):not(.free):not(.contact-btn):not(.free-download-btn):hover,
  .collection-actions-flex .buy-now-btn:has(button):not(.free):not(.contact-btn):not(.free-download-btn):hover {
    background: none !important;
    background-color: transparent !important;
    box-shadow: none !important;
    transform: none !important;
  }
}

/* ===== Audio transport ======================================================
   The native <audio> element is browser furniture — the same grey pill on every
   site on the internet, which is a strange thing to hand someone on a
   composer's page. This replaces it with a precision timeline: a graduated rule
   with major and minor divisions, the elapsed span inked in, a hairline cursor,
   and tabular timecode with time remaining. The <audio> element is still the
   engine underneath, so with the script blocked you get native controls back.

   Not inside a desktop-only query — a player has to work at every width. */

.ee-transport {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  padding: 0.7rem 0.85rem;
  background: #ffffff;
  border: 1px solid rgba(2, 6, 23, 0.3);
  border-radius: 8px;
  box-sizing: border-box;
}

.ee-transport .ee-tp-btn {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: #ffffff;
  color: hsl(221, 39%, 13%);
  border: 1px solid rgba(2, 6, 23, 0.45);
  border-radius: 6px;
  cursor: pointer;
  box-shadow: 2px 2px 0 rgba(2, 6, 23, 0.2);
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.ee-transport .ee-tp-btn svg { width: 16px; height: 16px; display: block; }
.ee-transport .ee-tp-btn:hover {
  background: hsl(45, 42%, 96%);
  transform: translate(-1px, -1px);
  box-shadow: 3px 3px 0 rgba(2, 6, 23, 0.28);
}
/* Playing is a held state, so the primary control stays pressed in rather than
   raised — you can see at a glance which take is running. */
.ee-transport.is-playing .ee-tp-play {
  background: hsl(221, 45%, 22%);
  border-color: hsl(221, 45%, 22%);
  color: #ffffff;
  box-shadow: none;
  transform: none;
}
.ee-transport .ee-tp-restart,
.ee-transport .ee-tp-vol { width: 30px; height: 30px; }
.ee-transport .ee-tp-restart svg,
.ee-transport .ee-tp-vol svg { width: 14px; height: 14px; }
.ee-transport.is-muted .ee-tp-vol { color: hsl(0, 55%, 42%); }

/* ---- the timeline ------------------------------------------------------ */
/* A graduated rule with major and minor divisions and a hairline cursor —
   the idiom editing tools use. An earlier version drew a notehead riding the
   line; it was a literal metaphor and read as decorative rather than precise. */
.ee-transport .ee-tp-stave {
  position: relative;
  flex: 1 1 auto;
  height: 50px;
  min-width: 80px;
  cursor: pointer;
  touch-action: none;
}
.ee-transport .ee-tp-stave:focus-visible {
  outline: 2px solid hsl(221, 45%, 22%);
  outline-offset: 3px;
  border-radius: 3px;
}
/* the baseline */
.ee-transport .ee-tp-rule {
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  margin-top: -0.5px;
  background: rgba(2, 6, 23, 0.22);
}
/* graduations: minor every 1/20, major every 1/4 */
.ee-transport .ee-tp-ticks {
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 14px;
  margin-top: -7px;
  pointer-events: none;
  background-image:
    linear-gradient(90deg, rgba(2, 6, 23, 0.3) 0 1px, transparent 1px),
    linear-gradient(90deg, rgba(2, 6, 23, 0.16) 0 1px, transparent 1px);
  background-size: 25% 100%, 5% 100%;
  background-position: 0 0, 0 0;
  background-repeat: repeat-x, repeat-x;
  -webkit-mask-image:
    linear-gradient(180deg, transparent 0 18%, #000 18% 82%, transparent 82%),
    linear-gradient(180deg, transparent 0 36%, #000 36% 64%, transparent 64%);
  -webkit-mask-composite: source-over;
  mask-image:
    linear-gradient(180deg, transparent 0 18%, #000 18% 82%, transparent 82%),
    linear-gradient(180deg, transparent 0 36%, #000 36% 64%, transparent 64%);
  mask-composite: add;
}
/* elapsed span */
.ee-transport .ee-tp-ink {
  position: absolute;
  left: 0; top: 50%;
  height: 2px;
  margin-top: -1px;
  width: 0;
  background: hsl(221, 45%, 22%);
  pointer-events: none;
}
/* playhead: a hairline cursor spanning the rule, with a fine cap top and bottom */
.ee-transport .ee-tp-cursor {
  position: absolute;
  top: 50%;
  left: 0;
  width: 1.5px;
  height: 20px;
  margin-top: -10px;
  margin-left: -0.75px;
  background: hsl(221, 45%, 22%);
  pointer-events: none;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.9);
}

/* ---- clock ------------------------------------------------------------- */
.ee-transport .ee-tp-clock {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: baseline;
  gap: 0.28rem;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  font-weight: 800;
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  color: hsl(221, 39%, 13%);
  white-space: nowrap;
}
.ee-transport .ee-tp-sep { opacity: 0.4; }
.ee-transport .ee-tp-dur { opacity: 0.62; }
/* time remaining, the way an editing tool shows it */
.ee-transport .ee-tp-rem {
  margin-left: 0.5rem;
  padding-left: 0.5rem;
  border-left: 1px solid rgba(2, 6, 23, 0.18);
  opacity: 0.55;
  font-size: 0.72rem;
}

@media (prefers-reduced-motion: reduce) {
  .ee-transport .ee-tp-btn { transition: none; }
  .ee-transport .ee-tp-btn:hover { transform: none; }
}

/* ---- waveform ----------------------------------------------------------
   Real peaks decoded from the file, not a decorative pattern — it is the shape
   of the actual take, so every piece looks like itself. It replaces the ruled
   timeline once decoded; if decoding is blocked or unsupported the rule stays
   and nothing is lost. */
.ee-transport .ee-tp-wave {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 32px;
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
}
.ee-transport.has-wave .ee-tp-wave { opacity: 1; }
/* once the waveform is up, the fallback rule and graduations step aside */
.ee-transport.has-wave .ee-tp-rule,
.ee-transport.has-wave .ee-tp-ticks,
.ee-transport.has-wave .ee-tp-ink { opacity: 0; }

.ee-transport .ee-tp-wave canvas {
  display: block;
  width: 100%;
  height: 100%;
}
/* the played span is the same waveform in ink, revealed by a clip that grows */
.ee-transport .ee-tp-wave-fill {
  position: absolute;
  left: 0; top: 0;
  height: 32px;
  width: 0;
  overflow: hidden;
  pointer-events: none;
}
.ee-transport .ee-tp-wave-fill canvas {
  height: 100%;
  max-width: none;
}

/* ---- timeline ruler + hover readout ------------------------------------
   The waveform says what the take sounds like; the ruler says where you are in
   it. Editors show both for exactly that reason, so this pairs them: peaks
   above, graduated rule with timestamps below, one cursor spanning the two. */
.ee-transport .ee-tp-ruler {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  width: 100%;
  height: 17px;
  display: none;
  pointer-events: none;
}
.ee-transport.has-wave .ee-tp-ruler { display: block; }
/* with the ruler carrying the graduations, the fallback ticks retire */
.ee-transport.has-wave .ee-tp-rule,
.ee-transport.has-wave .ee-tp-ticks { display: none; }

/* the cursor spans the waveform band only, so it does not cut the labels */
.ee-transport.has-wave .ee-tp-cursor {
  top: 0;
  height: 32px;
  margin-top: 0;
}

/* Ghost cursor under the pointer, with the time it would seek to. */
.ee-transport .ee-tp-hover {
  position: absolute;
  top: 0;
  height: 32px;
  width: 1px;
  margin-left: -0.5px;
  background: rgba(2, 6, 23, 0.35);
  opacity: 0;
  transition: opacity 0.12s ease;
  pointer-events: none;
}
.ee-transport.is-hovering .ee-tp-hover { opacity: 1; }
/* Seated inside the track rather than floating above it: above, it was clipped
   wherever the player sits in a container with its own bounds. */
.ee-transport .ee-tp-hover-time {
  position: absolute;
  top: 1px;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.1rem 0.32rem;
  border-radius: 3px;
  background: hsl(221, 45%, 22%);
  color: #ffffff;
  font-size: 0.62rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

/* ---- transport on a dark ground ----------------------------------------
   The score overlay is a dark glass panel. Dropping a white card into it would
   read as a page control that had fallen in, so the transport inverts: the
   plate becomes a hairline on the glass and the ink becomes light. */
.ee-transport.on-dark {
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.22);
}
.ee-transport.on-dark .ee-tp-btn {
  background: transparent;
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.4);
  box-shadow: none;
}
.ee-transport.on-dark .ee-tp-btn:hover {
  background: rgba(255, 255, 255, 0.14);
  transform: none;
  box-shadow: none;
}
.ee-transport.on-dark.is-playing .ee-tp-play {
  background: #ffffff;
  border-color: #ffffff;
  color: hsl(221, 45%, 22%);
}
.ee-transport.on-dark .ee-tp-clock { color: rgba(255, 255, 255, 0.92); }
.ee-transport.on-dark .ee-tp-rem { border-left-color: rgba(255, 255, 255, 0.25); }
.ee-transport.on-dark .ee-tp-rule { background: rgba(255, 255, 255, 0.25); }
.ee-transport.on-dark .ee-tp-ink { background: #ffffff; }
.ee-transport.on-dark .ee-tp-cursor {
  background: #ffffff;
  box-shadow: 0 0 0 1.5px rgba(2, 6, 23, 0.5);
}
.ee-transport.on-dark .ee-tp-hover { background: rgba(255, 255, 255, 0.5); }
.ee-transport.on-dark .ee-tp-hover-time { background: #ffffff; color: hsl(221, 45%, 22%); }


/* ===== Icons =============================================================
   Lucide (ISC), inlined as masked SVG: each takes currentColor and costs no
   request. Applied via ::before on existing controls, so adding one never
   means touching markup.

   The SVG is single-quoted deliberately. Double quotes inside would close
   the CSS url("...") on the spot, which fails silently with no icon. */

.ee-icon-search::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='11'%20cy='11'%20r='8'/%3E%3Cpath%20d='m21%2021-4.3-4.3'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='11'%20cy='11'%20r='8'/%3E%3Cpath%20d='m21%2021-4.3-4.3'/%3E%3C/svg%3E"); }
.ee-icon-sliders::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cline%20x1='21'%20x2='14'%20y1='4'%20y2='4'/%3E%3Cline%20x1='10'%20x2='3'%20y1='4'%20y2='4'/%3E%3Cline%20x1='21'%20x2='12'%20y1='12'%20y2='12'/%3E%3Cline%20x1='8'%20x2='3'%20y1='12'%20y2='12'/%3E%3Cline%20x1='21'%20x2='16'%20y1='20'%20y2='20'/%3E%3Cline%20x1='12'%20x2='3'%20y1='20'%20y2='20'/%3E%3Cline%20x1='14'%20x2='14'%20y1='2'%20y2='6'/%3E%3Cline%20x1='8'%20x2='8'%20y1='10'%20y2='14'/%3E%3Cline%20x1='16'%20x2='16'%20y1='18'%20y2='22'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cline%20x1='21'%20x2='14'%20y1='4'%20y2='4'/%3E%3Cline%20x1='10'%20x2='3'%20y1='4'%20y2='4'/%3E%3Cline%20x1='21'%20x2='12'%20y1='12'%20y2='12'/%3E%3Cline%20x1='8'%20x2='3'%20y1='12'%20y2='12'/%3E%3Cline%20x1='21'%20x2='16'%20y1='20'%20y2='20'/%3E%3Cline%20x1='12'%20x2='3'%20y1='20'%20y2='20'/%3E%3Cline%20x1='14'%20x2='14'%20y1='2'%20y2='6'/%3E%3Cline%20x1='8'%20x2='8'%20y1='10'%20y2='14'/%3E%3Cline%20x1='16'%20x2='16'%20y1='18'%20y2='22'/%3E%3C/svg%3E"); }
.ee-icon-x::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M18%206%206%2018'/%3E%3Cpath%20d='m6%206%2012%2012'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M18%206%206%2018'/%3E%3Cpath%20d='m6%206%2012%2012'/%3E%3C/svg%3E"); }
.ee-icon-sort::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m21%2016-4%204-4-4'/%3E%3Cpath%20d='M17%2020V4'/%3E%3Cpath%20d='m3%208%204-4%204%204'/%3E%3Cpath%20d='M7%204v16'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m21%2016-4%204-4-4'/%3E%3Cpath%20d='M17%2020V4'/%3E%3Cpath%20d='m3%208%204-4%204%204'/%3E%3Cpath%20d='M7%204v16'/%3E%3C/svg%3E"); }
.ee-icon-star::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M11.5%202.7a.7.7%200%200%201%201%200l2.4%205%205.4.8a.7.7%200%200%201%20.4%201.2l-4%203.8.9%205.4a.7.7%200%200%201-1%20.7l-4.8-2.5-4.8%202.5a.7.7%200%200%201-1-.7l.9-5.4-4-3.8a.7.7%200%200%201%20.4-1.2l5.4-.8z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M11.5%202.7a.7.7%200%200%201%201%200l2.4%205%205.4.8a.7.7%200%200%201%20.4%201.2l-4%203.8.9%205.4a.7.7%200%200%201-1%20.7l-4.8-2.5-4.8%202.5a.7.7%200%200%201-1-.7l.9-5.4-4-3.8a.7.7%200%200%201%20.4-1.2l5.4-.8z'/%3E%3C/svg%3E"); }
.ee-icon-score::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M14%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V8z'/%3E%3Cpath%20d='M14%202v6h6'/%3E%3Ccircle%20cx='10'%20cy='16'%20r='2'/%3E%3Cpath%20d='M12%2016V9l4%201'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M14%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V8z'/%3E%3Cpath%20d='M14%202v6h6'/%3E%3Ccircle%20cx='10'%20cy='16'%20r='2'/%3E%3Cpath%20d='M12%2016V9l4%201'/%3E%3C/svg%3E"); }
.ee-icon-music::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M9%2018V5l12-2v13'/%3E%3Ccircle%20cx='6'%20cy='18'%20r='3'/%3E%3Ccircle%20cx='18'%20cy='16'%20r='3'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M9%2018V5l12-2v13'/%3E%3Ccircle%20cx='6'%20cy='18'%20r='3'/%3E%3Ccircle%20cx='18'%20cy='16'%20r='3'/%3E%3C/svg%3E"); }
.ee-icon-wave::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M2%2013a2%202%200%200%200%202-2V7a2%202%200%200%201%204%200v13a2%202%200%200%200%204%200V4a2%202%200%200%201%204%200v13a2%202%200%200%200%204%200v-4a2%202%200%200%201%202-2'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M2%2013a2%202%200%200%200%202-2V7a2%202%200%200%201%204%200v13a2%202%200%200%200%204%200V4a2%202%200%200%201%204%200v13a2%202%200%200%200%204%200v-4a2%202%200%200%201%202-2'/%3E%3C/svg%3E"); }
.ee-icon-cap::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M22%2010v6'/%3E%3Cpath%20d='M6%2012.5V16a6%203%200%200%200%2012%200v-3.5'/%3E%3Cpath%20d='m2%2010%2010-5%2010%205-10%205z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M22%2010v6'/%3E%3Cpath%20d='M6%2012.5V16a6%203%200%200%200%2012%200v-3.5'/%3E%3Cpath%20d='m2%2010%2010-5%2010%205-10%205z'/%3E%3C/svg%3E"); }
.ee-icon-code::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m16%2018%206-6-6-6'/%3E%3Cpath%20d='m8%206-6%206%206%206'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m16%2018%206-6-6-6'/%3E%3Cpath%20d='m8%206-6%206%206%206'/%3E%3C/svg%3E"); }

/* lucide: circle-play — the one glyph the set was missing, for "Watch" */
.ee-icon-play::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='12'%20r='10'/%3E%3Cpath%20d='m10%208%206%204-6%204z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='12'%20r='10'/%3E%3Cpath%20d='m10%208%206%204-6%204z'/%3E%3C/svg%3E"); }

/* shared geometry for every glyph */
[class*="ee-icon-"]::before,
#catalog-filters #filterToggle::before,
#catalog-filters #clear-all-filters-top::before,
#catalog-filters .sort-button::before,
#catalog-filters .featured-toggle::before,
[data-ee-unused-role-marks]::before {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
}

@media (min-width: 1025px) {
  #catalog-filters #filterToggle { display: inline-flex !important; align-items: center; }
  #catalog-filters #filterToggle::before { margin-right: 0.42rem; -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cline%20x1='21'%20x2='14'%20y1='4'%20y2='4'/%3E%3Cline%20x1='10'%20x2='3'%20y1='4'%20y2='4'/%3E%3Cline%20x1='21'%20x2='12'%20y1='12'%20y2='12'/%3E%3Cline%20x1='8'%20x2='3'%20y1='12'%20y2='12'/%3E%3Cline%20x1='21'%20x2='16'%20y1='20'%20y2='20'/%3E%3Cline%20x1='12'%20x2='3'%20y1='20'%20y2='20'/%3E%3Cline%20x1='14'%20x2='14'%20y1='2'%20y2='6'/%3E%3Cline%20x1='8'%20x2='8'%20y1='10'%20y2='14'/%3E%3Cline%20x1='16'%20x2='16'%20y1='18'%20y2='22'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cline%20x1='21'%20x2='14'%20y1='4'%20y2='4'/%3E%3Cline%20x1='10'%20x2='3'%20y1='4'%20y2='4'/%3E%3Cline%20x1='21'%20x2='12'%20y1='12'%20y2='12'/%3E%3Cline%20x1='8'%20x2='3'%20y1='12'%20y2='12'/%3E%3Cline%20x1='21'%20x2='16'%20y1='20'%20y2='20'/%3E%3Cline%20x1='12'%20x2='3'%20y1='20'%20y2='20'/%3E%3Cline%20x1='14'%20x2='14'%20y1='2'%20y2='6'/%3E%3Cline%20x1='8'%20x2='8'%20y1='10'%20y2='14'/%3E%3Cline%20x1='16'%20x2='16'%20y1='18'%20y2='22'/%3E%3C/svg%3E"); }
  #catalog-filters #clear-all-filters-top { display: inline-flex !important; align-items: center; }
  #catalog-filters #clear-all-filters-top::before { margin-right: 0.42rem; -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M18%206%206%2018'/%3E%3Cpath%20d='m6%206%2012%2012'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M18%206%206%2018'/%3E%3Cpath%20d='m6%206%2012%2012'/%3E%3C/svg%3E"); }
  #catalog-filters .sort-button { display: inline-flex !important; align-items: center; }
  #catalog-filters .sort-button::before { margin-right: 0.42rem; -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m21%2016-4%204-4-4'/%3E%3Cpath%20d='M17%2020V4'/%3E%3Cpath%20d='m3%208%204-4%204%204'/%3E%3Cpath%20d='M7%204v16'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m21%2016-4%204-4-4'/%3E%3Cpath%20d='M17%2020V4'/%3E%3Cpath%20d='m3%208%204-4%204%204'/%3E%3Cpath%20d='M7%204v16'/%3E%3C/svg%3E"); }
  #catalog-filters .featured-toggle { display: inline-flex !important; align-items: center; }
  #catalog-filters .featured-toggle::before { margin-right: 0.42rem; -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M11.5%202.7a.7.7%200%200%201%201%200l2.4%205%205.4.8a.7.7%200%200%201%20.4%201.2l-4%203.8.9%205.4a.7.7%200%200%201-1%20.7l-4.8-2.5-4.8%202.5a.7.7%200%200%201-1-.7l.9-5.4-4-3.8a.7.7%200%200%201%20.4-1.2l5.4-.8z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M11.5%202.7a.7.7%200%200%201%201%200l2.4%205%205.4.8a.7.7%200%200%201%20.4%201.2l-4%203.8.9%205.4a.7.7%200%200%201-1%20.7l-4.8-2.5-4.8%202.5a.7.7%200%200%201-1-.7l.9-5.4-4-3.8a.7.7%200%200%201%20.4-1.2l5.4-.8z'/%3E%3C/svg%3E"); }
  #catalog-filters #filterToggle::after { display: none !important; }
  #catalog-filters .featured-toggle::before { opacity: 0.55; }
  #catalog-filters .featured-toggle:has(input:checked)::before { opacity: 1; }

  /* Teaching Books is the educator's shelf, so it carries the same mark */

}

/* ===== Material and motion ==================================================
   Nothing here depicts anything: no notes, no horns, no symbols. Every attempt
   to state the identity read as costume. What is left is the two things a
   physical object has that a hex value does not — a surface that catches light
   unevenly, and weight when it moves.

   The test every candidate has to pass: if a visitor can name it, it is
   already too loud. It should change how the page feels without ever
   presenting itself as a thing that was added.

   Two things deliberately NOT done, having tried them:
     - No entrance animation on the featured panel or the expanded collection.
       Both already run their own JS-driven reveals, and a second animation
       fights the first.
     - No new stacking contexts. The grain rides the full-bleed background layer
       that already exists, rather than a fresh positioned pseudo-element, which
       would put a z-index over the sticky panel and the expanded overlay. */

/* ---- substrate: three candidates, gated for comparison -------------------
   Grain was tried and pulled. Simulated noise on a screen does not read as
   paper; it reads as a compression artefact, and the field agrees — it is a
   known shortcut for making flat work feel "full" without earning it.

   The tiled hairline grid was ruled out for the opposite reason: it is so
   overused it has a name ("that Vercel grid"), and an arbitrary 24px tile is
   exactly the generic SaaS wallpaper this design set out to avoid.

   Ruled lines of every kind are ruled out, and this was learned the expensive
   way. Column rules on the works table, margin rules down each field, and a
   five-line staff behind the waveform were each built and each rejected on
   sight: drawn lines read as school stationery, not as engraving, however
   accurately they are aligned to real structure. Alignment does not rescue a
   line. Do not propose ruling anything again.

   What survives is tone, not line. */

/* Tonal press bed, on the open field.
   No pattern: each field is fractionally denser at its outer edges than at its
   centre, the way light actually falls across a sheet lying on a bed. There is
   no tile, no motif and no repeat, so there is nothing to recognise — it only
   stops the surface reading as a dead flat fill. */
#popular-works,
#catalog-collections-section,
#news-nr-thumb-rail {
  background-image:
    linear-gradient(
      to right,
      rgba(2, 6, 23, 0.05) 0%,
      rgba(2, 6, 23, 0) 22%,
      rgba(2, 6, 23, 0) 78%,
      rgba(2, 6, 23, 0.05) 100%
    );
}

/* ---- chroma: each work casts in its own colour ---------------------------
   Taken from the covers, which are the brand. What they share as a set is not
   a motif, a texture or a typeface — it is that every work owns a saturated
   colorway of its own. That is the publishing idea (each edition has a
   colorway) and the database idea (a computed attribute per record) turning
   out to be the same idea, so it is the one that belongs here.

   The accent is read out of the artwork offline (sync/build-cover-colors.mjs)
   and arrives as --work-accent. A plate then casts a shadow tinted by its own
   cover, the way coloured light bounces off a real printed sheet — which is
   why it lands on the cast rather than on a border or a fill. Nothing is
   drawn, nothing is depicted, and no line is added.

   Works with no cover art never get .has-chroma and keep the neutral cast. */
@media (min-width: 1025px) {
  #catalog-new-releases-host .nr-thumb.has-chroma:hover,
  .expanded-item.has-chroma:hover {
    box-shadow: 6px 6px 0 hsl(var(--work-accent) / 0.4) !important;
  }
  #catalog-new-releases-host .composition-image.has-chroma:hover {
    box-shadow: 10px 10px 0 hsl(var(--work-accent) / 0.42) !important;
  }

  /* The field takes the colour of the work on it.
     A few percent of the featured work's accent mixed into the cream, so the
     opening area is faintly warm under a sunset cover and faintly cool under a
     blue one. Because the mix is computed from a custom property, changing the
     property animates the result — the light in the room changes when the
     selection changes, which is motion that means something rather than a loop
     running on a timer.

     Held to single digits deliberately: at this strength nobody identifies a
     colour, they just find the page sits differently against each cover. */
  /* Both the section and its ::before, and both !important. The page CSS sets
     `background: var(--secondary-200)` on each — a shorthand, so a plain
     `background-color` here loses to it — and ::before is a 100vw full-bleed
     band, so missing it leaves the tint showing only in the narrow gutters.

     Held to single digits deliberately. At 16% a cool accent turns the cream
     grey-green and the field stops being cream at all, which trades a known
     good colour for a gimmick. At 8% the worst case (a blue cover against warm
     cream) still reads as cream, just cooler. */
  #popular-works,
  #popular-works::before {
    background-color: color-mix(in oklab, hsl(var(--field-accent, 40 20% 50%)) 5%, #f4efe2) !important;
    transition: background-color 0.9s ease;
  }

  /* The drifting backdrop: the cover itself, blurred past recognition.
     Not an abstract shape — a drifting blob is the stock move and would read
     as exactly the generic styling this design avoids. This is generated from
     the artwork, so it is the work's own colour in the work's own proportions,
     and it is different for all 67 of them.

     z-index -1 puts it behind the page content but above ::before, so it sits
     on the tinted field without touching the text. The drift runs on transform
     only, which stays on the compositor — animating a 90px blur any other way
     would repaint the whole band every frame. */
  /* The backdrop is deliberately larger than the field so the drift never
     exposes an edge, which made the page 171px wider than the viewport and
     scrollable sideways onto a bare block of colour.

     `clip` rather than `hidden`: clip does not create a scroll container, so it
     cannot trap scrolling or break a position:sticky descendant the way hidden
     would. The full-bleed ::before loses at most a pixel or two of a flat
     colour band at each edge, which is invisible. */
  #popular-works,
  .composition-top-frame {
    overflow: clip;
  }
  .ee-field-art {
    position: absolute;
    inset: -12%;
    z-index: -1;
    background-size: cover;
    background-position: center;
    /* Saturated and brightened before it is laid down, at low opacity. Two
       other recipes were tried and rejected against a near-black cover
       (Coming Home) and a cool one (WindSprints), both of which turned the
       cream to flat grey:
         - normal blend at 0.28 — dark art simply darkened the field;
         - mix-blend-mode: color — takes hue *and saturation* from the source,
           so a desaturated cover stripped the cream's own warmth.
       Brightening first means a dark cover cannot darken, and saturating first
       means only genuinely chromatic art registers at all. The cream can be
       tinted but never greyed. */
    /* 48px rather than 90px. Blur cost climbs steeply with radius, and at this
       scale and opacity the artwork is already unreadable — the extra radius
       bought nothing visible and cost real paint time. */
    filter: blur(48px) saturate(2.2) brightness(1.45);
    opacity: 0.22;
    pointer-events: none;
    will-change: transform;
    animation: ee-field-drift 54s ease-in-out infinite alternate;
  }
  @keyframes ee-field-drift {
    from { transform: translate3d(-3%, -2%, 0) scale(1.05); }
    to   { transform: translate3d(3%, 2%, 0) scale(1.14); }
  }
  @media (prefers-reduced-motion: reduce) {
    .ee-field-art { animation: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    #popular-works { transition: none; }
  }
}

/* ---- weight --------------------------------------------------------------
   One easing curve, and a touch more travel time than a UI default. A plate
   that takes 220ms to lift reads as having mass; the same plate at 120ms reads
   as a rectangle changing state. This is the whole of the motion work — no new
   animations, just the existing ones given weight. */
@media (min-width: 1025px) and (prefers-reduced-motion: no-preference) {
  #catalog-new-releases-host .composition-image.has-image,
  #catalog-new-releases-host .nr-thumb,
  #catalog-collections-section .collections-card-header,
  .results .card,
  .expanded-item {
    transition-duration: 0.22s !important;
    transition-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1) !important;
  }

  /* The waveform is the one place a genuine entrance belongs: it arrives with
     real data, so letting it rise once acknowledges that something was read
     rather than drawn. Self-contained, so it fights nothing. */
  .ee-transport .ee-tp-wave {
    transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
    transform: scaleY(0.72);
    transform-origin: center;
  }
  .ee-transport.has-wave .ee-tp-wave { transform: none; }
}

/* ===== Core identity, at every width ======================================
   Everything above is deliberately desktop-only: the brief was a desktop
   concept, and the hover tiers, plate casts and sticky behaviours are sized for
   a pointer and a wide field.

   But four things are not layout — they are the brand — and scoping them to
   desktop meant a phone still showed the old site. Most seriously it still
   showed the purple gradient Buy Now, which was rejected early on and has been
   gone from desktop for months. Someone on a phone has been looking at a
   design that no longer exists anywhere else.

   These carry no layout, no hover and no motion, so they are safe at any width:
   the call to action, the FEATURED stamp, the masthead roles and the press-bed
   rule the page hangs from. */

/* The call to action: one navy plate, no gradient, everywhere. */
.btn-buy.buy-now-btn,
.buy-now-btn,
.buy-button,
.composition-buy-btn {
  background-image: none !important;
  background-color: hsl(221, 45%, 22%) !important;
  color: #ffffff !important;
  border: 1px solid hsl(221, 45%, 18%) !important;
  border-radius: 8px !important;
  font-weight: 800 !important;
  box-shadow: 2px 2px 0 rgba(2, 6, 23, 0.2) !important;
}

/* FEATURED is a stamp pressed into the page, not a glowing pill. */
.card-badge {
  background-image: none !important;
  background-color: hsl(221, 62%, 47%) !important;
  color: #ffffff !important;
  border: 1px solid hsl(221, 62%, 38%) !important;
  border-radius: 4px !important;
  box-shadow: none !important;
  font-weight: 800 !important;
  text-transform: uppercase !important;
  letter-spacing: 0.14em !important;
}

/* The roles line is set as a colophon, not a sentence. */
.brand-roles .role-link,
.brand-roles .role-sep {
  text-transform: uppercase !important;
  letter-spacing: 0.1em !important;
  font-weight: 600 !important;
}

/* The masthead sits on its ink rule at every width. */
.header-base {
  border-bottom: 2px solid rgba(2, 6, 23, 0.85) !important;
}

/* Fixed masthead layers were measuring wider than the viewport, which gave the
   phone 55px of sideways scroll on every page. They are position:fixed, so
   clamping them to the viewport is enough and cannot disturb the flow. */
@media (max-width: 1024px) {
  .example-1,
  .header-base,
  .primary-nav,
  .menu-backdrop {
    max-width: 100vw;
  }
  html, body { overflow-x: hidden; }
}
